Skip to content

Commit

Permalink
Merge pull request #5795 from DevCharly/flatlaf-accent-color
Browse files Browse the repository at this point in the history
FlatLaf: change accent color in Options dialog (Appearance > FlatLaf)
  • Loading branch information
mbien committed Apr 14, 2023
2 parents 9a07595 + e2c1ee7 commit cfda31b
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ Editors/FontsColors/FlatLafDark=FlatLaf Dark
Editors/FontsColors/FlatLafLight=FlatLaf Light

FlatLaf_DisplayName=FlatLaf
KW_FlatLafOptions=FlatLaf, Look and Feel, Window decorations, Unified title bar, Embedded menu bar, underline menu, mnemonics
KW_FlatLafOptions=FlatLaf, Look and Feel, Accent color, Window decorations, Unified title bar, Embedded menu bar, underline menu, mnemonics

FlatLafOptionsPanel.accentColorLabel.text=Accent color:
FlatLafOptionsPanel.needsRestartLabel.text=(needs restart)
FlatLafOptionsPanel.useWindowDecorationsCheckBox.text=&Window decorations
FlatLafOptionsPanel.unifiedTitleBarCheckBox.text=&Unified window title bar
FlatLafOptionsPanel.menuBarEmbeddedCheckBox.text=&Embedded menu bar
Expand All @@ -41,6 +43,8 @@ FlatLafOptionsPanel.customProperties.content=\
\# FlatLaf custom property overrides.\n\
\# Save file and restart NetBeans to apply.\n\
\# For full documentation see https://www.formdev.com/flatlaf/properties-files/\n\
\#\n\
\# @accentColor=#dd2222\n\
\# [dark]@accentColor=#bb3232\n
\# and https://www.formdev.com/flatlaf/components/\n\
\#\n

FlatLafOptionsPanel.restartTitle=Restart IDE
FlatLafOptionsPanel.restartDetails=Click here to restart IDE and apply your selected accent color.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
Nb.LFCustoms={instance}org.netbeans.swing.laf.flatlaf.FlatLFCustoms


# accent colors from https://github.com/89netraM/SystemColors/blob/master/src/net/asberg/macos/AccentColor.java
nb.accentColors.predefined = \
blue: #0A84FF; \
purple: #BF5AF2; \
red: #FF453A; \
orange: #FF9F0A; \
green: #32D74B


nb.explorer.unfocusedSelBg=@selectionInactiveBackground
nb.explorer.unfocusedSelFg=@selectionInactiveForeground
nb.explorer.noFocusSelectionBackground=@selectionInactiveBackground
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,36 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="advPanel" alignment="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="useWindowDecorationsCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="unifiedTitleBarCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="menuBarEmbeddedCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="underlineMenuSelectionCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="alwaysShowMnemonicsCheckBox" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="accentColorLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="accentColorField" min="-2" pref="130" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="needsRestartLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="213" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Component id="advPanel" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="accentColorField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="needsRestartLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="accentColorLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="useWindowDecorationsCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="unifiedTitleBarCheckBox" min="-2" max="-2" attributes="0"/>
Expand All @@ -71,12 +85,31 @@
<Component id="alwaysShowMnemonicsCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="advPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace pref="69" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="accentColorLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/netbeans/swing/laf/flatlaf/Bundle.properties" key="FlatLafOptionsPanel.accentColorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="org.openide.awt.ColorComboBox" name="accentColorField">
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="accentColorFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="needsRestartLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/netbeans/swing/laf/flatlaf/Bundle.properties" key="FlatLafOptionsPanel.needsRestartLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="useWindowDecorationsCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
Expand Down Expand Up @@ -144,7 +177,7 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="customPropertiesLabel" max="32767" attributes="0"/>
<Component id="customPropertiesLabel" pref="368" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="customPropertiesButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,24 @@

import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.SystemInfo;
import java.awt.Color;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Properties;
import javax.swing.UIManager;
import org.netbeans.api.actions.Editable;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.LifecycleManager;
import org.openide.awt.Notification;
import org.openide.awt.NotificationDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

Expand All @@ -41,6 +51,9 @@
)
public class FlatLafOptionsPanel extends javax.swing.JPanel {

private static final Color DEFAULT = new Color(0, true);
private static final Color currentAccentColor = FlatLafPrefs.getAccentColor();

private static final RequestProcessor RP = new RequestProcessor(FlatLafOptionsPanel.class);

private final FlatLafOptionsPanelController controller;
Expand All @@ -51,9 +64,49 @@ public class FlatLafOptionsPanel extends javax.swing.JPanel {
public FlatLafOptionsPanel(FlatLafOptionsPanelController controller) {
this.controller = controller;
initComponents();
initAccentColor();
updateEnabled();
}

private void initAccentColor() {
ArrayList<String> names = new ArrayList<>();
ArrayList<Color> colors = new ArrayList<>();
names.add("default");
colors.add(DEFAULT);

String s = UIManager.getString("nb.accentColors.predefined");
if (s == null) {
// FlatLaf is not the current look and feel
Properties properties = new Properties();
try {
properties.load(getClass().getClassLoader().getResourceAsStream(
"org/netbeans/swing/laf/flatlaf/FlatLaf.properties"));
s = properties.getProperty("nb.accentColors.predefined");
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}

if (s != null) {
for (String part : s.split(";")) {
int sepIndex = part.indexOf(':');
if (sepIndex >= 1) {
String name = part.substring(0, sepIndex).trim();
String value = part.substring(sepIndex + 1).trim();
if (!name.isEmpty() && !value.isEmpty()) {
Color color = FlatLafPrefs.parseColor(value);
if (color != null) {
names.add(name);
colors.add(color);
}
}
}
}
}

accentColorField.setModel(colors.toArray(new Color[0]), names.toArray(new String[0]));
}

private void updateEnabled() {
boolean supportsWindowDecorations = FlatLaf.supportsNativeWindowDecorations();
useWindowDecorationsCheckBox.setEnabled(supportsWindowDecorations);
Expand All @@ -72,6 +125,9 @@ private void updateEnabled() {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {

accentColorLabel = new javax.swing.JLabel();
accentColorField = new org.openide.awt.ColorComboBox();
needsRestartLabel = new javax.swing.JLabel();
useWindowDecorationsCheckBox = new javax.swing.JCheckBox();
menuBarEmbeddedCheckBox = new javax.swing.JCheckBox();
unifiedTitleBarCheckBox = new javax.swing.JCheckBox();
Expand All @@ -83,6 +139,16 @@ private void initComponents() {

setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));

org.openide.awt.Mnemonics.setLocalizedText(accentColorLabel, org.openide.util.NbBundle.getMessage(FlatLafOptionsPanel.class, "FlatLafOptionsPanel.accentColorLabel.text")); // NOI18N

accentColorField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
accentColorFieldActionPerformed(evt);
}
});

org.openide.awt.Mnemonics.setLocalizedText(needsRestartLabel, org.openide.util.NbBundle.getMessage(FlatLafOptionsPanel.class, "FlatLafOptionsPanel.needsRestartLabel.text")); // NOI18N

org.openide.awt.Mnemonics.setLocalizedText(useWindowDecorationsCheckBox, org.openide.util.NbBundle.getMessage(FlatLafOptionsPanel.class, "FlatLafOptionsPanel.useWindowDecorationsCheckBox.text")); // NOI18N
useWindowDecorationsCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Expand Down Expand Up @@ -136,7 +202,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
.addGroup(advPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(advPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(customPropertiesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(customPropertiesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE)
.addGroup(advPanelLayout.createSequentialGroup()
.addComponent(customPropertiesButton)
.addGap(0, 0, Short.MAX_VALUE)))
Expand All @@ -156,19 +222,31 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(advPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(useWindowDecorationsCheckBox)
.addComponent(unifiedTitleBarCheckBox)
.addComponent(menuBarEmbeddedCheckBox)
.addComponent(underlineMenuSelectionCheckBox)
.addComponent(alwaysShowMnemonicsCheckBox))
.addContainerGap(213, Short.MAX_VALUE))
.addComponent(advPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(alwaysShowMnemonicsCheckBox)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(accentColorLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(accentColorField, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(needsRestartLabel)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(accentColorField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(needsRestartLabel)
.addComponent(accentColorLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(useWindowDecorationsCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(unifiedTitleBarCheckBox)
Expand All @@ -180,7 +258,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
.addComponent(alwaysShowMnemonicsCheckBox)
.addGap(18, 18, 18)
.addComponent(advPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
.addContainerGap(69, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents

Expand Down Expand Up @@ -226,9 +304,14 @@ private void customPropertiesButtonActionPerformed(java.awt.event.ActionEvent ev
});
}//GEN-LAST:event_customPropertiesButtonActionPerformed

private void accentColorFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accentColorFieldActionPerformed
fireChanged();
}//GEN-LAST:event_accentColorFieldActionPerformed

private void fireChanged() {
boolean isChanged = false;
if(useWindowDecorationsCheckBox.isSelected() != FlatLafPrefs.isUseWindowDecorations()
if(!Objects.equals(accentColorField.getSelectedColor(), getPrefsAccentColorOrDefault())
|| useWindowDecorationsCheckBox.isSelected() != FlatLafPrefs.isUseWindowDecorations()
|| unifiedTitleBarCheckBox.isSelected() != FlatLafPrefs.isUnifiedTitleBar()
|| menuBarEmbeddedCheckBox.isSelected() != FlatLafPrefs.isMenuBarEmbedded()
|| underlineMenuSelectionCheckBox.isSelected() != FlatLafPrefs.isUnderlineMenuSelection()
Expand All @@ -239,6 +322,7 @@ private void fireChanged() {
}

protected void load() {
accentColorField.setSelectedColor(getPrefsAccentColorOrDefault());
useWindowDecorationsCheckBox.setSelected(FlatLafPrefs.isUseWindowDecorations());
unifiedTitleBarCheckBox.setSelected(FlatLafPrefs.isUnifiedTitleBar());
menuBarEmbeddedCheckBox.setSelected(FlatLafPrefs.isMenuBarEmbedded());
Expand All @@ -249,25 +333,60 @@ protected void load() {
}

protected boolean store() {
Color accentColor = accentColorField.getSelectedColor();
FlatLafPrefs.setAccentColor(accentColor != DEFAULT ? accentColor : null);
FlatLafPrefs.setUseWindowDecorations(useWindowDecorationsCheckBox.isSelected());
FlatLafPrefs.setUnifiedTitleBar(unifiedTitleBarCheckBox.isSelected());
FlatLafPrefs.setMenuBarEmbedded(menuBarEmbeddedCheckBox.isSelected());
FlatLafPrefs.setUnderlineMenuSelection(underlineMenuSelectionCheckBox.isSelected());
FlatLafPrefs.setAlwaysShowMnemonics(alwaysShowMnemonicsCheckBox.isSelected());

if (!Objects.equals(accentColor, currentAccentColor)) {
askForRestart();
}
return false;
}

private static Notification restartNotification;

private void askForRestart() {
if(restartNotification != null) {
restartNotification.clear();
}
restartNotification = NotificationDisplayer.getDefault().notify(
NbBundle.getMessage(FlatLafOptionsPanel.class, "FlatLafOptionsPanel.restartTitle"),
ImageUtilities.loadImageIcon( "org/netbeans/core/windows/resources/restart.png", true ), //NOI18N
NbBundle.getMessage(FlatLafOptionsPanel.class, "FlatLafOptionsPanel.restartDetails"),
e -> {
if(restartNotification != null) {
restartNotification.clear();
restartNotification = null;
}
LifecycleManager.getDefault().markForRestart();
LifecycleManager.getDefault().exit();
},
NotificationDisplayer.Priority.NORMAL, NotificationDisplayer.Category.INFO);
}

private Color getPrefsAccentColorOrDefault() {
Color accentColor = FlatLafPrefs.getAccentColor();
return accentColor != null ? accentColor : DEFAULT;
}

boolean valid() {
// TODO check whether form is consistent and complete
return true;
}

// Variables declaration - do not modify//GEN-BEGIN:variables
private org.openide.awt.ColorComboBox accentColorField;
private javax.swing.JLabel accentColorLabel;
private javax.swing.JPanel advPanel;
private javax.swing.JCheckBox alwaysShowMnemonicsCheckBox;
private javax.swing.JButton customPropertiesButton;
private javax.swing.JLabel customPropertiesLabel;
private javax.swing.JCheckBox menuBarEmbeddedCheckBox;
private javax.swing.JLabel needsRestartLabel;
private javax.swing.JCheckBox underlineMenuSelectionCheckBox;
private javax.swing.JCheckBox unifiedTitleBarCheckBox;
private javax.swing.JCheckBox useWindowDecorationsCheckBox;
Expand Down

0 comments on commit cfda31b

Please sign in to comment.