Request for comments: Styling precedence proposal

David Grieve david.grieve at oracle.com
Fri Dec 7 06:36:21 PST 2012


I find this all somewhat confusing and I'm not following how this ensures "real, type safe, good old Java properties for each and every visual property in JavaFX." 

I believe a consistent policy is best. From lowest to highest, importance being equal, the order of precedence is: 
1. user agent stylesheet styles
2. values set by calls to setXXX, e.g., setFill
3. scene stylesheet styles
4. inline styles, i.e., styles from setStyle

This order of precedence ensures that a call to setXXX won't be overridden by a user agent stylesheet, but can be overridden by an external or inline style. Imagine you have a stop-light widget and you use setFill to color the lights red, yellow and green. This proves difficult for your color blind friend who can't discern red-green. So your friend adds his own stylesheet to color the lights in a way that is easier to distinguish. This is they way it should work. 

In my opinion, setStyle should seldom, if ever, be used and then should be used to with lookup values so that the style can still be overridden, for example, setStyle("-fx-background-color: -my-background-color;")

You may also be interested in providing input on 
http://javafx-jira.kenai.com/browse/RT-17293
http://javafx-jira.kenai.com/browse/RT-24214
and the proposed public API for CSS (https://wikis.oracle.com/display/OpenJDK/CSS+API+to+support+custom+UI+Controls).

On Dec 7, 2012, at 4:00 AM, Randahl Fink Isaksen <randahl at rockit.dk> wrote:

> Richard Bair and I had a useful discussion about the potential conflict between visual properties set by CSS and visual properties set in Java using properties (see RT-16395).
> 
> I have pondered some more on this, because it really makes me cringe when I set a background color in Java by invoking
> 
>    setStyle("-fx-background-color:green");
> 
> Why? Because this can easily be misspelled, and is not type safe.
> 
> I think this could be improved by adding real Java properties and introducing a precedence concept, and the following paragraphs explains my idea in detail.
> 
> 
> As developers we are already used to visual property precedence when working with CSS, where visual properties specified through style classes are applied first, and then the properties specified with the style attribute are applied – in other words style ends up taking precedence over class (last applied wins).
> 
> This is straight forward. JavaFX is also straight forward, in the sense that if you don't set a Java property, CSS wins, and if you do set a Java property, you win. That is a good system. The only problem is, not all visual properties have corresponding Java properties – there is no setBackgroundColor on Region, for instance, even though the -fx-background-color sets it.
> 
> What I am suggesting, is giving each visual property a real, type safe, Java property and a precedence rule, configurable through a map on each stylable Node in the scene graph. I suggest defining the precedence as follows:
> 
> public enum Precedence {
>    JAVA, //what we have today – will be the default
>    STYLE
> }
> 
> Here, Precendence.JAVA, works just like JavaFX 2.2.6 does today, meaning that a visual property, such as the fill of a Text, takes on the value defined by
> 
> 1. The value of a the Java property fill set using the setFill method, or if not set
> 2. The -fx-text-fill set using the style property, or if still not set
> 3. The -fx-text-fill defined using the assigned CSS classes.
> 
> In other words: The Java value wins if it is set by the developer. I propose this will be the default, so that JavaFX remains backwards compatible.
> 
> The other alternative, Precendence.STYLE means that a visual property, again exemplified by the fill of a Text, takes the value defined by
> 
> 1. The -fx-text-fill set using the style property, or if not set
> 2. The -fx-text-fill defined using the assigned CSS classes, and if still not set
> 3. The value of a corresponding Java property fill of the Text set using setFill.
> 
> 
> The precedence concept would require substantial changes to the JavaFX API, but I think these changes are worthwhile because they ensure we can get real, type safe, good old Java properties for each and every visual property in JavaFX.
> 
> The changes would entail
> 
> 1. More properties: All visual properties of a stylable node would be exposed as real Java properties, through methods such as setBackgroundColor, or getBackgroundColor. Many of these already exists (getEffect, setTextAligment, etc.).
> 2. A precedences map: All stylable nodes would get a new map property called precedences, accessible through a getPrecedences() method, where each precedence is kept. Initially the map would be empty, which means all properties have Precedence.JAVA, but you could change this by invoking getPrecedences().put("backgroundColor", Precedence.STYLE).
> 3. An appearances map: All stylable nodes would get another new map property called appearances, accessible through a getAppearances() method, where JavaFX automatically puts the final rendered values.
> 
> So, if you invoke setBackgroundColor(Color.RED) on a node which has no precedence set for the property, or which has a precedence of JAVA, everything works just like today: You set the color to RED and it ends up red on screen. The new thing is that it ends up red because JavaFX checks your  precedence rules and sees that the JAVA value takes precedence, and sets the rendered value to red by automatically invoking getAppearances().put("backgroundColor", Color.RED) for you. Note that this means you can check the map and get a precise answer, if you want to know what it looks like to your application users (great for debugging).
> 
> Now, if you continue and invoke setStyle("-fx-background-color: blue") and Precedence is still JAVA (the default), a call to getApperances().get("background-color") would yield Color.RED, because the JAVA property you set first still takes precedence.
> 
> Finally, if you then invoked getPrecedences().put("backgroundColor", Precedence.STYLE) then JavaFX would automatically update the appearance and getAppearances().get("background-color") would return Color.BLUE.
> 
> That is a lot of new API, so the obvious question is: Is it worth it? Personally, I think this approach is a huge benefit, because now developers can control which properties are locked to the value set by the developer (Precedence.JAVA) and which value is freely stylable by the designer (Precedence.STYLE). But most importantly, we now have a well-defined approach to adding real, type-safe, Java object properties for each and every visual property in JavaFX, which means we can get rid of the non-type-safe setStyle calls.
> 
> I am very interested in hearing comments from people on this list before deciding wether to file or not to file a Jira issue for this.
> 
> Thanks
> 
> Randahl



More information about the openjfx-dev mailing list