This email is a bit long but I think it represents a good way to move the 
styling discussion forward. Please read it if you are interested in this 
discussion.

I have been thinking about a way that we could support CSS either in addition 
to or instead of JSON for styling. My original proposal for adding named style 
support was something along these lines:

<Window styleClasses="@my_styles.json" 
    xmlns:bxml="http://pivot.apache.org/bxml";
    xmlns="org.apache.pivot.wtk">
    <BoxPane>
        <Label styleClassNames="a, b, c" styles="{color:green; 
font:Arial-BOLD-24}"/>
    </BoxPane>
</Window>

The "my_styles.json" file defines the (untyped) style classes "a", "b", and 
"c". These would be applied when the "styleClassNames" attribute is processed. 
The values in the "styles" attribute would then override any of the styles 
defined by the style classes.

However, this approach didn't work for two reasons:

1) Attributes aren't processed until the closing tag. This is by design - 
consider a CardPane with a "selectedIndex" attribute. This value can't be set 
until the card pane's children have been added. The implication here is that 
the named styles specified by Window's "styleClasses" attribute won't be loaded 
by the time the Label is created, so the named style classes won't be found.

2) Child elements aren't added to the parent until the closing tag. So, even if 
#1 is solved, Label won't be able to walk up the tree to find the named styles 
because BoxPane wouldn't have been added to the Window yet.

However, I believe I have a solution to both of these issues. I have already 
modified BXMLSerializer to add child elements in the start tag, which resolves 
#2. The resolution to #1 could be an annotation that specifies when an 
attribute should be processed (e.g. @PostApply). If this attribute is not 
specified, the attribute would be pre-applied (i.e. processed in the start tag).

Unfortunately, as we have discussed, another issue with this approach is that 
JSON doesn't support namespaces. So it would be cumbersome to try to support 
typed selectors in JSON. Typed selectors could be specified in WTKX, though:

<Window
    xmlns:bxml="http://pivot.apache.org/bxml";
    xmlns="org.apache.pivot.wtk">
    <styleClasses>
        <StyleClass type="org.apache.pivot.wtk.Label" name="a" 
styles="{foo:'bar'}"/>
    </styleClasses>
    
    <BoxPane>
        <Label styleClassNames="a, b, c" styles="{color:green; 
font:Arial-BOLD-24}"/>
    </BoxPane>
</Window>

Additionally, given CSS 3's proposed support for namespaces, it would become 
possible to declare both typed and untyped selectors in an external CSS file. 
WTK could also be updated to use inline CSS for local style specifications vs. 
JSON, which would be slightly less verbose (no opening and closing curly 
braces).

<Window styleClasses="@my_styles.css" 
    xmlns:bxml="http://pivot.apache.org/bxml";
    xmlns="org.apache.pivot.wtk">
    <BoxPane>
        <Label styleClassNames="a, b, c" styles="color:green; 
font:Arial-BOLD-24"/>
    </BoxPane>
</Window>

I think this approach would be much more intuitive than the current one. It 
would also be more consistent, since all styling would be specified via CSS, 
rather than by a combination of classpath, attribute, and page-level variables.

The changes required to support this feature include:

1) BXMLSerializer modifications discussed above (trivial, and nearly complete)
2) Addition of a StyleClassSequence to Container (easy, but slightly 
time-consuming)
3) Addition of serialization support for loading stylesheets and processing 
inline CSS

#3 is obviously the most challenging. It will require implementing a new 
serializer capable of processing CSS stylesheets:

  StylesheetSerializer : Serializer<StyleClass>
 
An instance of this class would be used to process the "styleClasses" 
attribute. It would probably also be used to process inline style declarations, 
perhaps via a readStyleDeclaration(InputStream):Map<String, ?> method.

I don't think that implementing such a class will be very difficult. However, 
as I mentioned earlier, I don't want to introduce a dependency on a 3rd party 
library to support it. I'm not opposed to porting an existing implementation 
that has a compatible license and including it in the platform, though. No need 
to build it from scratch if there is already a good one we can use.

One downside to moving to CSS for styling is the potential loss of support for 
font encodings such as this:

  font: {bold:true}

I don't think we'd want to mix this kind of JSON-oriented styling with CSS. 
Instead, we'd want to support the CSS syntax:

  font-weight: bold

This is doable - it just means that any skin that supports a "font" style 
should also define setFontFamily(), setFontSize(), and setFontWeight() methods.

So, here is what I propose: I will make the necessary changes to BXMLSerializer 
and Container that are required to support this. I will leave the existing 
JSON-based style support in place for now (though I will probably yank the 
classpath-based type selectors, since they will no longer be necessary). CSS 
won't be supported, but developers will be able to define and apply style 
classes in BXML as shown above.

I would very much like to see support for CSS added, though. If anyone is 
interested in working on the StylesheetSerializer class, please let me know. I 
think it would make a great addition to the platform, and I would be highly 
inclined to drop support for JSON styling in favor of CSS if this functionality 
becomes available.

Please let me know what you think.

Thanks,
Greg

Reply via email to