It's not that you can't use -fx-base, but that as it is currently that all styles used in Modena that rely on -fx-base directly or indirectly suddenly have a higher priority (above setters) even though you didn't specifically specify them in your own stylesheet.  All such styles are being elevated from USER_AGENT to AUTHOR level (which is above USER level which is used for setters).

--John

On 09/07/2024 17:03, Andy Goryachev wrote:

I've used this feature in the past to change the colors in all the controls, so to me this is the expected behavior.

So in your case (if I got it right), you need to set the direct style on the label (.setStyle("-fx-text-fill:yellow")) instead of setting the text fill programmatically.  Right?

-andy

*From: *openjfx-dev <openjfx-dev-r...@openjdk.org> on behalf of John Hendrikx <john.hendr...@gmail.com>
*Date: *Monday, July 8, 2024 at 17:11
*To: *openjfx-dev <openjfx-dev@openjdk.org>
*Subject: *Re: CSS Lookups and their origins (possible regression)

I realized I worded the TLDR poorly.

Let me try again:

TLDR; should styles which use references (like -fx-base used in Modena) become AUTHOR level styles if -fx-base is specified in an AUTHOR stylesheet?  The act of simply specifying -fx-base in your own AUTHOR stylesheet elevates hundreds of styles from Modena to AUTHOR level, as if you specified them directly...

--John

On 09/07/2024 02:07, John Hendrikx wrote:

    Hi List,

    TLDR; should a CSS reference like -fx-base convert all styles that
    use this value (or derive from it) become AUTHOR level styles
    (higher priority than setters) ?

    Long version:

    In JavaFX 21, I did a fix (see #1072) to solve a problem where a
    CSS value could be reset on an unrelated control.

    This happened when the CSS engine encountered a stylable that is
    overridden by the user (with a setter), and decided NOT to proceed
    with the full CSS value calculation (as it could not override the
    user setting if that CSS value had lower priority).  However, not
    proceeding with the calculation meant that a "SKIP" was stored in
    a shared cache which was incorrect.  This is because when this
    "SKIP" is later encountered for an unrelated control (the cache
    entries are shared for controls with the same styles at the same
    level), they could get their values reset because they were
    assumed to be unstyled.

    However, this fix has exposed what seems to be a deeper bug or
    perhaps an unfortunate default:

    JavaFX has a special feature where you can refer to certain other
    styles by using a reference (which is resolved, recursively, to a
    final value).  This does not seem to be a CSS standard, but is a
    feature only FX has.

    It works by saying something like:

        -fx-base: RED;

    And then using it like this:

        -fx-text-fill: -fx-base;

    This feature works accross stylesheets of different origins, so an
    AUTHOR stylesheet can specify -fx-base, and when a USER_AGENT
    refers to -fx-base, the value comes from the AUTHOR stylesheet.

    JavaFX then changes the origin of the style to the highest
    priority encountered while resolving the reference.  This means
    that Modena can specify "-fx-text-fill: -fx-base", and when
    "-fx-base" is then part of the AUTHOR style sheet, that ALL Modena
    styles that use -fx-base will be considered AUTHOR level styles,
    as per this comment:

    // The origin of this parsed value is the greatest of

    // any of the resolved reference. If a resolved reference

    // comes from an inline style, for example, then the value

    // calculated from the resolved lookup should have inline

    // as its origin. Otherwise, an inline style could be

    // stored in shared cache.

    I feel that this is a really unfortunate choice.  The style after
    all was specified by Modena, only its value came from another
    (higher priority) style sheet.  I think a more logical choice
    would have been to not change the priority at all, unless a
    "-fx-text-fill" is explicitly made part of the AUTHOR stylesheet.

    A consequence of this (and which is much more visible after the
    fix) is that creating a Label with a setTextFill(Color.YELLOW) in
    its constructor will only result in a yellow text fill if the
    AUTHOR stylesheet did not override any of the Modena colors
    involved in calculating the Modena -fx-text-fill default.
    Overriding -fx-base in any way will result in the text fill of the
    label to be overridden (as the reference came from an AUTHOR
    stylesheet, which trumps a setter which is of a lower style origin).

    The comment also alludes to a potential problem.  If an inline
    style would specify "-fx-base", but would be treated as if it came
    from Modena (USER_AGENT level), then this value could get stored
    in the cache as everything except INLINE styles can be cached. 
    However, I feel that the changing of style origin level was then
    probably done to solve a CACHING problem, instead of what made
    logical sense for users.  If we agree that a resolved reference
    should not change the style origin level, then this would need to
    be addressed, by perhaps marking such a calculated value as
    uncacheable, instead of overloading the meaning of style origin.

    I'd like to hear your thoughts, and also how to proceed.  JavaFX
    versions before 21 seemingly allowed overriding reference without
    much consequence because if the user overrode the value manually,
    the cache entry would be set to "SKIP".  Now that this is no
    longer the case, JavaFX more aggressively overrides user set
    values if they happen to use a referenced value.  See code below.

    --John

    .root {

    -fx-base: #ff0000;

    }

    *package*app;

    *import*javafx.application.Application;

    *import*javafx.scene.Scene;

    *import*javafx.scene.control.Label;

    *import*javafx.scene.paint.Color;

    *import*javafx.stage.Stage;

    *public**class*TestApp *extends*Application {

    *public**static**void*main(String[] args) {

    /launch/(args);

    }

    @Override

    *public**void*start(Stage primaryStage) {

    Scene scene = *new*Scene(*new*MyLabel());

    // See the difference with/without -fx-base in the _stylesheet_

    
scene.getStylesheets().add(TestApp.*class*.getResource("/style.css").toExternalForm());

    primaryStage.setScene(scene);

    primaryStage.show();

    }

    }

    *class*MyLabel *extends*Label {

    *public*MyLabel() {

    setTextFill(Color.YELLOW);

    setText("Hello world");

    }

    }

Reply via email to