From b14401dec856039aab20fda35116aa49ab5fbdf3 Mon Sep 17 00:00:00 2001 From: Nick Busey Date: Sat, 7 Feb 2026 10:26:42 -0700 Subject: [PATCH 1/3] Add flat dark, darker. Update Look and Feel without restart --- .../java/net/nikr/eve/jeveasset/Program.java | 34 +++++++++++ .../data/settings/ColorSettings.java | 34 +++++++---- .../data/settings/FlatDarkDarker.java | 57 +++++++++++++++++++ .../dialogs/settings/ColorSettingsPanel.java | 7 ++- .../eve/jeveasset/gui/frame/StatusPanel.java | 25 ++++++-- .../eve/jeveasset/i18n/DialoguesSettings.java | 1 + .../i18n/DialoguesSettings.properties | 5 +- 7 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 src/main/java/net/nikr/eve/jeveasset/data/settings/FlatDarkDarker.java diff --git a/src/main/java/net/nikr/eve/jeveasset/Program.java b/src/main/java/net/nikr/eve/jeveasset/Program.java index 638b8924fb..230f3087e1 100644 --- a/src/main/java/net/nikr/eve/jeveasset/Program.java +++ b/src/main/java/net/nikr/eve/jeveasset/Program.java @@ -414,6 +414,40 @@ private void initLookAndFeel(String lookAndFeel) { initLookAndFeel(lookAndFeel, true); } + public boolean applyLookAndFeel(String lookAndFeelClass) { + if (lookAndFeelClass == null || lookAndFeelClass.isEmpty()) { + return false; + } + String current = UIManager.getLookAndFeel().getClass().getName(); + if (current.equals(lookAndFeelClass)) { + return true; + } + final boolean[] applied = {false}; + ensureEDT(new Runnable() { + @Override + public void run() { + initLookAndFeel(lookAndFeelClass, false); + String active = UIManager.getLookAndFeel().getClass().getName(); + if (!active.equals(lookAndFeelClass)) { + return; + } + height = 22; + calcButtonsHeight(); + for (Window window : Window.getWindows()) { + if (!window.isDisplayable()) { + continue; + } + SwingUtilities.updateComponentTreeUI(window); + window.invalidate(); + window.validate(); + window.repaint(); + } + applied[0] = true; + } + }); + return applied[0]; + } + private void initLookAndFeel(String lookAndFeel, boolean tryDefault) { //Allow users to overwrite LaF if (System.getProperty("swing.defaultlaf") != null) { diff --git a/src/main/java/net/nikr/eve/jeveasset/data/settings/ColorSettings.java b/src/main/java/net/nikr/eve/jeveasset/data/settings/ColorSettings.java index b6dc84b090..ce7f385ef4 100644 --- a/src/main/java/net/nikr/eve/jeveasset/data/settings/ColorSettings.java +++ b/src/main/java/net/nikr/eve/jeveasset/data/settings/ColorSettings.java @@ -18,10 +18,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ -package net.nikr.eve.jeveasset.data.settings; - -import java.awt.Color; -import java.awt.Component; +package net.nikr.eve.jeveasset.data.settings; + +import com.formdev.flatlaf.FlatLaf; +import java.awt.Color; +import java.awt.Component; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; @@ -43,11 +44,12 @@ public class ColorSettings { public static enum PredefinedLookAndFeel { DEFAULT(null, UIManager.getSystemLookAndFeelClassName(), true), - FLAT_LIGHT(DialoguesSettings.get().lookAndFeelFlatLight(), "com.formdev.flatlaf.FlatLightLaf"), - FLAT_INTELLIJ(DialoguesSettings.get().lookAndFeelFlatIntelliJ(), "com.formdev.flatlaf.FlatIntelliJLaf"), - FLAT_DARK(DialoguesSettings.get().lookAndFeelFlatDark(), "com.formdev.flatlaf.FlatDarkLaf"), - FLAT_DARCULA(DialoguesSettings.get().lookAndFeelFlatDarcula(), "com.formdev.flatlaf.FlatDarculaLaf"), - DARK_NIMBUS(DialoguesSettings.get().lookAndFeelNimbusDark(), DarkNimbus.class.getName()), + FLAT_LIGHT(DialoguesSettings.get().lookAndFeelFlatLight(), "com.formdev.flatlaf.FlatLightLaf"), + FLAT_INTELLIJ(DialoguesSettings.get().lookAndFeelFlatIntelliJ(), "com.formdev.flatlaf.FlatIntelliJLaf"), + FLAT_DARK(DialoguesSettings.get().lookAndFeelFlatDark(), "com.formdev.flatlaf.FlatDarkLaf"), + FLAT_DARK_DARKER(DialoguesSettings.get().lookAndFeelFlatDarkDarker(), FlatDarkDarker.class.getName()), + FLAT_DARCULA(DialoguesSettings.get().lookAndFeelFlatDarcula(), "com.formdev.flatlaf.FlatDarculaLaf"), + DARK_NIMBUS(DialoguesSettings.get().lookAndFeelNimbusDark(), DarkNimbus.class.getName()), ; private final String name; @@ -101,9 +103,17 @@ public String getLookAndFeelClass() { return lookAndFeelClass; } - public boolean isFlatLAF() { - return lookAndFeelClass.startsWith("com.formdev.flatlaf"); - } + public boolean isFlatLAF() { + if (lookAndFeelClass.startsWith("com.formdev.flatlaf")) { + return true; + } + try { + Class lookAndFeel = Class.forName(lookAndFeelClass); + return FlatLaf.class.isAssignableFrom(lookAndFeel); + } catch (ClassNotFoundException ex) { + return false; + } + } public void setLookAndFeelClass(String lookAndFeelClass) { this.lookAndFeelClass = lookAndFeelClass; diff --git a/src/main/java/net/nikr/eve/jeveasset/data/settings/FlatDarkDarker.java b/src/main/java/net/nikr/eve/jeveasset/data/settings/FlatDarkDarker.java new file mode 100644 index 0000000000..13abb5ed43 --- /dev/null +++ b/src/main/java/net/nikr/eve/jeveasset/data/settings/FlatDarkDarker.java @@ -0,0 +1,57 @@ +/* + * Copyright 2009-2025 Contributors (see credits.txt) + * + * This file is part of jEveAssets. + * + * jEveAssets is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * jEveAssets is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with jEveAssets; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +package net.nikr.eve.jeveasset.data.settings; + +import com.formdev.flatlaf.FlatDarkLaf; +import java.util.Properties; + + +public class FlatDarkDarker extends FlatDarkLaf { + + @Override + public String getName() { + return "Flat Dark Darker"; + } + + @Override + protected Properties getAdditionalDefaults() { + Properties properties = new Properties(); + Properties defaults = super.getAdditionalDefaults(); + if (defaults != null) { + properties.putAll(defaults); + } + + // Keep Flat Dark behavior, but shift the base palette darker. + properties.put("@background", "#1A1A1A"); + properties.put("@foreground", "#D0D0D0"); + properties.put("@disabledForeground", "shade(@foreground,30%)"); + properties.put("@buttonBackground", "tint(@background,7%)"); + properties.put("@componentBackground", "tint(@background,4%)"); + properties.put("@menuBackground", "darken(@background,4%)"); + properties.put("@selectionBackground", "#304867"); + properties.put("@accentBaseColor", "#3D5F97"); + + // Improve panel contrast in desktop areas when using very dark backgrounds. + properties.put("Desktop.background", "#161616"); + properties.put("Component.borderColor", "tint(@background,16%)"); + return properties; + } +} diff --git a/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java b/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java index ff3fef8e3a..6b1eae01f3 100644 --- a/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java +++ b/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java @@ -316,8 +316,11 @@ public UpdateType save() { || Settings.get().isEasyChartColors() != easyChartColors; Settings.get().setEasyChartColors(easyChartColors); colors = Settings.get().getColorSettings().get(); //Copy to check for changes on save - if (lookAndfeelChanged && !UIManager.getLookAndFeel().getClass().getName().equals(lookAndFeelClass)) { - JOptionPane.showMessageDialog(parent, DialoguesSettings.get().lookAndFeelMsg(), DialoguesSettings.get().lookAndFeelTitle(), JOptionPane.PLAIN_MESSAGE); + if (lookAndfeelChanged) { + boolean applied = program.applyLookAndFeel(lookAndFeelClass); + if (!applied) { + JOptionPane.showMessageDialog(parent, DialoguesSettings.get().lookAndFeelMsg(), DialoguesSettings.get().lookAndFeelTitle(), JOptionPane.PLAIN_MESSAGE); + } } return repaint ? UpdateType.FULL_REPAINT : UpdateType.NONE; } diff --git a/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java b/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java index 968b1361e7..01da952e9c 100644 --- a/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java +++ b/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java @@ -35,10 +35,10 @@ import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.Timer; +import javax.swing.UIManager; import net.nikr.eve.jeveasset.Program; import net.nikr.eve.jeveasset.data.settings.Settings; import net.nikr.eve.jeveasset.gui.images.Images; -import net.nikr.eve.jeveasset.gui.shared.ColorUtil; import net.nikr.eve.jeveasset.gui.shared.CopyHandler; import net.nikr.eve.jeveasset.gui.shared.Formatter; import net.nikr.eve.jeveasset.gui.shared.components.JFixedToolBar; @@ -371,11 +371,7 @@ public JStatusLabel(final String toolTip, final Icon icon, AutoNumberFormat form private void init(final String toolTip, final Icon icon) { setIcon(icon); - if (ColorUtil.isBrightColor(getBackground())) { //Light background color - setForeground(getBackground().darker().darker().darker()); - } else { //Dark background color - setForeground(getBackground().brighter().brighter()); - } + updateForegroundFromLookAndFeel(); setIconTextGap(3); setToolTipText(GuiShared.get().clickToCopyWrap(toolTip)); setHorizontalAlignment(JLabel.LEFT); @@ -412,6 +408,23 @@ public void actionPerformed(ActionEvent e) { }); } + @Override + public void updateUI() { + super.updateUI(); + updateForegroundFromLookAndFeel(); + } + + private void updateForegroundFromLookAndFeel() { + // Match status label color behavior to the "New update available" button. + java.awt.Color foreground = UIManager.getColor("Button.foreground"); + if (foreground == null) { + foreground = UIManager.getColor("Label.foreground"); + } + if (foreground != null) { + setForeground(foreground); + } + } + @Override public void setText(String text) { this.text = text; diff --git a/src/main/java/net/nikr/eve/jeveasset/i18n/DialoguesSettings.java b/src/main/java/net/nikr/eve/jeveasset/i18n/DialoguesSettings.java index bc437dc07f..fea250e4f6 100644 --- a/src/main/java/net/nikr/eve/jeveasset/i18n/DialoguesSettings.java +++ b/src/main/java/net/nikr/eve/jeveasset/i18n/DialoguesSettings.java @@ -153,6 +153,7 @@ public DialoguesSettings(final Locale locale) { public abstract String lookAndFeelDefaultName(String name); public abstract String lookAndFeelFlatLight(); public abstract String lookAndFeelFlatDark(); + public abstract String lookAndFeelFlatDarkDarker(); public abstract String lookAndFeelFlatIntelliJ(); public abstract String lookAndFeelFlatDarcula(); public abstract String lookAndFeelNimbusDark(); diff --git a/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties b/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties index a4fbff0192..123dc5e4ed 100644 --- a/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties +++ b/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties @@ -128,10 +128,11 @@ lookAndFeelDefault=Default lookAndFeelDefaultName=Default ({0}) lookAndFeelFlatLight=Flat Light lookAndFeelFlatDark=Flat Dark +lookAndFeelFlatDarkDarker=Flat Dark (Darker) lookAndFeelFlatIntelliJ=Flat IntelliJ lookAndFeelFlatDarcula=Flat Darcula lookAndFeelNimbusDark=Dark Nimbus -lookAndFeelMsg=Changing the Look and Feel will not take effect until jEveAssets is restarted +lookAndFeelMsg=Unable to apply the selected Look and Feel immediately. Restart jEveAssets to apply it. lookAndFeelTitle=Look and Feel #Sounds @@ -267,4 +268,4 @@ windowWidth=Width: windowHeight=Height: windowX=X Position: windowY=Y Position: -windowMaximised=Maximized: \ No newline at end of file +windowMaximised=Maximized: From 57ae656271c7832713561ecee12173493f2492f0 Mon Sep 17 00:00:00 2001 From: Nick Busey Date: Sat, 7 Feb 2026 10:38:08 -0700 Subject: [PATCH 2/3] Fix tab change --- src/main/java/net/nikr/eve/jeveasset/Program.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/net/nikr/eve/jeveasset/Program.java b/src/main/java/net/nikr/eve/jeveasset/Program.java index 230f3087e1..85e2931d3b 100644 --- a/src/main/java/net/nikr/eve/jeveasset/Program.java +++ b/src/main/java/net/nikr/eve/jeveasset/Program.java @@ -442,6 +442,10 @@ public void run() { window.validate(); window.repaint(); } + // Also refresh hidden/lazy tabs that are not currently attached to a visible window. + for (JMainTab jMainTab : getMainTabs().values()) { + SwingUtilities.updateComponentTreeUI(jMainTab.getPanel()); + } applied[0] = true; } }); From c21f39d8c0603c4286d9df40268cf070deb1432b Mon Sep 17 00:00:00 2001 From: Nick Busey Date: Sun, 8 Feb 2026 23:50:40 -0700 Subject: [PATCH 3/3] Add dark theme --- .../java/net/nikr/eve/jeveasset/Program.java | 38 ------------------- .../dialogs/settings/ColorSettingsPanel.java | 7 +--- .../eve/jeveasset/gui/frame/StatusPanel.java | 19 ---------- .../i18n/DialoguesSettings.properties | 2 +- 4 files changed, 3 insertions(+), 63 deletions(-) diff --git a/src/main/java/net/nikr/eve/jeveasset/Program.java b/src/main/java/net/nikr/eve/jeveasset/Program.java index 85e2931d3b..638b8924fb 100644 --- a/src/main/java/net/nikr/eve/jeveasset/Program.java +++ b/src/main/java/net/nikr/eve/jeveasset/Program.java @@ -414,44 +414,6 @@ private void initLookAndFeel(String lookAndFeel) { initLookAndFeel(lookAndFeel, true); } - public boolean applyLookAndFeel(String lookAndFeelClass) { - if (lookAndFeelClass == null || lookAndFeelClass.isEmpty()) { - return false; - } - String current = UIManager.getLookAndFeel().getClass().getName(); - if (current.equals(lookAndFeelClass)) { - return true; - } - final boolean[] applied = {false}; - ensureEDT(new Runnable() { - @Override - public void run() { - initLookAndFeel(lookAndFeelClass, false); - String active = UIManager.getLookAndFeel().getClass().getName(); - if (!active.equals(lookAndFeelClass)) { - return; - } - height = 22; - calcButtonsHeight(); - for (Window window : Window.getWindows()) { - if (!window.isDisplayable()) { - continue; - } - SwingUtilities.updateComponentTreeUI(window); - window.invalidate(); - window.validate(); - window.repaint(); - } - // Also refresh hidden/lazy tabs that are not currently attached to a visible window. - for (JMainTab jMainTab : getMainTabs().values()) { - SwingUtilities.updateComponentTreeUI(jMainTab.getPanel()); - } - applied[0] = true; - } - }); - return applied[0]; - } - private void initLookAndFeel(String lookAndFeel, boolean tryDefault) { //Allow users to overwrite LaF if (System.getProperty("swing.defaultlaf") != null) { diff --git a/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java b/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java index 6b1eae01f3..ff3fef8e3a 100644 --- a/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java +++ b/src/main/java/net/nikr/eve/jeveasset/gui/dialogs/settings/ColorSettingsPanel.java @@ -316,11 +316,8 @@ public UpdateType save() { || Settings.get().isEasyChartColors() != easyChartColors; Settings.get().setEasyChartColors(easyChartColors); colors = Settings.get().getColorSettings().get(); //Copy to check for changes on save - if (lookAndfeelChanged) { - boolean applied = program.applyLookAndFeel(lookAndFeelClass); - if (!applied) { - JOptionPane.showMessageDialog(parent, DialoguesSettings.get().lookAndFeelMsg(), DialoguesSettings.get().lookAndFeelTitle(), JOptionPane.PLAIN_MESSAGE); - } + if (lookAndfeelChanged && !UIManager.getLookAndFeel().getClass().getName().equals(lookAndFeelClass)) { + JOptionPane.showMessageDialog(parent, DialoguesSettings.get().lookAndFeelMsg(), DialoguesSettings.get().lookAndFeelTitle(), JOptionPane.PLAIN_MESSAGE); } return repaint ? UpdateType.FULL_REPAINT : UpdateType.NONE; } diff --git a/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java b/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java index 01da952e9c..61620494f0 100644 --- a/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java +++ b/src/main/java/net/nikr/eve/jeveasset/gui/frame/StatusPanel.java @@ -35,7 +35,6 @@ import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.Timer; -import javax.swing.UIManager; import net.nikr.eve.jeveasset.Program; import net.nikr.eve.jeveasset.data.settings.Settings; import net.nikr.eve.jeveasset.gui.images.Images; @@ -371,7 +370,6 @@ public JStatusLabel(final String toolTip, final Icon icon, AutoNumberFormat form private void init(final String toolTip, final Icon icon) { setIcon(icon); - updateForegroundFromLookAndFeel(); setIconTextGap(3); setToolTipText(GuiShared.get().clickToCopyWrap(toolTip)); setHorizontalAlignment(JLabel.LEFT); @@ -408,23 +406,6 @@ public void actionPerformed(ActionEvent e) { }); } - @Override - public void updateUI() { - super.updateUI(); - updateForegroundFromLookAndFeel(); - } - - private void updateForegroundFromLookAndFeel() { - // Match status label color behavior to the "New update available" button. - java.awt.Color foreground = UIManager.getColor("Button.foreground"); - if (foreground == null) { - foreground = UIManager.getColor("Label.foreground"); - } - if (foreground != null) { - setForeground(foreground); - } - } - @Override public void setText(String text) { this.text = text; diff --git a/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties b/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties index 123dc5e4ed..9382072a06 100644 --- a/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties +++ b/src/main/resources/net/nikr/eve/jeveasset/i18n/DialoguesSettings.properties @@ -132,7 +132,7 @@ lookAndFeelFlatDarkDarker=Flat Dark (Darker) lookAndFeelFlatIntelliJ=Flat IntelliJ lookAndFeelFlatDarcula=Flat Darcula lookAndFeelNimbusDark=Dark Nimbus -lookAndFeelMsg=Unable to apply the selected Look and Feel immediately. Restart jEveAssets to apply it. +lookAndFeelMsg=Changing the Look and Feel will not take effect until jEveAssets is restarted lookAndFeelTitle=Look and Feel #Sounds