You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@pivot.apache.org by Bill van Melle <bi...@gmail.com> on 2010/11/18 01:41:02 UTC

How to wrap text and other form problems

Man, it's hard to get started in Pivot!  I think I may write more about that
in another message, but here's a concrete example.  I wanted to create a
simple popup control to handle a login, so I wrote a class that extends
Sheet.  I've included the bxml file below.  After several iterations, I
still have a whole bunch of problems to solve:

* How do I make the Label control wrap its text?  I gave it the
style wrapText:true, but it has no effect.

* How do I make the TextInput fields a reasonable size?  At first, I was
hoping maybe the container hierarchy would propagate size constraints down
from the top-level component (the sheet), but it doesn't -- the TextInput
fields get truncated.  I also tried putting a width="100" on the
individual TextInput fields, but that seems to be ignored.

* Is there a straightforward way to tell the standard dialog accelerators
(Enter, Esc) what to do?  In WPF, I can add IsDefault and IsCancel
properties to buttons to tell the system to "press" the button when Enter or
Esc is typed.  It looks like the default behavior in Pivot is that Enter
sets the dialog result to true, Esc to false, and both close the
dialog *without
invoking any useful code*!  That means I *must *do something to handle those
keys or my code is very wrong.  It looks like I can add
a ComponentKeyListener to the sheet to capture those keys, but that seems
like a tedious solution to have to apply to every dialog I ever write.  It's
also unclear to me how I get the listener to run in the UI thread.

* How do I space the buttons nicely?  In WPF, I can put them in a Grid and
set their horizontal alignment to Center.  The apparently equivalent Pivot
control is TablePane, but PushButton does not accept a horizontalAlignment
style!  I find this maddening.  Why doesn't *every *component have
properties/styles that tell its container how to lay it out (alignment and
stretch/fill) within the space the container allots?  I noticed, for
example, that BoxPane has style attributes fill & horiz/vert alignment, but
they apply to its children.  Usually that's not what I'm looking for -- I'd
want those attributes to apply to the BoxPane itself with respect to its
parent, and I might well want different values for the children.  As a
really specific example, if I want to put a Separator into a BoxPane and
have it stretch across the width of the container, I set fill:true on the
BoxPane.  But what if I don't want other elements in the pane, say a button,
to be stretched as well?  Am I totally missing something here?

* Are there things I could be writing more easily than I show here?

<my:LoginSheet title="Login to server"
    xmlns:bxml="http://pivot.apache.org/bxml"
    xmlns:my="com.fxpal.myunity"
    xmlns="org.apache.pivot.wtk"
    maximumWidth="300">
    <BoxPane
        styles="{padding:4, verticalAlignment:'top'}"
        orientation="vertical">
        <Form>
            <Form.Section>
                <TextInput bxml:id="textInputName" Form.label="User Name" />
                <TextInput bxml:id="textInputPassword" Form.label="Password"
password="true" />
                <TablePane>
                    <columns>
                        <TablePane.Column width="1*"/>
                        <TablePane.Column width="1*"/>
                    </columns>
                    <rows>
                        <TablePane.Row>
                            <PushButton bxml:id="buttonLogin"
buttonData="Login"
                                styles="{horizontalAlignment:'center'}" />
                            <PushButton bxml:id="buttonCancel"
buttonData="Cancel"
                                styles="{horizontalAlignment:'center'}" />
                        </TablePane.Row>
                    </rows>
                </TablePane>
            </Form.Section>
            <Form.Section>
                <Label bxml:id="labelProblem" styles="{wrapText:true,
color:'red'}" />
            </Form.Section>
        </Form>
    </BoxPane>
</my:LoginSheet>

I'm using Pivot 2.0, since that's what you've been recommending to people
starting new projects (which I am).

Re: How to wrap text and other form problems

Posted by Bill van Melle <bi...@gmail.com>.
>
> I just committed an update that should resolve the layout issue you are
> seeing. I posted some pre-release 2.0 binaries here that you can use to
> verify the fix:
>
> http://ixnay.biz/pivot-2.0/


Thanks.  Since I was already using the trunk via SVN, I just did an update
and rebuilt.  Works fine, both in the BoxPane version and the TablePane
version.

Re: How to wrap text and other form problems

Posted by Greg Brown <gk...@mac.com>.
I just committed an update that should resolve the layout issue you are seeing. I posted some pre-release 2.0 binaries here that you can use to verify the fix:

http://ixnay.biz/pivot-2.0/

You should be able to use the BoxPane approach, but TablePane should be OK too, if you prefer that. Let me know if this does not fix the problem.

Also, with respect to:

> Meanwhile, do you have a suggestion for how one lays out two buttons in a horizontal row and achieve a pleasant amount of space between them, perhaps even nicely balanced independent of window width (e.g., equal amounts of whitespace to the left, to the right, and in between)?  In the dread WPF, I might give them center alignment in 2 columns of a Grid.  Or I might set the buttons' horizontal margins to be a pleasing width (not quite as good, since that remains static as the parent window's size changes).  What can I do in Pivot?

I had suggested that you use the "spacing" style of BoxPane to define an appropriate distance between the buttons. You can also use the "padding" style of BoxPane to apply spacing around the buttons. In most cases, I'd expect this to be sufficient - as the user resizes the window, you generally don't want to increase the distance between the buttons and the edge of the window (assuming that they are right or left aligned - if centered, the left/right padding is dictated by the size of the window anyways). If you do want the padding to scale with the size of the window, you could use a table pane with relative-sized columns, though I think that might create a visually confusing user experience.

G


Re: How to wrap text and other form problems

Posted by Greg Brown <gk...@mac.com>.
We don't use Maven to build Pivot (we use Ant), and the process for getting releases into the central repo is manual and fairly cumbersome. We also don't currently do snapshot builds, so setting something like this up would probably take some doing. 

However, we do have a build target that will build and deploy to your local Maven repo. When you want to update to the latest, just download the most recent source and run "ant maven-install".

G


On Nov 18, 2010, at 11:18 PM, ocean ocean wrote:

> I have to ask... could we pretty please be possible to get the 2.0 snapshots into maven? Could this be part of the continuous build? What changes would that involve? I could download the jars and install them into the local repo but then they wouldn't get updates which kind of defeats the purpose. Any plans on this end?
> 
> On Thu, Nov 18, 2010 at 9:58 PM, Greg Brown <gk...@mac.com> wrote:
>> Ah, so the problem with my original example is that a vertical BoxPane thinks that it is infinitely wide until I give it the fill:true style?  No, it can't be that simple, because even in its absence, BoxPane is able to center- or right-align its contents within the actual width of its parent.  Or are those independent?  Is there any reason I wouldn't want to always say fill:true?
> 
> A BoxPane will align its contents within the width it is given by its own parent. If "fill" is set to true, then it will justify rather than align the contents. However, the preferred size of a BoxPane is independent of either the alignment or "fill" styles. If you want a Label to wrap in a BoxPane, something must apply a width constraint. This is often the parent of the BoxPane, but an explicit preferred width can also be set on the BoxPane itself (though again, in this case, the box pane's parent must be a container that respects preferred size).
> 
>>  There are a couple of ways to handle this. Generally, you'd override close(boolean) and execute your login code if the result is true. In this case, you wouldn't call the superclass close() method, since you want to prevent the dialog from closing. Once the login succeeds, you'll call close() again, but call the superclass method to actually close the dialog. 
>> 
>> Thanks, overriding close is a reasonable approach.  Not quite as simple as you suggest -- if I just call super.close() when the login succeeds, I seem to get into an infinite close loop.  I had to add a private flag to set in the login finished code and test in the close override.
> 
> That seems like a reasonable solution. Only your code would know when it is OK to call super.close(), so a flag is appropriate.
> 
>>>> * How do I space the buttons nicely?  . . .
>> Not sure exactly what you're envisioning, but maybe you could use a horizontal BoxPane with "horizontalAlignment='center'"? You can use the "spacing" style to control how much space is allocated between the buttons.
>> 
>> Ah, I somehow missed seeing that in the BoxPaneSkin.  That will do.  It will take some getting used to, this dichotomy between properties and style attributes.
> 
> Though Pivot currently provides only one theme, it is designed to support multiple themes (or "look-and-feels"). Each L&F may provide its own set of styles - however, the properties of a component (vs. styles) are generally meant to be respected by any skin implementation for that component. Unfortunately, for components that aren't generally "themeable", like layout containers, the line between properties and styles is a bit blurry. You might reasonably argue that the "horizontalAlignment" style of a BoxPane should simply be a property, for example.
> 
> G
> 
> 
> 


Re: How to wrap text and other form problems

Posted by ocean ocean <ri...@gmail.com>.
I have to ask... could we pretty please be possible to get the 2.0 snapshots
into maven? Could this be part of the continuous build? What changes would
that involve? I could download the jars and install them into the local repo
but then they wouldn't get updates which kind of defeats the purpose. Any
plans on this end?

On Thu, Nov 18, 2010 at 9:58 PM, Greg Brown <gk...@mac.com> wrote:

> Ah, so the problem with my original example is that a vertical BoxPane
>> thinks that it is infinitely wide until I give it the fill:true style?  No,
>> it can't be that simple, because even in its absence, BoxPane is able to
>> center- or right-align its contents within the actual width of its parent.
>>  Or are those independent?  Is there any reason I wouldn't want to *
>> always* say fill:true?
>>
>
> A BoxPane will align its contents within the width it is given by its own
> parent. If "fill" is set to true, then it will justify rather than align the
> contents. However, the preferred size of a BoxPane is independent of either
> the alignment or "fill" styles. If you want a Label to wrap in a BoxPane,
> something must apply a width constraint. This is often the parent of the
> BoxPane, but an explicit preferred width can also be set on the BoxPane
> itself (though again, in this case, the box pane's parent must be a
> container that respects preferred size).
>
>  There are a couple of ways to handle this. Generally, you'd override
> close(boolean) and execute your login code if the result is true. In this
> case, you wouldn't call the superclass close() method, since you want to
> prevent the dialog from closing. Once the login succeeds, you'll call
> close() again, but call the superclass method to actually close the dialog.
>
> Thanks, overriding close is a reasonable approach.  Not quite as simple as
> you suggest -- if I just call super.close() when the login succeeds, I seem
> to get into an infinite close loop.  I had to add a private flag to set in
> the login finished code and test in the close override.
>
>
> That seems like a reasonable solution. Only your code would know when it is
> OK to call super.close(), so a flag is appropriate.
>
>  * How do I space the buttons nicely?  . . .
>>>
>>> Not sure exactly what you're envisioning, but maybe you could use a
>> horizontal BoxPane with "horizontalAlignment='center'"? You can use the
>> "spacing" style to control how much space is allocated between the buttons.
>>
>
> Ah, I somehow missed seeing that in the BoxPaneSkin.  That will do.  It
> will take some getting used to, this dichotomy between properties and style
> attributes.
>
>
> Though Pivot currently provides only one theme, it is designed to support
> multiple themes (or "look-and-feels"). Each L&F may provide its own set of
> styles - however, the properties of a component (vs. styles) are generally
> meant to be respected by any skin implementation for that component.
> Unfortunately, for components that aren't generally "themeable", like layout
> containers, the line between properties and styles is a bit blurry. You
> might reasonably argue that the "horizontalAlignment" style of a BoxPane
> should simply be a property, for example.
>
> G
>
>
>

Re: How to wrap text and other form problems

Posted by Greg Brown <gk...@mac.com>.
> Ah, so the problem with my original example is that a vertical BoxPane thinks that it is infinitely wide until I give it the fill:true style?  No, it can't be that simple, because even in its absence, BoxPane is able to center- or right-align its contents within the actual width of its parent.  Or are those independent?  Is there any reason I wouldn't want to always say fill:true?

A BoxPane will align its contents within the width it is given by its own parent. If "fill" is set to true, then it will justify rather than align the contents. However, the preferred size of a BoxPane is independent of either the alignment or "fill" styles. If you want a Label to wrap in a BoxPane, something must apply a width constraint. This is often the parent of the BoxPane, but an explicit preferred width can also be set on the BoxPane itself (though again, in this case, the box pane's parent must be a container that respects preferred size).

>  There are a couple of ways to handle this. Generally, you'd override close(boolean) and execute your login code if the result is true. In this case, you wouldn't call the superclass close() method, since you want to prevent the dialog from closing. Once the login succeeds, you'll call close() again, but call the superclass method to actually close the dialog. 
> 
> Thanks, overriding close is a reasonable approach.  Not quite as simple as you suggest -- if I just call super.close() when the login succeeds, I seem to get into an infinite close loop.  I had to add a private flag to set in the login finished code and test in the close override.

That seems like a reasonable solution. Only your code would know when it is OK to call super.close(), so a flag is appropriate.

>>> * How do I space the buttons nicely?  . . .
> Not sure exactly what you're envisioning, but maybe you could use a horizontal BoxPane with "horizontalAlignment='center'"? You can use the "spacing" style to control how much space is allocated between the buttons.
> 
> Ah, I somehow missed seeing that in the BoxPaneSkin.  That will do.  It will take some getting used to, this dichotomy between properties and style attributes.

Though Pivot currently provides only one theme, it is designed to support multiple themes (or "look-and-feels"). Each L&F may provide its own set of styles - however, the properties of a component (vs. styles) are generally meant to be respected by any skin implementation for that component. Unfortunately, for components that aren't generally "themeable", like layout containers, the line between properties and styles is a bit blurry. You might reasonably argue that the "horizontalAlignment" style of a BoxPane should simply be a property, for example.

G



Re: How to wrap text and other form problems

Posted by Bill van Melle <bi...@gmail.com>.
>
> Don't agree. It's no different than specifying a preferred size on a
> component whose parent container doesn't respect it, for example.
>

> Specifically, a Label needs a width constraint in order to know where to
> break the text. Without a parent that can provide that, it wouldn't know
> where to wrap.
>

Ah, so the problem with my original example is that a vertical BoxPane
thinks that it is infinitely wide until I give it the fill:true style?  No,
it can't be that simple, because even in its absence, BoxPane is able to
center- or right-align its contents within the actual width of its parent.
 Or are those independent?  Is there any reason I wouldn't want to
*always*say fill:true?


There are a couple of ways to handle this. Generally, you'd override
> close(boolean) and execute your login code if the result is true. In this
> case, you wouldn't call the superclass close() method, since you want to
> prevent the dialog from closing. Once the login succeeds, you'll call
> close() again, but call the superclass method to actually close the dialog.
>

Thanks, overriding close is a reasonable approach.  Not quite as simple as
you suggest -- if I just call super.close() when the login succeeds, I seem
to get into an infinite close loop.  I had to add a private flag to set in
the login finished code and test in the close override.

Another way to handle it is to veto the close event, perform the login, and
> then re-close.
>

Okay.  I think that ends up being more verbose, given the verbosity of
listeners, and the fact that I'd still either need that private variable, or
a different one to hang onto the close listener so I can remove it.


> * How do I space the buttons nicely?  . . .
>>
>> Not sure exactly what you're envisioning, but maybe you could use a
> horizontal BoxPane with "horizontalAlignment='center'"? You can use the
> "spacing" style to control how much space is allocated between the buttons.
>

Ah, I somehow missed seeing that in the BoxPaneSkin.  That will do.  It will
take some getting used to, this dichotomy between properties and style
attributes.

Re: How to wrap text and other form problems

Posted by Greg Brown <gk...@mac.com>.
>> * How do I make the Label control wrap its text?  I gave it the style wrapText:true, but it has no effect.
> You need to make sure that the Label is in a container that will respect constrained preferred heights. For example, a TablePane, or a vertical BoxPane with the "fill" style set to true.
> 
> Neither of those quite works right, which I'll elaborate on below.  But it also strikes me as a kind of a broken model if styles only "work" if you pick the right container.

Don't agree. It's no different than specifying a preferred size on a component whose parent container doesn't respect it, for example.

Specifically, a Label needs a width constraint in order to know where to break the text. Without a parent that can provide that, it wouldn't know where to wrap.

>> * How do I make the TextInput fields a reasonable size?  
> 
> Try setting the textSize property.
> 
> That works, thanks.  So what, if anything, does setWidth do on a TextInput component?

It sets the actual width of the component. This is similar to how layout works in AWT/Swing - components specify a "preferred size" that indicates how much space they would like, but it is ultimately up to the parent container to decide how much space they actually get. In general, a caller should specify a preferred width and/or height, but leave the setting of the actual width/height to the layout container.

FYI, another way you could size your text input is to provide an explicit preferred width; e.g. "preferredWidth='120'". But "textSize" will respect the current font, whereas "preferredWidth" won't.

>> * Is there a straightforward way to tell the standard dialog accelerators (Enter, Esc) what to do?  ...
> You don't need to add explicit key listeners. You should open your dialog or sheet with a close listener - that is where you would put any "useful code".
> 
> Well, yes and no. I can certainly restructure the code so that pressing the buttons just closes the sheet, and whoever calls open on the sheet does the processing of the form based on the true/false result.  But it means that I can't keep the sheet open until the login succeeds -- I have to have a close listener that initiates the login code, and if an error comes back, I reopen the sheet, this time with an error message showing.  And to show the user that something is happening during the background authentication call, I can't simply spin an activity indicator on the login sheet, but have to do it somewhere else.  That all seems clumsier than I'd like.

There are a couple of ways to handle this. Generally, you'd override close(boolean) and execute your login code if the result is true. In this case, you wouldn't call the superclass close() method, since you want to prevent the dialog from closing. Once the login succeeds, you'll call close() again, but call the superclass method to actually close the dialog. 

Another way to handle it is to veto the close event, perform the login, and then re-close.

>> * How do I space the buttons nicely?  . . .
> I don't think you're necessarily missing anything - I think you are just expecting layout in Pivot to work the same way it does in WPF, which is not the case. 
> 
> If you don't want an element to stretch to fill the box pane, simply nest it in another box pane whose fill style is not set to true.
> 
> Yeah, okay, it's not WPF (I'll admit I didn't immediately understand the WPF model when I started with it, either).  Meanwhile, do you have a suggestion for how one lays out two buttons in a horizontal row and achieve a pleasant amount of space between them, perhaps even nicely balanced independent of window width (e.g., equal amounts of whitespace to the left, to the right, and in between)?  In the dread WPF, I might give them center alignment in 2 columns of a Grid.  Or I might set the buttons' horizontal margins to be a pleasing width (not quite as good, since that remains static as the parent window's size changes).  What can I do in Pivot?

Not sure exactly what you're envisioning, but maybe you could use a horizontal BoxPane with "horizontalAlignment='center'"? You can use the "spacing" style to control how much space is allocated between the buttons.

> Also, I'd take advantage of form flags if possible, rather than adding your own custom error message label. 
> 
> I'm not sure I see what's to be gained by that.  Flags are a great feature for a complicated form where you can pinpoint an area that's incorrect, but for a login, these days we don't usually tell the user where the error was.  And I need a place to put the error message in any case (the Forms tutorial certainly has one).

Fair enough.

> Anyway, back to the wrapping.  Here's the way my code looks with the BoxPane approach:
> 
> <my:LoginSheet title="Login to server"
>     xmlns:bxml="http://pivot.apache.org/bxml"
>     xmlns:my="com.fxpal.myunity"
>     xmlns="org.apache.pivot.wtk"
>     maximumWidth="300">
>     <BoxPane orientation="vertical" styles="{padding:4, fill:true}">
>         <Form>
>             <Form.Section>
>                 <TextInput bxml:id="textInputName" Form.label="User Name"
>                     textSize="15" />
>                 <TextInput bxml:id="textInputPassword" Form.label="Password"
>                     password="true" textSize="15" />
>             </Form.Section>
>         </Form>
>         
>         <BoxPane orientation="horizontal"
>             styles="{fill:true, horizontalAlignment:'center'}">
>             <PushButton bxml:id="buttonLogin" buttonData="Login" />
>             <PushButton bxml:id="buttonCancel" buttonData="Cancel" />
>         </BoxPane>
>         
>         <Separator />
>         
>         <Label bxml:id="labelProblem" styles="{wrapText:true, color:'red'}" />
>     </BoxPane>
> </my:LoginSheet>
> 
> I can tell it's trying to wrap the text, since some ascenders from the second line are showing thru, but the label's height does not grow as needed.

You have stumbled across a very interesting bug. I'll look into it.

> I also tried a more verbose TablePane:
> 
> <my:LoginSheet title="Login to server"
>     xmlns:bxml="http://pivot.apache.org/bxml"
>     xmlns:my="com.fxpal.myunity"
>     xmlns="org.apache.pivot.wtk"
>     maximumWidth="300">
>     <TablePane styles="{verticalSpacing:4}">
>         <columns>
>             <TablePane.Column width="1*" />
>         </columns>
>         
>         <TablePane.Row height="1*">
>             <Form>
>                 <Form.Section>
>                     <TextInput bxml:id="textInputName" Form.label="User Name"
>                         textSize="15" />
>                     <TextInput bxml:id="textInputPassword" Form.label="Password"
>                         password="true" textSize="15" />
>                 </Form.Section>
>             </Form>
>         </TablePane.Row>
>         
>         <TablePane.Row height="-1">
>             <BoxPane orientation="horizontal" styles="{fill:true, horizontalAlignment:'center'}">
>                 <PushButton bxml:id="buttonLogin" buttonData="Login" />
>                 <PushButton bxml:id="buttonCancel" buttonData="Cancel" />
>             </BoxPane>
>         </TablePane.Row>
>         
>         <TablePane.Row height="-1">
>             <Separator />
>         </TablePane.Row>
>         
>         <TablePane.Row height="-1">
>             <Label bxml:id="labelProblem" styles="{wrapText:true, color:'red'}" />
>         </TablePane.Row>
>     </TablePane>
> </my:LoginSheet>
> 
> This also did not result in a taller label.  The TablePane.Row height value of -1 doesn't seem to be documented anywhere, other than indirectly in the TablePane tutorial, but I'm guessing it means something like "the exact height you need".

It means "use the preferred height of the content". It's the default value, so you don't actually need to specify it.

I'll let you know about the other issue. Thanks for finding it.

G



Re: How to wrap text and other form problems

Posted by Bill van Melle <bi...@gmail.com>.
Thanks for the answers.  At least some of them :).


> * How do I make the Label control wrap its text?  I gave it the
> style wrapText:true, but it has no effect.
>
> You need to make sure that the Label is in a container that will respect
> constrained preferred heights. For example, a TablePane, or a vertical
> BoxPane with the "fill" style set to true.
>

Neither of those quite works right, which I'll elaborate on below.  But it
also strikes me as a kind of a broken model if styles only "work" if you
pick the right container.


> * How do I make the TextInput fields a reasonable size?
>
> Try setting the textSize property.
>

That works, thanks.  So what, if anything, does setWidth do on a TextInput
component?


> * Is there a straightforward way to tell the standard dialog accelerators
> (Enter, Esc) what to do?  ...
>
> You don't need to add explicit key listeners. You should open your dialog
> or sheet with a close listener - that is where you would put any "useful
> code".
>

Well, yes and no. I can certainly restructure the code so that pressing the
buttons just closes the sheet, and whoever calls open on the sheet does the
processing of the form based on the true/false result.  But it means that I
can't keep the sheet open until the login succeeds -- I have to have a close
listener that initiates the login code, and if an error comes back, I reopen
the sheet, this time with an error message showing.  And to show the user
that something is happening during the background authentication call, I
can't simply spin an activity indicator on the login sheet, but have to do
it somewhere else.  That all seems clumsier than I'd like.

Furthermore, adding a key listener doesn't actually work.  My keyPressed
method gets called, and it returns true ("consume the event") if keyCode ==
KeyCode.ENTER, but the dialog closes anyway.  Is there a way to place the
listener so that it can consume the event before the default sheet closer
sees it?

* How do I space the buttons nicely?  . . .
>
> I don't think you're necessarily missing anything - I think you are just
> expecting layout in Pivot to work the same way it does in WPF, which is not
> the case.
>
> If you don't want an element to stretch to fill the box pane, simply nest
> it in another box pane whose fill style is not set to true.
>

Yeah, okay, it's not WPF (I'll admit I didn't immediately understand the WPF
model when I started with it, either).  Meanwhile, do you have a suggestion
for how one lays out two buttons in a horizontal row and achieve a pleasant
amount of space between them, perhaps even nicely balanced independent of
window width (e.g., equal amounts of whitespace to the left, to the right,
and in between)?  In the dread WPF, I might give them center alignment in 2
columns of a Grid.  Or I might set the buttons' horizontal margins to be a
pleasing width (not quite as good, since that remains static as the parent
window's size changes).  What can I do in Pivot?


Also, I'd take advantage of form flags if possible, rather than adding your
> own custom error message label.
>

I'm not sure I see what's to be gained by that.  Flags are a great feature
for a complicated form where you can pinpoint an area that's incorrect, but
for a login, these days we don't usually tell the user where the error was.
 And I need a place to put the error message in any case (the Forms tutorial
certainly has one).

Anyway, back to the wrapping.  Here's the way my code looks with the BoxPane
approach:

<my:LoginSheet title="Login to server"
    xmlns:bxml="http://pivot.apache.org/bxml"
    xmlns:my="com.fxpal.myunity"
    xmlns="org.apache.pivot.wtk"
    maximumWidth="300">
    <BoxPane orientation="vertical" styles="{padding:4, fill:true}">
        <Form>
            <Form.Section>
                <TextInput bxml:id="textInputName" Form.label="User Name"
                    textSize="15" />
                <TextInput bxml:id="textInputPassword" Form.label="Password"
                    password="true" textSize="15" />
            </Form.Section>
        </Form>

        <BoxPane orientation="horizontal"
            styles="{fill:true, horizontalAlignment:'center'}">
            <PushButton bxml:id="buttonLogin" buttonData="Login" />
            <PushButton bxml:id="buttonCancel" buttonData="Cancel" />
        </BoxPane>

        <Separator />

        <Label bxml:id="labelProblem" styles="{wrapText:true, color:'red'}"
/>
    </BoxPane>
</my:LoginSheet>

I can tell it's trying to wrap the text, since some ascenders from the
second line are showing thru, but the label's height does not grow as
needed.

I also tried a more verbose TablePane:

<my:LoginSheet title="Login to server"
    xmlns:bxml="http://pivot.apache.org/bxml"
    xmlns:my="com.fxpal.myunity"
    xmlns="org.apache.pivot.wtk"
    maximumWidth="300">
    <TablePane styles="{verticalSpacing:4}">
        <columns>
            <TablePane.Column width="1*" />
        </columns>

        <TablePane.Row height="1*">
            <Form>
                <Form.Section>
                    <TextInput bxml:id="textInputName" Form.label="User
Name"
                        textSize="15" />
                    <TextInput bxml:id="textInputPassword"
Form.label="Password"
                        password="true" textSize="15" />
                </Form.Section>
            </Form>
        </TablePane.Row>

        <TablePane.Row height="-1">
            <BoxPane orientation="horizontal" styles="{fill:true,
horizontalAlignment:'center'}">
                <PushButton bxml:id="buttonLogin" buttonData="Login" />
                <PushButton bxml:id="buttonCancel" buttonData="Cancel" />
            </BoxPane>
        </TablePane.Row>

        <TablePane.Row height="-1">
            <Separator />
        </TablePane.Row>

        <TablePane.Row height="-1">
            <Label bxml:id="labelProblem" styles="{wrapText:true,
color:'red'}" />
        </TablePane.Row>
    </TablePane>
</my:LoginSheet>

This also did not result in a taller label.  The TablePane.Row height value
of -1 doesn't seem to be documented anywhere, other than indirectly in the
TablePane tutorial, but I'm guessing it means something like "the exact
height you need".  If I change the height of the first row to "1*", as in
some examples I've seen (even though it isn't what I mean), the behavior is
a little different -- the label grows with the wrapped text, but at the
expense of the first row.  That *really *isn't what I mean.

Re: How to wrap text and other form problems

Posted by Greg Brown <gk...@mac.com>.
> * How do I make the Label control wrap its text?  I gave it the style wrapText:true, but it has no effect.

You need to make sure that the Label is in a container that will respect constrained preferred heights. For example, a TablePane, or a vertical BoxPane with the "fill" style set to true.

> * How do I make the TextInput fields a reasonable size?  

Try setting the textSize property.

> * Is there a straightforward way to tell the standard dialog accelerators (Enter, Esc) what to do?  In WPF, I can add IsDefault and IsCancel properties to buttons to tell the system to "press" the button when Enter or Esc is typed.  It looks like the default behavior in Pivot is that Enter sets the dialog result to true, Esc to false, and both close the dialog without invoking any useful code!  That means I must do something to handle those keys or my code is very wrong.  It looks like I can add a ComponentKeyListener to the sheet to capture those keys, but that seems like a tedious solution to have to apply to every dialog I ever write.  It's also unclear to me how I get the listener to run in the UI thread.

You don't need to add explicit key listeners. You should open your dialog or sheet with a close listener - that is where you would put any "useful code".

FYI, all component event listeners run in the UI thread. It is only task listeners that run on a background thread.

> * How do I space the buttons nicely?  In WPF, I can put them in a Grid and set their horizontal alignment to Center.  The apparently equivalent Pivot control is TablePane, but PushButton does not accept a horizontalAlignment style!  I find this maddening.  Why doesn't every component have properties/styles that tell its container how to lay it out (alignment and stretch/fill) within the space the container allots?  I noticed, for example, that BoxPane has style attributes fill & horiz/vert alignment, but they apply to its children.  Usually that's not what I'm looking for -- I'd want those attributes to apply to the BoxPane itself with respect to its parent, and I might well want different values for the children.  As a really specific example, if I want to put a Separator into a BoxPane and have it stretch across the width of the container, I set fill:true on the BoxPane.  But what if I don't want other elements in the pane, say a button, to be stretched as well?  Am I totally missing something here?

I don't think you're necessarily missing anything - I think you are just expecting layout in Pivot to work the same way it does in WPF, which is not the case. 

If you don't want an element to stretch to fill the box pane, simply nest it in another box pane whose fill style is not set to true.

> * Are there things I could be writing more easily than I show here?

I'm not sure I'd put the push buttons in the form itself. Also, I'd take advantage of form flags if possible, rather than adding your own custom error message label. You might also be able to drop the root BoxPane and just move the Form up a level.

> <my:LoginSheet title="Login to server"
>     xmlns:bxml="http://pivot.apache.org/bxml"
>     xmlns:my="com.fxpal.myunity"
>     xmlns="org.apache.pivot.wtk"
>     maximumWidth="300">
>     <BoxPane 
>         styles="{padding:4, verticalAlignment:'top'}"
>         orientation="vertical">
>         <Form>
>             <Form.Section>
>                 <TextInput bxml:id="textInputName" Form.label="User Name" />
>                 <TextInput bxml:id="textInputPassword" Form.label="Password" password="true" />
>                 <TablePane>
>                     <columns>
>                         <TablePane.Column width="1*"/>
>                         <TablePane.Column width="1*"/>
>                     </columns>
>                     <rows>
>                         <TablePane.Row>
>                             <PushButton bxml:id="buttonLogin" buttonData="Login"
>                                 styles="{horizontalAlignment:'center'}" />
>                             <PushButton bxml:id="buttonCancel" buttonData="Cancel"
>                                 styles="{horizontalAlignment:'center'}" />
>                         </TablePane.Row>
>                     </rows>
>                 </TablePane>
>             </Form.Section>
>             <Form.Section>
>                 <Label bxml:id="labelProblem" styles="{wrapText:true, color:'red'}" />
>             </Form.Section>
>         </Form>
>     </BoxPane>
> </my:LoginSheet>