On Wed, 14 Jul 2010, Greg Brown wrote:

Michael,

I have been giving the styling discussion some thought. It seems like your primary objective is to provide support for CSS-like type selectors. In other words, you would like to ensure that a consistent set of styles is applied to all instances of a particular component type - is that correct?

That's one but not all of them. I also like CSS class selectors. Maybe attribute selectors, too. Maybe descendent and child selectors. I don't know. I haven't used it with Pivot enough to say. I do have a lot of experience using Adobe's implementation of CSS for Flex. It supports type, class, and id selectors. I frequently used the former but rarely used the latter. So my affinity for CSS comes in large part from that experience.

If so, I have a solution that I think will fit in well with the existing architecture but will still meet your needs. I am thinking that Component#setSkin() can be updated to apply a predefined set of styles to each component instance as it is created. For example, I could say that all PushButtons should have the "{font:'Arial-BOLD-24'}" style applied at creation time.

I thought about various means for how those styles should be specified. I first considered supporting a global stylesheet defined in CSS. However, the problem with this approach is that CSS doesn't know anything about Java packages. So you'd end up repeating quite a bit in your style declarations:

org.apache.pivot.wtk.PushButton: {
   font: "Arial-BOLD-24";
}

With Flex, if I had a lot of type selectors, I would put them in a global CSS file. However, one of the most useful features of Flex's CSS support is writing CSS style declarations in-line in your MXML file. They go inside a <Style> tag. You can import them from a file using <Style src="blah.css"/> but in most cases it's just more useful to write the styling in-line. In either case, these style declarations only applied to components within the containing MXML file.

Anyway, as for types for the time being I'm just comparing Java simple names. It's sloppy, but it did work for Flex. They don't have namespaces in their CSS files. Anyway, I still don't like it.

If you look at the CSS 3 draft, you'll see the editors have included support for namespaces. And they're pretty simple. Basically it goes like


@namespace blah "ms.allman.blah"

blah|MyBlahComponent {
        name: value
}


You can also define a default namespace like this:

@namespace "org.apache.pivot.wtk"


Personally, I don't have a problem with just using this convention, even if it's still in draft. There are no Java CSS parsers I'm aware of that support this syntax, but the SAC does and I think I could submit a patch to CSSParser that would implement it.

It would also necessitate writing or porting a CSS parser, which I would like to avoid. More importantly, it would introduce a dependency on CSS that we currently don't have.

Not sure why we couldn't just add a dep for a binary jar like CSSParser. It could even be optional. "If you want's CSS support, you need to include the CSSParser jar file on the classpath."

Unfortunately, the same problem would apply to a JSON-based global stylesheet, since JSON doesn't have a concept of namespaces either:

{   org.apache.pivot.wtk.PushButton: {
       font: "Arial-BOLD-24";
   }
}

Yeah, this is one reason I think JSON sucketh in general. But that's neither here nor there.

I also thought about an XML approach, since XML does support namespaces:

<styles xmlns="org.apache.pivot.wtk">
   <PushButton font="Arial-BOLD-24"/>
</styles>

However, this seems pretty clumsy, and it is a bit confusing, since it looks a bit like BXML but is not.

In all of these cases, there is also the issue of how the location of the stylesheet will be provided to the platform. It could be specified via a custom system property, but those are only available to trusted code. That's too limiting.

Well, Flex makes no assumption about where the stylesheets live. You tell it with a <Style src="asasd.css"/> tag in your mxml file. I'm not sure having such a tight relationship between the location of the BXML and CSS or whatever for the purposes of autodiscovery is worth the restriction this imposes.

So here is what I have come up with. To review, one current way to apply styles to any instance of a type is as follows:

<PushButton styles="@my_button_styles.json"/>

The button styles are encapsulated in an external JSON file named "my_button_styles.json" that looks like this:

{   font: "Arial-BOLD-24"
}

However, since we want all PushButton instances to have the same styles applied, we want to put them somewhere that the platform knows about, so they can be applied when the component is created. I think we can do it like this: create a directory structure that parallels the package structure of the component you want to style, and create a JSON file that represents the styles you want applied to that particular type:

Personally, I don't care if Pivot can automagically find my style sheets or not. If it can be done really well, then by all means. But otherwise, I don't mind typing something like <Styles src="asd.css"/>

/org
 /apache
   /pivot
     /wtk
       PushButton.json

When the component is created, Component#setSkin() will look for a file with the same name as the component class, but with a .json extension. If it finds one, it will apply the styles contained in the file to the new instance.

I like this approach because it is consistent with the existing infrastructure, but also because it applies the CSS notion of a "class" in a Java-centric manner: the actual Java class lives in /org/apache/pivot/wtk/PushButton.class, and the style "class" for that class lives in /org/apache/pivot/wtk/PushButton.json.

Please let me know what you think.

Greg

Reply via email to