FlowPanel vs. HorizontalPanel

1,492 views
Skip to first unread message

Greg Dougherty

unread,
Nov 30, 2010, 12:41:08 PM11/30/10
to Google Web Toolkit
I have created a FlowPanel that contains 4 ListBoxes and a button. I
wanted to put some space between the items, so I added empty
HorizontalPanels (with padding: 3px;) as spacers in between each
item. FlowPanel responded by placing each item (including each of the
HorizontalPanels), on its own line (IOW, it's now acting like a
VerticalPanel).

If I remove some of the spacers, then the items that don't have
spacers between them share a line with each other, and the ones with
spacers each go on a separate line.

Is this a bug? Is this supposed to happen? How do I fix it?

While I'm asking, if you resize the panel that a FlowPanel is in, does
it automatically "reflow" its items?

Thanks.

Greg

Brian Reilly

unread,
Nov 30, 2010, 1:06:06 PM11/30/10
to google-we...@googlegroups.com
On Tue, Nov 30, 2010 at 12:41 PM, Greg Dougherty <doughert...@mayo.edu> wrote:
I have created a FlowPanel that contains 4 ListBoxes and a button.  I
wanted to put some space between the items, so I added empty
HorizontalPanels (with padding: 3px;) as spacers in between each
item.  FlowPanel responded by placing each item (including each of the
HorizontalPanels), on its own line (IOW, it's now acting like a
VerticalPanel).

If I remove some of the spacers, then the items that don't have
spacers between them share a line with each other, and the ones with
spacers each go on a separate line.

Is this a bug?  Is this supposed to happen?  How do I fix it?

HorizontalPanel and VerticalPanel are implemented as an HTML table. Tables are block-level elements whereas your form elements are inline elements. Inserting block-level elements (div, p, etc.) cause exactly what you're seeing in terms of wrapping, so there isn't any bug there.

That said, you'd probably be better off using CSS to add margins to your form elements. At any rate, inserting empty tables is a pretty heavy-weight and unpredictable way of managing layout. Alternately, if you really want those items to be in a row, just put them inside of a single HorizontalPanel.
 
While I'm asking, if you resize the panel that a FlowPanel is in, does
it automatically "reflow" its items?

Yes, items will "reflow" to the extent possible within the constraints of any explicit widths that may be set. Note that if you put things in a HorizontalPanel as I suggested above, that will not reflow since it renders as an HTML table.

-Brian

Greg Dougherty

unread,
Nov 30, 2010, 1:46:39 PM11/30/10
to Google Web Toolkit
Ah, thanks.

I tried adding padding to my ListBoxes. That caused the inside of the
box to grow, but did not put any space between the borders of the
adjacent boxes, which is the behavior I want.

I put them in a FlowPanel because I want them to flow, one two or
three items per line, depending on what fits. Since they're above a
table that the user can grow or shrink, I don't want to manage this by
hand.

Greg

On Nov 30, 12:06 pm, Brian Reilly <br...@ireilly.com> wrote:
> On Tue, Nov 30, 2010 at 12:41 PM, Greg Dougherty <dougherty.greg...@mayo.edu

Greg Dougherty

unread,
Nov 30, 2010, 2:10:50 PM11/30/10
to Google Web Toolkit
"Inserting block-level elements (div, p, etc.) cause exactly what
you're seeing in terms of wrapping, so there isn't any bug there. "

So you're saying there's no way to have two elements (say a label and
the thing it's labeling) always stay together within an operable
FlowPanel, since all the ways of binding them together involve Block
Elements? (Or is there a way of sticking two Widgets together (other
than a custom widget), that doesn't use a block element?)

Greg

On Nov 30, 12:06 pm, Brian Reilly <br...@ireilly.com> wrote:
> On Tue, Nov 30, 2010 at 12:41 PM, Greg Dougherty <dougherty.greg...@mayo.edu

Brian Reilly

unread,
Nov 30, 2010, 2:55:27 PM11/30/10
to google-we...@googlegroups.com
First, let's separate two concepts. You suggested using a custom widget to bundle two things together. While that may bundle them together from a source code point of view, that custom widget it ultimately rendered as HTML. Therefore, HTML ultimately defines the rules for how your content will be rendered. When composing GWT widgets together to create specific layouts, it's always good to understand at least superficially what the resulting HTML will be (e.g., to know when to use InlineLabel instead of Label).

Now, to answer your question... if you have a bunch of inline elements, you can keep them together by wrapping them in a span styled with "white-space:nowrap;".

If your form elements aren't dynamic and you're using UiBinder, this is pretty easy to do by wrapping everything in an HTMLPanel (which will effectively behave like a FlowPanel, except that you can also mix in HTML with your widgets). If you're doing this all from java, you can still do it, but you have to use HTMLPanel.add() or HTMLPanel.addAndReplaceElement() yourself. As far as I know, GWT doesn't provide any container widgets that render as span elements; all Panel widgets render as divs.

If that doesn't work for you, you can look into using block elements and float:left;, but that comes with its own complications (and you also don't get nice text alignment across blocks.

-Brian

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


Greg Dougherty

unread,
Dec 10, 2010, 10:40:52 AM12/10/10
to Google Web Toolkit
Hi Brian,

Thanks for the reply. (I "solved" the initial problem by biting the
bullet, and switching to a table. But I'm still curious about this.)

So, if I understand you correctly, I could have an HTMLPanel Cell that
acts as a FlowPanel, and a "Container Widget" that added 'new HTML
("<span white-space:nowrap>")' to that Cell, then added the elements
it wanted to keep together, then added 'new HTML ("</span>")', and
those items would all stay together within the Cell. Yes?

Thanks!

Greg

On Nov 30, 1:55 pm, Brian Reilly <br...@ireilly.com> wrote:
> First, let's separate two concepts. You suggested using a custom widget to
> bundle two things together. While that may bundle them together from a
> source code point of view, that custom widget it ultimately rendered as
> HTML. Therefore, HTML ultimately defines the rules for how your content will
> be rendered. When composing GWT widgets together to create specific layouts,
> it's always good to understand at least superficially what the resulting
> HTML will be (e.g., to know when to use InlineLabel instead of Label).
>
> Now, to answer your question... if you have a bunch of inline elements, you
> can keep them together by wrapping them in a span styled with
> "white-space:nowrap;".
>
> If your form elements aren't dynamic and you're using UiBinder, this is
> pretty easy to do by wrapping everything in an HTMLPanel (which will
> effectively behave like a FlowPanel, except that you can also mix in HTML
> with your widgets). If you're doing this all from java, you can still do it,
> but you have to use HTMLPanel.add() or HTMLPanel.addAndReplaceElement()
> yourself. As far as I know, GWT doesn't provide any container widgets that
> render as span elements; all Panel widgets render as divs.
>
> If that doesn't work for you, you can look into using block elements and
> float:left;, but that comes with its own complications (and you also don't
> get nice text alignment across blocks.
>
> -Brian
>
> On Tue, Nov 30, 2010 at 2:10 PM, Greg Dougherty
> <dougherty.greg...@mayo.edu>wrote:
> > google-web-tool...@googlegroups.com<google-web-toolkit%2Bunsu...@googlegroups.com>
> > .

Brian Reilly

unread,
Dec 10, 2010, 11:38:52 AM12/10/10
to google-we...@googlegroups.com
Now I'm not sure if you're trying to prevent wrapping within a table
cell or if you're still considering not using a table and preventing
wrapping between form fields and their labels. However, the solution
is pretty much the same either way.

I think you have the right idea, but using a
com.google.gwt.user.client.ui.HTML widget won't work. That widget
renders its content inside of a div element, so it's already game over
before you've added the elements you want to keep together.

Again, from UiBinder, this is pretty easy:

<g:HTMLPanel>
<span style="white-space:nowrap">First name: <g:TextBox
ui:field="name"></span>
<span style="white-space:nowrap">Last name: <g:TextBox ui:field="name"></span>
</g:HTMLPanel>

This will tell the browser to do its best to not wrap between each
field and its label, even though there are spaces there.

From Java code, the idea is the same, but the implementation is a bit
different. I did this once before when I first started using GWT and I
don't know if this is the correct/best way to do this, but it did work
for me:

String nameId = HTMLPanel.createUniqueId();
HTMLPanel html = new HTMLPanel("<span
style=\"white-space:nowrap\">Name :<input id=\"" + nameId +
"\"></span>");
html.addAndReplaceElement(new TextBox(), nameId);

Obviously it gets more complicated the more elements and element
groups you have.

Finally, HTMLPanel itself is going to be within a div element.
However, there's another form of the HTMLPanel constructor that takes
a tag name as the first argument:

new HTMLPanel("span", "<span ...");

Personally, I might try to dig one level deeper to avoid the extra
span element that this would introduce, but it shouldn't do any harm.

-Brian

> To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages