[API Review]: Node validation
david.grieve at oracle.com
Fri Jul 12 09:03:46 PDT 2013
I hesitate to mention Node#impl_processCSS(boolean) which is very very close to your notion of applyCss(); impl_processCSS(boolean) is a thorn in my side, but is used in certain places in controls code to ensure CSS is applied before layout in order to ascertain a node's dimensions. What it does is walk up the tree to find the closest parent who's cssFlag is other than clean and then calls processCSS from that node on down. The flag says whether to simply update css or to reapply css (reapply involves figuring out what styles apply to a node).
impl_processCSS is also used by SceneBuilder. They created https://javafx-jira.kenai.com/browse/RT-21206 asking to make impl_processCSS(boolean) public.
It should also be mentioned that pseudo-class state matters, including the state of the parents, so depending on when you call applyStyle(), you might get different results. The applyStyle() method can't really ignore pseudo-class state since things like orientation (horizontal/vertical) are kind of important.
On Jul 12, 2013, at 11:32 AM, Richard Bair <richard.bair at oracle.com> wrote:
>>> Is there any reason why I might want to measure a node independent of the layout of its parent? If I have a Button in a StackPane, is there a time I might want to measure the Button independent of the StackPane? I suppose so, if for example I wanted to get snapshots of it at its min size, max size, and pref size, regardless of what the layout container might do with the button. That seems reasonable.
>> Yes, maybe. But that would require a completely different API.
> In what way? Just having applyCSS exposed allows me to do this?
>>>> The concept of layout roots is not documented well in the API ( we use the term in few place, but never define it) and people would have to know how to identify the layout root and also know that they need to start from the layout root. Also, there's no way to check which Node is the layout root, although you can identify it using managedProperty(), it's parent and/or sub scene.
>>> Hmmm. OK, so today suppose I have a scene graph with a root node and someplace down in the hierarchy is an unmanaged node. If I call layout() on the root node, then it will layout everything except for the unmanaged node. If i wanted to get a list of all the dirty layout roots, well, there is no public API to do so.
>>> After your change, the semantics of layout would be the same -- calling layout on the root node isn't going to cause the unmanaged node to be laid out. So for what Steve and I are proposing to make sense (just expose applyCSS), we also have to expose either another method (layoutEverythingForTheLove) that will force everything in the tree to be laid out, or we have to have another method (getLayoutRoots) which will accumulate the layout roots so that you can then call layout() on them all manually.
>> Actually, calling layout() on scene root will layout everything in the root after my changes (as the flags must always be set up to the root, so we can find the way to all dirty layout roots), currently this doesn't work as the scene root doesn't know whether there are other dirty layout roots in the scene. So if you have (Sub)Scene, you can just call getRoot().layout() and everything should be laid-out correctly (if you also called CSS before). But this would re-layout much more then is needed for some specific Node.
> If that's the case then it seems like all you need is applyCSS. Because from any node you get getScene().getRoot().layout(), or in the worst case walk up to the root and then fire off the applyCSS / layout.
> In this case, applyCSS becomes the essential API, and "validate" or whatever it would be called becomes the convenience API. In this case I would suggest adding the essential API and adding the convenience API subsequently when the pain is clearly felt and understood.
More information about the openjfx-dev