100% Component inside Panel

I extended the Panel class and added a Form component and a HorizontalLayout - acting as a footer, which contains a Link and a Button. I am attempting to expand the HorizontalLayout to 100%, while allowing the Panel to shrink to it’s natural size. In short, I would like the footer to expand to the size of the Form. I haven’t been able to accomplish this though.

There are two divs created between the default content VerticalLayout and the HorizontalLayout footer. While the grandparent div expands to the full width of the default content Vertical layout, the parent div of the HorizontalLayout expands only to the natural width, preventing it from taking up the full width.

I have reproduced this issue with other components as well. It can be solved if I remove the undefined width from the panel (defaulting to 100%), or set it to an explicit width. However, this is not ideal as I would like it to vary with the length of the form field captions, which are multi-lingual.

Any suggestions are greatly appreciated.


Here is the relevant code from the extended Panel:


private void createContent()
{
	// set up margins
	((VerticalLayout) getContent()).setMargin(false,true,false,true);

	// create form
	final Form form = new Form();
	form.setWriteThrough(false);
	form.setInvalidCommitted(false);
	
	// FieldFactory
	form.setFormFieldFactory(new LoginFieldFactory());
	form.setItemDataSource(loginItem);
		
	// determines which properties are shown, and in which order:
        form.setVisibleItemProperties(Arrays.asList(new String[] {
                "username", "password"}));
        
        // add form to layout
        addComponent(form);
        
        // add footer
        HorizontalLayout footer = new HorizontalLayout();
        footer.setWidth("100%");
        footer.setSpacing(true);
        footer.setStyleName("e-loginpanel-footer");
        addComponent(footer);
        
        
        // add forgot password link
        final Link forgotPass = new Link();
        forgotPass.setCaption("Forgot Password?");
        footer.addComponent(forgotPass);
        footer.setComponentAlignment(forgotPass, Alignment.MIDDLE_LEFT);
        		
        // add login button
        final Button submit = new Button("Submit");
        // TODO add handler
        footer.addComponent(submit);
        footer.setComponentAlignment(submit, Alignment.MIDDLE_RIGHT);
        
		
}

Here is the relevant code in the view:


// add login panel
loginPanel = new LoginPanel("Login");
loginPanel.setWidth(SIZE_UNDEFINED, 0);
mainLayout.addComponent(loginPanel);
mainLayout.setComponentAlignment(loginPanel, Alignment.MIDDLE_CENTER);

You can’t have a component with relative size within a layout with undefined size. An inner component with 100% width would try to be as big as possible inside a layout that tries to be as small as possible. That’s a paradox.

You can find this sort of problems with the debug mode by giving [tt]
?debug=1
[/tt] in the URL for your app, and then clicking “Analyze layouts” in the debug window. It prints both in the debug window and to the stdout of the application console.

By the way, why not use the built-in footer area in the Form with [tt]
setFooter()
[/tt]?

Speaking to the paradox, I don’t think this is true. In this case, the child at 100% width is only trying to be as wide as its widest sibling; i.e. the form, as this would be the smallest possible width the panel could shrink to.
If the child itself is the widest sibling (child), then it would be 100% width at its natural size. This would allow the undefined size of the parent container, and allow for sub-components to expand to the largest available width.

As for the setFooter() method, I use panels for more than just wrapping forms, so I need a non-specific solution.

Thanks for the info about debug… that’s a handy tool.

As far as I know, this was the intent when last reworking the layouts: an undefined width layout has to have at least one child that defines the width of the outer layout (by being an undefined width layout/component itself or having a defined absolute size). The other children could also have a relative width in such cases. The same also applies for height.

If you find bugs related to this, please double-check that the issue really is a bug in Vaadin and not in your code - it is easy to create invalid layout structures when combining undefined and relative sizes. Then provide a small sample program demonstrating the problem and
file a ticket
(requires registration).