1

How to place LayoutPanel in the middle center of parent LayoutPanel (RootLayoutPanel, screen, browser page)? Assuming the inner panel is of fixed size, outer panel is flexible and does resize (with the browser window).

In Vaadin it is one line command:
(VerticalLayout)outerPane).setComponentAlignment(innerPane, Alignment.MIDDLE_CENTER);

What is the GWT equivalent?
The GWT Layout.Alignment enum provides only BEGIN END STRETCH.
Inadequate. Screen centered placement is essential for displaying smaller forms, dialog boxes, warning messages, login screens etc.

Details on my post on the GWT forum
Thank you

--- UPDATE (27.2.2012) ---------------

To use suggested technique - using setWidgetLeftRight() and setWidgetTopBottom() - I need to compute in fact NW position (x,y) of inner component relative to outer component and do it after every resize of outer container or inner container (content height).

So if GWT does not support centering, and it seems that even in the latest version it does not, there is more coding involved:

outerComponent.setWidgetLeftRight(innerComponent, x, PX, x, PX);
outerComponent.setWidgetTopBottom(innerComponent, y, PX, y, PX);    

x,y to be computed as:
x = (w1 – w2) / 2
y = (h1 – h2) / 2
where:
w1 - outer component width (variable, easy to obtain?)
h1 - outer component height (variable, easy to obtain?)
w2 - inner centered component width (fixed)
h2 - inner centered component height (variable, depending on content, potentially tricky to obtain)

All preferably in pixels (PX?) or EM. When mixed with %, more conversion would have to take place.

With every resize event happens the coordinates has to be recalculated (w1, h1 change).

With every change of the internal content the coordinates has to be recalculated (h2 changes).

It is pretty much absolute layout (AbsolutePanel) in disguise.

CSS solution? I found several examples on this server, but none marked as solved. None with both vertical and horizontal centering and flexible inner component height.

Why I don't prefer CSS based layout solution:

  • Prone to cross browser issues. GWT doesn't help you here.
  • I consider mixing layout in code and in CSS a bad design decision. CSS is best to be left for “decorative” declarations (font sizes and colors, margins, paddings).
  • My own bad experience with CSS layouts; easy to break, difficult to debug, lot's of headaches before you put everything together. Best to avoid. I had great hopes towards GWT.

I am thinking about this code based solution:

  • new subclass of Widget? Panel? Layout? Component? (the inner component)
  • implement RequiresResize expect, implement onResize() callback method
  • obtain actual values for variable dimensions (w1, h1, h2). How?
  • set new coordinates for the inner component. How?

Points to anyone providing solution based on these premises :)

Espinosa
  • 2,491
  • 24
  • 28

2 Answers2

1

Well you could use a VerticalPanel and set the HorizontalAlignment field or in case you want to use LayoutPanels you can adapt the solution in the GWT docs which you posted in the google groups thread.

LayoutPanel p = new LayoutPanel(); 
Widget centercontent;
p.add(centercontent);
p.setWidgetLeftRight(centercontent, 5, EM, 5, EM);     // Center panel 
p.setWidgetTopBottom(centercontent, 5, EM, 5, EM); 

This will create a a center panel with 5 em margins left, right, top and bottom like below (only the white panel in the middle will be visible). EM is a fixed size similar to pixel but depends on the base font size. If your base font size (the one defined for your body) is set to 16 px then 1 EM = 16 px (see here for conversion infos).

enter image description here

You could also use relative values for the margins:

p.setWidgetLeftRight(centercontent, 5, PCT, 5, PCT);     //5 % left and right margin
p.setWidgetTopBottom(centercontent, 5, PCT, 5, PCT);     // 5 % top and bottom margin.

However this way you wont be able to solve your problem entirely (different form sizes -> see screenshots in the google thread) because the center panel will always have fixed margins (5 EM or 5 %) independent of the vertical size of the center panel.
Furthermore the center panel's content will be clipped if it is taller than the available screen size and will be resized when you resize your browser.

So I think the better approach is to put a FlowPanel/HTMLPanel inside a LayoutPanel and apply CSS styles to allow natural resizing.

Ümit
  • 17,379
  • 7
  • 55
  • 74
  • Ümit, thank you for your reply. Yor effort is well appreciated. However I cannot consider your reply as a solution to my problem. The GWT forum thread is mine, there is just a my monologue. None replied. I am exactly where I was. Please see my update. – Espinosa Feb 27 '12 at 20:45
  • Regarding the CSS solution I found 4 relevant, but none marked as solved, please could you point me more specifically? Thank you. I generally try to avoid CSS layout based solutions, see my reasons in the question update, I had great hopes that GWT would help me to achieve this. If the code way proves to be too difficult, I am keeping it as a backup option indeed. – Espinosa Feb 27 '12 at 20:49
  • What speaks against using percentage values for the margins of the inner component? This way you don't have to re-calculate anything when the browser resizes – Ümit Feb 28 '12 at 00:14
  • Percents, yes, I tried them. I tried 50% from all sides, but this caused the whole innerComponent to disappear, if I tried too small numbers it stretched the inner component. The only way I now suppose is to calculate exact percentage using variant of the formula above, – Espinosa Mar 08 '12 at 21:35
0

What if you added a ResizeListener to your center panel (I'm not sure this works, will try it now). Basically, whenever the window resizes, the panel centers itself (by calculating it's height relative to the height of its parent).

EDIT

I ended up getting what I wanted by letting my panel implement ResizeHandler and having the following:

@Override public void onResize(ResizeEvent event) {

    // for my case, this is the first parent element with the full height.
    Widget parent = getParent().getParent();
    int height = parent.getOffsetHeight();

    // could make this more exact by including height of this panel.
    getElement().getStyle().setPaddingTop((int)((height - 80)/2), Unit.PX);
}

// my panel is not initially visible
@Override public void onAttach() { 
    super.onAttach();
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
        @Override public void execute() {
            onResize(null);
        }
    });
}
opowell
  • 568
  • 4
  • 20