Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GXT (Ext-GWT): Layout problems with ContentPanel

Tags:

java

gwt

gxt

I have a ContentPanel that fits the entire window. It has a topComponent, a widget in the center, and a bottomComponent.

I'm getting layout problems, when I try to add widgets to the topComponent after the ContentPanel has been rendered once:

public void onModuleLoad() {

    final Viewport viewport = new Viewport();
    viewport.setLayout(new FitLayout());

    final ContentPanel contentPanel = new ContentPanel(new FitLayout());
    contentPanel.setHeaderVisible(false);

    final LayoutContainer topContainer = new LayoutContainer(
            new FlowLayout());

    final Button buttonOne = new Button("Top:One");
    topContainer.add(buttonOne);

    contentPanel.setTopComponent(topContainer);
    contentPanel.add(new Button("Center"));
    contentPanel.setBottomComponent(new Button("Bottom"));

    viewport.add(contentPanel);
    RootPanel.get().add(viewport);

    // Later, add a second button to the topComponent ...
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
        @Override
        public void execute() {
            final Button buttonTwo = new Button("Top:Two");
            topContainer.add(buttonTwo); // Doesn't show up at first.

            topContainer.layout(); // Now, buttonTwo shows up. But we have
                            // a new problem: the "Bottom" button disappears...

            contentPanel.layout(true); // This doesn't do anything, BTW.
        }
    });
}

One interesting thing about this is, that the layout corrects itself, as soon as I resize the browser window. What can I do to make it re-layout correctly immediately (I've tried adding several layout() calls etc. in several places and combinations, but haven't had any luck so far.)

(I'm using GWT 2.1.1 with GXT 2.2.1.)

like image 791
Chris Lercher Avatar asked Apr 05 '11 17:04

Chris Lercher


2 Answers

This is happening because when you add another component to a FlowLayout it resizes, thus increasing its own height, which pushes the bottom component below the visible area. There is nothing in the code which shrinks the center component, such that the bottom component stays in its original place.

One more thing is that you are using FitLayout for contentPanel which contains 3 components, a FitLayout is used for Containers with only one component inside, which is supposed to fill out its parent.

You need to consider the following:

1) Use RowLayout, which allows a much better control on how components should be laid out

2) Decide on which component are you willing to place a vertical scroll bar, since you are adding components dynamically.

For your current requirement the following code should suffice:

public void onModuleLoad() {
       final Viewport viewport = new Viewport();
       viewport.setLayout(new FitLayout());

//     final ContentPanel contentPanel = new ContentPanel(new FlowLayout());
//     contentPanel.setHeaderVisible(false);

        final LayoutContainer topContainer = new LayoutContainer(
                new FlowLayout());

        final Button buttonOne = new Button("Top:One");
        topContainer.add(buttonOne);
//    contentPanel.setTopComponent(topContainer);
        final LayoutContainer centerPanel = new LayoutContainer(new FitLayout());

        centerPanel.add(new Button("Center"));
//    contentPanel.add(centerPanel);
        final LayoutContainer botPanel = new LayoutContainer(new FlowLayout());
        botPanel.add(new Button("Bottom"));
//      contentPanel.setBottomComponent(botPanel);

        final ContentPanel panel = new ContentPanel();  
        panel.setHeaderVisible(false);  
        panel.setLayout(new RowLayout(Orientation.VERTICAL));    


        panel.add(topContainer, new RowData(1, -1, new Margins(4)));  
        panel.add(centerPanel, new RowData(1, 1, new Margins(0, 4, 0, 4)));  
        panel.add(botPanel, new RowData(1, -1, new Margins(4)));  

        viewport.add(panel, new FlowData(10));  


        RootPanel.get().add(viewport);

        // Later, add a second button to the topComponent ...
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
            @Override
            public void execute() {
                final Button buttonTwo = new Button("Top:Two");
                topContainer.add(buttonTwo); // Doesn't show up at first.
                panel.layout(true);
            }
        });
}
like image 105
Swapnil Avatar answered Nov 20 '22 06:11

Swapnil


This is happening because the onRender event of topComponent is being invoked in this statement:

contentPanel.setTopComponent(topContainer);

Then, later, you are adding a component: topContainer.add(buttonTwo);. When you resize the window, the onRender event is triggered, and the button you added shows up. The solution to your problem involves triggering the onRender event for topContainer.

Unfortunately, onRender is protected and therefore you cannot call it directly: http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/LayoutContainer.html#onRender%28com.google.gwt.user.client.Element,%20int%29

You will want to use fireEvent to trigger this programmatically instead of manually resizing the window: http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/Component.html#fireEvent%28com.extjs.gxt.ui.client.event.EventType%29

like image 29
Travis Webb Avatar answered Nov 20 '22 07:11

Travis Webb