Style themes API

Pedro Duque Vieira pedro.duquevieira at gmail.com
Tue Jan 31 17:14:28 UTC 2023


Hi Michael,

Truly sorry for the late reply but haven't had time to reply sooner,
unfortunately..

2 -

> > I've been building javafx themes for years now. Started creating JMetro
> in JavaFX version 2. During this time I've been following how other themes
> are being built and I can say that about 90% of the themes (rough estimate)
> that are out there, are composed of author stylesheets, i.e they override
> values set from code (including JMetro).
> > I agree that themes that are to be provided to other developers would
> probably be better off if they are user agent stylesheets. My point is that
> migrating those 90% of themes to use this API would be easier if this flag
> exists otherwise migration would likely introduce UI regressions for
> developers using those themes.
> >
> > To be clear, what I'm proposing is a flag, or enum, or whatever, in
> StyleTheme that defines whether the stylesheets in the StyleTheme should be
> a user agent stylesheet or author stylesheet.
> >
> > Another point is in making themes that are only to be used locally in a
> specific app that the developer is creating. It might be of interest that
> he can toggle this flag and make all settings defined in the theme override
> any styling set from code (or in FXML) so that he can have a centralized
> point where all styling is done.


I think that the likelihood of this feature making it into the 21
> release dramatically increases if we keep changes to the CSS subsystem
> to an absolute minimum. I understand your point, but I want to deliver
> this feature in the smallest useful package and add more features
> later with follow-on PRs.


That's why I've renamed `Application.styleTheme` to
> `Application.userAgentStyleTheme`. This makes it unmistakably clear
> that we're only talking about user-agent stylesheets.
> Also, it leaves open the possibility to add the
> `Application.styleTheme` property later, which would cause the theme
> to be interpreted as comprised of author stylesheets.
> Classifying author/UA themes at the property level is also more
> consistent with the way author/UA stylesheets are currently classified
> in JavaFX.
> What do you think about the styleTheme/userAgentStyleTheme API,
> instead of having a flag in the implementation of StyleTheme itself?


Since one of the objectives of the PR is to promote Caspian and Modena
> to first-class theme implementations, it makes sense to focus on UA
> themes first (since built-in themes are comprised of UA stylesheets).


OK.
Thinking of existing themes migrating to this StyleTheme API (90% are
implemented as author stylesheets), some visual glitches may start
appearing for users of those themes once they start using the migrated
versions (since they will go from being author stylesheets to user agent
stylesheets).
So, 2 things to think about:
2.1 - How important is it that we think about this use case: existing
themes migrating to this new API. I'd say we should probably think about it
when designing this new API.
2.2 - The second thing then is, how problematic will it be for programmers
using these themes to have their apps start having visual glitches because
of these themes changing from author stylesheets to user agent style
sheets?
Perhaps we simply don't bother with this last point and simply have it be
the price of innovation. And so programmers will have to adapt their
applications and remove any code that is overriding the styles defined in
the StyleThemes (which are likely causing these visual glitches when
migrating to Themes using this new StyleTheme API). The same for any styles
already defined in custom author stylesheets that are being used by the
application and that might be NOW overriding the styles of the theme.


3 -
> Style themes are generally either defined as dark or light. i.e. you'll
very rarely have a theme that has some Windows with dark decorations and
others with light decorations. So I think it makes sense to have this as a
theme property.
> The ability to toggle decorations (light or dark) on an individual Window
is a good point you're making. Perhaps we should have a global definition
in the StyleTheme (whether the theme is light or dark) and a definition
that can be set per Window.
> If you set it on the StyleTheme then all Windows will respect it, but you
can override that value on each Window. If you override it on a specific
Window, that definition would take precedence over the global StyleTheme
one.

In general, StyleTheme is a very simple concept: it's a dynamic
> collection of stylesheets.
> I don't think the interface should force implementers to deal with
> anything other than stylesheets. If we did that, the following code
> wouldn't work any more:


    Application.setUserAgentStyleTheme(
>         () -> List.of("stylesheet1.css", "stylesheet2.css");


Maybe we can add a new interface, for example DarkModeAware, and if an
> application theme is marked with this interface, JavaFX will try to
> respect dark/light mode for platform decorations:


    public class MyCustomTheme implements StyleTheme, DarkModeAware {
>         @Override
>         public List<String> getStylesheets() {
>             return List.of("stylesheet1.css", "stylesheet2.css");
>         }
>     }


    // Setting a DarkModeAware theme causes JavaFX to draw light or
>     // dark platform decorations by default, depending on the current
>     // platform preference. If the theme is not DarkModeAware, JavaFX
>     // defaults to light decorations.
>     //
>     Application.setUserAgentStyleTheme(new MyCustomTheme());


In any case, I think we can deliver this feature in a follow-on PR.


I don't think we should put having StyleTheme be just a collection of
stylesheets and nothing else as a requirement. I'd rather think of
StyleTheme as being the concept of a Theme and all the possible properties
and definitions of what a Theme is. This is one of the strengths of this
new feature you've proposed, i.e.
having the concept of a Theme exist in JavaFX whereas in the past there was
no such concept and a "Theme" was just a collection of stylesheets. Added
through the getStylesheets() method or through the setUserAgentStylesheet
method.

I'll just note that we don't just want the applications to be light or dark
depending on what is set in the Operating System. You'll also want the
ability to set whether the app is in dark or light mode on a per
application level irrespective of what is defined in the OS (this already
happens on many existing applications out there). So I think that
DarkModeAware interface would have to have a method like:
  ThemeMode getMode();
Where ThemeMode can either be LIGHT, DARK or OS_DEFINED (I've named it
ThemeMode just as an example).

So I think we could do it in 2 ways: one way would be to do it as you say
(though DarkModeAware interface would need the getMode() method that I
suggested, I think) or add a method in the StyleTheme interface itself in a
future release:
  ThemeMode getMode();
That method would probably need to have a default implementation that
simply returns LIGHT because of retro compatibility.

So, ThemeMode could be one of 3 possible values: LIGHT, DARK or OS_DEFINED.
Where OS_DEFINED means that the app will honor whatever is defined at the
OS level.
JavaFX Window decorations would need to respect whatever is returned in
this getMode() method and change their decorations to either LIGHT or DARK
depending on its value. This would also remove the need for boilerplate
code that for every Window that is created sets it to be LIGHT or DARK
depending on whether the Theme is LIGHT or DARK.

Of course, we can also simply support this from the get go and have this
method exist in StyleTheme from the start.

Thanks again,









On Sun, Jan 22, 2023 at 12:51 AM Michael Strauß <michaelstrau2 at gmail.com>
wrote:

> Hi Pedro,
>
> see my comments below.
>
>
> On Sat, Jan 21, 2023 at 5:19 PM Pedro Duque Vieira
> <pedro.duquevieira at gmail.com> wrote:
> > I've been building javafx themes for years now. Started creating JMetro
> in JavaFX version 2. During this time I've been following how other themes
> are being built and I can say that about 90% of the themes (rough estimate)
> that are out there, are composed of author stylesheets, i.e they override
> values set from code (including JMetro).
> > I agree that themes that are to be provided to other developers would
> probably be better off if they are user agent stylesheets. My point is that
> migrating those 90% of themes to use this API would be easier if this flag
> exists otherwise migration would likely introduce UI regressions for
> developers using those themes.
> >
> > To be clear, what I'm proposing is a flag, or enum, or whatever, in
> StyleTheme that defines whether the stylesheets in the StyleTheme should be
> a user agent stylesheet or author stylesheet.
> >
> > Another point is in making themes that are only to be used locally in a
> specific app that the developer is creating. It might be of interest that
> he can toggle this flag and make all settings defined in the theme override
> any styling set from code (or in FXML) so that he can have a centralized
> point where all styling is done.
>
> I think that the likelihood of this feature making it into the 21
> release dramatically increases if we keep changes to the CSS subsystem
> to an absolute minimum. I understand your point, but I want to deliver
> this feature in the smallest useful package and add more features
> later with follow-on PRs.
>
> That's why I've renamed `Application.styleTheme` to
> `Application.userAgentStyleTheme`. This makes it unmistakably clear
> that we're only talking about user-agent stylesheets.
> Also, it leaves open the possibility to add the
> `Application.styleTheme` property later, which would cause the theme
> to be interpreted as comprised of author stylesheets.
> Classifying author/UA themes at the property level is also more
> consistent with the way author/UA stylesheets are currently classified
> in JavaFX.
> What do you think about the styleTheme/userAgentStyleTheme API,
> instead of having a flag in the implementation of StyleTheme itself?
>
> Since one of the objectives of the PR is to promote Caspian and Modena
> to first-class theme implementations, it makes sense to focus on UA
> themes first (since built-in themes are comprised of UA stylesheets).
>
>
>
> > 3 -
> > Style themes are generally either defined as dark or light. i.e. you'll
> very rarely have a theme that has some Windows with dark decorations and
> others with light decorations. So I think it makes sense to have this as a
> theme property.
> > The ability to toggle decorations (light or dark) on an individual
> Window is a good point you're making. Perhaps we should have a global
> definition in the StyleTheme (whether the theme is light or dark) and a
> definition that can be set per Window.
> > If you set it on the StyleTheme then all Windows will respect it, but
> you can override that value on each Window. If you override it on a
> specific Window, that definition would take precedence over the global
> StyleTheme one.
>
> In general, StyleTheme is a very simple concept: it's a dynamic
> collection of stylesheets.
> I don't think the interface should force implementers to deal with
> anything other than stylesheets. If we did that, the following code
> wouldn't work any more:
>
>     Application.setUserAgentStyleTheme(
>         () -> List.of("stylesheet1.css", "stylesheet2.css");
>
> Maybe we can add a new interface, for example DarkModeAware, and if an
> application theme is marked with this interface, JavaFX will try to
> respect dark/light mode for platform decorations:
>
>     public class MyCustomTheme implements StyleTheme, DarkModeAware {
>         @Override
>         public List<String> getStylesheets() {
>             return List.of("stylesheet1.css", "stylesheet2.css");
>         }
>     }
>
>     // Setting a DarkModeAware theme causes JavaFX to draw light or
>     // dark platform decorations by default, depending on the current
>     // platform preference. If the theme is not DarkModeAware, JavaFX
>     // defaults to light decorations.
>     //
>     Application.setUserAgentStyleTheme(new MyCustomTheme());
>
> In any case, I think we can deliver this feature in a follow-on PR.
>
>
> > 4-
> >>
> >> If we wanted to expose this front-and-center, we could add these
> >>
> >> properties to the Platform.Properties interface:
> >
> >
> >>     public interface Preferences extends ObservableMap<String, Object> {
> >>         ReadOnlyBooleanProperty darkModeProperty();
> >>         ReadOnlyObjectProperty<Color> accentColorProperty();
> >>         ...
> >>     }
> >
> >
> > Yes, I think that would be great.
>
> Let's see what other people think.
>


-- 
Pedro Duque Vieira - https://www.pixelduke.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20230131/1dc08b84/attachment-0001.htm>


More information about the openjfx-dev mailing list