Make themes a first-class concept in JavaFX

Tom Eugelink tbee at tbee.org
Fri May 21 07:12:00 UTC 2021


I've been a proponent of a theme implementation for a long time, even before JavaFX was separated out (had quite a few discussions with Jonathan about it). So this proposal is great!


On 2021-05-21 06:36, Michael Strauß wrote:
> Currently, the two themes shipped with JavaFX (Caspian and Modena) are
> implemented as a set of stylesheets and some internal logic, mostly in
> `PlatformImpl`.
>
> Much of this logic deals with optional features or platform-specific
> theme modifications. Another piece of logic deals with accessibility
> themes: on Windows platforms, both Caspian and Modena have
> high-contrast stylesheets that are added or removed in response to OS
> theme changes.
>
> Apart from the fact that high-contrast detection only works on English
> locales (and there's no simple fix, see JDK-8185447), a major downside
> of this implementation is that it special-cases the built-in themes
> and doesn't offer enough extension points to make it easy for
> developers to create new rich themes.
>
> I think this can be very much improved by making themes a first-class
> citizen in JavaFX, and removing the special handling of the two
> built-in themes. Here's my draft PR of this feature:
> https://github.com/openjdk/jfx/pull/511
>
> This PR adds a new interface in the javafx.application package:
>
> public interface Theme {
>      ObservableList<String> getStylesheets();
>      void platformThemeChanged(Map<String, String> properties);
> }
>
> An implementation of this interface populates the list returned by
> `Theme.getStylesheets()` with its collection of stylesheets.
> Optionally, it can listen to the platform theme properties reported by
> `Theme.platformThemeChanged(...)` and modify its list of stylesheets
> accordingly.
>
> Platform properties are platform-specific key-value pairs, and theme
> implementations are responsible for interpreting the values. For
> example, on the Windows platform, a theme implementation might listen
> to the "Windows.SPI_HighContrastOn" property in order to detect
> whether or not a high-contrast stylesheet should be used. The `Theme`
> class documents all currently supported platform properties.
>
> A theme is activated by setting it as the user-agent stylesheet of the
> application, where "theme:" is a custom URI scheme:
>      Application.setUserAgentStylesheet("theme:com.example.CustomTheme");
>
> The existing constants `Application.STYLESHEET_CASPIAN` and
> `Application.STYLESHEET_MODENA` are simply redefined to their new
> `Theme` implementations
> ("theme:com.sun.javafx.application.theme.Caspian" and
> "theme:com.sun.javafx.application.theme.Modena").
>
> Because theme-specific code is now located in its corresponding
> `Theme` class, I've been able to clean up `PlatformImpl` so that it
> doesn't special-case the built-in themes anymore.
>
> Going forward: If we add support for loading stylesheets from
> data-URIs (similar to https://github.com/openjdk/jfx/pull/508), we can
> then fix the high-contrast themes by reading the system colors
> reported back by Windows, and creating an in-memory stylesheet for
> these colors within the `Modena` implementation.
>
> This feature will also allow developers to create themes that
> dynamically adjust to OS-level accent colors or dark mode settings.
> For example, a `Theme` implementation can detect dark mode on Windows
> 10 by listening to the
> "Windows.UI.ViewManagement.UISettings.ColorValue_Background" and
> "Windows.UI.ViewManagement.UISettings.ColorValue_Foreground"
> properties.
>
> I'm looking forward to any opinions on this.




More information about the openjfx-dev mailing list