On Wed, 26 May 2021 16:55:04 GMT, Jose Pereda <jper...@openjdk.org> wrote:

>> This PR adds style themes as a first-class concept to OpenJFX. A style theme 
>> is a collection of stylesheets and the logic that governs them. Style themes 
>> can respond to OS notifications and update their stylesheets dynamically. 
>> This PR also re-implements Caspian and Modena as style themes.
>> 
>> ### New APIs in `javafx.graphics`
>> The new theming-related APIs in `javafx.graphics` provide a basic framework 
>> to support application-wide style themes. Higher-level theming concepts (for 
>> example, "dark mode" detection or accent coloring) are not a part of this 
>> basic framework, because any API invented here might soon be out of date. 
>> Implementations can build on top of this framework to add useful 
>> higher-level features.
>> #### 1. StyleTheme
>> A style theme is an implementation of the `javafx.css.StyleTheme` interface:
>> 
>> /**
>>  * {@code StyleTheme} is a collection of stylesheets that specify the 
>> appearance of UI controls and other
>>  * nodes in the application. Like a user-agent stylesheet, a {@code 
>> StyleTheme} is implicitly used by all
>>  * JavaFX nodes in the scene graph.
>>  * <p>
>>  * The list of stylesheets that comprise a {@code StyleTheme} can be 
>> modified while the application is running,
>>  * enabling applications to create dynamic themes that respond to changing 
>> user preferences.
>>  * <p>
>>  * In the CSS subsystem, stylesheets that comprise a {@code StyleTheme} are 
>> classified as
>>  * {@link StyleOrigin#USER_AGENT} stylesheets, but have a higher precedence 
>> in the CSS cascade
>>  * than a stylesheet referenced by {@link 
>> Application#userAgentStylesheetProperty()}.
>>  */
>> public interface StyleTheme {
>>     /**
>>      * Gets the list of stylesheet URLs that comprise this {@code 
>> StyleTheme}.
>>      * <p>
>>      * If the list of stylesheets that comprise this {@code StyleTheme} is 
>> changed at runtime, this
>>      * method must return an {@link ObservableList} to allow the CSS 
>> subsystem to subscribe to list
>>      * change notifications.
>>      *
>>      * @implNote Implementations of this method that return an {@link 
>> ObservableList} are encouraged
>>      *           to minimize the number of subsequent list change 
>> notifications that are fired by the
>>      *           list, as each change notification causes the CSS subsystem 
>> to re-apply the referenced
>>      *           stylesheets.
>>      */
>>     List<String> getStylesheets();
>> }
>> 
>> 
>> A new `styleTheme` property is added to `javafx.application.Application`, 
>> and `userAgentStylesheet` is promoted to a JavaFX property (currently, this 
>> is just a getter/setter pair):
>> 
>> public class Application {
>>     ...
>>     /**
>>      * Specifies the user-agent stylesheet of the application.
>>      * <p>
>>      * A user-agent stylesheet is a global stylesheet that can be specified 
>> in addition to a
>>      * {@link StyleTheme} and that is implicitly used by all JavaFX nodes in 
>> the scene graph.
>>      * It can be used to provide default styling for UI controls and other 
>> nodes.
>>      * A user-agent stylesheets has the lowest precedence in the CSS cascade.
>>      * <p>
>>      * Before JavaFX 20, built-in themes were selectable using the special 
>> user-agent stylesheet constants
>>      * {@link #STYLESHEET_CASPIAN} and {@link #STYLESHEET_MODENA}. For 
>> backwards compatibility, the meaning
>>      * of these special constants is retained: setting the user-agent 
>> stylesheet to either {@code STYLESHEET_CASPIAN}
>>      * or {@code STYLESHEET_MODENA} will also set the value of the {@link 
>> #styleThemeProperty() styleTheme}
>>      * property to a new instance of the corresponding theme class.
>>      * <p>
>>      * Note: this property must only be modified on the JavaFX application 
>> thread.
>>      */
>>     public static StringProperty userAgentStylesheetProperty();
>>     public static String getUserAgentStylesheet();
>>     public static void setUserAgentStylesheet(String url);
>> 
>>     /**
>>      * Specifies the {@link StyleTheme} of the application.
>>      * <p>
>>      * {@code StyleTheme} is a collection of stylesheets that define the 
>> appearance of the application.
>>      * Like a user-agent stylesheet, a {@code StyleTheme} is implicitly used 
>> by all JavaFX nodes in the
>>      * scene graph.
>>      * <p>
>>      * Stylesheets that comprise a {@code StyleTheme} have a higher 
>> precedence in the CSS cascade than a
>>      * stylesheet referenced by the {@link #userAgentStylesheetProperty() 
>> userAgentStylesheet} property.
>>      * <p>
>>      * Note: this property must only be modified on the JavaFX application 
>> thread.
>>      */
>>     public static ObjectProperty<StyleTheme> styleThemeProperty();
>>     public static StyleTheme getStyleTheme();
>>     public static void setStyleTheme(StyleTheme theme);
>>     ...
>> }
>> 
>> 
>> `styleTheme` and `userAgentStylesheet` are correlated to preserve backwards 
>> compatibility: setting `userAgentStylesheet` to the magic values "CASPIAN" 
>> or "MODENA" will implicitly set `styleTheme` to a new instance of the 
>> `CaspianTheme` or `ModenaTheme` class. Aside from these magic values, 
>> `userAgentStylesheet` can be set independently from `styleTheme`. In the CSS 
>> cascade, `userAgentStylesheet` has a lower precedence than `styleTheme`.
>> 
>> #### 2. PlatformPreferences
>> `javafx.application.PlatformPreferences` can be used to query UI-related 
>> information about the current platform to allow theme implementations to 
>> adapt to the operating system. The interface extends `Map` and adds several 
>> useful methods, as well as the option to register a listener for change 
>> notifications:
>> 
>> /**
>>  * Contains UI preferences of the current platform.
>>  * <p>
>>  * {@code PlatformPreferences} implements {@link Map} to expose platform 
>> preferences as key-value pairs.
>>  * For convenience, {@link #getString}, {@link #getBoolean} and {@link 
>> #getColor} are provided as typed
>>  * alternatives to the untyped {@link #get} method.
>>  * <p>
>>  * The preferences that are reported by the platform may be dependent on the 
>> operating system version.
>>  * Applications should always test whether a preference is available, or use 
>> the {@link #getString(String, String)},
>>  * {@link #getBoolean(String, boolean)} or {@link #getColor(String, Color)} 
>> overloads that accept a fallback
>>  * value if the preference is not available.
>>  */
>> public interface PlatformPreferences extends Map<String, Object> {
>>     String getString(String key);
>>     String getString(String key, String fallbackValue);
>> 
>>     Boolean getBoolean(String key);
>>     boolean getBoolean(String key, boolean fallbackValue);
>> 
>>     Color getColor(String key);
>>     Color getColor(String key, Color fallbackValue);
>> 
>>     void addListener(PlatformPreferencesListener listener);
>>     void removeListener(PlatformPreferencesListener listener);
>> }
>> 
>> An instance of `PlatformPreferences` can be retrieved via 
>> `Platform.getPreferences()`.
>> 
>> ### Usage
>> In its simplest form, a style theme is just a static collection of 
>> stylesheets:
>> 
>> Application.setStyleTheme(() -> List.of("stylesheet1.css", 
>> "stylesheet2.css");
>> 
>> A dynamic theme can be created by returning an instance of `ObservableList`:
>> 
>> public class MyCustomTheme implements StyleTheme {
>>     private final ObservableList<String> stylesheets =
>>         FXCollections.observableArrayList("colors-light.css", 
>> "controls.css");
>> 
>>     @Override
>>     public List<String> getStylesheets() {
>>         return stylesheets;
>>     }
>> 
>>     public void setDarkMode(boolean enabled) {
>>         stylesheets.set(0, enabled ? "colors-dark.css" : "colors-light.css");
>>     }
>> }
>> 
>> `CaspianTheme` and `ModenaTheme` can be extended by prepending or appending 
>> additional stylesheets:
>> 
>> Application.setStyleTheme(new ModenaTheme() {
>>     {
>>         addFirst("stylesheet1.css");
>>         addLast("stylesheet2.css");
>>     }
>> });
>
> modules/javafx.graphics/src/main/native-glass/win/ThemeSupport.cpp line 44:
> 
>> 42: }
>> 43: 
>> 44: void ThemeSupport::queryHighContrastScheme(jobject properties)
> 
> @mstr2 Do you think it is possible to use here 
> `Windows.UI.ViewManagement.AccessibleSettings` instead, same as you do in 
> `queryWindows10ThemeColors` with `Windows.UI.ViewManagement.UISettings`?
> 
> I believe `Windows.UI.ViewManagement.AccessibleSettings.HighContrastScheme` 
> contains a not localised string for the high contrast scheme, and that would 
> allow solving https://bugs.openjdk.java.net/browse/JDK-8185447.

I just checked on Windows 10 v20H2 (build 19042.985), and unfortunately the 
`Windows.UI.ViewManagement.AccessibleSettings.HighContrastScheme` contains a 
localized name for the high contrast scheme.

-------------

PR: https://git.openjdk.org/jfx/pull/511

Reply via email to