Rely on javafx to change color theme

This commit is contained in:
Armin Schrenk
2026-02-09 17:48:23 +01:00
parent 4cf11cf293
commit c6717bd4e1
3 changed files with 84 additions and 0 deletions

View File

@@ -14,11 +14,13 @@ import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import org.cryptomator.logging.LogbackConfiguratorFactory;
import org.cryptomator.networking.SSLContextProvider;
import org.cryptomator.networking.SSLContextWithMacKeychain;
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
import org.cryptomator.ui.fxapp.JfxUiAppearanceProvider;
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
open module org.cryptomator.desktop {
@@ -61,6 +63,7 @@ open module org.cryptomator.desktop {
uses SSLContextProvider;
uses org.cryptomator.event.NotificationHandler;
provides UiAppearanceProvider with JfxUiAppearanceProvider;
provides TrayMenuController with AwtTrayMenuController;
provides Configurator with LogbackConfiguratorFactory;
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;

View File

@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
@@ -36,6 +37,11 @@ public class FxApplicationStyle {
}
public void initialize() {
appearanceProvider.ifPresent(service -> {
if(service instanceof JfxUiAppearanceProvider fxService) {
fxService.setJavaFXPlatform(Platform.getPreferences());
}
});
settings.theme.addListener(this::appThemeChanged);
loadSelectedStyleSheet(settings.theme.get());
}

View File

@@ -0,0 +1,75 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.integrations.common.DisplayName;
import org.cryptomator.integrations.common.OperatingSystem;
import org.cryptomator.integrations.common.Priority;
import org.cryptomator.integrations.uiappearance.Theme;
import org.cryptomator.integrations.uiappearance.UiAppearanceException;
import org.cryptomator.integrations.uiappearance.UiAppearanceListener;
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
import javafx.application.ColorScheme;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
@DisplayName("JavaFX Color Scheme switcher")
@OperatingSystem(OperatingSystem.Value.LINUX)
@OperatingSystem(OperatingSystem.Value.WINDOWS)
@OperatingSystem(OperatingSystem.Value.MAC)
@Priority(1050)
public class JfxUiAppearanceProvider implements UiAppearanceProvider {
final ConcurrentHashMap<UiAppearanceListener, ChangeListener<ColorScheme>> uiAppearanceListeners = new ConcurrentHashMap<>();
final AtomicReference<Platform.Preferences> fxPreferencesContainer = new AtomicReference<>();
public void setJavaFXPlatform(Platform.Preferences preferences) {
fxPreferencesContainer.set(preferences);
}
@Override
public Theme getSystemTheme() {
var pref = fxPreferencesContainer.get();
if (pref != null) {
return switch (pref.getColorScheme()) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
}
return Theme.LIGHT;
}
@Override
public void adjustToTheme(Theme theme) {
//no-op
}
@Override
public void addListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var pref = fxPreferencesContainer.get();
if (pref != null) {
var fxChangeListener = (ChangeListener<ColorScheme>) (_, _, newScheme) -> {
var newTheme = switch (newScheme) {
case DARK -> Theme.DARK;
case LIGHT -> Theme.LIGHT;
};
uiAppearanceListener.systemAppearanceChanged(newTheme);
};
uiAppearanceListeners.compute(uiAppearanceListener, (k, v) -> {
pref.colorSchemeProperty().addListener(fxChangeListener);
return fxChangeListener;
});
}
}
@Override
public void removeListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
var pref = fxPreferencesContainer.get();
var fxChangeListener = uiAppearanceListeners.remove(uiAppearanceListener);
if (pref != null && fxChangeListener != null) {
pref.colorSchemeProperty().removeListener(fxChangeListener);
}
}
}