Details
-
Type:
Improvement
-
Status:
Open
-
Priority:
Minor
-
Resolution: Unresolved
-
Affects Version/s: 0.2
-
Fix Version/s: None
-
Labels:None
-
Number of attachments :
Description
Layout constraints such as row indexes, column indexes, alignments, grows, etc. are currently handled in one of two places. Most are handled in AbstractNodeFactory#handleLayoutConstraints(). The only exception is the anchor constraints for AnchorPane, which are handled in FXHelper.fxAttribute().
The current system works well in that it allows layout constraints to be specified with all of the node's other properties. This makes setting constraints feel very natural. The problem with the current system is that the constraints can potentially be lost. This occurs when a node is defined on its own and added to the scene graph later.
stackPane(id: 'content', row: 1, column: 1) {
// ...
}
If the above node is later added to a GridPane, it will not know about the row and column constraints since the GridPane was not the parent of the StackPane when it was created. The same thing can happen if a node is created as a child, but later relocated to some other place in the scene graph. The original constraints will likely not apply to the new parent.
To address this problem, I propose that we unify the constraint handling into one place and utilize the following system:
- We intercept all constraint properties in AbstractFxBeanFactory before they are passed on to FXHelper.
- Any constraints that apply to only one layout type (i.e. anchor settings for the AnchorPane) are set using the static methods for that pane and then discarded. Since these properties are set statically, they can safely be discarded after they are set.
- Any properties that can apply to more than one parent are placed in a "constraints" map and stored in the Node's properties map (see Node#getProperties())
- A change listener is then attached to the Node's parent property. Each time a new, non-null parent is set we process the Node's constraints using a system similar to that used in handleLayoutConstraints currently.
Potential Drawbacks:
- There will be a performance penalty due to the overhead of detecting parent changes and resetting properties. However, this is done relatively infrequently and any additional overhead is probably negligible compared to that already incurred by changing the scene graph itself. In any case, I think that the improved behavior justifies the small performance hit for these relatively infrequent operations.
- If a property that only applies to one type of pane gets reused in a new pane (i.e. a new type of AnchorPane is added to JFXtras that we wish to support), then the GroovyFX code will have to be recompiled to add support for it.
I have the feeling that constraints should not live on the node since they are not a property of the node itself. They are parameters to the "adding" of the node to a parent.
So when a "detached" node is later added to a parent via the widget() method, this call should look like widget(node, row:1, column:1).