I am trying to create a screen layout that has three sections, the top two of which are a fixed size, and the last of which should expand to fill the remaining space on the screen. I'm using a VerticalLayoutContainer (VLC), which contains three HorizontalLayoutContainers (HLCs). I've attempted to control the size of the HLCs using VerticalLayoutData definitions. I don't want to specify a fixed height for the HLCs because I don't know what they will contain until runtime. The problem that I'm having is that the HLCs are all being placed at position 0,0 in the VLC, and are thus overlaying one another. Here's what this looks like (it's a mess!):
Here's the UiBinder code that I'm using:
<!DOCTYPE ui:UiBinder SYSTEM 'http://dl.google.com/gwt/DTD/xhtml.ent'>
<ui:UiBinder
xmlns:gwt='urn:import:com.google.gwt.user.client.ui'
xmlns:gxtbutton='urn:import:com.sencha.gxt.widget.core.client.button'
xmlns:gxtcontainer='urn:import:com.sencha.gxt.widget.core.client.container'
xmlns:gxtform='urn:import:com.sencha.gxt.widget.core.client.form'
xmlns:gxt='urn:import:com.sencha.gxt.widget.core.client'
xmlns:ui='urn:ui:com.google.gwt.uibinder'>
<!-- VerticalLayoutData declarations ========================================================= -->
<ui:with
type='com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData'
field='fillRemainingLayoutData'>
<ui:attributes height='1' width='1'/>
</ui:with>
<ui:with
type='com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData'
field='sizeToContentsLayoutData'>
<ui:attributes height='-1' width='1'/>
</ui:with>
<!-- ========================================================================================= -->
<gxtcontainer:Viewport>
<gxtcontainer:VerticalLayoutContainer>
<gxtcontainer:child layoutData='{sizeToContentsLayoutData}'>
<gxtcontainer:HorizontalLayoutContainer>
<gxtcontainer:VerticalLayoutContainer>
<gxtform:FieldLabel text='Person.FirstName'/>
</gxtcontainer:VerticalLayoutContainer>
<gxtcontainer:VerticalLayoutContainer>
<gxtform:FieldLabel text='Person.EmailAddress'/>
</gxtcontainer:VerticalLayoutContainer>
</gxtcontainer:HorizontalLayoutContainer>
</gxtcontainer:child>
<gxtcontainer:child layoutData='{sizeToContentsLayoutData}'>
<gxtcontainer:HorizontalLayoutContainer>
<gxtbutton:TextButton text='Save Changes'/>
<gxtbutton:TextButton text='Undo Changes'/>
</gxtcontainer:HorizontalLayoutContainer>
</gxtcontainer:child>
<gxtcontainer:child layoutData='{fillRemainingLayoutData}'>
<gxtcontainer:HorizontalLayoutContainer>
<gxtcontainer:VerticalLayoutContainer>
<gxtbutton:TextButton text='Organizations'/>
<gxtbutton:TextButton text='Relationships'/>
</gxtcontainer:VerticalLayoutContainer>
<gxtcontainer:CardLayoutContainer>
<gxt:ContentPanel headerVisible='false'/>
<gxt:ContentPanel headerVisible='false'/>
</gxtcontainer:CardLayoutContainer>
</gxtcontainer:HorizontalLayoutContainer>
</gxtcontainer:child>
</gxtcontainer:VerticalLayoutContainer>
</gxtcontainer:Viewport>
</ui:UiBinder>
And just for completeness, here's the UiBinder Java class:
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
public class PersonDetailsWidget extends Composite {
//==================================================================================================
interface PersonDetailsWidgetUiBinder extends UiBinder<Widget, PersonDetailsWidget> { //
}
//==================================================================================================
public PersonDetailsWidget() {
final PersonDetailsWidgetUiBinder uiBinder = GWT.create(PersonDetailsWidgetUiBinder.class);
initWidget(uiBinder.createAndBindUi(this));
}
//--------------------------------------------------------------------------------------------------
}
And here's the entry point class:
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootLayoutPanel;
public class GXTGrid implements EntryPoint {
//--------------------------------------------------------------------------------------------------
@Override
public void onModuleLoad() {
final PersonDetailsWidget personDetailsWidget = new PersonDetailsWidget();
RootLayoutPanel.get().add(personDetailsWidget);
}
//--------------------------------------------------------------------------------------------------
}
I'm very open to any suggestions for alternative/"correct" approaches to this!
** Edit **
After replacing the VerticalLayoutContainer
widgets with VBoxLayoutContainer
widgets, and the HorizontalLayoutContainer
widgets with HBoxLayoutContainer
widgets, and removing the layout data entries, the overlap problem is resolved. But now the labels and buttons are truncated. Here's the result:
Note: if I execute a ResizeContainer#forceLayout
on the outermost VBoxLayoutContainer
then the buttons are all visible; but the field labels are still truncated.
A HorizontalLayoutContainer within a VerticalLayoutContainer has to have a height set. It's just how it works. You should use a HBoxLayoutContainer instead. Here a quick example (without the use of UIBinder):
VerticalLayoutContainer vlc = new VerticalLayoutContainer();
HBoxLayoutContainer hbc1 = new HBoxLayoutContainer();
hbc1.add(new Label("Person.FirstName:"));
hbc1.add(new Label("Person.EmailAddress:"));
vlc.add(hbc1, new VerticalLayoutData(1, -1));
HBoxLayoutContainer hbc2 = new HBoxLayoutContainer();
hbc2.add(new TextButton("Save Changes"));
hbc2.add(new TextButton("Undo Changes"));
vlc.add(hbc2, new VerticalLayoutData(1, -1));
And that's how it looks like: