From 874ff69976c87bcef3543b5dd49e82d988783a94 Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Sun, 6 Oct 2024 10:56:46 +0100 Subject: [PATCH] Add branding option to filter out LAFs in UI selection. - add a branding option LafPanel.excludes to hide installed LAFs in combobox - add optional checkbox to show all installed LAFs - switched LafPanel layout to group layout and tweaked UI Co-authored-by: Michael Bien --- .../core/windows/options/Bundle.properties | 10 ++ .../core/windows/options/LafPanel.form | 165 ++++++++++-------- .../core/windows/options/LafPanel.java | 157 +++++++++++------ 3 files changed, 202 insertions(+), 130 deletions(-) diff --git a/platform/core.windows/src/org/netbeans/core/windows/options/Bundle.properties b/platform/core.windows/src/org/netbeans/core/windows/options/Bundle.properties index 955dcc08a247..633719af668c 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/options/Bundle.properties +++ b/platform/core.windows/src/org/netbeans/core/windows/options/Bundle.properties @@ -46,6 +46,8 @@ LafPanel.lblLaf.text=&Preferred look and feel: LafPanel.lblRestart.text=(needs restart) LafPanel.checkMaximizeNativeLaF.toolTipText=NetBeans uses native UI components when those components offer sufficient\nfunctionality.
Select this option to force use of native components, even when\nthat may limit functionality (e.g. standard Mac OS file chooser). LafPanel.checkMaximizeNativeLaF.text=M&aximize use of native look and feel +LafPanel.showAllLafs.text=Show all look and feels +LafPanel.showAllLafs.toolTipText=Show all installed look and feels.
Other look and feels may not be recommended or supported. TabsPanel.checkMultiRow.text=&Multi-row tabs TabsPanel.radioBottom.text=&bottom TabsPanel.radioTop.text=&top @@ -64,3 +66,11 @@ TabsPanel.radioSortFullFilePath.text=Sort by &full file path TabsPanel.radioSortFileNameWithParent.text=Sort by file name with &parent directory TabsPanel.radioSortFileName.text=Sort by file &name TabsPanel.sortTabsLabel.text=Sort tabs when a document opens: + +# Space separated list of LAF classes to hide in UI +#NOI18N +LafPanel.excludes= + +# Whether to show all LAF toggle option to reveal excluded LAFs +#NOI18N +LafPanel.showAllLafs.visible=false diff --git a/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.form b/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.form index 0ac2eb094fae..21ed318c3829 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.form +++ b/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.form @@ -22,10 +22,6 @@ -->
- - - - @@ -40,86 +36,107 @@ - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.java b/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.java index 4ecff34c30a3..396cc88bfd88 100644 --- a/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.java +++ b/platform/core.windows/src/org/netbeans/core/windows/options/LafPanel.java @@ -27,7 +27,9 @@ import java.awt.event.MouseEvent; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; @@ -58,10 +60,9 @@ public class LafPanel extends javax.swing.JPanel { private final Preferences prefs = NbPreferences.forModule(LafPanel.class); - private final boolean isAquaLaF = "Aqua".equals(UIManager.getLookAndFeel().getID()); //NOI18N private static final boolean NO_RESTART_ON_LAF_CHANGE = Boolean.getBoolean("nb.laf.norestart"); //NOI18N private int defaultLookAndFeelIndex; - private final ArrayList lafs = new ArrayList( 10 ); + private final List lafs = new ArrayList<>(); protected LafPanel(final LafOptionsPanelController controller) { this.controller = controller; @@ -74,13 +75,8 @@ public void itemStateChanged(ItemEvent e) { fireChanged(); } }); - initLookAndFeel(); + initLookAndFeels(); lblRestart.setVisible(!NO_RESTART_ON_LAF_CHANGE); - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - for( LookAndFeelInfo li : lafs ) { - model.addElement( li.getName() ); - } - comboLaf.setModel( model ); comboLaf.addItemListener( new ItemListener() { @Override @@ -106,51 +102,72 @@ private void fireChanged() { */ // //GEN-BEGIN:initComponents private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - buttonGroup1 = new javax.swing.ButtonGroup(); - panelLaF = new javax.swing.JPanel(); - checkMaximizeNativeLaF = new javax.swing.JCheckBox(); panelLaFCombo = new javax.swing.JPanel(); - comboLaf = new javax.swing.JComboBox(); - lblLaf = new javax.swing.JLabel(); + checkMaximizeNativeLaF = new javax.swing.JCheckBox(); lblRestart = new javax.swing.JLabel(); + comboLaf = new javax.swing.JComboBox(); + javax.swing.JLabel lblLaf = new javax.swing.JLabel(); + showAllLafs = new javax.swing.JCheckBox(); setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); - setLayout(new java.awt.GridBagLayout()); - panelLaF.setLayout(new java.awt.BorderLayout()); + panelLaFCombo.setLayout(new java.awt.BorderLayout(3, 0)); org.openide.awt.Mnemonics.setLocalizedText(checkMaximizeNativeLaF, org.openide.util.NbBundle.getMessage(LafPanel.class, "LafPanel.checkMaximizeNativeLaF.text")); // NOI18N checkMaximizeNativeLaF.setToolTipText(org.openide.util.NbBundle.getMessage(LafPanel.class, "LafPanel.checkMaximizeNativeLaF.toolTipText")); // NOI18N - panelLaF.add(checkMaximizeNativeLaF, java.awt.BorderLayout.WEST); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0); - add(panelLaF, gridBagConstraints); - panelLaFCombo.setLayout(new java.awt.BorderLayout(3, 0)); - panelLaFCombo.add(comboLaf, java.awt.BorderLayout.CENTER); + org.openide.awt.Mnemonics.setLocalizedText(lblRestart, NbBundle.getMessage(LafPanel.class, "LafPanel.lblRestart.text")); // NOI18N lblLaf.setLabelFor(comboLaf); org.openide.awt.Mnemonics.setLocalizedText(lblLaf, NbBundle.getMessage(LafPanel.class, "LafPanel.lblLaf.text")); // NOI18N - panelLaFCombo.add(lblLaf, java.awt.BorderLayout.WEST); - - org.openide.awt.Mnemonics.setLocalizedText(lblRestart, NbBundle.getMessage(LafPanel.class, "LafPanel.lblRestart.text")); // NOI18N - panelLaFCombo.add(lblRestart, java.awt.BorderLayout.LINE_END); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - add(panelLaFCombo, gridBagConstraints); + org.openide.awt.Mnemonics.setLocalizedText(showAllLafs, org.openide.util.NbBundle.getMessage(LafPanel.class, "LafPanel.showAllLafs.text")); // NOI18N + showAllLafs.setToolTipText(org.openide.util.NbBundle.getMessage(LafPanel.class, "LafPanel.showAllLafs.toolTipText")); // NOI18N + showAllLafs.addActionListener(this::showAllLafsActionPerformed); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panelLaFCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(lblLaf) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(comboLaf, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblRestart)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(showAllLafs) + .addComponent(checkMaximizeNativeLaF)))) + .addContainerGap(36, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(panelLaFCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblLaf) + .addComponent(comboLaf, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblRestart, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(showAllLafs) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(checkMaximizeNativeLaF) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); }// //GEN-END:initComponents + private void showAllLafsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAllLafsActionPerformed + initLookAndFeels(); + load(); + }//GEN-LAST:event_showAllLafsActionPerformed + protected void load() { checkMaximizeNativeLaF.setSelected(prefs.getBoolean(WinSysPrefs.MAXIMIZE_NATIVE_LAF, false)); @@ -158,6 +175,9 @@ protected void load() { defaultLookAndFeelIndex = lafs.indexOf( isForcedLaF ? getCurrentLaF() : getPreferredLaF() ); comboLaf.setSelectedIndex( defaultLookAndFeelIndex ); comboLaf.setEnabled( !isForcedLaF ); + if (isForcedLaF) { + showAllLafs.setVisible(false); + } } protected boolean store() { @@ -190,20 +210,44 @@ boolean valid() { } // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JCheckBox checkMaximizeNativeLaF; private javax.swing.JComboBox comboLaf; - private javax.swing.JLabel lblLaf; private javax.swing.JLabel lblRestart; - private javax.swing.JPanel panelLaF; private javax.swing.JPanel panelLaFCombo; + private javax.swing.JCheckBox showAllLafs; // End of variables declaration//GEN-END:variables - - private void initLookAndFeel() { + private void initLookAndFeels() { lafs.clear(); - for( LookAndFeelInfo i : UIManager.getInstalledLookAndFeels() ) { - lafs.add( i ); + String lafExcludes = NbBundle.getMessage(LafPanel.class, "LafPanel.excludes").trim(); + if (lafExcludes.isEmpty()) { + showAllLafs.setVisible(false); + } else { + boolean showAllLafsOption = Boolean.parseBoolean( + NbBundle.getMessage(LafPanel.class, "LafPanel.showAllLafs.visible")); + showAllLafs.setVisible(showAllLafsOption); + } + if (lafExcludes.isEmpty() || showAllLafs.isSelected()) { + lafs.addAll(Arrays.asList(UIManager.getInstalledLookAndFeels())); + } else { + String cur = getCurrentLaF().getClassName(); + String pref = getPreferredLaF().getClassName(); + for (LookAndFeelInfo li : UIManager.getInstalledLookAndFeels()) { + String cls = li.getClassName(); + String name = cls.substring(cls.lastIndexOf('.') + 1, cls.length()); + if (cls.equals(cur) || cls.equals(pref) || !lafExcludes.contains(name)) { + lafs.add(li); + } + } + } + Object lastSelection = comboLaf.getSelectedItem(); + DefaultComboBoxModel model = new DefaultComboBoxModel<>(); + for(LookAndFeelInfo info : lafs) { + model.addElement(info.getName()); + } + comboLaf.setModel(model); + if (lastSelection != null) { + comboLaf.setSelectedItem(lastSelection); } } @@ -213,32 +257,33 @@ private boolean isForcedLaF() { private LookAndFeelInfo getCurrentLaF() { LookAndFeelInfo currentLaf = null; - String currentLAFClassName = UIManager.getLookAndFeel().getClass().getName(); - boolean isAqua = "Aqua".equals(UIManager.getLookAndFeel().getID()); //NOI18N - for( LookAndFeelInfo li : lafs ) { - if( currentLAFClassName.equals( li.getClassName() ) - || (isAqua && li.getClassName().contains("com.apple.laf.AquaLookAndFeel")) ) { //NOI18N + LookAndFeel laf = UIManager.getLookAndFeel(); + String currentLAFClassName = laf.getClass().getName(); + boolean isAqua = "Aqua".equals(laf.getID()); //NOI18N + for (LookAndFeelInfo li : UIManager.getInstalledLookAndFeels()) { + if (currentLAFClassName.equals(li.getClassName()) + || (isAqua && li.getClassName().contains("com.apple.laf.AquaLookAndFeel"))) { //NOI18N currentLaf = li; break; } } - return currentLaf; + return currentLaf == null ? new LookAndFeelInfo(laf.getName(), currentLAFClassName) : currentLaf; } private LookAndFeelInfo getPreferredLaF() { String lafClassName = NbPreferences.root().node( "laf" ).get( "laf", null ); //NOI18N if( null == lafClassName ) return getCurrentLaF(); - LookAndFeelInfo currentLaf = null; + LookAndFeelInfo prefLaf = null; boolean isAqua = "Aqua".equals(UIManager.getLookAndFeel().getID()); //NOI18N - for( LookAndFeelInfo li : lafs ) { - if( lafClassName.equals( li.getClassName() ) - || (isAqua && li.getClassName().contains("com.apple.laf.AquaLookAndFeel")) ) { //NOI18N - currentLaf = li; + for (LookAndFeelInfo li : UIManager.getInstalledLookAndFeels()) { + if (lafClassName.equals(li.getClassName()) + || (isAqua && li.getClassName().contains("com.apple.laf.AquaLookAndFeel"))) { //NOI18N + prefLaf = li; break; } } - return currentLaf; + return prefLaf == null ? getCurrentLaF() : prefLaf; } private static Notification restartNotification;