diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 1cfdddc3f..e8dc1d512 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -403,7 +403,8 @@ PreferencesOptionPanel.checkbox.windowInfo = Export window information (position PreferencesOptionPanel.checkbox.windowInfo.ttip = If unchecked, window information (position, size\u2026) will not be exported. ! UI Themes -UITheme.Light = Light (Default) +UITheme.Auto = Auto (detect) +UITheme.Light = Light (default) UITheme.Dark = Dark ! Welcome dialog diff --git a/swing/.classpath b/swing/.classpath index 5aa1c307e..763ac63b0 100644 --- a/swing/.classpath +++ b/swing/.classpath @@ -11,6 +11,13 @@ + + + + + + + diff --git a/swing/OpenRocket Swing.iml b/swing/OpenRocket Swing.iml index 55f1c84b1..fd79a03a1 100644 --- a/swing/OpenRocket Swing.iml +++ b/swing/OpenRocket Swing.iml @@ -5,6 +5,13 @@ + $ + + + + + + @@ -109,9 +116,63 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/swing/build.xml b/swing/build.xml index af521340f..0a95921d1 100644 --- a/swing/build.xml +++ b/swing/build.xml @@ -116,6 +116,13 @@ + + + + + + + diff --git a/swing/lib/annotations-24.0.1.jar b/swing/lib/annotations-24.0.1.jar new file mode 100644 index 000000000..a4198f711 Binary files /dev/null and b/swing/lib/annotations-24.0.1.jar differ diff --git a/swing/lib/jSystemThemeDetector-3.8.jar b/swing/lib/jSystemThemeDetector-3.8.jar new file mode 100644 index 000000000..a8ac11f54 Binary files /dev/null and b/swing/lib/jSystemThemeDetector-3.8.jar differ diff --git a/swing/lib/jfa-1.2.0.jar b/swing/lib/jfa-1.2.0.jar new file mode 100644 index 000000000..2efd423eb Binary files /dev/null and b/swing/lib/jfa-1.2.0.jar differ diff --git a/swing/lib/jna-5.13.0.jar b/swing/lib/jna-5.13.0.jar new file mode 100644 index 000000000..3d49c8188 Binary files /dev/null and b/swing/lib/jna-5.13.0.jar differ diff --git a/swing/lib/jna-platform-5.13.0.jar b/swing/lib/jna-platform-5.13.0.jar new file mode 100644 index 000000000..816a567cc Binary files /dev/null and b/swing/lib/jna-platform-5.13.0.jar differ diff --git a/swing/lib/oshi-core-6.4.4.jar b/swing/lib/oshi-core-6.4.4.jar new file mode 100644 index 000000000..2e8b714f9 Binary files /dev/null and b/swing/lib/oshi-core-6.4.4.jar differ diff --git a/swing/lib/versioncompare-1.4.1.jar b/swing/lib/versioncompare-1.4.1.jar new file mode 100644 index 000000000..14ab48bd6 Binary files /dev/null and b/swing/lib/versioncompare-1.4.1.jar differ diff --git a/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java index 480c32367..880fdbae5 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java @@ -76,6 +76,7 @@ public class AboutDialog extends JDialog { "Java library for parsing and rendering CommonMark" + href("https://github.com/commonmark/commonmark-java", true, true) + "
" + "RSyntaxTextArea" + href("http://bobbylight.github.io/RSyntaxTextArea", true, true) + "
" + "Darklaf (dark theme)" + href("https://github.com/weisJ/darklaf", true, true) + "
" + + "jSystemThemeDetector" + href("https://github.com/Dansoftowner/jSystemThemeDetector", true, true) + "
" + "
" + "OpenRocket gratefully acknowledges our use of the following databases:
" + "
" + diff --git a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java index 004895c02..22dd90c15 100644 --- a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java +++ b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java @@ -337,8 +337,8 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences { } private UITheme.Theme getUIThemeAsTheme() { - String themeName = getString(net.sf.openrocket.startup.Preferences.UI_THEME, UITheme.Themes.LIGHT.name()); - if (themeName == null) return UITheme.Themes.LIGHT; // Default theme + String themeName = getString(net.sf.openrocket.startup.Preferences.UI_THEME, UITheme.Themes.AUTO.name()); + if (themeName == null) return UITheme.Themes.AUTO; // Default theme return UITheme.Themes.valueOf(themeName); } diff --git a/swing/src/net/sf/openrocket/gui/util/UITheme.java b/swing/src/net/sf/openrocket/gui/util/UITheme.java index 43805d870..ecc1a2d1a 100644 --- a/swing/src/net/sf/openrocket/gui/util/UITheme.java +++ b/swing/src/net/sf/openrocket/gui/util/UITheme.java @@ -2,6 +2,7 @@ package net.sf.openrocket.gui.util; import com.github.weisj.darklaf.LafManager; import com.github.weisj.darklaf.theme.DarculaTheme; +import com.jthemedetecor.OsThemeDetector; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; @@ -10,14 +11,17 @@ import org.slf4j.LoggerFactory; import javax.swing.BorderFactory; import javax.swing.Icon; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import java.awt.Color; import java.awt.Font; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; public class UITheme { private static final Translator trans = Application.getTranslator(); @@ -527,6 +531,243 @@ public class UITheme { log.warn("Unable to load RSyntaxTextArea theme", ioe); } } + }, + AUTO { + private final String displayName = trans.get("UITheme.Auto"); + + private Theme getCurrentTheme() { + try { + final OsThemeDetector detector = OsThemeDetector.getDetector(); + final boolean isDarkThemeUsed = detector.isDark(); + if (isDarkThemeUsed) { + return Themes.DARK; + } else { + return Themes.LIGHT; + } + } catch (Exception ignore) {} + + return Themes.LIGHT; + } + + @Override + public void applyTheme() { + getCurrentTheme().applyTheme(); + } + + @Override + public String getDisplayName() { + return displayName; + } + + @Override + public Color getBackgroundColor() { + return getCurrentTheme().getBackgroundColor(); + } + + @Override + public Color getBorderColor() { + return getCurrentTheme().getBorderColor(); + } + + @Override + public Color getTextColor() { + return getCurrentTheme().getTextColor(); + } + + @Override + public Color getDimTextColor() { + return getCurrentTheme().getDimTextColor(); + } + + @Override + public Color getTextSelectionForegroundColor() { + return getCurrentTheme().getTextSelectionForegroundColor(); + } + + @Override + public Color getTextSelectionBackgroundColor() { + return getCurrentTheme().getTextSelectionBackgroundColor(); + } + + @Override + public Color getWarningColor() { + return getCurrentTheme().getWarningColor(); + } + + @Override + public Color getDarkWarningColor() { + return getCurrentTheme().getDarkWarningColor(); + } + + @Override + public Color getRowBackgroundLighterColor() { + return getCurrentTheme().getRowBackgroundLighterColor(); + } + + @Override + public Color getRowBackgroundDarkerColor() { + return getCurrentTheme().getRowBackgroundDarkerColor(); + } + + @Override + public Color getFlightDataTextActiveColor() { + return getCurrentTheme().getFlightDataTextActiveColor(); + } + + @Override + public Color getFlightDataTextInactiveColor() { + return getCurrentTheme().getFlightDataTextInactiveColor(); + } + + @Override + public String getDefaultBodyComponentColor() { + return getCurrentTheme().getDefaultBodyComponentColor(); + } + + @Override + public String getDefaultTubeFinSetColor() { + return getCurrentTheme().getDefaultTubeFinSetColor(); + } + + @Override + public String getDefaultFinSetColor() { + return getCurrentTheme().getDefaultFinSetColor(); + } + + @Override + public String getDefaultLaunchLugColor() { + return getCurrentTheme().getDefaultLaunchLugColor(); + } + + @Override + public String getDefaultRailButtonColor() { + return getCurrentTheme().getDefaultRailButtonColor(); + } + + @Override + public String getDefaultInternalComponentColor() { + return getCurrentTheme().getDefaultInternalComponentColor(); + } + + @Override + public String getDefaultMassObjectColor() { + return getCurrentTheme().getDefaultMassObjectColor(); + } + + @Override + public String getDefaultRecoveryDeviceColor() { + return getCurrentTheme().getDefaultRecoveryDeviceColor(); + } + + @Override + public String getDefaultPodSetColor() { + return getCurrentTheme().getDefaultPodSetColor(); + } + + @Override + public String getDefaultParallelStageColor() { + return getCurrentTheme().getDefaultParallelStageColor(); + } + + @Override + public Color getMotorBorderColor() { + return getCurrentTheme().getMotorBorderColor(); + } + + @Override + public Color getMotorFillColor() { + return getCurrentTheme().getMotorFillColor(); + } + + @Override + public Color getCGColor() { + return getCurrentTheme().getCGColor(); + } + + @Override + public Color getCPColor() { + return getCurrentTheme().getCPColor(); + } + + @Override + public Color getURLColor() { + return getCurrentTheme().getURLColor(); + } + + @Override + public Color getComponentTreeBackgroundColor() { + return getCurrentTheme().getComponentTreeBackgroundColor(); + } + + @Override + public Color getComponentTreeForegroundColor() { + return getCurrentTheme().getComponentTreeForegroundColor(); + } + + @Override + public Color getFinPointGridMajorLineColor() { + return getCurrentTheme().getFinPointGridMajorLineColor(); + } + + @Override + public Color getFinPointGridMinorLineColor() { + return getCurrentTheme().getFinPointGridMinorLineColor(); + } + + @Override + public Color getFinPointPointColor() { + return getCurrentTheme().getFinPointPointColor(); + } + + @Override + public Color getFinPointSelectedPointColor() { + return getCurrentTheme().getFinPointSelectedPointColor(); + } + + @Override + public Color getFinPointBodyLineColor() { + return getCurrentTheme().getFinPointBodyLineColor(); + } + + @Override + public Icon getMassOverrideIcon() { + return getCurrentTheme().getMassOverrideIcon(); + } + + @Override + public Icon getMassOverrideSubcomponentIcon() { + return getCurrentTheme().getMassOverrideSubcomponentIcon(); + } + + @Override + public Icon getCGOverrideIcon() { + return getCurrentTheme().getCGOverrideIcon(); + } + + @Override + public Icon getCGOverrideSubcomponentIcon() { + return getCurrentTheme().getCGOverrideSubcomponentIcon(); + } + + @Override + public Icon getCDOverrideIcon() { + return getCurrentTheme().getCDOverrideIcon(); + } + + @Override + public Icon getCDOverrideSubcomponentIcon() { + return getCurrentTheme().getCDOverrideSubcomponentIcon(); + } + + @Override + public Border getBorder() { + return getCurrentTheme().getBorder(); + } + + @Override + public void formatScriptTextArea(RSyntaxTextArea textArea) { + getCurrentTheme().formatScriptTextArea(textArea); + } } }