package au.com.vaadinutils.crud; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import javax.persistence.metamodel.SingularAttribute; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import au.com.vaadinutils.crud.splitFields.SplitField; import au.com.vaadinutils.crud.splitFields.SplitLabel; import au.com.vaadinutils.domain.iColorFactory; import au.com.vaadinutils.fields.CKEditorEmailField; import au.com.vaadinutils.fields.ColorPickerField; import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.Alignment; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Component; import com.vaadin.ui.DateField; import com.vaadin.ui.GridLayout; import com.vaadin.ui.Label; import com.vaadin.ui.PasswordField; import com.vaadin.ui.TextArea; import com.vaadin.ui.TextField; public class MultiColumnFormLayout<E extends CrudEntity> extends GridLayout { private static transient Logger logger = LogManager.getLogger(MultiColumnFormLayout.class); private static final long serialVersionUID = 1L; private static final int DEFAULT_LABEL_WIDTH = 120; private static final int DEFAULT_FIELD_WIDTH = 100; private final int columns; private int colspan = 1; private int labelWidths[]; private int fieldWidths[]; private ValidatingFieldGroup<E> fieldGroup; private ArrayList<AbstractComponent> fieldList = new ArrayList<AbstractComponent>(); private FormHelper<E> formHelper; //final private GridLayout grid; int x = 0; int y = 0; public MultiColumnFormLayout(int columns, ValidatingFieldGroup<E> fieldGroup) { this.fieldGroup = fieldGroup; // super.setDescription("MultiColumnFormLayout"); this.columns = columns * 2; this.labelWidths = new int[columns]; this.fieldWidths = new int[columns]; for (int i = 0; i < columns; i++) { this.labelWidths[i] = DEFAULT_LABEL_WIDTH; this.fieldWidths[i] = DEFAULT_FIELD_WIDTH; } this.setColumns(columns * 2); this.setRows(1); this.setSpacing(true); formHelper = getFormHelper(this, fieldGroup); init(); for (int i = 1; i < columns * 2; i += 2) { this.setColumnExpandRatio(i, 1.0f); } } protected FormHelper<E> getFormHelper(MultiColumnFormLayout<E> layout, ValidatingFieldGroup<E> fieldGroup) { return new FormHelper<E>(layout, fieldGroup); } /** * Sets the width of the labels in the given column. * * @param column * - zero based column to set the width of * @param width * - the width to set all labels to. */ public void setColumnLabelWidth(int column, int width) { this.labelWidths[column] = width; } /** * Sets the width of the fields in the given column. * * @param column * - zero based column to set the width of * @param width * - the width to set all fields to. */ public void setColumnFieldWidth(int column, int width) { this.fieldWidths[column] = width; } public void setComponentAlignment(Component childComponent, Alignment alignment) { super.setComponentAlignment(childComponent, alignment); } private void init() { super.setSpacing(true); super.setMargin(true); } @Override public void addComponent(Component component) { if (component instanceof SplitField) { internalAddComponent((SplitField) component); } else { super.addComponent(component); x++; if (x > columns) { x = 0; y++; super.insertRow(y); } } } /** * Add a component to the grid. If colspan has been set then it is honoured. * If we are at the end of the row then automatically wrap this item to the * end of the next row. */ public void internalAddComponent(SplitField splitComponent) { // SplitField splitComponent = (SplitField) component; splitComponent.hideLabel(); int fieldSpan = colspan; int captionWidth = 1; if (x + fieldSpan + captionWidth > columns) { x = 0; y++; super.insertRow(y); } int labelWidth = this.labelWidths[x / 2]; Label caption; if (splitComponent.getCaption() == null || splitComponent.getCaption().length() == 0) caption = new Label(""); else caption = splitComponent.getLabel(); caption.setWidth("" + labelWidth); logger.debug("label: caption: {} width: {} x: {} y: {} for col: {}", caption.getValue(), labelWidth, x, y, x / 2); super.addComponent(caption, x, y, x, y); super.setComponentAlignment(caption, Alignment.MIDDLE_RIGHT); x++; String fieldWidth = getFieldWidth(x, fieldSpan); logger.debug("field: {} width: {} X: {} Y: {} X1: {} Y1: {}", caption.getValue(), fieldWidth, x, y, (x + fieldSpan - 1), y); splitComponent.setWidth(fieldWidth); if (!(splitComponent instanceof SplitLabel)) { super.addComponent(splitComponent, x, y, x + fieldSpan - 1, y); super.setComponentAlignment(splitComponent, Alignment.MIDDLE_LEFT); } x += fieldSpan; this.colspan = 1; } private String getFieldWidth(int x, int fieldSpan) { int column = x / 2; int width = 0; width = fieldWidths[column]; for (int i = 1; i < fieldSpan; i++) { width += labelWidths[column + i]; width += fieldWidths[column + i]; } return "" + width; } /** * Adds a new row to the grid and moves the cursor down one row. */ public void newLine() { x = 0; y++; super.insertRow(super.getRows()); super.newLine(); } /** * Set the colspan for the next component that is inserted after which the * colspan will be reset to 1. * * @param colspan */ public void colspan(int colspan) { this.colspan = colspan; } /** * * @param fieldLabel * - the label that will be displayed in the screen layout * @param fieldName * - the column name of the field in the database * @return */ public TextField bindTextField(String fieldLabel, String fieldName) { TextField field = formHelper.bindTextField(this, fieldGroup, fieldLabel, fieldName); this.fieldList.add(field); return field; } public <M> TextField bindTextField(String fieldLabel, SingularAttribute<E, M> member) { TextField field = formHelper.bindTextField(this, fieldGroup, fieldLabel, member); this.fieldList.add(field); return field; } public CKEditorEmailField bindEditorField(SingularAttribute<E, String> member, boolean readonly) { CKEditorEmailField field = formHelper.bindEditorField(this, fieldGroup, member, readonly); this.fieldList.add(field); return field; } /** * Adds a text field to the form without binding it to the FieldGroup * * @param caption * @return */ public TextField addTextField(String fieldLabel) { TextField field = formHelper.bindTextField(this, (ValidatingFieldGroup<E>) null, fieldLabel, (String) null); this.fieldList.add(field); return field; } public PasswordField bindPasswordField(String fieldLabel, SingularAttribute<E, String> fieldName) { PasswordField field = formHelper.bindPasswordField(this, fieldGroup, fieldLabel, fieldName); this.fieldList.add(field); return field; } public PasswordField bindPasswordField(String fieldLabel, String fieldName) { PasswordField field = formHelper.bindPasswordField(this, fieldGroup, fieldLabel, fieldName); this.fieldList.add(field); return field; } /** * Adds a text field to the form without binding it to the FieldGroup * * @param caption * @return */ public PasswordField addPasswordField(String fieldLabel) { PasswordField field = formHelper.bindPasswordField(this, (ValidatingFieldGroup<?>) null, fieldLabel, (SingularAttribute<E, String>) null); this.fieldList.add(field); return field; } public <M> TextArea bindTextAreaField(String fieldLabel, SingularAttribute<E, M> member, int rows) { TextArea field = formHelper.bindTextAreaField(this, fieldGroup, fieldLabel, member, rows); this.fieldList.add(field); return field; } /** * * @param fieldLabel * - the label that will be displayed in the screen layout * @param fieldName * - the column name of the field in the database * @return */ public TextArea bindTextAreaField(String fieldLabel, String fieldName, int rows) { TextArea field = formHelper.bindTextAreaField(this, fieldGroup, fieldLabel, fieldName, rows); this.fieldList.add(field); return field; } public DateField bindDateField(String fieldLabel, SingularAttribute<E, ? extends Date> dateField, String dateFormat, Resolution resolution) { DateField field = formHelper.bindDateField(this, fieldGroup, fieldLabel, dateField, dateFormat, resolution); this.fieldList.add(field); return field; } public DateField bindDateField(String fieldLabel, String fieldName, String dateFormat, Resolution resolution) { DateField field = formHelper.bindDateField(this, fieldGroup, fieldLabel, fieldName, dateFormat, resolution); this.fieldList.add(field); return field; } public Label bindLabel(String fieldLabel) { Label field = formHelper.bindLabel(this, fieldGroup, fieldLabel); this.fieldList.add(field); return field; } public Label bindLabel(Label label) { Label field = formHelper.bindLabel(this, fieldGroup, label); this.fieldList.add(field); return field; } public <M> ComboBox bindEnumField(String fieldLabel, SingularAttribute<E, M> member, Class<?> clazz) { ComboBox field = formHelper.bindEnumField(this, fieldGroup, fieldLabel, member, clazz); this.fieldList.add(field); return field; } public ComboBox bindEnumField(String fieldLabel, String fieldName, Class<?> clazz) { ComboBox field = formHelper.bindEnumField(this, fieldGroup, fieldLabel, fieldName, clazz); this.fieldList.add(field); return field; } public CheckBox bindBooleanField(String fieldLabel, SingularAttribute<E, Boolean> member) { CheckBox field = formHelper.bindBooleanField(this, fieldGroup, fieldLabel, member); this.fieldList.add(field); return field; } public CheckBox bindBooleanField(String fieldLabel, String member) { CheckBox field = formHelper.bindBooleanField(this, fieldGroup, fieldLabel, member); this.fieldList.add(field); return field; } public ColorPickerField bindColorPicker(iColorFactory factory, String fieldLabel, String member) { ColorPickerField field = formHelper.bindColorPickerField(this, fieldGroup, factory, fieldLabel, member); this.fieldList.add(field); return field; } // public ColorPickerField bindColorPicker(iColorFactory factory, String // fieldLabel, SingularAttribute<E, iColor> member) // { // ColorPickerField field = formHelper.bindColorPickerField(this, // fieldGroup, factory, fieldLabel, member); // this.fieldList.add(field); // return field; // } /** * Deprecated - Use EntityFieldBuilder instead * * @param fieldLabel * @param fieldName * - name of primary entities member field that holds the foreign * entity * @param listClazz * - Class of the foreign entity * @param listFieldName * - name of the field to display in the combo box from the * foreign entity * @return */ @Deprecated public <L extends CrudEntity> ComboBox bindEntityField(String fieldLabel, String fieldName, Class<L> listClazz, String listFieldName) { ComboBox field = formHelper.bindEntityField(this, fieldGroup, fieldLabel, fieldName, listClazz, listFieldName); this.fieldList.add(field); return field; } /** * Deprecated - Use EntityFieldBuilder instead * * @param fieldLabel * @param fieldName * @param listClazz * @param listFieldName * @return */ @Deprecated public <L extends CrudEntity> ComboBox bindEntityField(String fieldLabel, SingularAttribute<E, L> fieldName, Class<L> listClazz, SingularAttribute<L, ?> listFieldName) { ComboBox field = formHelper.bindEntityField(this, fieldGroup, fieldLabel, fieldName, listClazz, listFieldName); this.fieldList.add(field); return field; } public ComboBox bindComboBox(String fieldLabel, String fieldName,Collection<?> options) { ComboBox field = formHelper.bindComboBox(this, fieldGroup, fieldName,fieldLabel, options); this.fieldList.add(field); return field; } public ArrayList<AbstractComponent> getFieldList() { return this.fieldList; } public ValidatingFieldGroup<E> getFieldGroup() { return fieldGroup; } public FormHelper<E> getFormHelper() { return this.formHelper; } public void setReadOnly(boolean readOnly) { if (this.fieldGroup.getItemDataSource() != null) this.fieldGroup.setReadOnly(readOnly); } /** * Sets the expand ratio on the row that is currently last. * * @param ratio */ public void setExpandRatio(float ratio) { super.setRowExpandRatio(super.getRows() - 1, ratio); } /** * Sets the given columns expand ratio. * * @param columnIndex * @param ratio */ public void setColumnExpandRatio(int columnIndex, float ratio) { super.setColumnExpandRatio(columnIndex, ratio); } }