diff --git a/README.md b/README.md index 786afe20a..e973d2627 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ OpenRocket needs help to become even better. Implementing features, writing docu - Daniel Williams, pod support, maintainer - Joe Pfeiffer (maintainer) - Billy Olsen (maintainer) -- Sibo Van Gool (maintainer) +- Sibo Van Gool (RASAero file format, maintainer) - Neil Weinstock (tester, icons, forum support) - H. Craig Miller (tester) diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index b5ec1534c..1cfdddc3f 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -380,15 +380,15 @@ pref.dlg.PrefBooleanSelector2 = Confirm pref.dlg.Add = Add pref.dlg.DescriptionArea.Adddirectories = Add directories, RASP motor files (*.eng), RockSim engine files (*.rse) or ZIP archives separated by a semicolon (;) to load external thrust curves. Changes will take effect the next time you start OpenRocket. -PreferencesDialog.lbl.language = Interface language: -PreferencesDialog.languages.default = System default -PreferencesDialog.lbl.languageEffect = The language will change the next time you start OpenRocket. PreferencesDialog.CancelOperation.title = Discard Preference Changes PreferencesDialog.CancelOperation.msg.discardChanges = Are you sure you want to discard the preference changes? generalprefs.lbl.language = Interface language generalprefs.languages.default = System default generalprefs.lbl.languageEffect = The language will change the next time you start OpenRocket. +generalprefs.lbl.UITheme = UI Theme +generalprefs.lbl.FontSize = UI Font Size +generalprefs.lbl.themeRestartOR = You must restart OpenRocket for the UI changes to take effect. generalprefs.ImportWarning.title = Reload OpenRocket generalprefs.ImportWarning.msg = You may need to restart OpenRocket for some of the changes to take effect. @@ -402,6 +402,10 @@ PreferencesOptionPanel.checkbox.userDirectories.ttip = If unchecked, user direct PreferencesOptionPanel.checkbox.windowInfo = Export window information (position, size\u2026) PreferencesOptionPanel.checkbox.windowInfo.ttip = If unchecked, window information (position, size\u2026) will not be exported. +! UI Themes +UITheme.Light = Light (Default) +UITheme.Dark = Dark + ! Welcome dialog welcome.dlg.title = Welcome to OpenRocket welcome.dlg.lbl.thankYou = Thank you for downloading OpenRocket @@ -2331,7 +2335,7 @@ ComponentPresetChooserDialog.menu.units = Units ComponentPresetChooserDialog.checkbox.showLegacyCheckBox = Show Legacy Database ComponentPresetChooserDialog.lbl.favorites = Check to add preset to the preset drop-down menu in the component edit dialog
Directly apply a preset by double-clicking it or by selecting it and closing this window. ComponentPresetChooserDialog.checkbox.alwaysOpenPreset = Always open this dialog when creating a new %s -table.column.Favorite = Favorite +table.column.Favorite = \u2026 Favorite table.column.Legacy = Legacy table.column.Manufacturer = Manufacturer table.column.PartNo = Part Number diff --git a/core/resources/l10n/messages_ar.properties b/core/resources/l10n/messages_ar.properties index 65d2651d3..5a957d4cc 100644 --- a/core/resources/l10n/messages_ar.properties +++ b/core/resources/l10n/messages_ar.properties @@ -343,9 +343,6 @@ pref.dlg.PrefBooleanSelector2 = تأكيد pref.dlg.Add = أضف pref.dlg.DescriptionArea.Adddirectories =.ملفات محرك روكسيم أو أرشيفات زيب مفصولة بفاصلة منقوطة لتحميل منحنيات الدفع الخارجية. ستدخل التغييرات حيز التنفيذ في المرة التالية التي تفتح فيها أوبنروكت (* .rse)أو RASP ملفات محرك (* .eng), أضف الدلائل -PreferencesDialog.lbl.language = :لغة الواجهة -PreferencesDialog.languages.default = النظام الافتراضي -PreferencesDialog.lbl.languageEffect = .ستتغير اللغة في المرة التالية التي تعيد تشغيل أوبنروكت generalprefs.lbl.language = :لغة الواجهة generalprefs.languages.default = النظام الافتراضي generalprefs.lbl.languageEffect = .ستتغير اللغة في المرة التالية التي تعيد تشغيل أوبنروكت diff --git a/core/resources/l10n/messages_cs.properties b/core/resources/l10n/messages_cs.properties index 27d128273..a1b326463 100644 --- a/core/resources/l10n/messages_cs.properties +++ b/core/resources/l10n/messages_cs.properties @@ -264,9 +264,9 @@ pref.dlg.PrefBooleanSelector2 = Potvrd pref.dlg.Add = Pridej pref.dlg.DescriptionArea.Adddirectories = Pridej adresre, soubory RASP motor (*.eng), RockSim engine soubory (*.rse) nebo ZIP archiv oddelen oddelovacem (;) k nahrn externch vkonovch prubehu. Zmeny se projev po restaru programu OpenRocket. -PreferencesDialog.lbl.language = Jazyk rohrann: -PreferencesDialog.languages.default = Vchoz -PreferencesDialog.lbl.languageEffect = Jazyk se zmen pri dal\u0161m spu\u0161ten programu OpenRocket. +generalprefs.lbl.language = Jazyk rohrann: +generalprefs.languages.default = Vchoz +generalprefs.lbl.languageEffect = Jazyk se zmen pri dal\u0161m spu\u0161ten programu OpenRocket. ! Software update checker update.dlg.error.title = Nemohu zskat informace o aktualizacch diff --git a/core/resources/l10n/messages_de.properties b/core/resources/l10n/messages_de.properties index 908a48690..007a46da3 100644 --- a/core/resources/l10n/messages_de.properties +++ b/core/resources/l10n/messages_de.properties @@ -266,9 +266,9 @@ pref.dlg.PrefBooleanSelector2 = Best pref.dlg.Add = Hinzufgen pref.dlg.DescriptionArea.Adddirectories = Um eigene Schubkurven zu laden, Verzeichnisse, RASP-Motordateien (*.eng), RockSim-Motordateien (*.rse) oder ZIP-Archive mit Semikolon getrennt eingeben. nderungen werden beim nchsten Neustart von OpenRocket bernommen. -PreferencesDialog.lbl.language = Sprache: -PreferencesDialog.languages.default = Systemeinstellung -PreferencesDialog.lbl.languageEffect = Die Sprache wird beim nchsten Neustart von OpenRocket gendert. +generalprefs.lbl.language = Sprache: +generalprefs.languages.default = Systemeinstellung +generalprefs.lbl.languageEffect = Die Sprache wird beim nchsten Neustart von OpenRocket gendert. ! Software update checker update.dlg.error.title = Es konnten keine Informationen ber Programmaktualisierungen empfangen werden. diff --git a/core/resources/l10n/messages_es.properties b/core/resources/l10n/messages_es.properties index 30b830045..db5dc37d1 100644 --- a/core/resources/l10n/messages_es.properties +++ b/core/resources/l10n/messages_es.properties @@ -733,9 +733,9 @@ PlotDialog.title.Flightdataplot = Representaci\u00f3n de los datos de vuelo ComponentTreeRenderer.total = total -PreferencesDialog.languages.default = Idioma por defecto -PreferencesDialog.lbl.language = Idioma de la interfaz: -PreferencesDialog.lbl.languageEffect = El idioma cambiar\u00e1 la pr\u00f3xima vez que abra OpenRocket. +generalprefs.languages.default = Idioma por defecto +generalprefs.lbl.language = Idioma de la interfaz: +generalprefs.lbl.languageEffect = El idioma cambiar\u00e1 la pr\u00f3xima vez que abra OpenRocket. PresetModel.lbl.custompreset = Personalizado PresetModel.lbl.partsLib = Biblioteca de piezas diff --git a/core/resources/l10n/messages_fr.properties b/core/resources/l10n/messages_fr.properties index 2fd925ed2..fbbdd38e5 100644 --- a/core/resources/l10n/messages_fr.properties +++ b/core/resources/l10n/messages_fr.properties @@ -725,9 +725,9 @@ PlotDialog.title.Flightdataplot = Trac\u00E9 du vol ComponentTreeRenderer.total = total -PreferencesDialog.languages.default = Valeur syst\u00E8me par d\u00E9faut -PreferencesDialog.lbl.language = Langue du programme: -PreferencesDialog.lbl.languageEffect = La langue sera chang\u00E9e apr\u00E8s avoir red\u00E9marr\u00E9 OpenRocket. +generalprefs.languages.default = Valeur syst\u00E8me par d\u00E9faut +generalprefs.lbl.language = Langue du programme: +generalprefs.lbl.languageEffect = La langue sera chang\u00E9e apr\u00E8s avoir red\u00E9marr\u00E9 OpenRocket. PresetModel.lbl.custompreset = Personnalis PresetModel.lbl.partsLib = Biblioth\u00E8que de pi\u00E8ces diff --git a/core/resources/l10n/messages_it.properties b/core/resources/l10n/messages_it.properties index 34980ad02..58d24f634 100644 --- a/core/resources/l10n/messages_it.properties +++ b/core/resources/l10n/messages_it.properties @@ -268,9 +268,9 @@ pref.dlg.PrefBooleanSelector2 = Conferma pref.dlg.Add = Aggiungi pref.dlg.DescriptionArea.Adddirectories = Aggiungi cartelle, RASP motor files (*.eng), RockSim engine files (*.rse) or ZIP archives separate da puntoevirgola (;) per caricare curve di spinta esterne. I cambiamenti avranno effetto la prossima volta che avvierai OpenRocket. -PreferencesDialog.lbl.language = Lingua dell'interfaccia: -PreferencesDialog.languages.default = Predefinita di sistema -PreferencesDialog.lbl.languageEffect = La lingua sara' cambiata la prossima volta che avvierai OpenRocket. +generalprefs.lbl.language = Lingua dell'interfaccia: +generalprefs.languages.default = Predefinita di sistema +generalprefs.lbl.languageEffect = La lingua sara' cambiata la prossima volta che avvierai OpenRocket. ! Software update checker update.dlg.error.title = Non sono in grado di recuperare informazioni sugli aggiornamenti diff --git a/core/resources/l10n/messages_ja.properties b/core/resources/l10n/messages_ja.properties index 45d5c4003..a593c4c62 100644 --- a/core/resources/l10n/messages_ja.properties +++ b/core/resources/l10n/messages_ja.properties @@ -265,9 +265,9 @@ pref.dlg.PrefBooleanSelector2 = \u78BA\u8A8D pref.dlg.Add = \u8FFD\u52A0 pref.dlg.DescriptionArea.Adddirectories = \u30D5\u30A9\u30EB\u30C0, RASP motor files (*.eng), RockSim engine files (*.rse) \u3082\u3057\u304F\u306F ZIP archives \u3092\u30BB\u30DF\u30B3\u30ED\u30F3(;)\u306B\u3088\u3063\u3066\u5206\u3051\u3089\u308C\u305F\u5F62\u3067\u8FFD\u52A0\u306E\u63A8\u529B\u5C65\u6B74\u3068\u3057\u3066\u8FFD\u52A0\u3067\u304D\u307E\u3059\u3002\u3053\u306E\u5909\u66F4\u306FOpenRocket\u306E\u518D\u8D77\u52D5\u6642\u306B\u6709\u52B9\u306B\u306A\u308A\u307E\u3059 -PreferencesDialog.lbl.language = \u8A00\u8A9E\uFF1A -PreferencesDialog.languages.default = \u30B7\u30B9\u30C6\u30E0\u8A00\u8A9E -PreferencesDialog.lbl.languageEffect = \u8A00\u8A9E\u306F\u518D\u8D77\u52D5\u6642\u306B\u5909\u66F4\u3055\u308C\u307E\u3059 +generalprefs.lbl.language = \u8A00\u8A9E\uFF1A +generalprefs.languages.default = \u30B7\u30B9\u30C6\u30E0\u8A00\u8A9E +generalprefs.lbl.languageEffect = \u8A00\u8A9E\u306F\u518D\u8D77\u52D5\u6642\u306B\u5909\u66F4\u3055\u308C\u307E\u3059 ! Software update checker update.dlg.error.title = \u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u60C5\u5831\u306E\u8AAD\u307F\u51FA\u3057\u304C\u3067\u304D\u307E\u305B\u3093 diff --git a/core/resources/l10n/messages_nl.properties b/core/resources/l10n/messages_nl.properties index c44ec545e..9b9615c49 100644 --- a/core/resources/l10n/messages_nl.properties +++ b/core/resources/l10n/messages_nl.properties @@ -345,10 +345,6 @@ pref.dlg.PrefBooleanSelector2 = Bevestig pref.dlg.Add = Voeg toe pref.dlg.DescriptionArea.Adddirectories = Voeg folders, RASP motorbestanden (*.eng), RockSim motorbestanden (*.rse) of ZIP-archieven gescheiden door een puntkomma (;) om externe stuwkrachtcurves te laden. Wijzigingen zullen van kracht gaan de volgende keer dat u OpenRocket start. -PreferencesDialog.lbl.language = Interface taal: -PreferencesDialog.languages.default = Systeemstandaard -PreferencesDialog.lbl.languageEffect = De taal zal veranderen de volgende keer dat u OpenRocket start. - generalprefs.lbl.language = Interface taal generalprefs.languages.default = Systeemstandaard generalprefs.lbl.languageEffect = De taal zal veranderen de volgende keer dat u OpenRocket start. diff --git a/core/resources/l10n/messages_pl.properties b/core/resources/l10n/messages_pl.properties index cc4246b5f..69ba91cdb 100644 --- a/core/resources/l10n/messages_pl.properties +++ b/core/resources/l10n/messages_pl.properties @@ -265,10 +265,10 @@ pref.dlg.PrefBooleanSelector2 = Potwierd\u017A pref.dlg.Add = Dodaj pref.dlg.DescriptionArea.Adddirectories = Dodaj katalogi, pliki silnikowe RASP (*.eng), Pliki silnikowe RockSim (*.rse) albo archiwa ZIP rozdzielone \u015Brednikiem (;) by za\u0142adowa\u0107 zewn\u0119trzne krzywe si\u0142y ci\u0105gu. Zmiany zostan\u0105 wprowadzone przy kolejnym uruchomieniu OpenRocket. - - PreferencesDialog.lbl.language = J\u0119zyk programu: - PreferencesDialog.languages.default = Domy\u015Blny j\u0119zyk systemu - PreferencesDialog.lbl.languageEffect = Nowy j\u0119zyk zostanie ustawiony przy kolejnym uruchomieniu OpenRocket. + +generalprefs.lbl.language = J\u0119zyk programu: +generalprefs.languages.default = Domy\u015Blny j\u0119zyk systemu +generalprefs.lbl.languageEffect = Nowy j\u0119zyk zostanie ustawiony przy kolejnym uruchomieniu OpenRocket. ! Software update checker update.dlg.error.title = Nie mo\u017Cna uzyska\u0107 informacji o aktualizacji diff --git a/core/resources/l10n/messages_pt.properties b/core/resources/l10n/messages_pt.properties index b5d9d3ee9..89feaa3e6 100644 --- a/core/resources/l10n/messages_pt.properties +++ b/core/resources/l10n/messages_pt.properties @@ -709,9 +709,9 @@ PlotDialog.lbl.Chart = Clique e arraste para baixo+direita para am # PlotDialog PlotDialog.title.Flightdataplot = Plotagem dos dados de voo -PreferencesDialog.languages.default = Padr\u00e3o do sistema -PreferencesDialog.lbl.language = Idioma da interface: -PreferencesDialog.lbl.languageEffect = A linguagem vai mudar na pr\u00f3xima vez que voc\u00ea iniciar o OpenRocket. +generalprefs.languages.default = Padr\u00e3o do sistema +generalprefs.lbl.language = Idioma da interface: +generalprefs.lbl.languageEffect = A linguagem vai mudar na pr\u00f3xima vez que voc\u00ea iniciar o OpenRocket. PresetModel.lbl.custompreset = Personalizado PresetModel.lbl.partsLib = Biblioteca de pe\u00e7as diff --git a/core/resources/l10n/messages_ru.properties b/core/resources/l10n/messages_ru.properties index f5622ac0c..7da3fd403 100644 --- a/core/resources/l10n/messages_ru.properties +++ b/core/resources/l10n/messages_ru.properties @@ -341,10 +341,6 @@ pref.dlg.PrefBooleanSelector2 = \u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434 pref.dlg.Add = \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C pref.dlg.DescriptionArea.Adddirectories = \u0414\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0434\u0430\u043D\u043D\u044B\u0445 \u0441\u0432\u043E\u0438\u0445 \u0434\u0432\u0438\u0433\u0430\u0442\u0435\u043B\u0435\u0439 \u0434\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0438, \u0444\u0430\u0439\u043B\u044B \u0434\u0432\u0438\u0433\u0430\u0442\u0435\u043B\u0435\u0439 RASP (*.eng), \u0444\u0430\u0439\u043B\u044B \u0434\u0432\u0438\u0433\u0430\u0442\u0435\u043B\u0435\u0439 RockSim (*.rse) \u0438\u043B\u0438 ZIP-\u0430\u0440\u0445\u0438\u0432\u044B, \u0440\u0430\u0437\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0435 \u0442\u043E\u0447\u043A\u043E\u0439 \u0441 \u0437\u0430\u043F\u044F\u0442\u043E\u0439 (;). \u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u0441\u0442\u0443\u043F\u044F\u0442 \u0432 \u0441\u0438\u043B\u0443 \u043F\u0440\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u0437\u0430\u043F\u0443\u0441\u043A\u0435 OpenRocket. -PreferencesDialog.lbl.language = \u042F\u0437\u044B\u043A \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430: -PreferencesDialog.languages.default = \u0421\u0438\u0441\u0442\u0435\u043C\u043D\u044B\u0439 -PreferencesDialog.lbl.languageEffect = \u042F\u0437\u044B\u043A \u0441\u043C\u0435\u043D\u0438\u0442\u0441\u044F \u043F\u0440\u0438 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0435 OpenRocket. - generalprefs.lbl.language = \u042F\u0437\u044B\u043A \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 generalprefs.languages.default = \u0421\u0438\u0441\u0442\u0435\u043C\u043D\u044B\u0439 generalprefs.lbl.languageEffect = \u042F\u0437\u044B\u043A \u0441\u043C\u0435\u043D\u0438\u0442\u0441\u044F \u043F\u0440\u0438 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A\u0435 OpenRocket. diff --git a/core/resources/l10n/messages_uk_UA.properties b/core/resources/l10n/messages_uk_UA.properties index 4fea26db2..08550fd70 100644 --- a/core/resources/l10n/messages_uk_UA.properties +++ b/core/resources/l10n/messages_uk_UA.properties @@ -304,9 +304,9 @@ pref.dlg.PrefBooleanSelector2 = Confirm pref.dlg.Add = Add pref.dlg.DescriptionArea.Adddirectories = Add directories, RASP motor files (*.eng), RockSim engine files (*.rse) or ZIP archives separated by a semicolon (;) to load external thrust curves. Changes will take effect the next time you start OpenRocket. -PreferencesDialog.lbl.language = Interface language: -PreferencesDialog.languages.default = System default -PreferencesDialog.lbl.languageEffect = The language will change the next time you start OpenRocket. +generalprefs.lbl.language = Interface language: +generalprefs.languages.default = System default +generalprefs.lbl.languageEffect = The language will change the next time you start OpenRocket. ! Software update checker update.dlg.error.title = Unable to retrieve update information diff --git a/core/resources/l10n/messages_zh_CN.properties b/core/resources/l10n/messages_zh_CN.properties index 05811ded0..0a6180ad8 100644 --- a/core/resources/l10n/messages_zh_CN.properties +++ b/core/resources/l10n/messages_zh_CN.properties @@ -797,9 +797,9 @@ PlotConfiguration.Verticalmotion = \u5782\u76F4\u8FD0\u52A8 vs. \u65F6\u95F PlotDialog.CheckBox.Showdatapoints = \u663E\u793A\u6570\u636E\u70B9 PlotDialog.lbl.Chart = \u5DE6\u952E\u62D6\u62FD\u79FB\u52A8\u6570\u636E\u533A. \u6EDA\u8F6E\u7F29\u653E. ctrl-\u6EDA\u8F6E\u4EC5\u7F29\u653EX\u8F74. ctrl-\u5DE6\u952E\u62D6\u62FD\u79FB\u52A8\u89C6\u56FE. \u53F3\u952E\u8FC7\u62FD\u8C03\u6574\u663E\u793A\u5927\u5C0F. -PreferencesDialog.languages.default = \u7CFB\u7EDF\u9ED8\u8BA4 -PreferencesDialog.lbl.language = \u754C\u9762\u8BED\u8A00: -PreferencesDialog.lbl.languageEffect = \u8BED\u8A00\u8BBE\u7F6E\u5C06\u5728OpenRocket\u91CD\u542F\u540E\u751F\u6548 +generalprefs.languages.default = \u7CFB\u7EDF\u9ED8\u8BA4 +generalprefs.lbl.language = \u754C\u9762\u8BED\u8A00: +generalprefs.lbl.languageEffect = \u8BED\u8A00\u8BBE\u7F6E\u5C06\u5728OpenRocket\u91CD\u542F\u540E\u751F\u6548 PresetModel.lbl.custompreset = \u5b9a\u5236 PresetModel.lbl.partsLib = \u96f6\u4ef6\u5e93 diff --git a/core/resources/pix/componenticons/pods-small.png b/core/resources/pix/componenticons/pods-small.png index 17371e846..d000955a2 100644 Binary files a/core/resources/pix/componenticons/pods-small.png and b/core/resources/pix/componenticons/pods-small.png differ diff --git a/core/resources/pix/icons/cd-override-subcomponent_dark.png b/core/resources/pix/icons/cd-override-subcomponent_dark.png new file mode 100644 index 000000000..6ffec0bc4 Binary files /dev/null and b/core/resources/pix/icons/cd-override-subcomponent_dark.png differ diff --git a/core/resources/pix/icons/cd-override-subcomponent.png b/core/resources/pix/icons/cd-override-subcomponent_light.png similarity index 100% rename from core/resources/pix/icons/cd-override-subcomponent.png rename to core/resources/pix/icons/cd-override-subcomponent_light.png diff --git a/core/resources/pix/icons/cd-override_dark.png b/core/resources/pix/icons/cd-override_dark.png new file mode 100644 index 000000000..566d47bcf Binary files /dev/null and b/core/resources/pix/icons/cd-override_dark.png differ diff --git a/core/resources/pix/icons/cd-override.png b/core/resources/pix/icons/cd-override_light.png similarity index 100% rename from core/resources/pix/icons/cd-override.png rename to core/resources/pix/icons/cd-override_light.png diff --git a/core/resources/pix/icons/cg-override-subcomponent_dark.png b/core/resources/pix/icons/cg-override-subcomponent_dark.png new file mode 100644 index 000000000..4930915e0 Binary files /dev/null and b/core/resources/pix/icons/cg-override-subcomponent_dark.png differ diff --git a/core/resources/pix/icons/cg-override-subcomponent.png b/core/resources/pix/icons/cg-override-subcomponent_light.png similarity index 100% rename from core/resources/pix/icons/cg-override-subcomponent.png rename to core/resources/pix/icons/cg-override-subcomponent_light.png diff --git a/core/resources/pix/icons/cg-override_dark.png b/core/resources/pix/icons/cg-override_dark.png new file mode 100644 index 000000000..1e1bb74f7 Binary files /dev/null and b/core/resources/pix/icons/cg-override_dark.png differ diff --git a/core/resources/pix/icons/cg-override.png b/core/resources/pix/icons/cg-override_light.png similarity index 100% rename from core/resources/pix/icons/cg-override.png rename to core/resources/pix/icons/cg-override_light.png diff --git a/core/resources/pix/icons/mass-override-subcomponent_dark.png b/core/resources/pix/icons/mass-override-subcomponent_dark.png new file mode 100755 index 000000000..60d6fa5b8 Binary files /dev/null and b/core/resources/pix/icons/mass-override-subcomponent_dark.png differ diff --git a/core/resources/pix/icons/mass-override-subcomponent.png b/core/resources/pix/icons/mass-override-subcomponent_light.png similarity index 100% rename from core/resources/pix/icons/mass-override-subcomponent.png rename to core/resources/pix/icons/mass-override-subcomponent_light.png diff --git a/core/resources/pix/icons/mass-override_dark.png b/core/resources/pix/icons/mass-override_dark.png new file mode 100755 index 000000000..3096bf60f Binary files /dev/null and b/core/resources/pix/icons/mass-override_dark.png differ diff --git a/core/resources/pix/icons/mass-override.png b/core/resources/pix/icons/mass-override_light.png similarity index 100% rename from core/resources/pix/icons/mass-override.png rename to core/resources/pix/icons/mass-override_light.png diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 02d272f03..4c4f60ef0 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -118,6 +118,8 @@ public abstract class Preferences implements ChangeSource { public static final String LAUNCH_USE_ISA = "LaunchUseISA"; public static final String SIMULATION_TIME_STEP = "SimulationTimeStep"; public static final String GEODETIC_COMPUTATION = "GeodeticComputationStrategy"; + + public static final String UI_THEME = "UITheme"; private static final AtmosphericModel ISA_ATMOSPHERIC_MODEL = new ExtendedISAModel(); @@ -549,11 +551,6 @@ public abstract class Preferences implements ChangeSource { fireChangeEvent(); } - - public final float getRocketInfoFontSize() { - return (float) (11.0 + 3 * Application.getPreferences().getChoice(Preferences.ROCKET_INFO_FONT_SIZE, 2, 0)); - } - /** * Enable/Disable the auto-opening of the last edited design file on startup. */ @@ -820,25 +817,6 @@ public abstract class Preferences implements ChangeSource { } } - public Color getDefaultColor(Class c) { - String color = get("componentColors", c, StaticFieldHolder.DEFAULT_COLORS); - if (color == null) - return Color.BLACK; - - Color clr = parseColor(color); - if (clr != null) { - return clr; - } else { - return Color.BLACK; - } - } - - public final void setDefaultColor(Class c, Color color) { - if (color == null) - return; - putString("componentColors", c.getSimpleName(), stringifyColor(color)); - } - /** * Retrieve a Line style for the given component. @@ -1014,6 +992,29 @@ public abstract class Preferences implements ChangeSource { public abstract void setComponentFavorite(ComponentPreset preset, ComponentPreset.Type type, boolean favorite); public abstract Set getComponentFavorites(ComponentPreset.Type type); + + + /* + NOTE: It is unusual for the UI Theme to be stored in the preferences instead of SwingPreferences. In fact, this code + is not pretty. Sometimes I just really hate Java and circular dependencies... + But the reason why this is implemented is because it would otherwise be an even bigger nightmare to fix unit tests + that use their own preferences... Also wasn't a fan of always casting the preferences to SwingPreferences. + */ + /** + * Get the current theme used for the UI. + * @return the current theme + */ + public Object getUITheme() { + return null; + } + + /** + * Set the theme used for the UI. + * @param theme the theme to set + */ + public void setUITheme(Object theme) {} + + /* * Within a holder class so they will load only when needed. @@ -1032,19 +1033,6 @@ public abstract class Preferences implements ChangeSource { DEFAULT_LINE_STYLES.put(RocketComponent.class, LineStyle.SOLID.name()); DEFAULT_LINE_STYLES.put(MassObject.class, LineStyle.DASHED.name()); } - - private static final HashMap, String> DEFAULT_COLORS = new HashMap, String>(); - - static { - DEFAULT_COLORS.put(BodyComponent.class, "0,0,240"); - DEFAULT_COLORS.put(TubeFinSet.class, "0,0,200"); - DEFAULT_COLORS.put(FinSet.class, "0,0,200"); - DEFAULT_COLORS.put(LaunchLug.class, "0,0,180"); - DEFAULT_COLORS.put(RailButton.class, "0,0,180"); - DEFAULT_COLORS.put(InternalComponent.class, "170,0,100"); - DEFAULT_COLORS.put(MassObject.class, "0,0,0"); - DEFAULT_COLORS.put(RecoveryDevice.class, "255,0,0"); - } } private final List listeners = new ArrayList(); diff --git a/core/src/net/sf/openrocket/util/Color.java b/core/src/net/sf/openrocket/util/Color.java index 7c3186d34..4f912bb4e 100644 --- a/core/src/net/sf/openrocket/util/Color.java +++ b/core/src/net/sf/openrocket/util/Color.java @@ -66,6 +66,10 @@ public class Color { return new java.awt.Color(red, green, blue, alpha); } + public static Color fromAWTColor(java.awt.Color AWTColor) { + return new Color(AWTColor.getRed(), AWTColor.getGreen(), AWTColor.getBlue(), AWTColor.getAlpha()); + } + @Override public boolean equals(Object obj) { if (super.equals(obj)) { diff --git a/install4j/23.xx/openrocket-23.xx.install4j b/install4j/23.xx/openrocket-23.xx.install4j index 10a55f19a..c9c664d8f 100644 --- a/install4j/23.xx/openrocket-23.xx.install4j +++ b/install4j/23.xx/openrocket-23.xx.install4j @@ -48,6 +48,7 @@ + diff --git a/swing/.classpath b/swing/.classpath index d57e69a4c..5aa1c307e 100644 --- a/swing/.classpath +++ b/swing/.classpath @@ -11,6 +11,7 @@ + diff --git a/swing/OpenRocket Swing.iml b/swing/OpenRocket Swing.iml index c9df46ca4..55f1c84b1 100644 --- a/swing/OpenRocket Swing.iml +++ b/swing/OpenRocket Swing.iml @@ -5,6 +5,7 @@ + @@ -107,6 +108,39 @@ + + + + + + + + + + + + "" + + + + + + + + + + + + + + + + + + + + + diff --git a/swing/build.xml b/swing/build.xml index d1945c272..af521340f 100644 --- a/swing/build.xml +++ b/swing/build.xml @@ -74,7 +74,7 @@ Java/JVM detail version: ${java.version} Compiling main classes - + @@ -116,6 +116,22 @@ + + + + + + + + + + + + + + + + diff --git a/swing/lib/darklaf/darklaf-compatibility-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-compatibility-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..22945e1ff Binary files /dev/null and b/swing/lib/darklaf/darklaf-compatibility-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-core-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-core-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..964cae4b1 Binary files /dev/null and b/swing/lib/darklaf/darklaf-core-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-iconset-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-iconset-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..e355b8786 Binary files /dev/null and b/swing/lib/darklaf/darklaf-iconset-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-macos-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-macos-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..f2cc41960 Binary files /dev/null and b/swing/lib/darklaf/darklaf-macos-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-native-utils-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-native-utils-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..26fdbb0ab Binary files /dev/null and b/swing/lib/darklaf/darklaf-native-utils-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-platform-base-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-platform-base-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..6b91bc95e Binary files /dev/null and b/swing/lib/darklaf/darklaf-platform-base-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-platform-decorations-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-platform-decorations-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..246e8d1b1 Binary files /dev/null and b/swing/lib/darklaf/darklaf-platform-decorations-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-platform-preferences-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-platform-preferences-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..b1768e88f Binary files /dev/null and b/swing/lib/darklaf/darklaf-platform-preferences-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-property-loader-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-property-loader-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..1db5e00e0 Binary files /dev/null and b/swing/lib/darklaf/darklaf-property-loader-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-theme-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-theme-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..b39af8f8b Binary files /dev/null and b/swing/lib/darklaf/darklaf-theme-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-theme-spec-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-theme-spec-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..e8119013f Binary files /dev/null and b/swing/lib/darklaf/darklaf-theme-spec-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-utils-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-utils-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..8e22ee456 Binary files /dev/null and b/swing/lib/darklaf/darklaf-utils-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/darklaf-windows-3.0.3-SNAPSHOT.jar b/swing/lib/darklaf/darklaf-windows-3.0.3-SNAPSHOT.jar new file mode 100644 index 000000000..139299518 Binary files /dev/null and b/swing/lib/darklaf/darklaf-windows-3.0.3-SNAPSHOT.jar differ diff --git a/swing/lib/darklaf/jsvg-0.0.9.jar b/swing/lib/darklaf/jsvg-0.0.9.jar new file mode 100644 index 000000000..e8fbeba38 Binary files /dev/null and b/swing/lib/darklaf/jsvg-0.0.9.jar differ diff --git a/swing/lib/darklaf/swing-extensions-laf-support-0.1.3.jar b/swing/lib/darklaf/swing-extensions-laf-support-0.1.3.jar new file mode 100644 index 000000000..2d2ec6b86 Binary files /dev/null and b/swing/lib/darklaf/swing-extensions-laf-support-0.1.3.jar differ diff --git a/swing/lib/darklaf/swing-extensions-visual-padding-0.1.3.jar b/swing/lib/darklaf/swing-extensions-visual-padding-0.1.3.jar new file mode 100644 index 000000000..5b39901e5 Binary files /dev/null and b/swing/lib/darklaf/swing-extensions-visual-padding-0.1.3.jar differ diff --git a/swing/src/net/sf/openrocket/communication/AssetHandler.java b/swing/src/net/sf/openrocket/communication/AssetHandler.java index a04d0080b..b0aa4d7b1 100644 --- a/swing/src/net/sf/openrocket/communication/AssetHandler.java +++ b/swing/src/net/sf/openrocket/communication/AssetHandler.java @@ -2,12 +2,10 @@ package net.sf.openrocket.communication; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.util.BuildProperties; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; /** * This class handles assets extracted from a GitHub release page. diff --git a/swing/src/net/sf/openrocket/database/ComponentPresetDatabaseLoader.java b/swing/src/net/sf/openrocket/database/ComponentPresetDatabaseLoader.java index ea0961462..177188785 100644 --- a/swing/src/net/sf/openrocket/database/ComponentPresetDatabaseLoader.java +++ b/swing/src/net/sf/openrocket/database/ComponentPresetDatabaseLoader.java @@ -3,9 +3,7 @@ package net.sf.openrocket.database; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.ObjectInputStream; import java.util.Collection; -import java.util.List; import net.sf.openrocket.file.iterator.DirectoryIterator; import net.sf.openrocket.file.iterator.FileIterator; @@ -14,7 +12,6 @@ import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.preset.xml.OpenRocketComponentLoader; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Pair; import org.slf4j.Logger; diff --git a/swing/src/net/sf/openrocket/gui/components/BasicTree.java b/swing/src/net/sf/openrocket/gui/components/BasicTree.java index 09d8b3d72..c3d75231e 100644 --- a/swing/src/net/sf/openrocket/gui/components/BasicTree.java +++ b/swing/src/net/sf/openrocket/gui/components/BasicTree.java @@ -1,5 +1,7 @@ package net.sf.openrocket.gui.components; +import net.sf.openrocket.gui.util.GUIUtil; + import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; @@ -14,7 +16,6 @@ import javax.swing.tree.TreePath; @SuppressWarnings("serial") public class BasicTree extends JTree { - public BasicTree() { super(); setDefaultOptions(); @@ -36,7 +37,7 @@ public class BasicTree extends JTree { plainUI.setLeftChildIndent(15); - this.setBackground(Color.WHITE); + this.setBackground(GUIUtil.getUITheme().getBackgroundColor()); this.setShowsRootHandles(false); } diff --git a/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java b/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java index 2c666eff2..947f70335 100644 --- a/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java +++ b/swing/src/net/sf/openrocket/gui/components/DescriptionArea.java @@ -1,9 +1,9 @@ package net.sf.openrocket.gui.components; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.URLUtil; import java.awt.Color; -import java.awt.Desktop; import java.awt.Dimension; import java.awt.Font; import java.awt.Rectangle; @@ -31,6 +31,8 @@ import javax.swing.SwingUtilities; public class DescriptionArea extends JScrollPane { private final JEditorPane editorPane; + + private final float size; /** @@ -86,15 +88,14 @@ public class DescriptionArea extends JScrollPane { public DescriptionArea(String text, int rows, float size, boolean opaque) { super(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + this.size = size; editorPane = new JEditorPane("text/html", ""); - Font font = editorPane.getFont(); - editorPane.setFont(font.deriveFont(font.getSize2D() + size)); editorPane.setEditable(false); editorPane.addHyperlinkListener(new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - URI uri = null; + URI uri; try { uri = e.getURL().toURI(); } @@ -125,8 +126,8 @@ public class DescriptionArea extends JScrollPane { // create temporary file and copy resource to it - File of = null; - BufferedOutputStream os = null; + File of; + BufferedOutputStream os; try { of = File.createTempFile(prefix, suffix); os = new BufferedOutputStream(new FileOutputStream(of)); @@ -163,11 +164,11 @@ public class DescriptionArea extends JScrollPane { } // Calculate correct height - editorPane.setText("abc"); + this.setText("abc"); Dimension oneline = editorPane.getPreferredSize(); - editorPane.setText("abc
def"); + this.setText("abc
def"); Dimension twolines = editorPane.getPreferredSize(); - editorPane.setText(""); + this.setText(""); int lineheight = twolines.height - oneline.height; int extraheight = oneline.height - lineheight; @@ -175,13 +176,20 @@ public class DescriptionArea extends JScrollPane { Dimension dim = editorPane.getPreferredSize(); dim.height = lineheight * rows + extraheight + 2; this.setPreferredSize(dim); + + editorPane.setBorder(GUIUtil.getUITheme().getBorder()); this.setViewportView(editorPane); this.setText(text); } public void setText(String txt) { - editorPane.setText(txt); + // Set the font size (we can't simply set the font to change the font size, because we're using text/html) + Font defaultFont = editorPane.getFont(); + String fontName = defaultFont.getFontName(); + float fontSize = defaultFont.getSize2D() + size; + + editorPane.setText("" + txt + ""); editorPane.revalidate(); SwingUtilities.invokeLater(new Runnable() { diff --git a/swing/src/net/sf/openrocket/gui/components/URLLabel.java b/swing/src/net/sf/openrocket/gui/components/URLLabel.java index 5656eaa96..3d9a45321 100644 --- a/swing/src/net/sf/openrocket/gui/components/URLLabel.java +++ b/swing/src/net/sf/openrocket/gui/components/URLLabel.java @@ -1,23 +1,18 @@ package net.sf.openrocket.gui.components; -import java.awt.Color; import java.awt.Cursor; import java.awt.Desktop; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.font.TextAttribute; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.URLUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.sf.openrocket.util.BugException; - /** * A label of a URL that is clickable. Clicking the URL will launch the URL in * the default browser if the Desktop class is supported. @@ -26,7 +21,7 @@ import net.sf.openrocket.util.BugException; */ public class URLLabel extends SelectableLabel { private static final Logger log = LoggerFactory.getLogger(URLLabel.class); - + /** * Create a label showing the url it will direct to. * @@ -53,7 +48,7 @@ public class URLLabel extends SelectableLabel { Map map = new HashMap(); map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); this.setFont(this.getFont().deriveFont(map)); - this.setForeground(Color.BLUE); + this.setForeground(GUIUtil.getUITheme().getURLColor()); this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); diff --git a/swing/src/net/sf/openrocket/gui/components/compass/Tester.java b/swing/src/net/sf/openrocket/gui/components/compass/Tester.java index 97ca176b2..edac03799 100644 --- a/swing/src/net/sf/openrocket/gui/components/compass/Tester.java +++ b/swing/src/net/sf/openrocket/gui/components/compass/Tester.java @@ -22,7 +22,7 @@ public class Tester { BasicApplication baseApp = new BasicApplication(); baseApp.initializeApplication(); - GUIUtil.setBestLAF(); + GUIUtil.applyLAF(); SwingUtilities.invokeAndWait(new Runnable() { @Override diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index d0569ea2f..f35e5dba2 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -2,7 +2,6 @@ package net.sf.openrocket.gui.configdialog; import java.awt.Color; import java.awt.Component; -import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Method; @@ -170,6 +169,7 @@ public class AppearancePanel extends JPanel { Color awtColor = ColorConversion.toAwtColor(c); colorChooser.setColor(awtColor); + colorChooser.updateUI(); // Needed for darklaf color chooser to update // Bind a change of color selection to a change in the components color ColorSelectionModel model = colorChooser.getSelectionModel(); @@ -183,7 +183,8 @@ public class AppearancePanel extends JPanel { JDialog d = JColorChooser.createDialog(AppearancePanel.this, trans.get("RocketCompCfg.lbl.Choosecolor"), true, - colorChooser, new ActionListener() { + colorChooser, + new ActionListener() { @Override public void actionPerformed(ActionEvent okEvent) { changeComponentColor(colorChooser.getColor()); @@ -262,8 +263,7 @@ public class AppearancePanel extends JPanel { net.sf.openrocket.util.Color figureColor = c.getColor(); if (figureColor == null) { - figureColor = Application.getPreferences().getDefaultColor( - c.getClass()); + figureColor = ((SwingPreferences) Application.getPreferences()).getDefaultColor(c.getClass()); } final JButton figureColorButton = new SelectColorButton( new ColorIcon(figureColor)); @@ -278,8 +278,7 @@ public class AppearancePanel extends JPanel { public void stateChanged(EventObject e) { net.sf.openrocket.util.Color col = c.getColor(); if (col == null) { - col = Application.getPreferences().getDefaultColor( - c.getClass()); + col = ((SwingPreferences) Application.getPreferences()).getDefaultColor(c.getClass()); } figureColorButton.setIcon(new ColorIcon(col)); } diff --git a/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java index c98e2c6c2..98709e734 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/InnerTubeConfig.java @@ -40,6 +40,7 @@ import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.DescriptionArea; import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.widgets.SelectColorButton; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.material.Material; @@ -465,10 +466,17 @@ class ClusterSelectionPanel extends JPanel { private static final int BUTTON_SIZE = 50; private static final int MOTOR_DIAMETER = 10; - private static final Color SELECTED_COLOR = Color.RED; - private static final Color UNSELECTED_COLOR = Color.WHITE; - private static final Color MOTOR_FILL_COLOR = Color.GREEN; - private static final Color MOTOR_BORDER_COLOR = Color.BLACK; + private static final Color SELECTED_COLOR; + private static final Color UNSELECTED_COLOR; + private static final Color MOTOR_FILL_COLOR; + private static final Color MOTOR_BORDER_COLOR; + + static { + SELECTED_COLOR = Color.RED; + UNSELECTED_COLOR = GUIUtil.getUITheme().getBackgroundColor(); + MOTOR_FILL_COLOR = Color.GREEN; + MOTOR_BORDER_COLOR = Color.BLACK; + } public ClusterSelectionPanel(Clusterable component) { super(new MigLayout("gap 0 0", diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java index fb9dc9a95..6a8dad3ef 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketComponentConfig.java @@ -506,7 +506,7 @@ public class RocketComponentConfig extends JPanel { StyledLabel labelMassOverriddenBy = new StyledLabel( String.format(trans.get("RocketCompCfg.lbl.MassOverriddenBy"), component.getMassOverriddenBy().getName()), 0, StyledLabel.Style.BOLD); - labelMassOverriddenBy.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + labelMassOverriddenBy.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); labelMassOverriddenBy.setToolTipText( String.format(trans.get("RocketCompCfg.lbl.MassOverriddenBy.ttip"), component.getMassOverriddenBy().getName())); checkboxes.add(labelMassOverriddenBy, "gapleft 25lp, wrap"); @@ -569,7 +569,7 @@ public class RocketComponentConfig extends JPanel { StyledLabel labelCGOverriddenBy = new StyledLabel( String.format(trans.get("RocketCompCfg.lbl.CGOverriddenBy"), component.getCGOverriddenBy().getName()), 0, StyledLabel.Style.BOLD); - labelCGOverriddenBy.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + labelCGOverriddenBy.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); labelCGOverriddenBy.setToolTipText( String.format(trans.get("RocketCompCfg.lbl.CGOverriddenBy.ttip"), component.getCGOverriddenBy().getName())); checkboxes.add(labelCGOverriddenBy, "gapleft 25lp, wrap"); @@ -663,7 +663,7 @@ public class RocketComponentConfig extends JPanel { StyledLabel labelCDOverriddenBy = new StyledLabel( String.format(trans.get("RocketCompCfg.lbl.CDOverriddenBy"), component.getCDOverriddenBy().getName()), 0, StyledLabel.Style.BOLD); - labelCDOverriddenBy.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + labelCDOverriddenBy.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); labelCDOverriddenBy.setToolTipText( String.format(trans.get("RocketCompCfg.lbl.CDOverriddenBy"), component.getCDOverriddenBy().getName())); checkboxes.add(labelCDOverriddenBy, "gapleft 25lp, wrap"); @@ -719,6 +719,7 @@ public class RocketComponentConfig extends JPanel { commentTextArea.setLineWrap(true); commentTextArea.setWrapStyleWord(true); commentTextArea.setEditable(true); + commentTextArea.setBorder(GUIUtil.getUITheme().getBorder()); GUIUtil.setTabToFocusing(commentTextArea); commentTextArea.addFocusListener(textFieldListener); commentTextArea.addKeyListener(new TextComponentSelectionKeyListener(commentTextArea)); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/RocketConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/RocketConfig.java index acd4ee47b..9835778ca 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/RocketConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/RocketConfig.java @@ -27,7 +27,7 @@ import net.sf.openrocket.startup.Application; public class RocketConfig extends RocketComponentConfig { private static final Translator trans = Application.getTranslator(); - + private TextFieldListener textFieldListener; private JTextArea designerTextArea; @@ -55,6 +55,7 @@ public class RocketConfig extends RocketComponentConfig { designerTextArea.setLineWrap(true); designerTextArea.setWrapStyleWord(true); designerTextArea.setEditable(true); + designerTextArea.setBorder(GUIUtil.getUITheme().getBorder()); GUIUtil.setTabToFocusing(designerTextArea); designerTextArea.addFocusListener(textFieldListener); this.add(new JScrollPane(designerTextArea), "wmin 400lp, height 60lp:60lp:, grow 30, wrap para"); @@ -69,6 +70,7 @@ public class RocketConfig extends RocketComponentConfig { revisionTextArea.setLineWrap(true); revisionTextArea.setWrapStyleWord(true); revisionTextArea.setEditable(true); + revisionTextArea.setBorder(GUIUtil.getUITheme().getBorder()); GUIUtil.setTabToFocusing(revisionTextArea); revisionTextArea.addFocusListener(textFieldListener); diff --git a/swing/src/net/sf/openrocket/gui/customexpression/CustomExpressionPanel.java b/swing/src/net/sf/openrocket/gui/customexpression/CustomExpressionPanel.java index 394daec86..c37e8ed2b 100644 --- a/swing/src/net/sf/openrocket/gui/customexpression/CustomExpressionPanel.java +++ b/swing/src/net/sf/openrocket/gui/customexpression/CustomExpressionPanel.java @@ -1,6 +1,5 @@ package net.sf.openrocket.gui.customexpression; -import java.awt.Color; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -18,6 +17,7 @@ import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileNameExtensionFilter; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.SwingPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +39,7 @@ public class CustomExpressionPanel extends JPanel { private static final Logger log = LoggerFactory.getLogger(CustomExpressionPanel.class); private static final Translator trans = Application.getTranslator(); - + private JPanel expressionSelectorPanel; private OpenRocketDocument doc; @@ -51,6 +51,7 @@ public class CustomExpressionPanel extends JPanel { expressionSelectorPanel.setToolTipText(trans.get("customExpressionPanel.lbl.CalcNote")); JScrollPane scroll = new JScrollPane(expressionSelectorPanel); + expressionSelectorPanel.setBorder(GUIUtil.getUITheme().getBorder()); //Border bdr = BorderFactory.createTitledBorder(trans.get("customExpressionPanel.lbl.CustomExpressions")); //scroll.setBorder(bdr); @@ -170,10 +171,10 @@ public class CustomExpressionPanel extends JPanel { * A JPanel which configures a single expression */ private class SingleExpression extends JPanel { - + // Convenience method to make the labels consistent private JLabel setLabelStyle(JLabel l) { - l.setBackground(Color.WHITE); + l.setBackground(GUIUtil.getUITheme().getBackgroundColor()); l.setOpaque(true); l.setBorder(BorderFactory.createRaisedBevelBorder()); l.setText(" " + l.getText() + " "); @@ -191,13 +192,13 @@ public class CustomExpressionPanel extends JPanel { JLabel symbolLabel = new JLabel(trans.get("customExpression.Symbol") + " :"); JLabel symbol = new JLabel(expression.getSymbol()); symbol = setLabelStyle(symbol); - symbol.setBackground(Color.WHITE); + symbol.setBackground(GUIUtil.getUITheme().getBackgroundColor()); JLabel unitLabel = new JLabel(trans.get("customExpression.Units") + " :"); UnitSelector unitSelector = new UnitSelector(expression.getType().getUnitGroup()); //JLabel unitSelector = new JLabel ( expression.getUnit() ); //unitSelector = setLabelStyle(unitSelector); - //unitSelector.setBackground(Color.WHITE); + //unitSelector.setBackground(GUIUtil.getUITheme().getBackgroundColor()); JButton editButton = new SelectColorButton(Icons.EDIT_EDIT); editButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Edit")); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java index bb9f0b1eb..480c32367 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/AboutDialog.java @@ -60,6 +60,9 @@ public class AboutDialog extends JDialog { "
" + "See all contributors at
" + href("https://github.com/openrocket/openrocket/graphs/contributors", false, false) + "
" + "
" + + "Thank you to our financial contributors who have provided us with the necessary resources to continue this project:
" + + href("https://opencollective.com/openrocket", true, true) + "
" + + "
" + "OpenRocket utilizes the following libraries:
" + "
" + "MiG Layout" + href("http://www.miglayout.com", true, true) + "
" + @@ -72,6 +75,7 @@ public class AboutDialog extends JDialog { "Simple Logging Facade for Java" + href("http://www.slf4j.org", true, true) + "
" + "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) + "
" + "
" + "OpenRocket gratefully acknowledges our use of the following databases:
" + "
" + diff --git a/swing/src/net/sf/openrocket/gui/dialogs/BugReportDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/BugReportDialog.java index 763f873b0..117384b51 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/BugReportDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/BugReportDialog.java @@ -1,5 +1,6 @@ package net.sf.openrocket.gui.dialogs; +import java.awt.Color; import java.awt.Dialog; import java.awt.Dimension; import java.awt.Window; @@ -177,8 +178,9 @@ public class BugReportDialog extends JDialog { private static void addBugReportInformation(StringBuilder sb) { sb.append("---------- Bug report ----------\n"); sb.append('\n'); - sb.append("Please include a description about what actions you were " + - "performing when the exception occurred:\n"); + Color color = GUIUtil.getUITheme().getDarkWarningColor(); + sb.append(String.format("Please include a description about what actions you were " + + "performing when the exception occurred:\n", color.getRed(), color.getGreen(), color.getBlue())); sb.append("(You can edit text directly in this window)\n"); sb.append('\n'); sb.append("1. \n"); @@ -204,6 +206,7 @@ public class BugReportDialog extends JDialog { sbTemp.append("OpenRocket source: " + BuildProperties.getBuildSource() + "\n"); sbTemp.append("OpenRocket location: " + JarUtil.getCurrentJarFile() + "\n"); sbTemp.append("User-defined thrust curves location: " + preferences.getUserThrustCurveFilesAsString() + "\n"); + sbTemp.append("LAF: " + UIManager.getLookAndFeel().getClass().getName() + "\n"); sbTemp.append("JOGL version: " + JoglVersion.getInstance().getImplementationVersion() + "\n"); sbTemp.append("Current default locale: " + Locale.getDefault() + "\n"); sbTemp.append("System properties:\n"); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java index 12cd39195..2a9d598d7 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java @@ -150,6 +150,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe warningList = new JList<>(); JScrollPane scrollPane = new JScrollPane(warningList); + warningList.setBorder(GUIUtil.getUITheme().getBorder()); ////Warnings: scrollPane.setBorder(BorderFactory.createTitledBorder(trans.get("componentanalysisdlg.TitledBorder.warnings"))); panel.add(scrollPane, "gap paragraph, spany 4, w 300lp, grow, height :100lp:, wrap"); @@ -646,7 +647,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe } label.setOpaque(true); - label.setBackground(Color.WHITE); + label.setBackground(GUIUtil.getUITheme().getBackgroundColor()); label.setHorizontalAlignment(SwingConstants.LEFT); if ((row < 0) || (row >= data.size())) @@ -693,7 +694,6 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe private class DragCellRenderer extends CustomCellRenderer { private static final long serialVersionUID = 1L; - public DragCellRenderer() { super(dragData, 3); } @@ -712,6 +712,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe float val = 1.0f; label.setBackground(Color.getHSBColor(hue, sat, val)); + label.setForeground(Color.BLACK); } if ((row < 0) || (row >= dragData.size())) diff --git a/swing/src/net/sf/openrocket/gui/dialogs/DebugLogDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/DebugLogDialog.java index 4a2e81794..26bbd5ddf 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/DebugLogDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/DebugLogDialog.java @@ -67,7 +67,7 @@ public class DebugLogDialog extends JDialog { private static final int POLL_TIME = 250; private static final String STACK_TRACE_MARK = "\uFF01"; private static final Translator trans = Application.getTranslator(); - + private static final EnumMap backgroundColors = new EnumMap(LogLevel.class); static { for (LogLevel l : LogLevel.values()) { @@ -343,6 +343,7 @@ public class DebugLogDialog extends JDialog { bottomPanel.add(new JLabel(trans.get("debuglogdlg.lbl.Stacktrace")), "wrap rel"); stackTraceLabel = new JTextArea(8, 80); stackTraceLabel.setEditable(false); + stackTraceLabel.setBorder(GUIUtil.getUITheme().getBorder()); GUIUtil.changeFontSize(stackTraceLabel, -2); bottomPanel.add(new JScrollPane(stackTraceLabel), "grow, pushy 200, growprioy 200"); @@ -503,7 +504,7 @@ public class DebugLogDialog extends JDialog { if (STACK_TRACE_MARK.equals(value)) { fg = Color.RED; } else { - fg = table1.getForeground(); + fg = Color.BLACK; } bg = backgroundColors.get(buffer.get(row).getLevel()); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/ErrorWarningDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/ErrorWarningDialog.java index 335fe25b8..29e74dcde 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/ErrorWarningDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/ErrorWarningDialog.java @@ -3,6 +3,7 @@ package net.sf.openrocket.gui.dialogs; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.util.BetterListCellRenderer; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.logging.Error; import net.sf.openrocket.logging.ErrorSet; import net.sf.openrocket.logging.Warning; @@ -15,7 +16,6 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.ListSelectionModel; -import java.awt.Color; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -25,11 +25,12 @@ import java.awt.event.MouseEvent; */ @SuppressWarnings("serial") public abstract class ErrorWarningDialog { + public static void showErrorsAndWarnings(Component parent, Object message, String title, ErrorSet errors, WarningSet warnings) { JPanel content = new JPanel(new MigLayout("ins 0, fillx")); StyledLabel label = new StyledLabel("Errors"); - label.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + label.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); content.add(label, "wrap, gaptop 15lp"); Error[] e = errors.toArray(new Error[0]); @@ -37,6 +38,7 @@ public abstract class ErrorWarningDialog { errorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); errorList.setCellRenderer(new ErrorListCellRenderer()); JScrollPane errorPane = new JScrollPane(errorList); + errorList.setBorder(GUIUtil.getUITheme().getBorder()); content.add(errorPane, "wrap, growx"); // Deselect items if clicked on blank region @@ -58,6 +60,7 @@ public abstract class ErrorWarningDialog { final JList warningList = new JList<>(w); warningList.setCellRenderer(new BetterListCellRenderer()); JScrollPane warningPane = new JScrollPane(warningList); + warningList.setBorder(GUIUtil.getUITheme().getBorder()); content.add(warningPane, "wrap, growx"); // Deselect items if clicked on blank region @@ -84,9 +87,9 @@ public abstract class ErrorWarningDialog { // Text color if (isSelected) { - label.setForeground(Color.WHITE); + label.setForeground(GUIUtil.getUITheme().getTextSelectionForegroundColor()); } else { - label.setForeground(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + label.setForeground(GUIUtil.getUITheme().getDarkWarningColor()); } return label; diff --git a/swing/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java index 006222aed..cf84659ca 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/UpdateInfoDialog.java @@ -1,16 +1,15 @@ package net.sf.openrocket.gui.dialogs; import java.awt.Component; -import java.awt.Desktop; import java.awt.Dimension; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; +import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; @@ -75,6 +74,7 @@ public class UpdateInfoDialog extends JDialog { // Release information box final JTextPane textPane = new JTextPane(); + textPane.setBorder(BorderFactory.createLineBorder(GUIUtil.getUITheme().getTextColor())); textPane.setEditable(false); textPane.setContentType("text/html"); textPane.setMargin(new Insets(10, 10, 40, 10)); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/WarningDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/WarningDialog.java index f856bd8a0..ec2a0a34a 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/WarningDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/WarningDialog.java @@ -2,23 +2,25 @@ package net.sf.openrocket.gui.dialogs; import java.awt.Component; +import javax.swing.BorderFactory; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import net.sf.openrocket.gui.util.BetterListCellRenderer; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; @SuppressWarnings("serial") public abstract class WarningDialog { - public static void showWarnings(Component parent, Object message, String title, WarningSet warnings) { Warning[] w = warnings.toArray(new Warning[0]); final JList list = new JList(w); list.setCellRenderer(new BetterListCellRenderer()); JScrollPane pane = new JScrollPane(list); + pane.setBorder(GUIUtil.getUITheme().getBorder()); JOptionPane.showMessageDialog(parent, new Object[] { message, pane }, title, JOptionPane.WARNING_MESSAGE); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java index ee295ee9f..88222ec54 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/flightconfiguration/RenameConfigDialog.java @@ -1,6 +1,5 @@ package net.sf.openrocket.gui.dialogs.flightconfiguration; -import java.awt.Color; import java.awt.Dialog; import java.awt.Window; import java.awt.event.ActionEvent; @@ -25,7 +24,7 @@ import net.sf.openrocket.gui.widgets.SelectColorButton; public class RenameConfigDialog extends JDialog { private static final long serialVersionUID = -5423008694485357248L; private static final Translator trans = Application.getTranslator(); - + public RenameConfigDialog(final Window parent, final Rocket rocket, final FlightConfigurationId fcid) { super(parent, trans.get("RenameConfigDialog.title"), Dialog.ModalityType.APPLICATION_MODAL); @@ -47,7 +46,7 @@ public class RenameConfigDialog extends JDialog { RenameConfigDialog.this.setVisible(false); } }); - panel.add(okButton); + panel.add(okButton, "growx"); JButton renameToDefaultButton = new SelectColorButton(trans.get("RenameConfigDialog.but.reset")); renameToDefaultButton.addActionListener(new ActionListener() { @@ -57,7 +56,7 @@ public class RenameConfigDialog extends JDialog { RenameConfigDialog.this.setVisible(false); } }); - panel.add(renameToDefaultButton); + panel.add(renameToDefaultButton, "growx"); JButton cancel = new SelectColorButton(trans.get("button.cancel")); cancel.addActionListener(new ActionListener() { @@ -66,14 +65,14 @@ public class RenameConfigDialog extends JDialog { RenameConfigDialog.this.setVisible(false); } }); - panel.add(cancel, "wrap para"); + panel.add(cancel, "growx, wrap para"); // {motors} & {manufacturers} info String text = "" + CommonStrings.dagger + " " + trans.get("RenameConfigDialog.lbl.infoMotors") + trans.get("RenameConfigDialog.lbl.infoManufacturers") + trans.get("RenameConfigDialog.lbl.infoCombination"); StyledLabel info = new StyledLabel(text, -2); - info.setFontColor(Color.DARK_GRAY); + info.setFontColor(GUIUtil.getUITheme().getDimTextColor()); panel.add(info, "spanx, growx, wrap"); this.add(panel); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorInformationPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorInformationPanel.java index dcbf04aa0..de63acf0e 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorInformationPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/motor/thrustcurve/MotorInformationPanel.java @@ -37,14 +37,13 @@ import net.sf.openrocket.unit.UnitGroup; @SuppressWarnings("serial") class MotorInformationPanel extends JPanel { - + private static final Translator trans = Application.getTranslator(); + private static final int ZOOM_ICON_POSITION_NEGATIVE_X = 50; private static final int ZOOM_ICON_POSITION_POSITIVE_Y = 12; - private static final Color NO_COMMENT_COLOR = Color.GRAY; - private static final Color WITH_COMMENT_COLOR = Color.BLACK; - - private static final Translator trans = Application.getTranslator(); + private static final Color NO_COMMENT_COLOR = GUIUtil.getUITheme().getDimTextColor(); + private static final Color WITH_COMMENT_COLOR = GUIUtil.getUITheme().getTextColor(); // Motors in set private List selectedMotorSet; @@ -190,7 +189,9 @@ class MotorInformationPanel extends JPanel { changeLabelFont(plot.getDomainAxis(), -2); //// Thrust curve: - chart.setTitle(new TextTitle(trans.get("TCMotorSelPan.title.Thrustcurve"), this.getFont())); + TextTitle title = new TextTitle(trans.get("TCMotorSelPan.title.Thrustcurve"), this.getFont()); + title.setPaint(GUIUtil.getUITheme().getTextColor()); + chart.setTitle(title); chart.setBackgroundPaint(this.getBackground()); plot.setBackgroundPaint(Color.WHITE); plot.setDomainGridlinePaint(Color.LIGHT_GRAY); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java b/swing/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java index 64b106336..8718a48a6 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/optimization/SimulationModifierTree.java @@ -1,6 +1,5 @@ package net.sf.openrocket.gui.dialogs.optimization; -import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.util.Enumeration; @@ -17,6 +16,7 @@ import javax.swing.tree.TreePath; import net.sf.openrocket.gui.components.BasicTree; import net.sf.openrocket.gui.main.ComponentIcons; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.optimization.rocketoptimization.SimulationModifier; import net.sf.openrocket.rocketcomponent.Rocket; @@ -37,7 +37,7 @@ public class SimulationModifierTree extends BasicTree { private final List selectedModifiers; private static final Translator trans = Application.getTranslator(); - + /** * Sole constructor. * @@ -151,11 +151,13 @@ public class SimulationModifierTree extends BasicTree { // Set icon (for rocket components, null for others) setIcon(ComponentIcons.getSmallIcon(object.getClass())); - + + // By default, set background to transparent + setOpaque(false); // Set text color/style if (object instanceof RocketComponent) { - setForeground(Color.GRAY); + setForeground(GUIUtil.getUITheme().getDimTextColor()); setFont(componentFont); // Set tooltip @@ -169,21 +171,24 @@ public class SimulationModifierTree extends BasicTree { this.setToolTipText(null); } } else if (object instanceof String) { - setForeground(Color.GRAY); + setForeground(GUIUtil.getUITheme().getDimTextColor()); setFont(stringFont); } else if (object instanceof SimulationModifier) { if (selectedModifiers.contains(object)) { - setForeground(Color.GRAY); + setForeground(GUIUtil.getUITheme().getDimTextColor()); + setFont(stringFont); } else { if (tree.getSelectionRows() != null && IntStream.of(tree.getSelectionRows()).anyMatch(r -> r == row)) { - setForeground(Color.WHITE); + setForeground(GUIUtil.getUITheme().getTextSelectionForegroundColor()); + setBackground(GUIUtil.getUITheme().getTextSelectionBackgroundColor()); + setOpaque(true); } else { - setForeground(Color.BLACK); + setForeground(GUIUtil.getUITheme().getTextColor()); } + setFont(modifierFont); } - setFont(modifierFont); setText(((SimulationModifier) object).getName()); setToolTipText(((SimulationModifier) object).getDescription()); } diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java index 4457b9786..98e993c6f 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/GeneralPreferencesPanel.java @@ -20,9 +20,12 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; +import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.Timer; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -31,6 +34,8 @@ import net.sf.openrocket.communication.ReleaseInfo; import net.sf.openrocket.communication.UpdateInfo; import net.sf.openrocket.communication.UpdateInfoRetriever; import net.sf.openrocket.communication.UpdateInfoRetriever.ReleaseStatus; +import net.sf.openrocket.gui.SpinnerEditor; +import net.sf.openrocket.gui.adaptors.IntegerModel; import net.sf.openrocket.gui.components.DescriptionArea; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; @@ -40,6 +45,7 @@ import net.sf.openrocket.gui.util.SimpleFileFilter; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.gui.util.PreferencesExporter; import net.sf.openrocket.gui.util.PreferencesImporter; +import net.sf.openrocket.gui.util.UITheme; import net.sf.openrocket.l10n.L10N; import net.sf.openrocket.logging.Markers; import net.sf.openrocket.startup.Preferences; @@ -50,13 +56,17 @@ import net.sf.openrocket.gui.widgets.SelectColorButton; @SuppressWarnings("serial") public class GeneralPreferencesPanel extends PreferencesPanel { + private final UITheme.Theme currentTheme; + private final int currentFontSize; public GeneralPreferencesPanel(PreferencesDialog parent) { super(parent, new MigLayout("fillx, ins 30lp n n n")); - + + this.currentTheme = GUIUtil.getUITheme(); + this.currentFontSize = preferences.getUIFontSize(); //// Language selector - Locale userLocale = null; + Locale userLocale; { String locale = preferences.getString("locale", null); userLocale = L10N.toLocale(locale); @@ -79,6 +89,7 @@ public class GeneralPreferencesPanel extends PreferencesPanel { @SuppressWarnings("unchecked") public void actionPerformed(ActionEvent e) { Named selection = (Named) languageCombo.getSelectedItem(); + if (selection == null) return; Locale l = selection.get(); preferences.putString(Preferences.USER_LOCAL, l == null ? null : l.toString()); } @@ -86,8 +97,64 @@ public class GeneralPreferencesPanel extends PreferencesPanel { this.add(new JLabel(trans.get("generalprefs.lbl.language")), "gapright para"); this.add(languageCombo, "wrap rel, growx, sg combos"); - this.add(new StyledLabel(trans.get("generalprefs.lbl.languageEffect"), -3, Style.ITALIC), "span, wrap para*2"); - + this.add(new StyledLabel(trans.get("generalprefs.lbl.languageEffect"), -3, Style.ITALIC), "span, wrap rel"); + + //// UI Theme + UITheme.Theme currentTheme = GUIUtil.getUITheme(); + List> themes = new ArrayList<>(); + for (UITheme.Theme t : UITheme.Themes.values()) { + themes.add(new Named<>(t, t.getDisplayName())); + } + Collections.sort(themes); + + final JComboBox themesCombo = new JComboBox<>(themes.toArray()); + for (int i = 0; i < themes.size(); i++) { + if (Utils.equals(currentTheme, themes.get(i).get())) { + themesCombo.setSelectedIndex(i); + } + } + + this.add(new JLabel(trans.get("generalprefs.lbl.UITheme")), "gapright para"); + this.add(themesCombo, "wrap, growx, sg combos"); + + //// Font size + this.add(new JLabel(trans.get("generalprefs.lbl.FontSize")), "gapright para"); + final IntegerModel fontSizeModel = new IntegerModel(preferences, "UIFontSize", 5, 25); + final JSpinner fontSizeSpinner = new JSpinner(fontSizeModel.getSpinnerModel()); + fontSizeSpinner.setEditor(new SpinnerEditor(fontSizeSpinner)); + this.add(fontSizeSpinner, "growx, wrap"); + + //// You need to restart OpenRocket for the theme change to take effect. + final JLabel lblRestartORTheme = new JLabel(); + lblRestartORTheme.setForeground(GUIUtil.getUITheme().getDarkWarningColor()); + this.add(lblRestartORTheme, "spanx, wrap para*2, growx"); + + fontSizeSpinner.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (fontSizeModel.getValue() == currentFontSize) { + lblRestartORTheme.setText(""); + return; + } + lblRestartORTheme.setText(trans.get("generalprefs.lbl.themeRestartOR")); + } + }); + themesCombo.addActionListener(new ActionListener() { + @Override + @SuppressWarnings("unchecked") + public void actionPerformed(ActionEvent e) { + Named selection = (Named) themesCombo.getSelectedItem(); + if (selection == null) return; + UITheme.Theme t = selection.get(); + if (t == currentTheme) { + lblRestartORTheme.setText(""); + return; + } + preferences.setUITheme(t); + lblRestartORTheme.setText(trans.get("generalprefs.lbl.themeRestartOR")); + } + }); + //// User-defined thrust curves: this.add(new JLabel(trans.get("pref.dlg.lbl.User-definedthrust")), "spanx, wrap"); final JTextField field = new JTextField(); @@ -180,8 +247,9 @@ public class GeneralPreferencesPanel extends PreferencesPanel { this.add(button, "wrap"); //// Add directories, RASP motor files (*.eng), RockSim engine files (*.rse) or ZIP archives separated by a semicolon (;) to load external thrust curves. Changes will take effect the next time you start OpenRocket. - DescriptionArea desc = new DescriptionArea(trans.get("pref.dlg.DescriptionArea.Adddirectories"), 3, -3, false); - desc.setBackground(getBackground()); + DescriptionArea desc = new DescriptionArea(trans.get("pref.dlg.DescriptionArea.Adddirectories"), 3, -1.5f, false); + desc.setBackground(GUIUtil.getUITheme().getBackgroundColor()); + desc.setForeground(GUIUtil.getUITheme().getTextColor()); this.add(desc, "spanx, growx, wrap 40lp"); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java index 459c6f747..2cb386954 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java @@ -23,6 +23,7 @@ import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.models.atmosphere.ExtendedISAModel; import net.sf.openrocket.simulation.SimulationOptions; import net.sf.openrocket.unit.UnitGroup; @@ -43,7 +44,7 @@ public class LaunchPreferencesPanel extends PreferencesPanel { StyledLabel warning = new StyledLabel(String.format( "%s", trans.get("pref.dlg.lbl.launchWarning")), 0.5f, StyledLabel.Style.BOLD); - warning.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + warning.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); warning.setToolTipText(trans.get("pref.dlg.lbl.launchWarning.ttip")); add(warning, "spanx, growx 0, gapbottom para, wrap"); diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java index a45a68efc..051e312ac 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/SimulationPreferencesPanel.java @@ -17,6 +17,7 @@ import net.sf.openrocket.gui.adaptors.EnumModel; import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.simulation.RK4SimulationStepper; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.GeodeticComputationStrategy; @@ -24,7 +25,7 @@ import net.sf.openrocket.gui.widgets.SelectColorButton; public class SimulationPreferencesPanel extends PreferencesPanel { private static final long serialVersionUID = 7983195730016979888L; - + /* * private GeodeticComputationStrategy geodeticComputation = * GeodeticComputationStrategy.SPHERICAL; @@ -84,7 +85,7 @@ public class SimulationPreferencesPanel extends PreferencesPanel { StyledLabel warning = new StyledLabel(String.format( "%s", trans.get("pref.dlg.lbl.launchWarning")), 0, StyledLabel.Style.BOLD); - warning.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor()); + warning.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); warning.setToolTipText(trans.get("pref.dlg.lbl.launchWarning.ttip")); subsub.add(warning, "spanx, wrap para"); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java index 65df4d52f..a9c2eacf4 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java @@ -10,6 +10,7 @@ import com.jogamp.opengl.fixedfunc.GLLightingFunc; import net.sf.openrocket.gui.figure3d.geometry.Geometry; import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface; +import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.ExternalComponent; @@ -80,7 +81,7 @@ public class FigureRenderer extends RocketRenderer { if (defaultColorCache.containsKey(c.getClass())) { figureColor = defaultColorCache.get(c.getClass()); } else { - figureColor = Application.getPreferences().getDefaultColor(c.getClass()); + figureColor = ((SwingPreferences) Application.getPreferences()).getDefaultColor(c.getClass()); defaultColorCache.put(c.getClass(), figureColor); } } diff --git a/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java index 578817921..41cac74ba 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java @@ -42,9 +42,9 @@ public class RealisticRenderer extends RocketRenderer { gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT, new float[] { 0, 0, 0 }, 0); - float amb = 0.3f; - float dif = 1.0f - amb; - float spc = 1.0f; + float amb = 0.4f; + float dif = 0.65f; + float spc = 0.65f; gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_AMBIENT, new float[] { amb, amb, amb, 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_DIFFUSE, new float[] { dif, dif, dif, 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_SPECULAR, new float[] { spc, spc, spc, 1 }, 0); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java b/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java index 38769db88..cc65d95ae 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java @@ -34,6 +34,7 @@ import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; import javax.swing.event.MouseInputAdapter; +import net.sf.openrocket.gui.util.GUIUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,7 +65,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(RocketFigure3d.class); - + static { //this allows the GL canvas and things like the motor selection //drop down to z-order themselves. @@ -288,7 +289,9 @@ public class RocketFigure3d extends JPanel implements GLEventListener { GL2 gl = drawable.getGL().getGL2(); GLU glu = new GLU(); - gl.glClearColor(1, 1, 1, 1); + Color backgroundColor = GUIUtil.getUITheme().getBackgroundColor(); + gl.glClearColor(backgroundColor.getRed()/255f, backgroundColor.getGreen()/255f, + backgroundColor.getBlue()/255f, backgroundColor.getAlpha()/255f); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); setupView(gl, glu); @@ -315,8 +318,9 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } pickPoint = null; - - gl.glClearColor(1, 1, 1, 1); + + gl.glClearColor(backgroundColor.getRed()/255f, backgroundColor.getGreen()/255f, + backgroundColor.getBlue()/255f, backgroundColor.getAlpha()/255f); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glEnable(GL.GL_MULTISAMPLE); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java index 76af03823..d43c79ef6 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java @@ -371,9 +371,9 @@ public class PhotoFrame extends JFrame { guiModule.startLoader(); - // Set the best available look-and-feel - log.info("Setting best LAF"); - GUIUtil.setBestLAF(); + // Set the look-and-feel + log.info("Setting LAF"); + GUIUtil.applyLAF(); // Load defaults ((SwingPreferences) Application.getPreferences()).loadDefaultUnits(); diff --git a/swing/src/net/sf/openrocket/gui/figureelements/CGCaret.java b/swing/src/net/sf/openrocket/gui/figureelements/CGCaret.java index 14a8a677d..77361260f 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/CGCaret.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/CGCaret.java @@ -1,5 +1,7 @@ package net.sf.openrocket.gui.figureelements; +import net.sf.openrocket.gui.util.GUIUtil; + import java.awt.Color; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; @@ -16,7 +18,7 @@ public class CGCaret extends Caret { private static final float RADIUS = 7; private static Area caret = null; - + /** * Create a new CGCaret at the specified coordinates. */ @@ -56,7 +58,7 @@ public class CGCaret extends Caret { */ @Override protected Color getColor() { - return Color.BLUE; + return GUIUtil.getUITheme().getCGColor(); } } diff --git a/swing/src/net/sf/openrocket/gui/figureelements/CPCaret.java b/swing/src/net/sf/openrocket/gui/figureelements/CPCaret.java index 09e9cceba..a5b66a233 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/CPCaret.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/CPCaret.java @@ -1,5 +1,7 @@ package net.sf.openrocket.gui.figureelements; +import net.sf.openrocket.gui.util.GUIUtil; + import java.awt.Color; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; @@ -15,7 +17,7 @@ public class CPCaret extends Caret { private static final float RADIUS = 7; private static Area caret = null; - + /** * Create a new CPCaret at the specified coordinates. */ @@ -51,6 +53,6 @@ public class CPCaret extends Caret { */ @Override protected Color getColor() { - return Color.RED; + return GUIUtil.getUITheme().getCPColor(); } } diff --git a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java index 1af88b65b..1836ae644 100644 --- a/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java +++ b/swing/src/net/sf/openrocket/gui/figureelements/RocketInfo.java @@ -3,7 +3,6 @@ package net.sf.openrocket.gui.figureelements; import static net.sf.openrocket.util.Chars.ALPHA; import static net.sf.openrocket.util.Chars.THETA; -import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; @@ -11,6 +10,7 @@ import java.awt.Rectangle; import java.awt.font.GlyphVector; import java.awt.geom.Rectangle2D; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; @@ -176,7 +176,7 @@ public class RocketInfo implements FigureElement { GlyphVector massLineWithoutMotors = createText(massTextWithoutMotors); - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getTextColor()); g2.drawGlyphVector(name, x1, y1); g2.drawGlyphVector(lengthLine, x1, y1+line); @@ -234,7 +234,7 @@ public class RocketInfo implements FigureElement { unitWidth = unitWidth + spaceWidth; stabUnitWidth = stabUnitWidth + spaceWidth; - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getTextColor()); // Draw the stability, CG & CP values (and units) g2.drawGlyphVector(stabValue, (float)(x2-stabRect.getWidth()), y1); @@ -261,7 +261,7 @@ public class RocketInfo implements FigureElement { atPos = (float)(x2 - atTextRect.getWidth()); } - g2.setColor(Color.GRAY); + g2.setColor(GUIUtil.getUITheme().getDimTextColor()); g2.drawGlyphVector(atText, atPos, y1 + 3*line); } @@ -411,7 +411,7 @@ public class RocketInfo implements FigureElement { float y = y2 - line * (texts.length-1); - g2.setColor(Color.RED); + g2.setColor(GUIUtil.getUITheme().getWarningColor()); for (GlyphVector v: texts) { Rectangle2D rect = v.getVisualBounds(); @@ -427,7 +427,7 @@ public class RocketInfo implements FigureElement { if (calculatingData) { //// Calculating... GlyphVector calculating = createText(trans.get("RocketInfo.Calculating")); - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getTextColor()); g2.drawGlyphVector(calculating, x1, (float)(y2-height)); } } @@ -485,11 +485,10 @@ public class RocketInfo implements FigureElement { width += 5; if (!calculatingData) - g2.setColor(new Color(0,0,127)); + g2.setColor(GUIUtil.getUITheme().getFlightDataTextActiveColor()); else - g2.setColor(new Color(0,0,127,127)); + g2.setColor(GUIUtil.getUITheme().getFlightDataTextInactiveColor()); - g2.drawGlyphVector(apogee, (float)x1, (float)(y2-2*line)); g2.drawGlyphVector(maxVelocity, (float)x1, (float)(y2-line)); g2.drawGlyphVector(maxAcceleration, (float)x1, (float)(y2)); @@ -502,7 +501,7 @@ public class RocketInfo implements FigureElement { } private synchronized void updateFontSizes() { - float size = Application.getPreferences().getRocketInfoFontSize(); + float size = ((SwingPreferences) Application.getPreferences()).getRocketInfoFontSize(); // No change necessary as the font is the same size, just use the existing version if (font.getSize2D() == size) { return; diff --git a/swing/src/net/sf/openrocket/gui/help/tours/SlideSetManager.java b/swing/src/net/sf/openrocket/gui/help/tours/SlideSetManager.java index 0d9e38155..7828dfd8d 100644 --- a/swing/src/net/sf/openrocket/gui/help/tours/SlideSetManager.java +++ b/swing/src/net/sf/openrocket/gui/help/tours/SlideSetManager.java @@ -1,5 +1,6 @@ package net.sf.openrocket.gui.help.tours; +import java.awt.Color; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -11,6 +12,7 @@ import java.util.Map; import javax.swing.text.html.StyleSheet; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.util.BugException; /** @@ -130,6 +132,9 @@ public class SlideSetManager { try { StyleSheet ss = new StyleSheet(); + Color textColor = GUIUtil.getUITheme().getTextColor(); + ss.addRule(String.format("p { color: rgb(%d, %d, %d, %d)", + textColor.getRed(), textColor.getGreen(), textColor.getBlue(), textColor.getAlpha())); InputStreamReader reader = new InputStreamReader(in, "UTF-8"); ss.loadRules(reader, null); return ss; diff --git a/swing/src/net/sf/openrocket/gui/help/tours/SlideShowComponent.java b/swing/src/net/sf/openrocket/gui/help/tours/SlideShowComponent.java index 07cffdcc6..561ee518b 100644 --- a/swing/src/net/sf/openrocket/gui/help/tours/SlideShowComponent.java +++ b/swing/src/net/sf/openrocket/gui/help/tours/SlideShowComponent.java @@ -12,6 +12,7 @@ import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.StyleSheet; import net.sf.openrocket.gui.components.ImageDisplayComponent; +import net.sf.openrocket.gui.util.GUIUtil; /** * Component that displays a single slide, with the image on top and @@ -28,7 +29,7 @@ public class SlideShowComponent extends JSplitPane { private final ImageDisplayComponent imageDisplay; private final JEditorPane textPane; - + public SlideShowComponent() { super(VERTICAL_SPLIT); @@ -44,6 +45,7 @@ public class SlideShowComponent extends JSplitPane { textPane.setPreferredSize(new Dimension(WIDTH, HEIGHT_TEXT)); JScrollPane scrollPanel = new JScrollPane(textPane); + textPane.setBorder(GUIUtil.getUITheme().getBorder()); this.setRightComponent(scrollPanel); this.setResizeWeight(((double) HEIGHT_IMAGE) / (HEIGHT_IMAGE + HEIGHT_TEXT)); diff --git a/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java b/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java index 69869526c..1f194ce05 100644 --- a/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java +++ b/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java @@ -4,6 +4,7 @@ package net.sf.openrocket.gui.main; import java.awt.Component; import java.awt.Dimension; import java.awt.Rectangle; +import java.awt.Font; import java.awt.event.ActionEvent; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -209,7 +210,7 @@ public class ComponentAddButtons extends JPanel implements Scrollable { for (col = 0; col < buttons[row].length; col++) { buttons[row][col].setMinimumSize(d); buttons[row][col].setPreferredSize(d); - buttons[row][col].getComponent(0).validate(); + buttons[row][col].validate(); } } @@ -315,29 +316,32 @@ public class ComponentAddButtons extends JPanel implements Scrollable { * The label may contain "\n" as a newline. */ public ComponentButton(String text, Icon enabled, Icon disabled) { - super(); - setLayout(new MigLayout("fill, flowy, insets 0, gap 0", "", "")); - - add(new JLabel(), "push, sizegroup spacing"); - - // Add Icon - if (enabled != null) { - JLabel label = new JLabel(enabled); - if (disabled != null) - label.setDisabledIcon(disabled); - add(label, "growx"); + super(text, enabled); + + setVerticalTextPosition(SwingConstants.BOTTOM); // this will put the text below the icon + setHorizontalTextPosition(SwingConstants.CENTER); // this will center the text horizontally beneath the icon + //setIconTextGap(0); // this is optional, it sets the gap between the icon and the text + + // set the disabled icon if it is not null + if (disabled != null) { + setDisabledIcon(disabled); } - - // Add labels - String[] l = text.split("\n"); - for (int i = 0; i < l.length; i++) { - add(new StyledLabel(l[i], SwingConstants.CENTER, -2.0f), "growx"); + + setHorizontalAlignment(SwingConstants.CENTER); // this will center the button itself in its parent component + + // if you have multiline text, you could use html to format it + if (text != null && text.contains("\n")) { + text = "" + text.replace("\n", "
") + ""; + setText(text); + } + + // Initialize enabled status + valueChanged(null); + + // Attach a tree selection listener if selection model is not null + if (selectionModel != null) { + selectionModel.addTreeSelectionListener(this); } - - add(new JLabel(), "push, sizegroup spacing"); - - valueChanged(null); // Update enabled status - selectionModel.addTreeSelectionListener(this); } diff --git a/swing/src/net/sf/openrocket/gui/main/DesignPanel.java b/swing/src/net/sf/openrocket/gui/main/DesignPanel.java index 226c7f8c8..f4e7c274d 100644 --- a/swing/src/net/sf/openrocket/gui/main/DesignPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/DesignPanel.java @@ -174,6 +174,7 @@ public class DesignPanel extends JSplitPane { // Place tree inside scroll pane JScrollPane scroll = new JScrollPane(tree); + tree.setBorder(GUIUtil.getUITheme().getBorder()); panel.add(scroll, "spany, wmin 140px, grow, wrap"); diff --git a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java index 0bac65b69..36f87e2da 100644 --- a/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java +++ b/swing/src/net/sf/openrocket/gui/main/SimulationPanel.java @@ -5,6 +5,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.Font; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; diff --git a/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java b/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java index a852e94b7..e5d422e36 100644 --- a/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java +++ b/swing/src/net/sf/openrocket/gui/main/componenttree/ComponentTreeRenderer.java @@ -1,20 +1,22 @@ package net.sf.openrocket.gui.main.componenttree; +import java.awt.BorderLayout; import java.awt.Component; -import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.util.List; +import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTree; import javax.swing.UIManager; +import javax.swing.border.Border; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; import net.sf.openrocket.gui.main.ComponentIcons; -import net.sf.openrocket.gui.util.Icons; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.MassComponent.MassComponentType; @@ -34,45 +36,83 @@ public class ComponentTreeRenderer extends DefaultTreeCellRenderer { boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus1) { - Component comp = super.getTreeCellRendererComponent(tree, value, sel, - expanded, leaf, row, hasFocus1); + // Create a new JPanel + JPanel panel = new JPanel(); + panel.setOpaque(false); // Set this to false if you want to keep the tree's default background intact + panel.setLayout(new BorderLayout()); + + // Create two JLabels, one for the icon and one for the text + JLabel iconLabel = new JLabel(); + JLabel textLabel = new JLabel(); + + // Retrieve the component from the super method + Component comp = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus1); if (tree == null) return comp; TreePath[] paths = tree.getSelectionPaths(); List components = null; if (paths != null && paths.length > 0) { components = new ArrayList<>(ComponentTreeModel.componentsFromPaths(paths)); } + if (comp instanceof JLabel) { + textLabel.setText(((JLabel) comp).getText()); - // Set icon + // Set the font to the tree font + Font treeFont = UIManager.getFont("Tree.font"); + textLabel.setFont(treeFont); + } + + // Set the icon RocketComponent c = (RocketComponent) value; + Border iconMarginBorder = BorderFactory.createEmptyBorder(0, 0, 0, 4); // 4-pixel gap to the right of the icon if (c.getClass().isAssignableFrom(MassComponent.class)) { MassComponentType t = ((MassComponent) c).getMassComponentType(); - setIcon(ComponentIcons.getSmallMassTypeIcon(t)); + iconLabel.setIcon(ComponentIcons.getSmallMassTypeIcon(t)); + iconLabel.setBorder(iconMarginBorder); } else { - setIcon(ComponentIcons.getSmallIcon(value.getClass())); + iconLabel.setIcon(ComponentIcons.getSmallIcon(value.getClass())); + iconLabel.setBorder(iconMarginBorder); } + + // Add the JLabels to the JPanel + panel.add(iconLabel, BorderLayout.WEST); + panel.add(textLabel, BorderLayout.CENTER); + + // Set the background and foreground colors of the text JLabel + if (sel) { + textLabel.setOpaque(true); + textLabel.setBackground(GUIUtil.getUITheme().getTextSelectionBackgroundColor()); + textLabel.setForeground(GUIUtil.getUITheme().getTextSelectionForegroundColor()); + } else { + textLabel.setOpaque(true); // Set this to true to allow the background color to be visible + textLabel.setBackground(GUIUtil.getUITheme().getComponentTreeBackgroundColor()); + textLabel.setForeground(GUIUtil.getUITheme().getComponentTreeForegroundColor()); + } + + comp = panel; + + // Add mass/CG/CD overridden icons if (c.isMassOverridden() || c.getMassOverriddenBy() != null || c.isCGOverridden() || c.getCGOverriddenBy() != null || c.isCDOverridden() || c.getCDOverriddenBy() != null) { JPanel p = new JPanel(); p.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1)); - p.setBackground(UIManager.getColor("Tree.textBackground")); - p.setForeground(UIManager.getColor("Tree.textForeground")); + p.setBackground(GUIUtil.getUITheme().getComponentTreeBackgroundColor()); + p.setForeground(GUIUtil.getUITheme().getComponentTreeForegroundColor()); p.add(comp/* , BorderLayout.WEST */); if (c.getMassOverriddenBy() != null) { - p.add(new JLabel(Icons.MASS_OVERRIDE_SUBCOMPONENT)); + p.add(new JLabel(GUIUtil.getUITheme().getMassOverrideSubcomponentIcon())); } else if (c.isMassOverridden()) { - p.add(new JLabel(Icons.MASS_OVERRIDE)); + p.add(new JLabel(GUIUtil.getUITheme().getMassOverrideIcon())); } if (c.getCGOverriddenBy() != null) { - p.add(new JLabel(Icons.CG_OVERRIDE_SUBCOMPONENT)); + p.add(new JLabel(GUIUtil.getUITheme().getCGOverrideSubcomponentIcon())); } else if (c.isCGOverridden()) { - p.add(new JLabel(Icons.CG_OVERRIDE)); + p.add(new JLabel(GUIUtil.getUITheme().getCGOverrideIcon())); } if (c.getCDOverriddenBy() != null) { - p.add(new JLabel(Icons.CD_OVERRIDE_SUBCOMPONENT)); + p.add(new JLabel(GUIUtil.getUITheme().getCDOverrideSubcomponentIcon())); } else if (c.isCDOverridden()) { - p.add(new JLabel(Icons.CD_OVERRIDE)); + p.add(new JLabel(GUIUtil.getUITheme().getCDOverrideIcon())); } // Make sure the tooltip also works on the override icons diff --git a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurablePanel.java b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurablePanel.java index 5baec6802..ee9e53dec 100644 --- a/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurablePanel.java +++ b/swing/src/net/sf/openrocket/gui/main/flightconfigpanel/FlightConfigurablePanel.java @@ -23,6 +23,7 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import net.sf.openrocket.gui.main.FlightConfigurationPanel; +import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +45,8 @@ import net.sf.openrocket.util.Pair; public abstract class FlightConfigurablePanel extends JPanel implements ComponentChangeListener { protected static final Translator trans = Application.getTranslator(); + protected static final SwingPreferences prefs = (SwingPreferences) Application.getPreferences(); + private static final Logger log = LoggerFactory.getLogger(FlightConfigurablePanel.class); protected RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); @@ -387,12 +390,12 @@ public abstract class FlightConfigurablePanel */ public class SimulationPlotDialog extends JDialog { - private static final Translator trans = Application.getTranslator(); - + private SimulationPlotDialog(Window parent, Simulation simulation, PlotConfiguration config) { //// Flight data plot super(parent, simulation.getName()); @@ -77,7 +73,7 @@ public class SimulationPlotDialog extends JDialog { // Add warning if X axis type is not time if (config.getDomainAxisType() != FlightDataType.TYPE_TIME) { JLabel msg = new StyledLabel(trans.get("PlotDialog.lbl.timeSeriesWarning"), -2); - msg.setForeground(Color.DARK_RED.toAWTColor()); + msg.setForeground(GUIUtil.getUITheme().getDarkWarningColor()); panel.add(msg, "wrap"); } diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/ComponentAssemblyShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/ComponentAssemblyShapes.java index d3a4068f0..edc683f1c 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/ComponentAssemblyShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/ComponentAssemblyShapes.java @@ -40,11 +40,6 @@ public class ComponentAssemblyShapes extends RocketComponentShape { Shape[] s = EmptyShapes.getShapesSideWithSelectionSquare(correctedTransform, markerRadius); RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component); - // Set the color of the shapes - Color color = getColor(component); - for (int i = 0; i < shapes.length - 1; i++) { - shapes[i].setColor(color); - } shapes[shapes.length - 1].setColor(Color.INVISIBLE); return shapes; @@ -69,11 +64,7 @@ public class ComponentAssemblyShapes extends RocketComponentShape { Shape[] s = EmptyShapes.getShapesBackWithSelectionSquare(correctedTransform, markerRadius); RocketComponentShape[] shapes = RocketComponentShape.toArray(s, component); - // Set the color of the shapes - Color color = getColor(component); - for (int i = 0; i < shapes.length - 1; i++) { - shapes[i].setColor(color); - } + shapes[shapes.length - 1].setColor(Color.INVISIBLE); return shapes; } @@ -86,14 +77,4 @@ public class ComponentAssemblyShapes extends RocketComponentShape { private static double getDisplayRadius(RocketComponent component) { return component.getRocket().getBoundingRadius() * 0.03; } - - private static Color getColor(RocketComponent component) { - if (component instanceof PodSet) { - return new Color(160,160,215); - } else if (component instanceof ParallelStage) { - return new Color(198,163,184); - } else { - return new Color(160, 160, 160); - } - } } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/AbstractScaleFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/AbstractScaleFigure.java index 25585320c..01f5120b6 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/AbstractScaleFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/AbstractScaleFigure.java @@ -70,7 +70,7 @@ public abstract class AbstractScaleFigure extends JPanel { this.setPreferredSize(new Dimension(100,100)); setSize(100,100); - setBackground(Color.WHITE); + setBackground(GUIUtil.getUITheme().getBackgroundColor()); setOpaque(true); } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/FinPointFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/FinPointFigure.java index 83d5f9600..cf5662574 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/FinPointFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/FinPointFigure.java @@ -1,7 +1,6 @@ package net.sf.openrocket.gui.scalefigure; import java.awt.BasicStroke; -import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; @@ -15,6 +14,7 @@ import java.awt.geom.Rectangle2D; import java.util.LinkedList; import java.util.List; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.rocketcomponent.FreeformFinSet; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.SymmetricComponent; @@ -31,11 +31,7 @@ import net.sf.openrocket.util.StateChangeListener; @SuppressWarnings("serial") public class FinPointFigure extends AbstractScaleFigure { - - //private final static Logger log = LoggerFactory.getLogger(FinPointFigure.class); - private static final Color GRID_MAJOR_LINE_COLOR = new Color( 0, 0, 255, 80); - private static final Color GRID_MINOR_LINE_COLOR = new Color( 0, 0, 255, 30); private static final int GRID_LINE_BASE_WIDTH_PIXELS = 1; private static final int LINE_WIDTH_FIN_PIXELS = 1; @@ -45,8 +41,6 @@ public class FinPointFigure extends AbstractScaleFigure { private static final int LINE_WIDTH_BOX_PIXELS = 1; private static final float BOX_WIDTH_PIXELS = 12; private static final float SELECTED_BOX_WIDTH_PIXELS = BOX_WIDTH_PIXELS + 4; - private static final Color POINT_COLOR = new Color(200, 0, 0, 255); - private static final Color SELECTED_POINT_COLOR = new Color(200, 0, 0, 255); private static final double MINOR_TICKS = 10.0; private static final double MAJOR_TICKS = 100.0; @@ -65,9 +59,8 @@ public class FinPointFigure extends AbstractScaleFigure { public FinPointFigure(FreeformFinSet finset) { this.finset = finset; - - // useful for debugging -- shows a contrast against un-drawn space. - setBackground(Color.WHITE); + + setBackground(GUIUtil.getUITheme().getBackgroundColor()); setOpaque(true); updateFigure(); @@ -129,11 +122,11 @@ public class FinPointFigure extends AbstractScaleFigure { Line2D.Double line = new Line2D.Double(); for (Tick t : verticalTicks) { if (t.major) { - g2.setColor(FinPointFigure.GRID_MAJOR_LINE_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointGridMajorLineColor()); line.setLine( t.value, y0, t.value, y1); g2.draw(line); }else{ - g2.setColor(FinPointFigure.GRID_MINOR_LINE_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointGridMinorLineColor()); line.setLine( t.value, y0, t.value, y1); g2.draw(line); } @@ -143,11 +136,11 @@ public class FinPointFigure extends AbstractScaleFigure { Tick[] horizontalTicks = unit.getTicks(y0, y1, MINOR_TICKS / this.scale, MAJOR_TICKS / this.scale); for (Tick t : horizontalTicks) { if (t.major) { - g2.setColor(FinPointFigure.GRID_MAJOR_LINE_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointGridMajorLineColor()); line.setLine( x0, t.value, x1, t.value); g2.draw(line); }else{ - g2.setColor(FinPointFigure.GRID_MINOR_LINE_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointGridMinorLineColor()); line.setLine( x0, t.value, x1, t.value); g2.draw(line); } @@ -170,7 +163,7 @@ public class FinPointFigure extends AbstractScaleFigure { // setup lines final float bodyLineWidth = (float) ( LINE_WIDTH_BODY_PIXELS / scale ); g2.setStroke(new BasicStroke( bodyLineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getFinPointBodyLineColor()); Transition body = (Transition) finset.getParent(); final float xResolution_m = 0.01f; // distance between draw points, in meters @@ -220,7 +213,7 @@ public class FinPointFigure extends AbstractScaleFigure { final float bodyLineWidth = (float) ( LINE_WIDTH_BODY_PIXELS / scale ); g2.setStroke(new BasicStroke( bodyLineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getFinPointBodyLineColor()); g2.draw(shape); } @@ -237,7 +230,7 @@ public class FinPointFigure extends AbstractScaleFigure { final float finEdgeWidth_m = (float) (LINE_WIDTH_FIN_PIXELS / scale ); g2.setStroke(new BasicStroke( finEdgeWidth_m, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getFinPointBodyLineColor()); g2.draw(shape); } @@ -251,7 +244,7 @@ public class FinPointFigure extends AbstractScaleFigure { final float boxEdgeWidth_m = (float) ( LINE_WIDTH_BOX_PIXELS / scale ); g2.setStroke(new BasicStroke( boxEdgeWidth_m, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - g2.setColor(POINT_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointPointColor()); finPointHandles = new Rectangle2D.Double[ drawPoints.length]; for (int currentIndex = 0; currentIndex < drawPoints.length; currentIndex++) { @@ -264,11 +257,11 @@ public class FinPointFigure extends AbstractScaleFigure { final Rectangle2D.Double selectedPointHighlight = new Rectangle2D.Double(c.x - selBoxHalfWidth, c.y - selBoxHalfWidth, selBoxWidth, selBoxWidth); // switch to the highlight color - g2.setColor(SELECTED_POINT_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointSelectedPointColor()); g2.draw(selectedPointHighlight); // reset to the normal color - g2.setColor(POINT_COLOR); + g2.setColor(GUIUtil.getUITheme().getFinPointPointColor()); } // normal boxes diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index df1ebb08d..22f4d8d67 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -17,6 +17,7 @@ import java.awt.geom.Rectangle2D; import java.util.*; import java.util.Map.Entry; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.ParallelStage; import net.sf.openrocket.rocketcomponent.PodSet; @@ -257,7 +258,7 @@ public class RocketFigure extends AbstractScaleFigure { // Set component color and line style net.sf.openrocket.util.Color color = rcs.color; if (color == null) { - color = Application.getPreferences().getDefaultColor(c.getClass()); + color = ((SwingPreferences) Application.getPreferences()).getDefaultColor(c.getClass()); } g2.setColor(ColorConversion.toAwtColor(color)); @@ -290,8 +291,8 @@ public class RocketFigure extends AbstractScaleFigure { RenderingHints.VALUE_STROKE_NORMALIZE); // Draw motors - Color fillColor = ((SwingPreferences)Application.getPreferences()).getMotorFillColor(); - Color borderColor = ((SwingPreferences)Application.getPreferences()).getMotorBorderColor(); + Color fillColor = GUIUtil.getUITheme().getMotorFillColor(); + Color borderColor = GUIUtil.getUITheme().getMotorBorderColor(); FlightConfiguration config = rocket.getSelectedConfiguration(); for (MotorConfiguration curInstance : config.getActiveMotors()) { diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index bce0980f0..7cf764261 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -35,6 +35,7 @@ import net.miginfocom.swing.MigLayout; import net.sf.openrocket.aerodynamics.AerodynamicCalculator; import net.sf.openrocket.aerodynamics.BarrowmanCalculator; import net.sf.openrocket.aerodynamics.FlightConditions; +import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.Simulation; @@ -439,8 +440,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change JPanel bottomRow = new JPanel(new MigLayout("fill, gapy 0, ins 0")); //// Click to select    Shift+click to select other    Double-click to edit    Click+drag to move - infoMessage = new JLabel(trans.get("RocketPanel.lbl.infoMessage")); - infoMessage.setFont(new Font("Sans Serif", Font.PLAIN, 9)); + infoMessage = new StyledLabel(trans.get("RocketPanel.lbl.infoMessage"), -3); bottomRow.add(infoMessage); //// Show warnings diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java b/swing/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java index db7ebad82..e30bfe840 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/ScaleScrollPane.java @@ -25,6 +25,7 @@ import javax.swing.event.ChangeListener; import net.sf.openrocket.gui.adaptors.DoubleModel; import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.unit.Tick; import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.UnitGroup; @@ -398,7 +399,7 @@ public class ScaleScrollPane extends JScrollPane } // Set color & hints - g2.setColor(Color.BLACK); + g2.setColor(GUIUtil.getUITheme().getTextColor()); g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); g2.setRenderingHint(RenderingHints.KEY_RENDERING, diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/ScaleSelector.java b/swing/src/net/sf/openrocket/gui/scalefigure/ScaleSelector.java index c216b4f50..27de23c00 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/ScaleSelector.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/ScaleSelector.java @@ -13,7 +13,7 @@ import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.gui.util.Icons; -import net.sf.openrocket.gui.widgets.SelectColorButton; +import net.sf.openrocket.gui.widgets.IconButton; import net.sf.openrocket.util.StateChangeListener; @SuppressWarnings("serial") @@ -41,7 +41,7 @@ public class ScaleSelector { this.scrollPane = scroll; // Zoom out button - zoomOutButton = new SelectColorButton(Icons.ZOOM_OUT); + zoomOutButton = new IconButton(Icons.ZOOM_OUT); zoomOutButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -93,7 +93,7 @@ public class ScaleSelector { }); // Zoom in button - zoomInButton = new SelectColorButton(Icons.ZOOM_IN); + zoomInButton = new IconButton(Icons.ZOOM_IN); zoomInButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java index e105af540..82e49ff9a 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationOptionsPanel.java @@ -207,6 +207,8 @@ class SimulationOptionsPanel extends JPanel { currentExtensions = new JPanel(new MigLayout("fillx, gap 0 0, ins 0")); JScrollPane scroll = new JScrollPane(currentExtensions); + currentExtensions.setBorder(GUIUtil.getUITheme().getBorder()); + scroll.setForeground(GUIUtil.getUITheme().getTextColor()); // &#$%! scroll pane will not honor "growy"... sub.add(scroll, "growx, growy, h 100%"); diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationPlotPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationPlotPanel.java index d926118a9..ac2f98010 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationPlotPanel.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationPlotPanel.java @@ -205,7 +205,7 @@ public class SimulationPlotPanel extends JPanel { //// The data will be plotted in time order even if the X axis type is not time. simPlotPanelDesc = new DescriptionArea("", 2, -2f, false); simPlotPanelDesc.setVisible(false); - simPlotPanelDesc.setForeground(Color.DARK_RED.toAWTColor()); + simPlotPanelDesc.setForeground(GUIUtil.getUITheme().getDarkWarningColor()); simPlotPanelDesc.setViewportBorder(BorderFactory.createEmptyBorder()); this.add(simPlotPanelDesc, "width 1px, growx 1, wrap unrel"); diff --git a/swing/src/net/sf/openrocket/gui/util/BetterListCellRenderer.java b/swing/src/net/sf/openrocket/gui/util/BetterListCellRenderer.java index b8bbdd40f..a91da30c5 100644 --- a/swing/src/net/sf/openrocket/gui/util/BetterListCellRenderer.java +++ b/swing/src/net/sf/openrocket/gui/util/BetterListCellRenderer.java @@ -1,9 +1,9 @@ package net.sf.openrocket.gui.util; + import javax.swing.DefaultListCellRenderer; import javax.swing.JLabel; import javax.swing.JList; -import java.awt.Color; import java.awt.Component; /** @@ -12,6 +12,7 @@ import java.awt.Component; * @author Sibo Van Gool */ public class BetterListCellRenderer extends DefaultListCellRenderer { + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -20,16 +21,16 @@ public class BetterListCellRenderer extends DefaultListCellRenderer { // Alternating row colors if (!isSelected) { if (index % 2 == 0) { - label.setBackground(Color.WHITE); + label.setBackground(GUIUtil.getUITheme().getRowBackgroundDarkerColor()); } else { - label.setBackground(new Color(245, 245, 245)); + label.setBackground(GUIUtil.getUITheme().getRowBackgroundLighterColor()); } } // Text color if (isSelected) { - label.setForeground(Color.WHITE); + label.setForeground(GUIUtil.getUITheme().getTextSelectionForegroundColor()); } else { - label.setForeground(Color.BLACK); + label.setForeground(GUIUtil.getUITheme().getTextColor()); } return label; } diff --git a/swing/src/net/sf/openrocket/gui/util/GUIUtil.java b/swing/src/net/sf/openrocket/gui/util/GUIUtil.java index af1d3d16d..4fac6edd7 100644 --- a/swing/src/net/sf/openrocket/gui/util/GUIUtil.java +++ b/swing/src/net/sf/openrocket/gui/util/GUIUtil.java @@ -64,9 +64,13 @@ import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreeModel; import javax.swing.tree.TreeSelectionModel; +import com.github.weisj.darklaf.LafManager; +import com.github.weisj.darklaf.theme.IntelliJTheme; +import net.sf.openrocket.arch.SystemInfo; import net.sf.openrocket.gui.Resettable; import net.sf.openrocket.logging.Markers; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.startup.Preferences; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Invalidatable; import net.sf.openrocket.util.MemoryManagement; @@ -76,7 +80,7 @@ import org.slf4j.LoggerFactory; public class GUIUtil { private static final Logger log = LoggerFactory.getLogger(GUIUtil.class); - + private static final KeyStroke ESCAPE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); private static final String CLOSE_ACTION_KEY = "escape:WINDOW_CLOSING"; @@ -252,8 +256,24 @@ public class GUIUtil { } }); } + + /** + * Get the current theme used for the UI. + * @return the current theme + */ + public static UITheme.Theme getUITheme() { + Preferences prefs = Application.getPreferences(); + Object theme = prefs.getUITheme(); + if (theme instanceof UITheme.Theme) { + return (UITheme.Theme) theme; + } + return UITheme.Themes.LIGHT; + } - + public static void applyLAF() { + UITheme.Theme theme = getUITheme(); + theme.applyTheme(); + } /** * Set the best available look-and-feel into use. @@ -265,8 +285,13 @@ public class GUIUtil { * other alternatives. */ try { - // Set system L&F - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + // Linux systems often default to a dark mode LAF, so explicitly use light mode + if (SystemInfo.getPlatform() == SystemInfo.Platform.UNIX) { + LafManager.install(new IntelliJTheme()); + } else { + // Set system L&F + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } // Check whether we have an ugly L&F LookAndFeel laf = UIManager.getLookAndFeel(); @@ -295,6 +320,15 @@ public class GUIUtil { } // Set the select foreground for buttons to not be black on a blue background UIManager.put("Button.selectForeground", Color.WHITE); + + // Fix some UI bugs on macOS + if (SystemInfo.getPlatform() == SystemInfo.Platform.MAC_OS) { + // Set the foreground of active tabs to black; there was a bug where you had a white background and white foreground + UIManager.put("TabbedPane.foreground", Color.black); + + // Set the select foreground for buttons to not be black on a blue background + UIManager.put("ToggleButton.selectForeground", Color.WHITE); + } } catch (Exception e) { log.warn("Error setting LAF: " + e); } diff --git a/swing/src/net/sf/openrocket/gui/util/Icons.java b/swing/src/net/sf/openrocket/gui/util/Icons.java index 89f827483..db8fdaa7e 100644 --- a/swing/src/net/sf/openrocket/gui/util/Icons.java +++ b/swing/src/net/sf/openrocket/gui/util/Icons.java @@ -94,13 +94,19 @@ public class Icons { public static final Icon NOT_FAVORITE = loadImageIcon("pix/icons/star_silver.png", "Not favorite"); public static final Icon FAVORITE = loadImageIcon("pix/icons/star_gold.png", "Favorite"); - - public static final Icon CG_OVERRIDE = loadImageIcon("pix/icons/cg-override.png", "CG Override"); - public static final Icon CG_OVERRIDE_SUBCOMPONENT = loadImageIcon("pix/icons/cg-override-subcomponent.png", "CG Override Subcomponent"); - public static final Icon CD_OVERRIDE = loadImageIcon("pix/icons/cd-override.png", "CD Override"); - public static final Icon CD_OVERRIDE_SUBCOMPONENT = loadImageIcon("pix/icons/cd-override-subcomponent.png", "CD Override Subcomponent"); - public static final Icon MASS_OVERRIDE = loadImageIcon("pix/icons/mass-override.png", "Mass Override"); - public static final Icon MASS_OVERRIDE_SUBCOMPONENT = loadImageIcon("pix/icons/mass-override-subcomponent.png", "Mass Override Subcomponent"); + + public static final Icon MASS_OVERRIDE_LIGHT = loadImageIcon("pix/icons/mass-override_light.png", "Mass Override"); + public static final Icon MASS_OVERRIDE_DARK = loadImageIcon("pix/icons/mass-override_dark.png", "Mass Override"); + public static final Icon MASS_OVERRIDE_SUBCOMPONENT_LIGHT = loadImageIcon("pix/icons/mass-override-subcomponent_light.png", "Mass Override Subcomponent"); + public static final Icon MASS_OVERRIDE_SUBCOMPONENT_DARK = loadImageIcon("pix/icons/mass-override-subcomponent_dark.png", "Mass Override Subcomponent"); + public static final Icon CG_OVERRIDE_LIGHT = loadImageIcon("pix/icons/cg-override_light.png", "CG Override"); + public static final Icon CG_OVERRIDE_DARK = loadImageIcon("pix/icons/cg-override_dark.png", "CG Override"); + public static final Icon CG_OVERRIDE_SUBCOMPONENT_LIGHT = loadImageIcon("pix/icons/cg-override-subcomponent_light.png", "CG Override Subcomponent"); + public static final Icon CG_OVERRIDE_SUBCOMPONENT_DARK = loadImageIcon("pix/icons/cg-override-subcomponent_dark.png", "CG Override Subcomponent"); + public static final Icon CD_OVERRIDE_LIGHT = loadImageIcon("pix/icons/cd-override_light.png", "CD Override"); + public static final Icon CD_OVERRIDE_DARK = loadImageIcon("pix/icons/cd-override_dark.png", "CD Override"); + public static final Icon CD_OVERRIDE_SUBCOMPONENT_LIGHT = loadImageIcon("pix/icons/cd-override-subcomponent_light.png", "CD Override Subcomponent"); + public static final Icon CD_OVERRIDE_SUBCOMPONENT_DARK = loadImageIcon("pix/icons/cd-override-subcomponent_dark.png", "CD Override Subcomponent"); // MANUFACTURERS ICONS public static final Icon RASAERO = loadImageIcon("pix/icons/RASAero_16.png", "RASAero Icon"); diff --git a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java index 7e9db6af1..004895c02 100644 --- a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java +++ b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -20,6 +21,17 @@ import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import net.sf.openrocket.communication.AssetHandler.UpdatePlatform; +import net.sf.openrocket.rocketcomponent.BodyComponent; +import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.InternalComponent; +import net.sf.openrocket.rocketcomponent.LaunchLug; +import net.sf.openrocket.rocketcomponent.MassObject; +import net.sf.openrocket.rocketcomponent.ParallelStage; +import net.sf.openrocket.rocketcomponent.PodSet; +import net.sf.openrocket.rocketcomponent.RailButton; +import net.sf.openrocket.rocketcomponent.RecoveryDevice; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.TubeFinSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +58,7 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences { public static final String NODE_WINDOWS = "windows"; public static final String NODE_TABLES = "tables"; + private static final String UI_FONT_SIZE = "UIFontSize"; public static final String UPDATE_PLATFORM = "UpdatePlatform"; private static final List SUPPORTED_LOCALES; @@ -58,6 +71,8 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences { list.add(new Locale("uk", "UA")); SUPPORTED_LOCALES = Collections.unmodifiableList(list); } + + private final HashMap, String> DEFAULT_COLORS = new HashMap<>(); /** @@ -94,8 +109,22 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences { } } PREFNODE = root.node(NODENAME); + fillDefaultComponentColors(); } - + + private void fillDefaultComponentColors() { + DEFAULT_COLORS.put(BodyComponent.class, getUIThemeAsTheme().getDefaultBodyComponentColor()); + DEFAULT_COLORS.put(TubeFinSet.class, getUIThemeAsTheme().getDefaultTubeFinSetColor()); + DEFAULT_COLORS.put(FinSet.class, getUIThemeAsTheme().getDefaultFinSetColor()); + DEFAULT_COLORS.put(LaunchLug.class, getUIThemeAsTheme().getDefaultLaunchLugColor()); + DEFAULT_COLORS.put(RailButton.class, getUIThemeAsTheme().getDefaultRailButtonColor()); + DEFAULT_COLORS.put(InternalComponent.class, getUIThemeAsTheme().getDefaultInternalComponentColor()); + DEFAULT_COLORS.put(MassObject.class, getUIThemeAsTheme().getDefaultMassObjectColor()); + DEFAULT_COLORS.put(RecoveryDevice.class, getUIThemeAsTheme().getDefaultRecoveryDeviceColor()); + DEFAULT_COLORS.put(PodSet.class, getUIThemeAsTheme().getDefaultPodSetColor()); + DEFAULT_COLORS.put(ParallelStage.class, getUIThemeAsTheme().getDefaultParallelStageColor()); + } + public String getNodename() { return NODENAME; } @@ -297,6 +326,82 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences { public static List getSupportedLocales() { return SUPPORTED_LOCALES; } + + /** + * Get the current theme used for the UI. + * @return the current theme + */ + @Override + public Object getUITheme() { + return getUIThemeAsTheme(); + } + + 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 + return UITheme.Themes.valueOf(themeName); + } + + /** + * Set the theme used for the UI. + * @param theme the theme to set + */ + @Override + public void setUITheme(Object theme) { + if (!(theme instanceof UITheme.Theme)) return; + putString(net.sf.openrocket.startup.Preferences.UI_THEME, ((UITheme.Theme) theme).name()); + storeVersion(); + } + + /** + * Get the current font size used for the UI. + * @return the current font size + */ + public int getUIFontSize() { + return getInt(UI_FONT_SIZE, getDefaultFontSize()); + } + + public final float getRocketInfoFontSize() { + return (float) ((getUIFontSize() - 2) + 3 * Application.getPreferences().getChoice(net.sf.openrocket.startup.Preferences.ROCKET_INFO_FONT_SIZE, 2, 0)); + } + + private static int getDefaultFontSize() { + javax.swing.UIDefaults uiDefaults = javax.swing.UIManager.getDefaults(); + Object value = uiDefaults.get("defaultFont"); + if (value instanceof javax.swing.plaf.FontUIResource fontUIResource) { + return fontUIResource.getSize(); + } else { + return 12; + } + } + + /** + * Set the font size used for the UI. + * @param size the font size to set + */ + public void setUIFontSize(int size) { + putInt(UI_FONT_SIZE, size); + storeVersion(); + } + + public net.sf.openrocket.util.Color getDefaultColor(Class c) { + String color = get("componentColors", c, DEFAULT_COLORS); + if (color == null) + return net.sf.openrocket.util.Color.fromAWTColor(getUIThemeAsTheme().getTextColor()); + + net.sf.openrocket.util.Color clr = parseColor(color); + if (clr != null) { + return clr; + } else { + return net.sf.openrocket.util.Color.fromAWTColor(getUIThemeAsTheme().getTextColor()); + } + } + + public final void setDefaultColor(Class c, net.sf.openrocket.util.Color color) { + if (color == null) + return; + putString("componentColors", c.getSimpleName(), stringifyColor(color)); + } public File getDefaultDirectory() { String file = getString(net.sf.openrocket.startup.Preferences.DEFAULT_DIRECTORY, null); @@ -432,18 +537,6 @@ public class SwingPreferences extends net.sf.openrocket.startup.Preferences { putString(USER_THRUST_CURVES_KEY, str); } - public Color getMotorBorderColor() { - // TODO: MEDIUM: Motor color (settable?) - return new Color(0, 0, 0, 200); - } - - - public Color getMotorFillColor() { - // TODO: MEDIUM: Motor fill color (settable?) - return new Color(0, 0, 0, 100); - } - - public static int getMaxThreadCount() { return Runtime.getRuntime().availableProcessors(); } diff --git a/swing/src/net/sf/openrocket/gui/util/UITheme.java b/swing/src/net/sf/openrocket/gui/util/UITheme.java new file mode 100644 index 000000000..43805d870 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/util/UITheme.java @@ -0,0 +1,572 @@ +package net.sf.openrocket.gui.util; + +import com.github.weisj.darklaf.LafManager; +import com.github.weisj.darklaf.theme.DarculaTheme; +import net.sf.openrocket.l10n.Translator; +import net.sf.openrocket.startup.Application; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.UIManager; +import javax.swing.border.Border; +import java.awt.Color; +import java.awt.Font; +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +public class UITheme { + private static final Translator trans = Application.getTranslator(); + private static final Logger log = LoggerFactory.getLogger(UITheme.class); + + public interface Theme { + void applyTheme(); + String name(); // Provided by enum, gives the name of the enum constant + String getDisplayName(); + Color getBackgroundColor(); + Color getBorderColor(); + Color getTextColor(); + Color getDimTextColor(); + Color getTextSelectionForegroundColor(); + Color getTextSelectionBackgroundColor(); + Color getWarningColor(); + Color getDarkWarningColor(); + Color getRowBackgroundLighterColor(); + Color getRowBackgroundDarkerColor(); + Color getFlightDataTextActiveColor(); + Color getFlightDataTextInactiveColor(); + + // Component colors + String getDefaultBodyComponentColor(); + String getDefaultTubeFinSetColor(); + String getDefaultFinSetColor(); + String getDefaultLaunchLugColor(); + String getDefaultRailButtonColor(); + String getDefaultInternalComponentColor(); + String getDefaultMassObjectColor(); + String getDefaultRecoveryDeviceColor(); + String getDefaultPodSetColor(); + String getDefaultParallelStageColor(); + + Color getMotorBorderColor(); + Color getMotorFillColor(); + + Color getCGColor(); + Color getCPColor(); + + Color getURLColor(); + + Color getComponentTreeBackgroundColor(); + Color getComponentTreeForegroundColor(); + + Color getFinPointGridMajorLineColor(); + Color getFinPointGridMinorLineColor(); + Color getFinPointPointColor(); + Color getFinPointSelectedPointColor(); + Color getFinPointBodyLineColor(); + + Icon getMassOverrideIcon(); + Icon getMassOverrideSubcomponentIcon(); + Icon getCGOverrideIcon(); + Icon getCGOverrideSubcomponentIcon(); + Icon getCDOverrideIcon(); + Icon getCDOverrideSubcomponentIcon(); + + Border getBorder(); + + void formatScriptTextArea(RSyntaxTextArea textArea); + } + + public enum Themes implements Theme { + LIGHT { + private final String displayName = trans.get("UITheme.Light"); + + @Override + public void applyTheme() { + final SwingPreferences prefs = (SwingPreferences) Application.getPreferences(); + + GUIUtil.setBestLAF(); + setGlobalFontSize(prefs.getUIFontSize()); + } + + @Override + public String getDisplayName() { + return displayName; + } + + @Override + public Color getBackgroundColor() { + return Color.WHITE; + } + + @Override + public Color getBorderColor() { + return Color.BLACK; + } + + @Override + public Color getTextColor() { + return Color.BLACK; + } + + @Override + public Color getDimTextColor() { + return Color.GRAY; + } + + @Override + public Color getTextSelectionForegroundColor() { + return UIManager.getColor("Tree.selectionForeground"); + } + + @Override + public Color getTextSelectionBackgroundColor() { + return UIManager.getColor("Tree.selectionBackground"); + } + + @Override + public Color getWarningColor() { + return Color.RED; + } + + @Override + public Color getDarkWarningColor() { + return new Color(200,0,0); + } + + @Override + public Color getRowBackgroundLighterColor() { + return Color.WHITE; + } + + @Override + public Color getRowBackgroundDarkerColor() { + return new Color(245, 245, 245); + } + + @Override + public Color getFlightDataTextActiveColor() { + return new Color(0,0,127); + } + + @Override + public Color getFlightDataTextInactiveColor() { + return new Color(0,0,127,127); + } + + @Override + public String getDefaultBodyComponentColor() { + return "0,0,240"; + } + @Override + public String getDefaultTubeFinSetColor() { + return "0,0,200"; + } + @Override + public String getDefaultFinSetColor() { + return "0,0,200"; + } + @Override + public String getDefaultLaunchLugColor() { + return "0,0,180"; + } + @Override + public String getDefaultRailButtonColor() { + return "0,0,180"; + } + @Override + public String getDefaultInternalComponentColor() { + return "170,0,100"; + } + @Override + public String getDefaultMassObjectColor() { + return "0,0,0"; + } + @Override + public String getDefaultRecoveryDeviceColor() { + return "255,0,0"; + } + @Override + public String getDefaultPodSetColor() { + return "160,160,215"; + } + @Override + public String getDefaultParallelStageColor() { + return "198,163,184"; + } + + @Override + public Color getMotorBorderColor() { + return new Color(0, 0, 0, 200); + } + + @Override + public Color getMotorFillColor() { + return new Color(0, 0, 0, 100); + } + + @Override + public Color getCGColor() { + return Color.BLUE; + } + + @Override + public Color getCPColor() { + return Color.RED; + } + + @Override + public Color getURLColor() { + return Color.BLUE; + } + + @Override + public Color getComponentTreeBackgroundColor() { + return UIManager.getColor("Tree.textBackground"); + } + + @Override + public Color getComponentTreeForegroundColor() { + return UIManager.getColor("Tree.textForeground"); + } + + @Override + public Color getFinPointGridMajorLineColor() { + return new Color( 0, 0, 255, 80); + } + + @Override + public Color getFinPointGridMinorLineColor() { + return new Color( 0, 0, 255, 30); + } + + @Override + public Color getFinPointPointColor() { + return new Color(200, 0, 0, 255); + } + + @Override + public Color getFinPointSelectedPointColor() { + return new Color(200, 0, 0, 255); + } + + @Override + public Color getFinPointBodyLineColor() { + return Color.BLACK; + } + + @Override + public Icon getMassOverrideIcon() { + return Icons.MASS_OVERRIDE_LIGHT; + } + + @Override + public Icon getMassOverrideSubcomponentIcon() { + return Icons.MASS_OVERRIDE_SUBCOMPONENT_LIGHT; + } + + @Override + public Icon getCGOverrideIcon() { + return Icons.CG_OVERRIDE_LIGHT; + } + + @Override + public Icon getCGOverrideSubcomponentIcon() { + return Icons.CG_OVERRIDE_SUBCOMPONENT_LIGHT; + } + + @Override + public Icon getCDOverrideIcon() { + return Icons.CD_OVERRIDE_LIGHT; + } + + @Override + public Icon getCDOverrideSubcomponentIcon() { + return Icons.CD_OVERRIDE_SUBCOMPONENT_LIGHT; + } + + @Override + public Border getBorder() { + return null; + } + + @Override + public void formatScriptTextArea(RSyntaxTextArea textArea) { + try { + org.fife.ui.rsyntaxtextarea.Theme theme = org.fife.ui.rsyntaxtextarea.Theme.load(getClass().getResourceAsStream( + "/org/fife/ui/rsyntaxtextarea/themes/default.xml")); + theme.apply(textArea); + textArea.setCurrentLineHighlightColor(new Color(255, 255, 230)); + } catch (IOException ioe) { + log.warn("Unable to load RSyntaxTextArea theme", ioe); + } + } + }, + DARK { + private final String displayName = trans.get("UITheme.Dark"); + @Override + public void applyTheme() { + final SwingPreferences prefs = (SwingPreferences) Application.getPreferences(); + + LafManager.install(new DarculaTheme()); + setGlobalFontSize(prefs.getUIFontSize()); + } + + @Override + public String getDisplayName() { + return displayName; + } + + @Override + public Color getBackgroundColor() { + return new Color(73, 76, 79); + } + + @Override + public Color getBorderColor() { + return new Color(97, 99, 101); + } + + @Override + public Color getTextColor() { + return UIManager.getColor("Label.foreground"); + } + + @Override + public Color getDimTextColor() { + return new Color(162, 162, 162); + } + + @Override + public Color getTextSelectionForegroundColor() { + return Color.WHITE; + } + + @Override + public Color getTextSelectionBackgroundColor() { + return new Color(75, 110, 175); + } + + @Override + public Color getWarningColor() { + return new Color(246, 143, 143); + } + + @Override + public Color getDarkWarningColor() { + return new Color(229, 103, 103); + } + + @Override + public Color getRowBackgroundLighterColor() { + return new Color(65, 69, 71); + } + + @Override + public Color getRowBackgroundDarkerColor() { + return new Color(60, 63, 65); + } + + @Override + public Color getFlightDataTextActiveColor() { + return new Color(145, 183, 231); + } + + @Override + public Color getFlightDataTextInactiveColor() { + return new Color(128, 166, 230, 127); + } + + @Override + public String getDefaultBodyComponentColor() { + return "150,162,255"; + } + @Override + public String getDefaultTubeFinSetColor() { + return "150,178,255"; + } + @Override + public String getDefaultFinSetColor() { + return "150,178,255"; + } + @Override + public String getDefaultLaunchLugColor() { + return "142,153,238"; + } + @Override + public String getDefaultRailButtonColor() { + return "142,153,238"; + } + @Override + public String getDefaultInternalComponentColor() { + return "181,128,151"; + } + @Override + public String getDefaultMassObjectColor() { + return "210,210,210"; + } + @Override + public String getDefaultRecoveryDeviceColor() { + return "220,90,90"; + } + @Override + public String getDefaultPodSetColor() { + return "190,190,235"; + } + @Override + public String getDefaultParallelStageColor() { + return "210,180,195"; + } + + @Override + public Color getMotorBorderColor() { + return new Color(0, 0, 0, 100); + } + + @Override + public Color getMotorFillColor() { + return new Color(0, 0, 0, 50); + } + + @Override + public Color getCGColor() { + return new Color(85, 133, 253); + } + + @Override + public Color getCPColor() { + return new Color(255, 72, 106); + } + + @Override + public Color getURLColor() { + return new Color(150, 167, 255); + } + + @Override + public Color getComponentTreeBackgroundColor() { + return getBackgroundColor(); + } + + @Override + public Color getComponentTreeForegroundColor() { + return getTextColor(); + } + + @Override + public Color getFinPointGridMajorLineColor() { + return new Color(135, 135, 199, 197); + } + + @Override + public Color getFinPointGridMinorLineColor() { + return new Color(121, 121, 189, 69); + } + + @Override + public Color getFinPointPointColor() { + return new Color(217, 108, 108, 255); + } + + @Override + public Color getFinPointSelectedPointColor() { + return new Color(232, 78, 78, 255); + } + + @Override + public Color getFinPointBodyLineColor() { + return Color.WHITE; + } + + @Override + public Icon getMassOverrideIcon() { + return Icons.MASS_OVERRIDE_DARK; + } + + @Override + public Icon getMassOverrideSubcomponentIcon() { + return Icons.MASS_OVERRIDE_SUBCOMPONENT_DARK; + } + + @Override + public Icon getCGOverrideIcon() { + return Icons.CG_OVERRIDE_DARK; + } + + @Override + public Icon getCGOverrideSubcomponentIcon() { + return Icons.CG_OVERRIDE_SUBCOMPONENT_DARK; + } + + @Override + public Icon getCDOverrideIcon() { + return Icons.CD_OVERRIDE_DARK; + } + + @Override + public Icon getCDOverrideSubcomponentIcon() { + return Icons.CD_OVERRIDE_SUBCOMPONENT_DARK; + } + + @Override + public Border getBorder() { + return BorderFactory.createLineBorder(getBorderColor()); + } + + @Override + public void formatScriptTextArea(RSyntaxTextArea textArea) { + try { + org.fife.ui.rsyntaxtextarea.Theme theme = org.fife.ui.rsyntaxtextarea.Theme.load(getClass().getResourceAsStream( + "/org/fife/ui/rsyntaxtextarea/themes/dark.xml")); + theme.apply(textArea); + } catch (IOException ioe) { + log.warn("Unable to load RSyntaxTextArea theme", ioe); + } + } + } + } + + private static void setGlobalFontSize(int size) { + // Some fonts have different sizes for different components, so we need to adjust them + final Map fontOffsets = new HashMap<>(); + fontOffsets.put("MenuBar.font", 1f); + fontOffsets.put("Tree.font", -1f); + fontOffsets.put("Slider.font", -2f); + fontOffsets.put("TableHeader.font", -2f); + fontOffsets.put("ColorChooser.font", -1f); + fontOffsets.put("Menu.acceleratorFont", 1f); + fontOffsets.put("InternalFrame.optionDialogTitleFont", 1f); + fontOffsets.put("InternalFrame.paletteTitleFont", 1f); + fontOffsets.put("MenuItem.font", 1f); + fontOffsets.put("PopupMenu.font", 1f); + fontOffsets.put("MenuItem.acceleratorFont", 1f); + fontOffsets.put("RadioButtonMenuItem.font", 1f); + fontOffsets.put("Table.font", -1f); + //fontOffsets.put("IconButton.font", -2f); // The default doesn't really look nice, we want the normal font size instead + fontOffsets.put("InternalFrame.titleFont", 1f); + fontOffsets.put("List.font", -1f); + fontOffsets.put("RadioButtonMenuItem.acceleratorFont", 1f); + fontOffsets.put("CheckBoxMenuItem.acceleratorFont", 1f); + fontOffsets.put("Menu.font", 1f); + fontOffsets.put("TabbedPane.smallFont", -2f); + fontOffsets.put("CheckBoxMenuItem.font", 1f); + fontOffsets.put("ToolTip.font", -2f); + + // Iterate over all keys in the UIManager defaults and set the font + for (Enumeration keys = UIManager.getDefaults().keys(); keys.hasMoreElements();) { + Object key = keys.nextElement(); + Object value = UIManager.get(key); + if (value instanceof Font) { + Font newFont = (Font) value; + float offset = fontOffsets.getOrDefault(key.toString(), 0f); + newFont = newFont.deriveFont(Integer.valueOf(size).floatValue() + offset); + UIManager.put(key, newFont); + } + } + } + +} diff --git a/swing/src/net/sf/openrocket/gui/widgets/SelectColorButton.java b/swing/src/net/sf/openrocket/gui/widgets/SelectColorButton.java index c9229887c..db7b4d4d9 100644 --- a/swing/src/net/sf/openrocket/gui/widgets/SelectColorButton.java +++ b/swing/src/net/sf/openrocket/gui/widgets/SelectColorButton.java @@ -1,5 +1,7 @@ package net.sf.openrocket.gui.widgets; +import net.sf.openrocket.gui.util.GUIUtil; +import net.sf.openrocket.gui.util.UITheme; import javax.swing.Action; import javax.swing.Icon; @@ -7,11 +9,11 @@ import javax.swing.JButton; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.Graphics; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; public class SelectColorButton extends JButton { + public SelectColorButton() { addChangeListenerSelectColor(); } @@ -37,8 +39,9 @@ public class SelectColorButton extends JButton { } private void addChangeListenerSelectColor() { - if (UIManager.getColor("Button.selectForeground") == null - || UIManager.getColor("Button.foreground") == null) + if ((GUIUtil.getUITheme() != UITheme.Themes.LIGHT) || + (UIManager.getColor("Button.selectForeground") == null) || + (UIManager.getColor("Button.foreground") == null)) return; // Fixes the issue of the background of the button not being blue when selected on macOS diff --git a/swing/src/net/sf/openrocket/gui/widgets/SelectColorToggleButton.java b/swing/src/net/sf/openrocket/gui/widgets/SelectColorToggleButton.java index 8ed0873b0..a29355f26 100644 --- a/swing/src/net/sf/openrocket/gui/widgets/SelectColorToggleButton.java +++ b/swing/src/net/sf/openrocket/gui/widgets/SelectColorToggleButton.java @@ -1,5 +1,8 @@ package net.sf.openrocket.gui.widgets; +import net.sf.openrocket.gui.util.GUIUtil; +import net.sf.openrocket.gui.util.UITheme; + import javax.swing.JToggleButton; import javax.swing.Action; import javax.swing.Icon; @@ -14,6 +17,7 @@ import java.beans.PropertyChangeListener; * @author Sibo Van Gool */ public class SelectColorToggleButton extends JToggleButton { + public SelectColorToggleButton(Action a) { super(a); addChangeListenerSelectColor(); @@ -60,8 +64,9 @@ public class SelectColorToggleButton extends JToggleButton { * This is to fix an issue on OSX devices where the foreground color would be black on blue (hardly readable) */ private void addChangeListenerSelectColor() { - if (UIManager.getColor("ToggleButton.selectForeground") == null - || UIManager.getColor("ToggleButton.foreground") == null) + if ((GUIUtil.getUITheme() != UITheme.Themes.LIGHT) || + (UIManager.getColor("ToggleButton.selectForeground") == null) || + (UIManager.getColor("ToggleButton.foreground") == null)) return; // Fixes the issue of the background of the button not being blue when selected on macOS diff --git a/swing/src/net/sf/openrocket/simulation/extension/impl/JavaCodeConfigurator.java b/swing/src/net/sf/openrocket/simulation/extension/impl/JavaCodeConfigurator.java index ba9fe43b6..eea237e11 100644 --- a/swing/src/net/sf/openrocket/simulation/extension/impl/JavaCodeConfigurator.java +++ b/swing/src/net/sf/openrocket/simulation/extension/impl/JavaCodeConfigurator.java @@ -9,11 +9,11 @@ import javax.swing.event.DocumentListener; import net.sf.openrocket.document.Simulation; import net.sf.openrocket.gui.components.StyledLabel; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.plugin.Plugin; import net.sf.openrocket.simulation.extension.AbstractSwingSimulationExtensionConfigurator; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.util.Color; @Plugin public class JavaCodeConfigurator extends AbstractSwingSimulationExtensionConfigurator { @@ -35,7 +35,7 @@ public class JavaCodeConfigurator extends AbstractSwingSimulationExtensionConfig classNameField = new JTextField(extension.getClassName()); panel.add(classNameField, "growx, wrap"); this.errorMsg = new StyledLabel(); - errorMsg.setFontColor(Color.DARK_RED.toAWTColor()); + errorMsg.setFontColor(GUIUtil.getUITheme().getDarkWarningColor()); errorMsg.setVisible(false); panel.add(errorMsg, "growx, wrap"); diff --git a/swing/src/net/sf/openrocket/simulation/extension/impl/ScriptingConfigurator.java b/swing/src/net/sf/openrocket/simulation/extension/impl/ScriptingConfigurator.java index 178d15cca..a49a47b75 100644 --- a/swing/src/net/sf/openrocket/simulation/extension/impl/ScriptingConfigurator.java +++ b/swing/src/net/sf/openrocket/simulation/extension/impl/ScriptingConfigurator.java @@ -19,6 +19,7 @@ import net.sf.openrocket.document.Simulation; import net.sf.openrocket.gui.adaptors.BooleanModel; import net.sf.openrocket.gui.components.StyledLabel; import net.sf.openrocket.gui.components.StyledLabel.Style; +import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.plugin.Plugin; import net.sf.openrocket.simulation.extension.AbstractSwingSimulationExtensionConfigurator; import net.sf.openrocket.gui.widgets.SelectColorButton; @@ -41,7 +42,7 @@ public class ScriptingConfigurator extends AbstractSwingSimulationExtensionConfi private ScriptingExtension extension; private Simulation simulation; - + public ScriptingConfigurator() { super(ScriptingExtension.class); } @@ -70,7 +71,7 @@ public class ScriptingConfigurator extends AbstractSwingSimulationExtensionConfi text.setLineWrap(true); text.setWrapStyleWord(true); text.setEditable(true); - text.setCurrentLineHighlightColor(new Color(255, 255, 230)); + GUIUtil.getUITheme().formatScriptTextArea(text); text.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent event) { diff --git a/swing/src/net/sf/openrocket/startup/OSXSetup.java b/swing/src/net/sf/openrocket/startup/OSXSetup.java index d2c14140e..cd78b53b9 100644 --- a/swing/src/net/sf/openrocket/startup/OSXSetup.java +++ b/swing/src/net/sf/openrocket/startup/OSXSetup.java @@ -9,8 +9,6 @@ import java.awt.desktop.AppReopenedListener; import java.io.File; import net.sf.openrocket.communication.UpdateInfoRetriever; -import net.sf.openrocket.gui.main.MRUDesignFile; -import net.sf.openrocket.gui.util.DummyFrameMenuOSX; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,7 +18,6 @@ import net.sf.openrocket.gui.dialogs.AboutDialog; import net.sf.openrocket.gui.dialogs.preferences.PreferencesDialog; import net.sf.openrocket.gui.main.BasicFrame; -import javax.swing.*; /** * Static code for initialization of OSX UI Elements: Menu, Icon, Name and @@ -117,12 +114,6 @@ final class OSXSetup { final Taskbar osxTaskbar = Taskbar.getTaskbar(); osxTaskbar.setIconImage(dockIcon); - // Set the foreground of active tabs to black; there was a bug where you had a white background and white foreground - UIManager.put("TabbedPane.foreground", Color.black); - - // Set the select foreground for buttons to not be black on a blue background - UIManager.put("ToggleButton.selectForeground", Color.WHITE); - } catch (final Throwable t) { // None of the preceding is critical to the app, // so at worst case log an error and continue diff --git a/swing/src/net/sf/openrocket/startup/SwingStartup.java b/swing/src/net/sf/openrocket/startup/SwingStartup.java index 3ee7c32f9..35763cddc 100644 --- a/swing/src/net/sf/openrocket/startup/SwingStartup.java +++ b/swing/src/net/sf/openrocket/startup/SwingStartup.java @@ -29,6 +29,7 @@ import net.sf.openrocket.gui.main.Splash; import net.sf.openrocket.gui.main.SwingExceptionHandler; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.SwingPreferences; +import net.sf.openrocket.gui.util.UITheme; import net.sf.openrocket.logging.LoggingSystemSetup; import net.sf.openrocket.logging.PrintStreamToSLF4J; import net.sf.openrocket.plugin.PluginModule; @@ -198,9 +199,15 @@ public class SwingStartup { // Start update info fetching final UpdateInfoRetriever updateRetriever = startUpdateChecker(); - // Set the best available look-and-feel - log.info("Setting best LAF"); - GUIUtil.setBestLAF(); + // Set the look-and-feel + log.info("Setting LAF"); + String cmdLAF = System.getProperty("openrocket.laf"); + if (cmdLAF != null) { + log.info("Setting cmd line LAF '{}'", cmdLAF); + Preferences prefs = Application.getPreferences(); + prefs.setUITheme(UITheme.Themes.valueOf(cmdLAF)); + } + GUIUtil.applyLAF(); // Set tooltip delay time. Tooltips are used in MotorChooserDialog extensively. ToolTipManager.sharedInstance().setDismissDelay(30000);