Hi John,

the rule that values set from code are less specific than values set
in author and inline styles is probably lifted from the CSS
specification, which says [0]:

"The UA may choose to honor presentational attributes in an HTML
source document. If so, these attributes are translated to the
corresponding CSS rules with specificity equal to 0, and are treated
as if they were inserted at the start of the author style sheet."

However, it seems like an arbitrary fact that attributes in an FXML
document are equivalent to calling setters from code. Attributes in
FXML documents could just as well be their own thing, couldn't they?

Let's assume for a moment that we could change that (which is a
breaking change), and make a distinction between values that come from
FXML attributes and values that come from code. This would introduce a
new StyleOrigin.ATTRIBUTE, which would be the origin for all attribute
values set by FXMLLoader (or by anyone, this is a public API in
StyleableProperty after all). However, bindings in FXML documents
would probably continue to use the USER origin. The CSS system would
then never change values with USER origin, since they definitely don't
come from attribute values.

With regards to your idea of only allowing cssProperty.setValue() if
the current value doesn't come from an AUTHOR or INLINE style: it
seems like this *will* work some of the time, namely before CSS is
applied for the first time.


[0] https://www.w3.org/TR/CSS22/cascade.html#preshint


On Tue, Jan 30, 2024 at 3:22 PM John Hendrikx <john.hendr...@gmail.com> wrote:
>
> Hi Michael,
>
> I think we first need to decide what the correct behavior is for CSS
> properties, as the "bind" solution IMHO is a bug.
>
> The StyleOrigin enum encodes the relative priorities of styles and user
> set values, but it is incomplete and not fully enforced.  There is
> (currently) actually a 5th level (next to USER_AGENT, USER, AUTHOR and
> INLINE) where it checks the binding state (it has no choice, as it will
> get an exception otherwise, or has to call `unbind` first).  Whether
> that's a bug or should more formally be accepted as the correct behavior
> remains to be seen.  Also the AUTHOR and INLINE levels are only best
> effort, as setting a value in code (USER level) will override AUTHOR and
> INLINE values **temporarily** until the next CSS pass...
>
> So first questions to answer IMHO are:
>
> 1) Does it make sense to treat values set in code (which IMHO should
> always be the last word on anything) as less important than values from
> AUTHOR and INLINE styles?  This is specified in the CSS document, but
> not fully enforced.
>
> 2) Should bound values (which IMHO fall under "values set from code") be
> able to override AUTHOR and INLINE styles?  Why are they being treated
> differently at all?  Which StyleOrigin level do they fall under?
> "USER"?  A 5th level with higher priority than "INLINE"?
>
> 3) Should properties which hold an AUTHOR or INLINE value reject calls
> to `setValue` (to make it clear they are temporary and that your code is
> probably wrong)?  This currently is not in line with the CSS document.
> Note that this will be slightly annoying for the CSS engine as it may
> not be able to "reset" such values as easily as before (which is
> probably the reason it currently works the way it does, but that's no
> excuse IMHO).
>
> As for your potential solution, if you introduce a constant binding
> system (to solve a CSS problem), does that make sense for properties as
> a whole?  What can be achieved with `bindConstant` that can't be done
> with `setValue`?  `bindConstant` will become the "setter" that always
> works (never throws an exception...), but probably at a higher cost than
> using `setValue`.  Would it not make more sense to only have such
> methods on the Styleable properties (which can then also signal this by
> using an even higher precedence StyleOrigin instead of relying on
> bound/unbound) once there is agreement on the above questions?
>
> In other words, I'd look more in the direction of providing users with a
> better "setter" only for CSS properties, that also uses a different
> StyleOrigin, and to bring both binding and setting in line with the CSS
> document's specification (or alternatively, to change that
> specification).  This means that the normal setter provided next to the
> property method (ie. setXXX) would have to default to some standard
> behavior, while a more specific setter provided on the property itself
> can have an overriding behavior, something like:
>
>      setX() -> calls cssProperty.setValue()
>      cssProperty.setValue() -> sets values if not originated from an
> AUTHOR or INLINE stylesheet, otherwise throws exception (as if bound)
>      cssProperty.forceValue() -> sets value unconditionally, setting
> StyleOrigin to some new to introduce 5th level
> (StyleOrigin.FORCED/DEVELOPER/DEBUG/CONSTANT/FINAL)
>
> Binding can then either be categorized as the StyleOrigin.FORCED or if
> it is StyleOrigin.USER, the CSS engine is free to **unbind** if the need
> arises.
>
> --John

Reply via email to