Form has a footer, but not a header

Why does the form item not have a header item? This would make sense that you would want the Edit button at the top and the save/cancel button at the bottom. Since it will probably be scrollable, you would want to lead the user to the bottom for a save, but let them know about the edit button first by placing that at the top.

I thought I would extend for and try to do this myself by overriding the paintComponent method, but by doing that, it will not show the footer. My code was this:

    @Override
    public void paintContent(PaintTarget target) throws PaintException {

        if (formHeader != null) {
            formHeader.paint(target);
        }

        super.paintContent(target);
    }

This showed the Edit button at the top, but it would not show the save/cancel buttons at the bottom. I used the example from the book. The next thing I did was to copy all the code from form and make a new form item, adding the header. After I got it working, I was going to submit for evaluation to add to Vaadin.

But, I can not do that because AbstractField has a a protected isEmpty method that should probably be public since it would be nice to use that method outside the core classes. Because of that, unless I get the full source code for Vaadin and put my class inside the core classes, it cannot use this method, so either I rewrite an isEmpty method or I can not do this.

So, can we add a formHeader item in Form or can we make isEmpty public since there is not logical reason to protect that method.

I would be happy to do the work, but I am not a contributer and am still learning the framework. This is not a huge change to make and would make things more usable. I do plan to submit some enhancements I have already made by extending core classes, but I have to learn how to make a widget first.

Further information.

The isEmpty() in Form is fine, but the isEmpty call to the casted AbstractField is the problem. It is protected and this is the problem I am running into with overriding this method.

Found a work around. Here is the code. I extends Form and did the following:

public class EventEditForm extends Form implements ClickListener{
private GridLayout _layout = new GridLayout(4,6);

VerticalLayout _formLayout = new VerticalLayout();

HorizontalLayout _footer = new HorizontalLayout();
HorizontalLayout _header = new HorizontalLayout();

private Button _btnSave = new Button("Save", (ClickListener) this);
private Button _btnCancel = new Button("Cancel", (ClickListener) this);
private Button _btnEdit = new Button("Edit", (ClickListener) this);

.....

public EventEditForm(DbDataSet ds) {
	setCaption("Event Details");
	_layout.setMargin(true,false,false,true);
	_layout.setSpacing(true);

	_header.setSpacing(true);
	_header.addComponent(_btnEdit);
	_header.setVisible(true);

	_footer.setSpacing(true);
	_footer.addComponent(_btnSave);
	_footer.addComponent(_btnCancel);
	_footer.setVisible(true);

	_formLayout.addComponent(_header);
	_formLayout.addComponent(_layout);
	_formLayout.addComponent(_footer);

	setLayout(_formLayout);

	// Enable buffering so that commit() must be called for the form
	// before input is written to the data. (Form input is not written
	// immediately through to the underlying object.)
	setWriteThrough(false);
	setInvalidCommitted(false);


	//Removed since I will manage the footer.      
            //setFooter(_footer);
	
           setFormFieldFactory(new EventFieldFactory(ds));

	_btnEdit.setEnabled(false);
	_btnSave.setEnabled(false);
	_btnCancel.setEnabled(false);

}//constructor

Not sure if this would work in core classed, but I have seen other frameworks do it this way.