/*
* Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of JGoodies Karsten Lentzsch nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jgoodies.forms.factories;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.ConstantSize;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.FormSpec;
import com.jgoodies.forms.layout.RowSpec;
import com.jgoodies.forms.layout.Sizes;
import com.jgoodies.forms.util.LayoutStyle;
/**
* A factory that creates instances of FormLayout for frequently used
* form layouts. It makes form creation easier and more consistent.<p>
*
* <strong>I consider removing the <code>FormLayout</code> factory methods.
* These seem to be less usefull and may lead to poor layout readability.
* If you want to use these methods, you may consider copying them
* to your codebase.</strong><p>
*
* The forms are described by major and minor columns. Major columns
* consist of a leading label and a set of related components, for example: a
* label plus textfield, or label plus textfield plus button. The component
* part of a major column is divided into minor columns as shown in this
* layout:
* <pre>
* <- major column 1 -> <- major column 2 ->
* label1 textfield1a textfield1b label2 textfield2a textfield2b
* label3 textfield3a textfield3b label4 textfield4
* label5 textfield5 label6 textfield6
* </pre><p>
*
* Many forms use 1, 2, 3 or 4 major columns, which in turn are often split
* into 1, 2, 3 or 4 minor columns.
*
* @author Karsten Lentzsch
* @version $Revision$
*
* @see com.jgoodies.forms.layout.FormLayout
* @see ColumnSpec
*/
public final class FormFactory {
private FormFactory() {
// Suppresses default constructor, ensuring non-instantiability.
}
// Frequently used Column Specifications ********************************
/**
* An unmodifyable <code>ColumnSpec</code> that determines its width by
* computing the maximum of all column component minimum widths.
*
* @see #PREF_COLSPEC
* @see #DEFAULT_COLSPEC
*/
public static final ColumnSpec MIN_COLSPEC = new ColumnSpec(Sizes.MINIMUM);
/**
* An unmodifyable <code>ColumnSpec</code> that determines its width by
* computing the maximum of all column component preferred widths.
*
* @see #MIN_COLSPEC
* @see #DEFAULT_COLSPEC
*/
public static final ColumnSpec PREF_COLSPEC = new ColumnSpec(
Sizes.PREFERRED);
/**
* An unmodifyable <code>ColumnSpec</code> that determines its preferred
* width by computing the maximum of all column component preferred widths
* and its minimum width by computing all column component minimum widths.<p>
*
* Useful to let a column shrink from preferred width to minimum width
* if the container space gets scarce.
*
* @see #MIN_COLSPEC
* @see #PREF_COLSPEC
*/
public static final ColumnSpec DEFAULT_COLSPEC = new ColumnSpec(
Sizes.DEFAULT);
/**
* An unmodifyable <code>ColumnSpec</code> that has an initial width
* of 0 pixels and that grows. Useful to describe <em>glue</em> columns
* that fill the space between other columns.
*
* @see #GLUE_ROWSPEC
*/
public static final ColumnSpec GLUE_COLSPEC = new ColumnSpec(
ColumnSpec.DEFAULT, Sizes.ZERO, FormSpec.DEFAULT_GROW);
// Layout Style Dependent Column Specs ***********************************
/**
* Describes a logical horizontal gap between a label and an associated
* component. Useful for builders that automatically fill a grid with labels
* and components.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @since 1.0.3
*/
public static final ColumnSpec LABEL_COMPONENT_GAP_COLSPEC = createGapColumnSpec(LayoutStyle
.getCurrent().getLabelComponentPadX());
/**
* Describes a logical horizontal gap between two related components.
* For example the <em>OK</em> and <em>Cancel</em> buttons are considered
* related.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #UNRELATED_GAP_COLSPEC
*/
public static final ColumnSpec RELATED_GAP_COLSPEC = createGapColumnSpec(LayoutStyle
.getCurrent().getRelatedComponentsPadX());
/**
* Describes a logical horizontal gap between two unrelated components.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #RELATED_GAP_COLSPEC
*/
public static final ColumnSpec UNRELATED_GAP_COLSPEC = createGapColumnSpec(LayoutStyle
.getCurrent().getUnrelatedComponentsPadX());
/**
* Describes a logical horizontal column for a fixed size button. This spec
* honors the current layout style's default button minimum width.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #GROWING_BUTTON_COLSPEC
*/
public static final ColumnSpec BUTTON_COLSPEC = new ColumnSpec(Sizes
.bounded(Sizes.PREFERRED, LayoutStyle.getCurrent()
.getDefaultButtonWidth(), null));
/**
* Describes a logical horizontal column for a growing button. This spec
* does <em>not</em> use the layout style's default button minimum width.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #BUTTON_COLSPEC
*/
public static final ColumnSpec GROWING_BUTTON_COLSPEC = new ColumnSpec(
ColumnSpec.DEFAULT, BUTTON_COLSPEC.getSize(), FormSpec.DEFAULT_GROW);
// Frequently used Row Specifications ***********************************
/**
* An unmodifyable <code>RowSpec</code> that determines its height by
* computing the maximum of all column component minimum heights.
*
* @see #PREF_ROWSPEC
* @see #DEFAULT_ROWSPEC
*/
public static final RowSpec MIN_ROWSPEC = new RowSpec(Sizes.MINIMUM);
/**
* An unmodifyable <code>RowSpec</code> that determines its height by
* computing the maximum of all column component preferred heights.
*
* @see #MIN_ROWSPEC
* @see #DEFAULT_ROWSPEC
*/
public static final RowSpec PREF_ROWSPEC = new RowSpec(Sizes.PREFERRED);
/**
* An unmodifyable <code>RowSpec</code> that determines its preferred
* height by computing the maximum of all column component preferred heights
* and its minimum height by computing all column component minimum heights.<p>
*
* Useful to let a column shrink from preferred height to minimum height
* if the container space gets scarce.
*
* @see #MIN_COLSPEC
* @see #PREF_COLSPEC
*/
public static final RowSpec DEFAULT_ROWSPEC = new RowSpec(Sizes.DEFAULT);
/**
* An unmodifyable <code>RowSpec</code> that has an initial height
* of 0 pixels and that grows. Useful to describe <em>glue</em> rows
* that fill the space between other rows.
*
* @see #GLUE_COLSPEC
*/
public static final RowSpec GLUE_ROWSPEC = new RowSpec(RowSpec.DEFAULT,
Sizes.ZERO, FormSpec.DEFAULT_GROW);
// Layout Style Dependent Row Specs *************************************
/**
* Describes a logical vertzical gap between two related components.
* For example the <em>OK</em> and <em>Cancel</em> buttons are considered
* related.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #UNRELATED_GAP_ROWSPEC
*/
public static final RowSpec RELATED_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
.getCurrent().getRelatedComponentsPadY());
/**
* Describes a logical vertical gap between two unrelated components.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #RELATED_GAP_ROWSPEC
*/
public static final RowSpec UNRELATED_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
.getCurrent().getUnrelatedComponentsPadY());
/**
* Describes a logical vertical narrow gap between two rows in the grid.
* Useful if the vertical space is scarce or if an individual vertical gap
* shall be small than the default line gap.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #LINE_GAP_ROWSPEC
* @see #PARAGRAPH_GAP_ROWSPEC
*/
public static final RowSpec NARROW_LINE_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
.getCurrent().getNarrowLinePad());
/**
* Describes the logical vertical default gap between two rows in the grid.
* A little bit larger than the narrow line gap.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #NARROW_LINE_GAP_ROWSPEC
* @see #PARAGRAPH_GAP_ROWSPEC
*/
public static final RowSpec LINE_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
.getCurrent().getLinePad());
/**
* Describes the logical vertical default gap between two paragraphs in
* the layout grid. This gap is larger than the default line gap.<p>
*
* <strong>Note:</strong> In a future version this constant will likely
* be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
*
* @see #NARROW_LINE_GAP_ROWSPEC
* @see #LINE_GAP_ROWSPEC
*/
public static final RowSpec PARAGRAPH_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
.getCurrent().getParagraphPad());
// Factory Methods ******************************************************
/**
* Creates and returns an instance of <code>FormLayout</code>
* to build forms with the specified number of major and minor columns.<p>
*
* The layout will use default values for all gaps.<p>
*
* <strong>This method may be removed from a future version.</strong>
*
* @param majorColumns the number of used major columns
* @param minorColumns the number of used minor columns
* @param labelColumnSpec specifies the label columns
* @return a prepared <code>FormLayout</code>
*/
public static FormLayout createColumnLayout(int majorColumns,
int minorColumns, ColumnSpec labelColumnSpec) {
return createColumnLayout(majorColumns, minorColumns, labelColumnSpec,
Sizes.DLUX14, Sizes.DLUX2);
}
/**
* Creates and returns an instance of <code>FormLayout</code>
* to build forms with the given number of major columns.
* Major columns consists of a label and a component section, where each
* component section is divided into the given number of minor columns.<p>
*
* The layout will use the specified gaps to separate major columns,
* and the label and component section.<p>
*
* <strong>This method may be removed from a future version.</strong>
*
* @param majorColumns the number of major columns
* @param minorColumns the number of minor columns
* @param labelColumnSpec specifies the label columns
* @param indent an optional <code>ConstantSize</code>
* that describes the width of the leading indent column
* @param minorColumnGap a <code>ConstantSize</code> that describes
* the gap between minor columns
* @return a prepared <code>FormLayout</code>
*/
public static FormLayout createColumnLayout(int majorColumns,
int minorColumns, ColumnSpec labelColumnSpec, ConstantSize indent,
ConstantSize minorColumnGap) {
return createColumnLayout(majorColumns, minorColumns, labelColumnSpec,
PREF_COLSPEC, indent, Sizes.DLUX14, minorColumnGap);
}
/**
* Creates and returns an instance of <code>FormLayout</code>
* to build forms with the given number of major columns.
* Major columns consists of a label and a component section, where each
* component section is divided into the given number of minor columns.<p>
*
* The layout will use the specified gaps to separate major columns,
* minor columns, and the label and component section.<p>
*
* <strong>This method may be removed from a future version.</strong>
*
* @param majorColumns the number of major columns
* @param minorColumns the number of minor columns
* @param labelColumnSpec specifies the label columns
* @param componentColumnSpec specifies the label columns
* @param indent an optional <code>ConstantSize</code>
* that describes the width of the leading indent column
* @param majorColumnGap a <code>ConstantSize</code> that describes
* the gap between major columns
* @param minorColumnGap a <code>ConstantSize</code> that describes
* the gap between minor columns
* @return a prepared <code>FormLayout</code>
*/
public static FormLayout createColumnLayout(int majorColumns,
int minorColumns, ColumnSpec labelColumnSpec,
ColumnSpec componentColumnSpec, ConstantSize indent,
ConstantSize majorColumnGap, ConstantSize minorColumnGap) {
ColumnSpec majorGapColSpec = createGapColumnSpec(majorColumnGap);
ColumnSpec minorGapColSpec = createGapColumnSpec(minorColumnGap);
FormLayout layout = new FormLayout(new ColumnSpec[] {},
new RowSpec[] {});
// Add the optional leading indent.
if (indent != null) {
layout.appendColumn(createGapColumnSpec(indent));
}
for (int i = 0; i < majorColumns; i++) {
// Add the optional label column with gap.
if (labelColumnSpec != null) {
layout.appendColumn(labelColumnSpec);
layout.appendColumn(RELATED_GAP_COLSPEC);
}
// Add the minor columns with separating gaps.
for (int j = 0; j < minorColumns; j++) {
layout.appendColumn(componentColumnSpec);
layout.addGroupedColumn(layout.getColumnCount());
if (j < minorColumns - 1) {
layout.appendColumn(minorGapColSpec);
}
}
// Add a gap between major columns.
if (i < majorColumns - 1) {
layout.appendColumn(majorGapColSpec);
}
}
return layout;
}
// Helper Code **********************************************************
/**
* Creates and returns a {@link ColumnSpec} that represents a gap with the
* specified {@link ConstantSize}.
*
* @param gapSize a <code>ConstantSize</code> that specifies the gap
* @return a <code>ColumnSpec</code> that describes a horizontal gap
*/
public static ColumnSpec createGapColumnSpec(ConstantSize gapSize) {
return new ColumnSpec(ColumnSpec.LEFT, gapSize, FormSpec.NO_GROW);
}
/**
* Creates and returns a {@link RowSpec} that represents a gap with the
* specified {@link ConstantSize}.
*
* @param gapSize a <code>ConstantSize</code> that specifies the gap
* @return a <code>RowSpec</code> that describes a vertical gap
*/
public static RowSpec createGapRowSpec(ConstantSize gapSize) {
return new RowSpec(RowSpec.TOP, gapSize, FormSpec.NO_GROW);
}
}