/* * Copyright 2008-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jdal.vaadin.ui.form; import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdal.vaadin.ui.Box; import org.springframework.context.MessageSource; import com.vaadin.server.Sizeable; import com.vaadin.server.Sizeable.Unit; import com.vaadin.ui.Alignment; import com.vaadin.ui.Component; import com.vaadin.ui.Field; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; /** * A FormBuilder that create Layouts using horizontal and vertical layouts. * Add components using a implicit cursor. * * @author Jose Luis Martin - (jlm@joseluismartin.info) */ public class SimpleBoxFormBuilder { public static final int SIZE_FULL = Short.MAX_VALUE; public static final int SIZE_UNDEFINED = 0; private static final int DEFAULT_HEIGHT = 50; private static final Log log = LogFactory.getLog(SimpleBoxFormBuilder.class); private HorizontalLayout container = new HorizontalLayout(); private List<VerticalLayout> columns = new ArrayList<VerticalLayout>(); private List<Integer> columnsWidth = new ArrayList<Integer>(); private List<Integer> rowsHeight = new ArrayList<Integer>(); private int index = 0; private int rows = 0; private int rowHeight = 0; private int defaultRowHeight = DEFAULT_HEIGHT; private int defaultSpace = 5; private int defaultWidth = SIZE_UNDEFINED; private MessageSource messageSource; private boolean spacing = true; private boolean rowCellSpand; private boolean fixedHeight; private boolean fixedWidth; private boolean debug; private boolean useTabIndex; private int tabIndex = 1; /** * Default Ctor */ public SimpleBoxFormBuilder() { this(SIZE_UNDEFINED); } public SimpleBoxFormBuilder(int defaultRowHeight) { this.defaultRowHeight = defaultRowHeight; container.setSpacing(spacing); } public SimpleBoxFormBuilder(SimpleBoxFormBuilder other) { this.defaultRowHeight = other.defaultRowHeight; this.defaultWidth = other.defaultWidth; this.spacing = other.spacing; this.rowCellSpand = other.rowCellSpand; this.debug = other.debug; this.tabIndex = other.tabIndex; } /** * Add a component to Form at position pointer by cursor, * Increments cursor by one. * @param c Component to add */ public void add(Component c) { add(c, null, defaultWidth, Alignment.MIDDLE_CENTER); } public void add(Component c, String label) { add(c, label, defaultWidth, Alignment.MIDDLE_CENTER); } public void add(Component c, int width) { add(c, null, width, Alignment.MIDDLE_CENTER); } public void add(Component c, String label, int width) { add(c, label, width, Alignment.MIDDLE_CENTER); } public void add(Component c, Alignment alignment) { add(c, null, defaultWidth, alignment); } public void add(Component c, String label, Alignment alignment) { add(c, label, defaultWidth, alignment); } public void add(Component c, int width, Alignment alignment) { add(c, null, width, alignment); } public void add(Component c, String label, int width, Alignment alignment) { if (rows == 0 && rowsHeight.isEmpty()) { log.warn("You must call row() before adding components. I will add a row with default height for you"); row(); } if (label != null) c.setCaption(label); VerticalLayout column = getColumn(); column.addComponent(c); index++; setWidth(width); if (alignment != null) { column.setComponentAlignment(c, alignment); } if (rowCellSpand) { c.setWidth(100, Unit.PERCENTAGE); } if (useTabIndex && c instanceof Field) { ((Field<?>) c).setTabIndex(tabIndex++); } } /** * Add a component with label, increments cursor by two. * @param name label string * @param c component. */ public void add(String name, Component c) { c.setCaption(name); add(c); } /** * Gets current column pointed to cursor, create one if none. * @return a new or existent column Box. */ private VerticalLayout getColumn() { VerticalLayout column = null; if (index < columns.size()) { column = (VerticalLayout) columns.get(index); } else { column = Box.createVerticalBox(); column.setSpacing(spacing); column.addStyleName("jd-box-column"); if (debug) column.addStyleName("jd-box-column-debug"); columns.add(column); container.addComponent(column); columnsWidth.add(SIZE_UNDEFINED); } return column; } /** * @param width */ public void setWidth(int width) { if (width > columnsWidth.get(index - 1)) { columnsWidth.set(index - 1, width); } } public void row() { row(defaultRowHeight, true); } public void row(boolean rowCellSpand) { row(defaultRowHeight, this.rowCellSpand); } public void row(int height) { row(height, true); } /** * Move cursor to next row. */ public void row(int rowHeight, boolean rowCellSpand) { index = 0; rows++; rowsHeight.add(rowHeight); this.rowHeight = rowHeight; this.rowCellSpand = rowCellSpand; } /** * Builds the panel form. * @return the form component */ public Component getForm() { for (int i = 0; i < columns.size(); i++) { VerticalLayout box = columns.get(i); int width = columnsWidth.get(i); if (width > SIZE_UNDEFINED && width < SIZE_FULL) { box.setWidth(width, Unit.PIXELS); // shrink container container.setExpandRatio(box, 0); } else if (width == SIZE_FULL) { box.setWidth("100%"); container.setExpandRatio(box, 1); } else { container.setExpandRatio(box, 0); box.setWidth(Sizeable.SIZE_UNDEFINED, Unit.PIXELS); } for (int j = 0; j < rowsHeight.size(); j++) { Component c = box.getComponent(j); int height = rowsHeight.get(j); if (height > SIZE_UNDEFINED && height < SIZE_FULL) { c.setHeight(height, Unit.PIXELS); box.setExpandRatio(c, 0); } else if (height == SIZE_FULL) { c.setHeight("100%"); box.setExpandRatio(c, 1); } else { box.setExpandRatio(c, 0); } } } if (fixedHeight) { container.setHeight(getFormHeight(), Unit.PIXELS); } else { container.setHeight(100, Unit.PERCENTAGE); } if (fixedWidth) { container.setWidth(Sizeable.SIZE_UNDEFINED, Unit.PIXELS); } else { container.setWidth(100, Unit.PERCENTAGE); } container.addStyleName("jd-box"); if (debug) container.addStyleName("jd-box-debug"); return container; } /** * Reset the form builder to reuse for creating a new panel */ public void reset() { columns = new ArrayList<VerticalLayout>(); columnsWidth = new ArrayList<Integer>(); rowsHeight = new ArrayList<Integer>(); container = Box.createHorizontalBox(); index = 0; rows = 0; } public void next() { getColumn(); index++; } public int getFormHeight() { int height = 0; for (int h : rowsHeight) height += h == SIZE_UNDEFINED ? DEFAULT_HEIGHT : h; height += (rows - 1) * 10; return height; } // Getters & Setters public int getHeight() { return rowHeight; } public void setHeight(int height) { this.rowHeight = height < SIZE_FULL ? height : SIZE_FULL; if (rowsHeight.size() > 0 && rows > 0) { rowsHeight.remove(rows -1); rowsHeight.add(height); } } public MessageSource getMessageSource() { return messageSource; } public void setMessageSource(MessageSource messageSource) { this.messageSource = messageSource; } /** * @return the defaultRowHeight */ public int getDefaultRowHeight() { return defaultRowHeight; } /** * @param defaultRowHeight the defaultRowHeight to set */ public void setDefaultRowHeight(int defaultRowHeight) { this.defaultRowHeight = defaultRowHeight; } /** * @return the defaultSpace */ public int getDefaultSpace() { return defaultSpace; } /** * @param defaultSpace the defaultSpace to set */ public void setDefaultSpace(int defaultSpace) { this.defaultSpace = defaultSpace; } /** * @return the spacing */ public boolean isSpacing() { return spacing; } /** * @param spacing the spacing to set */ public void setSpacing(boolean spacing) { this.spacing = spacing; container.setSpacing(spacing); } /** * @return the rowCellSpand */ public boolean isRowCellSpand() { return rowCellSpand; } /** * @param rowCellSpand the rowCellSpand to set */ public void setRowCellSpand(boolean rowCellSpand) { this.rowCellSpand = rowCellSpand; } /** * @return the defaultWidth */ public int getDefaultWidth() { return defaultWidth; } /** * @param defaultWidth the defaultWidth to set */ public void setDefaultWidth(int defaultWidth) { this.defaultWidth = defaultWidth; } public void addGlue() { Label label = new Label(); label.setSizeFull(); add(label, SIZE_FULL); setHeight(SIZE_FULL); } public void addVerticalGlue() { Label label = new Label(); add(label); setHeight(SIZE_FULL); } public void addHorizontalGlue() { Label label = new Label(); label.setHeight("0px"); add(label, SIZE_FULL); } public boolean isFixedHeight() { return fixedHeight; } public void setFixedHeight(boolean fixedHeight) { this.fixedHeight = fixedHeight; } public boolean isFixedWidth() { return fixedWidth; } public void setFixedWidth(boolean fixedWidth) { this.fixedWidth = fixedWidth; } public boolean isDebug() { return debug; } public void setDebug(boolean debug) { this.debug = debug; } public int getTabIndex() { return tabIndex; } public void setTabIndex(int tabIndex) { this.tabIndex = tabIndex; } public boolean isUseTabIndex() { return useTabIndex; } public void setUseTabIndex(boolean useTabIndex) { this.useTabIndex = useTabIndex; } }