org.jdal.swing.form.SimpleBoxFormBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.jdal.swing.form.SimpleBoxFormBuilder.java

Source

/*
 * Copyright 2008-2011 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.swing.form;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.border.Border;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.MessageSource;

/**
 * A FormBuilder that create form using BoxLayouts
 * Add components using a implicit cursor.
 * 
 * @author Jose Luis Martin - (jlm@joseluismartin.info)
 */
public class SimpleBoxFormBuilder {

    public static final int SIZE_UNDEFINED = Short.MAX_VALUE;

    private static final Log log = LogFactory.getLog(SimpleBoxFormBuilder.class);
    private Box container = Box.createHorizontalBox();
    private List<Box> columns = new ArrayList<Box>();
    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 = 25;
    private int defaultRowHeight = 25;
    private int defaultSpace = 5;
    private int charWidth = 6;
    private boolean debug = false;
    private boolean fixedHeight = false;
    private MessageSource messageSource;
    private FormFocusTransversalPolicy focusTransversal = new FormFocusTransversalPolicy();
    private Border border = null;

    /** 
     * Default Ctor 
     */
    public SimpleBoxFormBuilder() {
        this(calculateDefaultHeight(), null);
    }

    public SimpleBoxFormBuilder(Border border) {
        this(calculateDefaultHeight(), border);
    }

    public SimpleBoxFormBuilder(int defaultRowHeight) {
        this(defaultRowHeight, null);
    }

    public SimpleBoxFormBuilder(int defaultRowHeight, Border border) {
        this.defaultRowHeight = defaultRowHeight;
        this.border = border;
    }

    /**
     * Add a component to Form at position pointer by cursor, 
     * Increments cursor by one.
     * @param c Component to add
     */
    public void add(Component c) {
        if (debug) {
            if (c instanceof JComponent)
                ((JComponent) c).setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
        }
        addBox(c);

        if (rowHeight < Short.MAX_VALUE) {
            Dimension d = c.getPreferredSize();
            d.height = rowHeight;
            c.setPreferredSize(d);

            c.setMinimumSize(d);

            if (!c.isMaximumSizeSet() || c.getMaximumSize().getHeight() > rowHeight) {
                c.setMaximumSize(new Dimension(Short.MAX_VALUE, rowHeight));
            }
        }

    }

    public void add(Component c, int maxWidth) {
        add(c);
        setMaxWidth(maxWidth);
    }

    public void addBox(Component c) {
        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();
        }
        Box column = getColumn();

        if (rows > 1)
            column.add(Box.createVerticalStrut(defaultSpace));

        column.add(c);

        // don't add Labels to focus transversal
        if (!(c instanceof JLabel)) {
            focusTransversal.add(c);
        } else { // null or empty labels don't size well
            if (StringUtils.isEmpty(((JLabel) c).getText()))
                ((JLabel) c).setText(" ");
        }

        index++;

    }

    /**
     * Gets current column pointed to cursor, create one if none.
     * @return a new or existent column Box.
     */
    private Box getColumn() {
        Box column = null;
        if (index < columns.size()) {
            column = (Box) columns.get(index);
        } else {
            if (!columns.isEmpty())
                container.add(Box.createHorizontalStrut(defaultSpace));

            column = Box.createVerticalBox();
            columns.add(column);
            container.add(column);
            columnsWidth.add(0);

            if (debug) {
                column.setBorder(BorderFactory.createLineBorder(Color.RED));
            }
        }
        return column;
    }

    /**
     * Add a component with label, increments cursor by two.
     * @param name label string
     * @param c component.
     */
    public void add(String name, Component c) {
        JLabel label = new JLabel(name);
        add(label);
        Rectangle2D rec = label.getFontMetrics(label.getFont()).getStringBounds(name, container.getGraphics());
        setMaxWidth(rec.getBounds().width + 10);
        add(c);
    }

    /**
     * @param i
     */
    public void setMaxWidth(int i) {
        if (i > columnsWidth.get(index - 1)) {
            columnsWidth.set(index - 1, i);
        }

    }

    public void row() {
        row(defaultRowHeight);
    }

    /**
     * Move cursor to next row.
     */
    public void row(int rowHeight) {
        index = 0;
        rows++;
        rowsHeight.add(rowHeight);
        this.rowHeight = rowHeight;

    }

    /**
     * Builds the panel form.
     * @return the form component
     */
    public JComponent getForm() {
        // set sizes;
        int columnHeight = 0;
        for (int h : rowsHeight)
            columnHeight += h;

        // add space into components (fillers)
        columnHeight += (rows - 1) * defaultSpace;

        for (int i = 0; i < columns.size(); i++) {
            Box box = columns.get(i);
            int maxWidth = columnsWidth.get(i) == 0 ? Short.MAX_VALUE : columnsWidth.get(i);
            box.setMaximumSize(new Dimension(maxWidth, columnHeight));

            if (maxWidth < Short.MAX_VALUE && columnHeight < Short.MAX_VALUE) {
                box.setMinimumSize(new Dimension(maxWidth, columnHeight));
                box.setPreferredSize(new Dimension(maxWidth, columnHeight));
            }
        }

        container.setFocusTraversalPolicy(focusTransversal);
        container.setFocusTraversalPolicyProvider(true);
        container.setSize(Short.MAX_VALUE, columnHeight);

        if (isFixedHeight()) {
            Dimension maxSize = new Dimension(Short.MAX_VALUE, columnHeight);

            if (container.isMaximumSizeSet()) {
                maxSize = container.getMaximumSize();
                maxSize.height = columnHeight;
            }

            container.setMaximumSize(maxSize);
        }

        if (isDebug())
            container.setBorder(BorderFactory.createLineBorder(Color.BLUE));

        if (border != null)
            container.setBorder(border);

        return container;
    }

    /**
     * Reset the form builder to reuse for creating a new panel
     */
    public void reset() {
        columns = new ArrayList<Box>();
        columnsWidth = new ArrayList<Integer>();
        rowsHeight = new ArrayList<Integer>();
        container = Box.createHorizontalBox();

        index = 0;
        rows = 0;

        focusTransversal = new FormFocusTransversalPolicy();
    }

    public void next() {
        getColumn();
        index++;
    }

    // Getters & Setters

    public int getHeight() {
        return rowHeight;
    }

    public void setHeight(int height) {
        this.rowHeight = height;
        if (rowsHeight.size() > 0 && rows > 0) {
            rowsHeight.remove(rows - 1);
            rowsHeight.add(height);
        }
    }

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public MessageSource getMessageSource() {
        return messageSource;
    }

    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    /**
     * @return the fixedHeight
     */
    public boolean isFixedHeight() {
        return fixedHeight;
    }

    /**
     * @param fixedHeight the fixedHeight to set
     */
    public void setFixedHeight(boolean fixedHeight) {
        this.fixedHeight = fixedHeight;
    }

    /**
     * @return the defaultRowHeight
     */
    public int getDefaultRowHeight() {
        return defaultRowHeight;
    }

    /**
     * @param defaultRowHeight the defaultRowHeight to set
     */
    public void setDefaultRowHeight(int defaultRowHeight) {
        this.defaultRowHeight = defaultRowHeight;
    }

    /**
     * @return the border
     */
    public Border getBorder() {
        return border;
    }

    /**
     * @param border the border to set
     */
    public void setBorder(Border border) {
        this.border = border;
    }

    /**
     * @return the defaultSpace
     */
    public int getDefaultSpace() {
        return defaultSpace;
    }

    /**
     * @param defaultSpace the defaultSpace to set
     */
    public void setDefaultSpace(int defaultSpace) {
        this.defaultSpace = defaultSpace;
    }

    /**
     * @return the charWidth
     */
    public int getCharWidth() {
        return charWidth;
    }

    /**
     * @param charWidth the charWidth to set
     */
    public void setCharWidth(int charWidth) {
        this.charWidth = charWidth;
    }

    /**
     * @return
     */
    private static int calculateDefaultHeight() {
        Dimension d = new JTextField().getPreferredSize();
        return d != null ? d.height : 25;
    }

}