diff --git a/app/build.gradle b/app/build.gradle index 462b05e48..22b088f3e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -79,6 +79,7 @@ dependencies { api 'io.xpipe:modulefs:0.1.8' api 'net.synedra:validatorfx:0.4.2' api files("$rootDir/gradle/gradle_scripts/atlantafx-base-2.0.2.jar") + api("com.dlsc.atlantafx:themes:1.9.0") api("org.int4.fx:fx-values:0.4") api files("$rootDir/gradle/gradle_scripts/fx-builders-1.0.0-SNAPSHOT.jar") diff --git a/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java b/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java index 942815801..e61c93170 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/AppMainWindowContentComp.java @@ -12,6 +12,7 @@ import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.util.GlobalTimer; import javafx.animation.*; +import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleIntegerProperty; @@ -51,10 +52,16 @@ public class AppMainWindowContentComp extends SimpleRegionBuilder { AppPrefs.get() != null && AppPrefs.get().theme().getValue().isDark(); loadingIcon.setOpacity(dark ? 0.95 : 0.93); - var color = AppPrefs.get() != null - ? ColorHelper.withOpacity( - AppPrefs.get().theme().getValue().getEmphasisColor().get(), dark ? 0.7 : 0.85) - : Color.TRANSPARENT; + Color color; + if (AppPrefs.get() != null) { + var baseColor = AppPrefs.get().theme().getValue().getEmphasisColor().get(); + if (baseColor == null) { + baseColor = Platform.getPreferences().getAccentColor(); + } + color = ColorHelper.withOpacity(baseColor, dark ? 0.7 : 0.85); + } else { + color = Color.TRANSPARENT; + } DropShadow shadow = new DropShadow(); shadow.setRadius(10); shadow.setColor(color); diff --git a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java index f642a1edb..22fcb88b7 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java @@ -167,31 +167,6 @@ public class SideMenuBarComp extends RegionBuilder { }); }); - var selectedBorder = Bindings.createObjectBinding( - () -> { - var c = Platform.getPreferences() - .getAccentColor() - .desaturate() - .desaturate(); - return new Background(new BackgroundFill(c, new CornerRadii(8), new Insets(17, 1, 15, 2))); - }, - Platform.getPreferences().accentColorProperty()); - var hoverBorder = Bindings.createObjectBinding( - () -> { - var c = Platform.getPreferences() - .getAccentColor() - .darker() - .desaturate() - .desaturate(); - return new Background(new BackgroundFill(c, new CornerRadii(8), new Insets(17, 1, 15, 2))); - }, - Platform.getPreferences().accentColorProperty()); - var noneBorder = Bindings.createObjectBinding( - () -> { - return Background.fill(Color.TRANSPARENT); - }, - Platform.getPreferences().accentColorProperty()); - var indicator = RegionBuilder.empty().style("indicator"); var stack = new StackComp(List.of(indicator, b)).apply(struc -> struc.setAlignment(Pos.CENTER_RIGHT)); stack.apply(struc -> { @@ -199,26 +174,12 @@ public class SideMenuBarComp extends RegionBuilder { var buttonRegion = (Region) struc.getChildren().get(1); indicatorRegion.setMaxWidth(7); indicatorRegion.prefHeightProperty().bind(buttonRegion.heightProperty()); - indicatorRegion - .backgroundProperty() - .bind(Bindings.createObjectBinding( - () -> { - if (struc.isHover()) { - return hoverBorder.get(); - } - - if (highlight || value.getValue().equals(e)) { - return selectedBorder.get(); - } - - return noneBorder.get(); - }, - struc.hoverProperty(), - value, - hoverBorder, - selectedBorder, - noneBorder)); + value.subscribe(entry -> { + var s = entry == e || highlight; + struc.pseudoClassStateChanged(selected, s); + }); }); + stack.style("sidebar-button"); return stack; } } diff --git a/app/src/main/java/io/xpipe/app/core/AppTheme.java b/app/src/main/java/io/xpipe/app/core/AppTheme.java index f32417ae6..16a67c614 100644 --- a/app/src/main/java/io/xpipe/app/core/AppTheme.java +++ b/app/src/main/java/io/xpipe/app/core/AppTheme.java @@ -1,5 +1,9 @@ package io.xpipe.app.core; +import com.dlsc.atlantafx.themes.FallDark; +import com.dlsc.atlantafx.themes.FallLight; +import com.dlsc.atlantafx.themes.SpringDark; +import com.dlsc.atlantafx.themes.WinterDark; import io.xpipe.app.core.window.AppMainWindow; import io.xpipe.app.ext.PrefsChoiceValue; import io.xpipe.app.issue.ErrorEventFactory; @@ -421,6 +425,70 @@ public class AppTheme { 0.2), () -> Platform.getPreferences().getAccentColor(), 6); + public static final Theme SPRING_DARK = new Theme( + "springDark", + "springDark", + new SpringDark(), + () -> AppFontSizes.forOs(AppFontSizes.BASE_11, AppFontSizes.BASE_10_5, AppFontSizes.BASE_11), + Color.web("#0c1a10"), + Color.web("#44a844"), + () -> ColorHelper.withOpacity( + Platform.getPreferences() + .getAccentColor() + .desaturate() + .desaturate() + .darker(), + 0.2), + () -> null, + 4); + public static final Theme FALL_LIGHT = new Theme( + "fallLight", + "fallLight", + new FallLight(), + () -> AppFontSizes.forOs(AppFontSizes.BASE_10_5, AppFontSizes.BASE_10_5, AppFontSizes.BASE_11), + Color.web("#fdf8f0"), + Color.web("#c0a080"), + () -> ColorHelper.withOpacity( + Platform.getPreferences() + .getAccentColor() + .desaturate() + .desaturate() + .darker(), + 0.2), + () -> null, + 4); + public static final Theme FALL_DARK = new Theme( + "fallDark", + "fallDark", + new FallDark(), + () -> AppFontSizes.forOs(AppFontSizes.BASE_11, AppFontSizes.BASE_10_5, AppFontSizes.BASE_11), + Color.web("#1e0c06"), + Color.web("#c88418"), + () -> ColorHelper.withOpacity( + Platform.getPreferences() + .getAccentColor() + .desaturate() + .desaturate() + .darker(), + 0.2), + () -> null, + 4); + public static final Theme WINTER_DARK = new Theme( + "winterDark", + "winterDark", + new WinterDark(), + () -> AppFontSizes.forOs(AppFontSizes.BASE_11, AppFontSizes.BASE_10_5, AppFontSizes.BASE_11), + Color.web("#080c18"), + Color.web("#4488ff"), + () -> ColorHelper.withOpacity( + Platform.getPreferences() + .getAccentColor() + .desaturate() + .desaturate() + .darker(), + 0.2), + () -> null, + 4); public static final Theme MOCHA = new DerivedTheme( "mocha", "mocha", @@ -458,7 +526,7 @@ public class AppTheme { // Also include your custom theme here public static final List ALL = List.of( - PRIMER_LIGHT, PRIMER_DARK, NORD_LIGHT, NORD_DARK, CUPERTINO_LIGHT, CUPERTINO_DARK, DRACULA, MOCHA); + PRIMER_LIGHT, PRIMER_DARK, NORD_LIGHT, NORD_DARK, CUPERTINO_LIGHT, CUPERTINO_DARK, DRACULA, MOCHA, SPRING_DARK, FALL_LIGHT, FALL_DARK, WINTER_DARK); protected final String id; @Getter @@ -512,18 +580,23 @@ public class AppTheme { var s = """ * { -color-context-menu: %s; - -color-accent-fg: %s; - -color-accent-emphasis: %s; - -color-accent-muted: %s; - -color-accent-subtle: %s; } """.formatted( - ColorHelper.toWeb(contextMenuColor.get()), - ColorHelper.toWeb(emphasisColor.get()), - ColorHelper.toWeb(emphasisColor.get().darker()), - ColorHelper.toWeb(emphasisColor.get().desaturate()), - ColorHelper.toWeb(ColorHelper.withOpacity( - emphasisColor.get().darker().desaturate().desaturate(), 0.2))); + ColorHelper.toWeb(contextMenuColor.get())); + var accentColor = emphasisColor.get(); + if (accentColor != null) { + s += """ + * { + -color-accent-fg: %s; + -color-accent-emphasis: %s; + -color-accent-muted: %s; + -color-accent-subtle: %s; + } + """.formatted(ColorHelper.toWeb(accentColor), + ColorHelper.toWeb(accentColor.darker()), + ColorHelper.toWeb(accentColor.desaturate()), + ColorHelper.toWeb(ColorHelper.withOpacity(accentColor.darker().desaturate().desaturate(), 0.2))); + } return s; } diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index f965c0cce..795d0f96a 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -69,6 +69,7 @@ open module io.xpipe.app { requires org.slf4j; requires org.slf4j.jdk.platform.logging; requires atlantafx.base; + requires com.dlsc.atlantafx.themes; requires com.vladsch.flexmark; requires com.fasterxml.jackson.core; requires com.fasterxml.jackson.databind; diff --git a/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css index 057077d87..c33300f3b 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css @@ -35,4 +35,16 @@ .sidebar-comp .icon-button-comp .vbox { -fx-spacing: 0.5em; +} + +.sidebar-comp .sidebar-button:hover .indicator { + -fx-background-radius: 8; + -fx-background-insets: 17 1 15 2; + -fx-background-color: -color-accent-emphasis; +} + +.sidebar-comp .sidebar-button:selected .indicator { + -fx-background-radius: 8; + -fx-background-insets: 17 1 15 2; + -fx-background-color: -color-accent-fg; } \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/fallDark.css b/app/src/main/resources/io/xpipe/app/resources/theme/fallDark.css new file mode 100644 index 000000000..91598d9b3 --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/fallDark.css @@ -0,0 +1,18 @@ +.root:windows { -color-bg-default-transparent: #1e0c06c2; } + +.root:linux { -color-bg-default-transparent: #1e0c06c2; } + +.root:macos { -color-bg-default-transparent: #1e0c06e3; } + +.root .table-view { + -color-cell-bg-odd: derive(-color-bg-subtle, -35%); + -color-cell-bg: derive(-color-bg-subtle, -18%); +} + +.root:dark * { + -color-foreground-base: derive(-color-bg-default-transparent, 9%); +} + +.root:light * { + -color-foreground-base: derive(-color-bg-default-transparent, -3%); +} \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/fallLight.css b/app/src/main/resources/io/xpipe/app/resources/theme/fallLight.css new file mode 100644 index 000000000..21d0c5d68 --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/fallLight.css @@ -0,0 +1,17 @@ +.root:windows { -color-bg-default-transparent: #fdf8f0AF; } + +.root:linux { -color-bg-default-transparent: #fdf8f0AF; } + +.root:macos { -color-bg-default-transparent: #fdf8f0BF; } + +.root .table-view { + -color-cell-bg-odd: derive(-color-bg-subtle, 35%); +} + +.root:dark * { + -color-foreground-base: derive(-color-bg-default-transparent, 13%); +} + +.root:light * { + -color-foreground-base: derive(-color-bg-default-transparent, -3%); +} \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/springDark.css b/app/src/main/resources/io/xpipe/app/resources/theme/springDark.css new file mode 100644 index 000000000..34ef8c41a --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/springDark.css @@ -0,0 +1,18 @@ +.root:windows { -color-bg-default-transparent: #0c1a10c2; } + +.root:linux { -color-bg-default-transparent: #0c1a10c2; } + +.root:macos { -color-bg-default-transparent: #0c1a10e3; } + +.root .table-view { + -color-cell-bg-odd: derive(-color-bg-subtle, -35%); + -color-cell-bg: derive(-color-bg-subtle, -18%); +} + +.root:dark * { + -color-foreground-base: derive(-color-bg-default-transparent, 9%); +} + +.root:light * { + -color-foreground-base: derive(-color-bg-default-transparent, -3%); +} \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/winterDark.css b/app/src/main/resources/io/xpipe/app/resources/theme/winterDark.css new file mode 100644 index 000000000..6ab45ff0e --- /dev/null +++ b/app/src/main/resources/io/xpipe/app/resources/theme/winterDark.css @@ -0,0 +1,18 @@ +.root:windows { -color-bg-default-transparent: #080c18c2; } + +.root:linux { -color-bg-default-transparent: #080c18c2; } + +.root:macos { -color-bg-default-transparent: #080c18e3; } + +.root .table-view { + -color-cell-bg-odd: derive(-color-bg-subtle, -55%); + -color-cell-bg: derive(-color-bg-subtle, -38%); +} + +.root:dark * { + -color-foreground-base: derive(-color-bg-default-transparent, 9%); +} + +.root:light * { + -color-foreground-base: derive(-color-bg-default-transparent, -3%); +} \ No newline at end of file diff --git a/dist/licenses/atlantafx-themes.license b/dist/licenses/atlantafx-themes.license new file mode 100644 index 000000000..994d1fc2a --- /dev/null +++ b/dist/licenses/atlantafx-themes.license @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2022] [mkpaz] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist/licenses/atlantafx-themes.properties b/dist/licenses/atlantafx-themes.properties new file mode 100644 index 000000000..b0da6944b --- /dev/null +++ b/dist/licenses/atlantafx-themes.properties @@ -0,0 +1,4 @@ +name=AtlantaFX themes +version=1.9.0 +license=MIT License +link=https://github.com/dlsc-software-consulting-gmbh/atlantafx-themes \ No newline at end of file