Layouts with constraint classes

Tom Eugelink tbee at tbee.org
Sat Dec 1 11:00:36 PST 2012


Since it is an equal relationship, it is defend-able to set all constraints on the node.

<VBox>
     <HBox id="hb1">
     </HBox>

     <HBox>
        <Label  alignment="center" text="">
            <HBox.C vgrow="ALWAYS"  valignment="LEFT" maxWidth="Infinity"/>
            <HBox.C layout="hb1" vgrow="NEVER" valignment="RIGHT"/>
        <Label>
     </HBox>
</VBox>


That would be a matter of taste. I prefer it the other way around, because a layout is complicated enough without additional constraints of another layout.

Tom



On 2012-12-01 12:58, Tom Schindl wrote:
> I agree predefining the constraint for a node that might get added
> somewhere feels wrong (=> your 2nd sample looks good!). That's why I
> think it makes no sense to store to constraint on the container but it
> should be stored on the node itself and when you move the Node you
> update the constraint.
>
> BTW: I think the samples would be more interesting if the source and
> target container are of different type. e.g. HBox => VBox
>
> Tom
>
> Am 01.12.12 11:57, schrieb Daniel Zwolenski:
>> I've slapped up two examples for you - they are pretty rough and could be
>> cleaned up, but it's just to demonstrate.
>>
>>
>> *Example 1* is basically how you requested it.
>>
>> The FXML looks like this:
>>
>>
>>      <HBox fx:id="hbox1">
>>          <constraints>
>>              <HBoxConstraints forNode="myLabel" hgrow="ALWAYS"/>
>>          </constraints>
>>          <Label fx:id="myLabel" text="I'm a Label"
>> style="-fx-background-color:green" maxWidth="10000"/>
>>      </HBox>
>>
>>      <HBox fx:id="hbox2">
>>          <constraints>
>>              <HBoxConstraints forNode="myLabel" hgrow="NEVER"/>
>>          </constraints>
>>          <!-- label will get moved here -->
>>      </HBox>
>>
>>
>> For the full FXML see:
>> http://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/resources/fxml/example1.fxml
>> (Note
>> that I defined the Animation in the FXML, but this is totally optional, you
>> could define it in the controller).
>>
>> This needed a fair few support classes because you have to create new
>> builders for the layout manager. If this was a common use case then you
>> could put all the customised builders and constraint classes in something
>> like JFXtras for shared reuse.
>>
>> Main support class is the HBoxBuilder:
>> http://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/java/com/playtime/layouts/example1/CustomHBoxBuilder.java
>>
>> (strangely extending the default HBoxBuilder didn't work with FXML - not
>> sure if I was just doing something dumb, I didn't look into it deeper)
>>
>> Other support classes are all in the same package:
>> http://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/java/com/playtime/layouts/example1/
>>
>>
>> *Example 2* is where the animation itself defines the constraints (as per
>> my suggestion). This one feels more natural to me as the animation knows
>> context and could decide to use a different layout depending on what action
>> was picked. In the animation dance there is the source parent, the target
>> parent and the node being moved. All of these are 'passive' and only the
>> animation does the "action" and really knows that there is a move happening
>> and why it is happening so in my book it is the one that should make
>> decisions about how the node looks when it is moved. That's a subjective
>> opinion though and you have both options to choose from.
>>
>> The FXML looks like this
>>
>>      <HBox fx:id="hbox1">
>>          <Label fx:id="myLabel" text="I'm a Label"
>> style="-fx-background-color:green" HBox.hgrow="ALWAYS" maxWidth="10000"/>
>>      </HBox>
>>
>>      <HBox fx:id="hbox2">
>>          <!-- label will get moved here -->
>>      </HBox>
>>
>>      <fx:define>
>>          <MoveAnimation fx:id="moveForwardAnimation" node="$myLabel"
>> newParent="$hbox2">
>>              <HBoxConstraints hgrow="NEVER"/>
>>          </MoveAnimation>
>>          <MoveAnimation fx:id="moveBackAnimation" node="$myLabel"
>> newParent="$hbox1">
>>              <HBoxConstraints hgrow="ALWAYS"/>
>>          </MoveAnimation>
>>      </fx:define>
>>
>> There are considerably fewer/simpler support classes for this. The only
>> really interesting one is this:
>>
>> http://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/java/com/playtime/layouts/example2/MoveAnimation.java
>>
>> As a side note, the JFX animation/transition classes being final make the
>> code a little messier. This is one area where I would vote for relaxing the
>> use of 'final' - extending transitions makes as much sense as extending
>> Nodes in my book. We can already extend Transition so I don't see why we
>> can't extend SequentialTransition for example.
>>
>> I hope this time I got it right and that solves your use case. My main
>> point though is that pretty much all of this sort of stuff *should* be
>> possible through the use of builders and support classes. The glue may not
>> always be the nicest but the driving force should be to keep the FXML and
>> Java clean without compromising each other - the mess should be in the glue
>> because only the glue author sees that, not the end user of the API, that's
>> why the glue exists in the first place.
>>
>>
>>
>>
>>
>> On Sat, Dec 1, 2012 at 6:47 PM, Tom Eugelink <tbee at tbee.org> wrote:
>>
>>> Yes, correct :-)
>>>
>>> The approach where the constraint is set in the animation feels procedural
>>> and not declarative to me. Like you say yourself, I think it should be
>>> define like: when node X is part of this layout, use these constraints. In
>>> this way it is not relevant where the animation is defined or how the node
>>> got there.
>>>
>>> Tom
>>>
>>>
>>>
>>> On 2012-12-01 08:38, Daniel Zwolenski wrote:
>>>
>>>> Ah ok, so in the first hbox you are saying when the "arrow" node is moved
>>>> into here use these new constraints. I think I've got you now.
>>>>
>>>> That should be do-able using some more helper classes. I can knock some
>>>> up but my first thought would be to do it as part of the animation since
>>>> its the thing that has the most knowledge about what's going on and why.
>>>>
>>>> How/where do you define and trigger your animation - are you specifying
>>>> it in the FXML? If so the constraints could be part of that eg. (made up
>>>> pseudo FXML):
>>>>
>>>> <MoveAnimation nodeToMove="arrow" moveTo="hbox1">
>>>>      <NewConstraints>
>>>>
>>>>> <HBox.C vgrow="NEVER" valignment="RIGHT"/>
>>>>>
>>>>      </NewConstraints>
>>>> </MoveAnimation>
>>>>
>>>> (also slightly confusing is that the constraints you are using aren't
>>>> applicable to HBox)
>>>>
>>>> If you don't like that approach I can knock up the alternative?
>>>>
>>>>
>>>>
>>>> On 01/12/2012, at 6:17 PM, Tom Eugelink <tbee at tbee.org> wrote:
>>>>
>>>>   Because of animation the label may move from one HBox to the other. This
>>>>> is the reason why the current approach stores constraints inside the node,
>>>>> so that when it moves from layout A to B, the constraints also move. My
>>>>> approach allows to specify different constraints for the same node in each
>>>>> layout.
>>>>>
>>>>> You are right that there should be a parent layout, I left it out to not
>>>>> confuse things, but apparently that is confusing :-)
>>>>>
>>>>> <VBox>
>>>>>      <HBox>
>>>>>         <HBox.C for="arrow" vgrow="NEVER" valignment="RIGHT"/>
>>>>>      </HBox>
>>>>>
>>>>>      <HBox>
>>>>>         <Label  fx:id="arrow"  alignment="center" text="">
>>>>>             <HBox.C vgrow="ALWAYS"  valignment="LEFT"
>>>>> maxWidth="Infinity"/>
>>>>>         <Label>
>>>>>      </HBox>
>>>>> </VBox>
>>>>>
>>>>>
>>>>>
>>>>> On 2012-12-01 08:01, Daniel Zwolenski wrote:
>>>>>
>>>>>> You've lost me. What are you expecting  the actual view to look like
>>>>>> with this FXML?
>>>>>>
>>>>>> If I interpret it literally you've defined two HBox's one after the
>>>>>> other. The first one has no children and an unused constraint, the second
>>>>>> one has a Label in it with a constraint on it. I'm guessing you are trying
>>>>>> to do something more but it's not real clear what that more is?
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 01/12/2012, at 5:28 PM, Tom Eugelink <tbee at tbee.org> wrote:
>>>>>>
>>>>>>   Not variables, but references. There are constraints specified for
>>>>>>> nodes that are not yet part of a layout (or even exist at that time,
>>>>>>> because they are declared further down). Note the absense of a label in the
>>>>>>> first HBox.C.
>>>>>>>
>>>>>>> <HBox>
>>>>>>>      <HBox.C for="arrow" vgrow="NEVER"  valignment="RIGHT"/>
>>>>>>> </HBox>
>>>>>>>
>>>>>>> <HBox>
>>>>>>>      <Label  fx:id="arrow"  alignment="center" text="">
>>>>>>>          <HBox.C vgrow="ALWAYS"  valignment="LEFT" maxWidth="Infinity"/>
>>>>>>>      <Label>
>>>>>>> </HBox>
>>>>>>>
>>>>>>>
>>>>>>> Tom
>>>>>>>
>>>>>>>
>>>>>>> On 2012-11-30 14:11, Daniel Zwolenski wrote:
>>>>>>>
>>>>>>>> Ah ok, from your example code it looks like you want to use variables
>>>>>>>> in FXML to define your constraints - getting into that territory of
>>>>>>>> CSS-like style definitions that Richard was talking about?
>>>>>>>>
>>>>>>>> Assuming this is what you want, this can be done in the current setup
>>>>>>>> using the ridiculously under-documented <fx:define> thing.
>>>>>>>>
>>>>>>>> I knocked up a very rough sample for you quickly. The FXML looks like
>>>>>>>> this:
>>>>>>>>
>>>>>>>>    <BorderPane xmlns:fx="http://javafx.com/**fxml<http://javafx.com/fxml>
>>>>>>>> ">
>>>>>>>>
>>>>>>>>      <fx:define>
>>>>>>>>          <HBoxConstraints fx:id="noGrow" hgrow="NEVER"/>
>>>>>>>>          <HBoxConstraints fx:id="growLots" hgrow="ALWAYS"/>
>>>>>>>>      </fx:define>
>>>>>>>>
>>>>>>>>      <center>
>>>>>>>>          <HBox>
>>>>>>>>              <Label text="I don't grow" style="-fx-background-color:**green"
>>>>>>>> Constraints.constraints="$**noGrow"/>
>>>>>>>>              <Label text="I grow big" style="-fx-background-color:**yellow"
>>>>>>>> Constraints.constraints="$**growLots"/>
>>>>>>>>          </HBox>
>>>>>>>>      </center>
>>>>>>>>
>>>>>>>>    </BorderPane>
>>>>>>>>
>>>>>>>> (see https://code.google.com/p/**zenjava-playtime/source/**
>>>>>>>> browse/trunk/layouts/src/main/**resources/fxml/example.fxml<https://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/resources/fxml/example.fxml>
>>>>>>>> )
>>>>>>>>
>>>>>>>> I made a base Constraints class with a static helper method on it
>>>>>>>> (called via "Constraints.constraints" in the FXML above):
>>>>>>>> https://code.google.com/p/**zenjava-playtime/source/**
>>>>>>>> browse/trunk/layouts/src/main/**java/com/playtime/layouts/**
>>>>>>>> Constraints.java<https://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/java/com/playtime/layouts/Constraints.java>
>>>>>>>>
>>>>>>>> And then a specific instance of HBoxConstraints:
>>>>>>>> https://code.google.com/p/**zenjava-playtime/source/**
>>>>>>>> browse/trunk/layouts/src/main/**java/com/playtime/layouts/**
>>>>>>>> HBoxConstraints.java<https://code.google.com/p/zenjava-playtime/source/browse/trunk/layouts/src/main/java/com/playtime/layouts/HBoxConstraints.java>
>>>>>>>>
>>>>>>>> Obviously you would add others, like VBoxConstraints,
>>>>>>>> GridPaneConstraints, etc. All pretty trivial. These helper classes could
>>>>>>>> easily be included in something like JFXtras.
>>>>>>>>
>>>>>>>> So I stick with the stance that FXML is more or less OK here (not to
>>>>>>>> say I wouldn't improve it lots in other areas), and really your
>>>>>>>> conversation is about the Java API which is nicely decoupled to what
>>>>>>>> can/can't be done in FXML. Kudos to Richard and the JFX team for designing
>>>>>>>> the builders right.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Fri, Nov 30, 2012 at 9:20 PM, Tom Eugelink <tbee at tbee.org <mailto:
>>>>>>>> tbee at tbee.org>> wrote:
>>>>>>>>
>>>>>>>>      On 2012-11-30 10:59, Daniel Zwolenski wrote:
>>>>>>>>
>>>>>>>>          It just doesn't do it the exact way you suggest where you
>>>>>>>> specify multiple possibilities directly in the child in case it ends up in
>>>>>>>> a different parent - not an approach I agree with anyway (see my previous
>>>>>>>> comments), but that's just my opinion.
>>>>>>>>
>>>>>>>>
>>>>>>>>      Just to make sure my suggestion is not misunderstood, it does not
>>>>>>>> specify multiple possibilities in the child, but in the layout.
>>>>>>>>
>>>>>>>>      <HBox>
>>>>>>>>          <HBox.C for="arrow" vgrow="NEVER"  valignment="RIGHT"/>
>>>>>>>>      </HBox>
>>>>>>>>
>>>>>>>>      <HBox>
>>>>>>>>          <Label  fx:id="arrow"  alignment="center" text="">
>>>>>>>>              <HBox.C vgrow="ALWAYS"  valignment="LEFT"
>>>>>>>> maxWidth="Infinity"/>
>>>>>>>>          <Label>
>>>>>>>>      </HBox>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>



More information about the openjfx-dev mailing list