Extending Builders: Layout Builders
Tom Eugelink
tbee at tbee.org
Fri Nov 23 23:18:35 PST 2012
Ah, yes. We can start by agreeing that it will not be easy, or even possible, to always create a good Java API that also is easy mappable and readable onto FXML by simple serialization. So then you come into a conflict of priorities, what is more important: a good Java API or a readable FXML?
We had similar issues with MigPane which also has a constaint class:
<TextFieldfx:id="firstNameField"text=""MigPane.cc="growx, wrap"/>
Here we decided to use the string notation for the controls. But in order to process this, we also needed a few static methods on MigPane. Since I really feel uncomfortable with polluting the Java API with things that basically are required by the layer above, I decided (to the dismay of some others) to create a separate MigPane class in a fxml subpackage which contains these methods.
http://code.google.com/p/miglayout/source/browse/javafx/src/main/java/org/tbee/javafx/scene/layout/fxml/MigPane.java
A similar approach for the alternative HBox would basically result in the same API as HBox currently has:
<HBox>
<Label fx:id="arrow" alignment="center" text="" maxWidth="Infinity" HBox.vgrow="ALWAYS" HBox.valignment="LEFT"/>
</HBox>
With one important difference in that there still is a formal constraint class being set instead of an obscure internal map. And, like MigPane, I would not place these methods in the HBox class directly, but a special FXML version. Keep the Java API clean.
But I'd rather use a different approach: provide (de)serializers that help map the FXML onto the objects. I see FXML as a layer on top of the API and good software development teachings say that lower layers should not have any knowledge of higher layers, so I feel really really bad about polluting the Java API to support FXML. Providing glue might be a better approach. Java has standard plugin-style solutions in place, like META-INF/services, so it should be easily possible to provide plugins together with the components that help in those places where simple serialization does not cut it.
http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider
In this way both Java API and FXML can be optimal. The plugin can also be extended to help the scene builder, by providing meta data for when it can't rely on reflection alone. I suspect the future will only introduce more of such conflict areas and rolling in a good solution instead of patching it would be IMHO the right way (tm).
Tom
On 2012-11-23 11:08, Tom Schindl wrote:
> Hi,
>
> Let me retry - I hope this doesn't get too long.
>
> FXML is simply a serialization definition to serialize ANY given
> java-object graph.
>
> Let's take your example:
>
> <HBox>
> <Label
> fx:id="arrow"
> alignment="center"
> text=""
> maxWidth="Infinity">
> <HBox.C vgrow="ALWAYS" hgrow="ALWAYS"/>
> <Label>
> </HBox>
>
> which means in full blown FXML without default-attributes
>
> <HBox>
> <children>
> <Label
> fx:id="arrow"
> alignment="center"
> text=""
> maxWidth="Infinity">
> <constraint>
> <HBox.C vgrow="ALWAYS" hgrow="ALWAYS"/>
> </constraint>
> <Label>
> </children>
> </HBox>
>
> So written in Java-Code it means
>
> HBox box = new HBox();
> Label l = new Label();
> l.set...
> HBox.C c = new HBox.C();
> c.set...
> l.setConstraint(c);
> box.getChildren().add(l);
>
> Definately not what you want because your layout-containers code looks
> like this:
>
> HBox box = new HBox();
> Label l = new Label();
> l.set...
> HBox.C c = new HBox.C();
> c.set...
> box.add(l,c);
>
> Which clearly violates the generic serialisation which says sub-elements
> are always added (if it is a list) / set (single attribute) on the
> attribute they are the child of.
>
> So if we take your proposed FXML as shown above we have a problem
> because when we follow the general serialization/deserialization
> strategy we'd have to have a layoutConstraint-Property on the *Node*
> although things like layouts only make sense when you add the node
> inside a layout-container but not if it is e.g. a child of a Group, ...
>
> To summerize: My point - I fully agree with you that when coding the UI
> in Java your layout-container additions make a whole lot of sense but
> they break the serialization infrastructure because the addition is not
> done on the attribute itself (children) but through the owner of the
> attribute (HBox).
>
> Tom
>
> Am 22.11.12 19:51, schrieb Tom Eugelink:
>> Not sure I understand what you are trying to say here. Each layout has
>> different and much deviating constraints, so they cannot be unified into
>> one model.
>>
>> I think I summarized it well in my blogpost: "All information about the
>> layout of a single node should be stored in one place." This means
>> absolute layout can suffice with the X,Y,W,H information available in
>> the nodes (and thus allow binding), but all more advanced layouts
>> require a separate constraint class.
>>
>> Tom
>>
>>
>>
>>
>> On 2012-11-21 22:42, Tom Schindl wrote:
>>> the nice thing about the current expression with static calls is that
>>> the semantics for adding children are always the same whether your
>>> target is a Layout-Container or e.g. a Group.
>>>
>>> You always call add on the target your specified. Your way of layout
>>> containers expects two different things to happen:
>>> * for layout container you want to call add on the owner because you
>>> want to pass the constraint object
>>> * you can add on the list itself for stuff like Group but also Tables
>>>
>>> Not to forget how would you like set the constraint when you not add to
>>> a list e.g. when using a borderpane?
>>>
>>> Tom
>>>
>>> Am 21.11.12 19:02, schrieb Tom Eugelink:
>>>> I suspect the constraints were already "out" before FXML, but this would
>>>> be a fairly acceptable notation:
>>>>
>>>> |<HBox>
>>>> <Label fx:id="arrow" alignment="center" text=""
>>>> maxWidth="Infinity"> |
>>>> || <HBox.Cvgrow="ALWAYS" hgrow="ALWAYS"|/>
>>>> <Label>
>>>> </HBox>
>>>> |
>>>>
>>>>
>>>> Or:
>>>>
>>>> |<HBox>
>>>> <Label fx:id="arrow" alignment="center" text=""
>>>> maxWidth="Infinity"|||HBox.C.vgrow="ALWAYS" HBox.C.hgrow="ALWAYS"|/>
>>>> </HBox>
>>>> |
>>>>
>>>>
>>>>
>>>> On 2012-11-21 17:46, Tom Schindl wrote:
>>>>> Am 21.11.12 09:46, schrieb Richard Bair:
>>>>>> I wanted constraint classes from the start. There was a problem
>>>>>> there, which I don't accurately remember now, but I do want to see
>>>>>> some discussion around deprecating (or at least no longer depending
>>>>>> on) the static methods and having some constraint classes again.
>>>>> They've probably been harder to implement in FXML?
>>>>>
>>>>> Tom
>>>>>
>>>>>
>
More information about the openjfx-dev
mailing list