com.jgoodies.forms.builder.DefaultFormBuilder Maven / Gradle / Ivy
Show all versions of jgoodies-forms Show documentation
/*
* Copyright (c) 2002-2015 JGoodies Software GmbH. 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 Software GmbH 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.builder;
import java.awt.Color;
import java.awt.Component;
import java.util.ResourceBundle;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import com.jgoodies.common.internal.StringResourceAccessor;
import com.jgoodies.common.swing.MnemonicUtils;
import com.jgoodies.forms.layout.ConstantSize;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.FormSpecs;
import com.jgoodies.forms.layout.RowSpec;
/**
* Provides a means to build form-oriented panels quickly and consistently
* using the {@link FormLayout}. This builder combines frequently used
* panel building steps: add a new row, add a label, proceed to the next
* data column, then add a component.
*
* The extra value lies in the {@code #append} methods that
* append gap rows and component rows if necessary and then add
* the given components. They are built upon the superclass behavior
* {@code #appendRow} and the set of {@code #add} methods.
* A set of component appenders allows to add a textual label and
* associated component in a single step.
*
* This builder can map resource keys to internationalized (i15d) texts
* when creating text labels, titles and titled separators. Therefore
* you must specify a {@code ResourceBundle} in the constructor.
* The builder methods throw an {@code IllegalStateException} if one
* of the mapping builder methods is invoked and no bundle has been set.
*
* You can configure the build process by setting a leading column,
* enabling the row grouping and by modifying the gaps between normal
* lines and between paragraphs. The leading column will be honored
* if the cursor proceeds to the next row. All appended components
* start in the specified lead column, except appended separators that
* span all columns.
*
* It is temptive to use the DefaultFormBuilder all the time and
* to let it add rows automatically. Use a simpler style if it increases
* the code readability. Explicit row specifications and cell constraints
* make your layout easier to understand - but harder to maintain.
* See also the accompanying tutorial sources and the Tips & Tricks
* that are part of the Forms documentation.
*
* Sometimes a form consists of many standardized rows but has a few
* rows that require a customization. The DefaultFormBuilder can do everything
* that the superclasses {@link com.jgoodies.forms.internal.AbstractFormBuilder}
* and {@link com.jgoodies.forms.builder.PanelBuilder} can do;
* among other things: appending new rows and moving the cursor.
* Again, ask yourself if the DefaultFormBuilder is the appropriate builder.
* As a rule of thumb you should have more components than builder commands.
* There are different ways to add custom rows. Find below example code
* that presents and compares the pros and cons of three approaches.
*
* The texts for labels and titles can be marked texts,
* i.e. strings with an optional mnemonic marker.
* See the {@link MnemonicUtils} class comment for details.
*
* Example:
*
* public void build() {
* FormLayout layout = new FormLayout(
* "right:max(40dlu;pref), 3dlu, 80dlu, 7dlu, " // 1st major colum
* + "right:max(40dlu;pref), 3dlu, 80dlu", // 2nd major column
* ""); // add rows dynamically
* DefaultFormBuilder builder = new DefaultFormBuilder(layout)
* .border(Borders.DIALOG);
*
* builder.appendSeparator("Flange");
*
* builder.append("Identifier", identifierField);
* builder.nextLine();
*
* builder.append("PTI [kW]", new JTextField());
* builder.append("Power [kW]", new JTextField());
*
* builder.append("s [mm]", new JTextField());
* builder.nextLine();
*
* builder.appendSeparator("Diameters");
*
* builder.append("da [mm]", new JTextField());
* builder.append("di [mm]", new JTextField());
*
* builder.append("da2 [mm]", new JTextField());
* builder.append("di2 [mm]", new JTextField());
*
* builder.append("R [mm]", new JTextField());
* builder.append("D [mm]", new JTextField());
*
* builder.appendSeparator("Criteria");
*
* builder.append("Location", buildLocationComboBox());
* builder.append("k-factor", new JTextField());
*
* builder.appendSeparator("Bolts");
*
* builder.append("Material", ViewerUIFactory.buildMaterialComboBox());
* builder.nextLine();
*
* builder.append("Numbers", new JTextField());
* builder.nextLine();
*
* builder.append("ds [mm]", new JTextField());
* }
*
*
* Custom Row Example:
*
* public JComponent buildPanel() {
* initComponents();
*
* FormLayout layout = new FormLayout(
* "right:pref, 3dlu, default:grow",
* "");
* DefaultFormBuilder builder = new DefaultFormBuilder(layout)
* .border(Borders.DIALOG)
* .rowGroupingEnabled(true);
*
* // In this approach, we add a gap and a custom row.
* // The advantage of this approach is, that we can express
* // the row spec and comment area cell constraints freely.
* // The disadvantage is the misalignment of the leading label.
* // Also the row's height may be inconsistent with other rows.
* builder.appendSeparator("Single Custom Row");
* builder.append("Name", name1Field);
* builder.appendLineGapRow();
* builder.appendRow(RowSpec.decode("top:31dlu")); // Assumes line is 14, gap is 3
* builder.nextLine(2);
* builder.append("Comment");
* builder.add(new JScrollPane(comment1Area),
* CC.xy(builder.getColumn(), builder.getRow(), "fill, fill"));
* builder.nextLine();
*
* // In this approach, we append a standard row with gap before it.
* // The advantage is, that the leading label is aligned well.
* // The disadvantage is that the comment area now spans
* // multiple cells and is slightly less flexible.
* // Also the row's height may be inconsistent with other rows.
* builder.appendSeparator("Standard + Custom Row");
* builder.append("Name", name2Field);
* builder.append("Comment");
* builder.appendRow(RowSpec.decode("17dlu")); // Assumes line is 14, gap is 3
* builder.add(new JScrollPane(comment2Area),
* CC.xywh(builder.getColumn(), builder.getRow(), 1, 2));
* builder.nextLine(2);
*
* // In this approach, we append two standard rows with associated gaps.
* // The advantage is, that the leading label is aligned well,
* // and the height is consistent with other rows.
* // The disadvantage is that the comment area now spans
* // multiple cells and is slightly less flexible.
* builder.appendSeparator("Two Standard Rows");
* builder.append("Name", name3Field);
* builder.append("Comment");
* builder.nextLine();
* builder.append("");
* builder.nextRow(-2);
* builder.add(new JScrollPane(comment3Area),
* CC.xywh(builder.getColumn(), builder.getRow(), 1, 3));
*
* return builder.build();
* }
*
*
* TODO: Consider adding a method for appending a component that spans the
* remaining columns in the current row. Method name candidates are
* {@code #appendFullSpan} and {@code #appendRemaining}.
*
* @author Karsten Lentzsch
* @version $Revision: 1.16 $
* @since 1.0.3
*
* @see com.jgoodies.forms.internal.AbstractFormBuilder
* @see com.jgoodies.forms.layout.FormSpecs
* @see com.jgoodies.forms.layout.FormLayout
*
* @deprecated Replaced by the {@link FormBuilder} and
* the internationalization support provided
* by the JGoodies Smart Client {@code Resources} class.
* Although deprecated, this class will remain in the Forms library
* for the next versions.
*/
@Deprecated
public final class DefaultFormBuilder extends I15dPanelBuilder {
/**
* Holds the row specification that is reused to describe rows
* that are intended for labels and components.
*
* @see #setDefaultRowSpec(RowSpec)
*/
private RowSpec defaultRowSpec = FormSpecs.PREF_ROWSPEC;
/**
* Holds the row specification that is reused to describe
* the constant gaps between component lines.
*
* @see #setLineGapSize(ConstantSize)
*/
private RowSpec lineGapSpec = FormSpecs.LINE_GAP_ROWSPEC;
/**
* Holds the row specification that describes the constant gaps
* between paragraphs.
*
* @see #setParagraphGapSize(ConstantSize)
*/
private RowSpec paragraphGapSpec = FormSpecs.PARAGRAPH_GAP_ROWSPEC;
/**
* Holds the offset of the leading column - often 0 or 1.
*
* @see #getLeadingColumnOffset()
* @see #setLeadingColumnOffset(int)
* @see #getLeadingColumn()
*/
private int leadingColumnOffset = 0;
/**
* Determines whether new data rows are being grouped or not.
*
* @see #isRowGroupingEnabled()
* @see #setRowGroupingEnabled(boolean)
*/
private boolean rowGroupingEnabled = false;
// Instance Creation ****************************************************
/**
* Constructs a {@code DefaultFormBuilder} for the given
* layout.
*
* @param layout the {@code FormLayout} to be used
*
* @throws NullPointerException if {@code layout} is {@code null}
*/
public DefaultFormBuilder(FormLayout layout) {
this(layout, new JPanel(null));
}
/**
* Constructs a {@code DefaultFormBuilder} for the given
* layout and panel.
*
* @param layout the {@code FormLayout} to be used
* @param container the layout container
*
* @throws NullPointerException if {@code layout} or {@code container} is {@code null}
*/
public DefaultFormBuilder(FormLayout layout, JPanel container) {
this(layout, (StringResourceAccessor) null, container);
}
/**
* Constructs a {@code DefaultFormBuilder} for the given
* layout and resource bundle.
*
* @param layout the {@code FormLayout} to be used
* @param bundle the {@code ResourceBundle} used to lookup i15d
* strings
*
* @throws NullPointerException if {@code layout} is {@code null}
*/
public DefaultFormBuilder(FormLayout layout, ResourceBundle bundle) {
super(layout, bundle);
}
/**
* Constructs a {@code DefaultFormBuilder} for the given
* layout, resource bundle, and panel.
*
* @param layout the {@code FormLayout} to be used
* @param container the layout container
* @param bundle the {@code ResourceBundle} used to lookup i15d
* strings
*
* @throws NullPointerException if {@code layout} or {@code container} is {@code null}
*/
public DefaultFormBuilder(FormLayout layout, ResourceBundle bundle, JPanel container) {
super(layout, bundle, container);
}
/**
* Constructs a {@code DefaultFormBuilder} for the given
* layout and resource bundle.
*
* @param layout the {@code FormLayout} to be used
* @param localizer used to lookup i15d strings
*
* @throws NullPointerException if {@code layout} is {@code null}
*/
public DefaultFormBuilder(FormLayout layout, StringResourceAccessor localizer) {
super(layout, localizer);
}
/**
* Constructs a {@code DefaultFormBuilder} for the given
* layout, resource bundle, and panel.
*
* @param layout the {@code FormLayout} to be used
* @param container the layout container
* @param localizer used to lookup i15d strings
*
* @throws NullPointerException if {@code layout} or {@code container} is {@code null}
*/
public DefaultFormBuilder(FormLayout layout, StringResourceAccessor localizer, JPanel container) {
super(layout, localizer, container);
}
// Frequently Used Panel Properties ***************************************
@Override
public DefaultFormBuilder background(Color background) {
super.background(background);
return this;
}
@Override
public DefaultFormBuilder border(Border border) {
super.border(border);
return this;
}
@Override
public DefaultFormBuilder border(String emptyBorderSpec) {
super.border(emptyBorderSpec);
return this;
}
@Override
public DefaultFormBuilder padding(EmptyBorder padding) {
super.padding(padding);
return this;
}
@Override
public DefaultFormBuilder padding(String paddingSpec, Object... args) {
super.padding(paddingSpec);
return this;
}
@Override
public DefaultFormBuilder opaque(boolean b) {
super.opaque(b);
return this;
}
// Modern (Cascading) Style Configuration *********************************
/**
* Sets the row specification that shall be used for component rows.
* It is {@link FormSpecs#PREF_ROWSPEC} by default.
*
* @param defaultRowSpec the RowSpec to be used for component rows
*/
public DefaultFormBuilder defaultRowSpec(RowSpec defaultRowSpec) {
this.defaultRowSpec = defaultRowSpec;
return this;
}
/**
* Sets the size of gaps between component lines using the given
* constant size.
*
* Examples:
* .lineGapSize(Sizes.ZERO);
* .lineGapSize(Sizes.DLUY9);
* .lineGapSize(Sizes.pixel(1));
*
*
* @param lineGapSize the {@code ConstantSize} that describes
* the size of the gaps between component lines
*/
public DefaultFormBuilder lineGapSize(ConstantSize lineGapSize) {
RowSpec rowSpec = RowSpec.createGap(lineGapSize);
this.lineGapSpec = rowSpec;
return this;
}
/**
* Sets the size of gaps between paragraphs using the given
* constant size.
*
* Examples:
* .setParagraphGapSize(Sizes.DLUY14);
* .setParagraphGapSize(Sizes.dluY(22));
* .setParagraphGapSize(Sizes.pixel(42));
*
*
* @param paragraphGapSize the {@code ConstantSize} that describes
* the size of the gaps between paragraphs
*/
public DefaultFormBuilder paragraphGapSize(ConstantSize paragraphGapSize) {
RowSpec rowSpec = RowSpec.createGap(paragraphGapSize);
this.paragraphGapSpec = rowSpec;
return this;
}
/**
* Sets the offset of the leading column, often 0 or 1.
*
* @param columnOffset the new offset of the leading column
*/
public DefaultFormBuilder leadingColumnOffset(int columnOffset) {
this.leadingColumnOffset = columnOffset;
return this;
}
/**
* Enables or disables the grouping of new data rows.
*
* @param enabled indicates grouping enabled, false disabled
*/
public DefaultFormBuilder rowGroupingEnabled(boolean enabled) {
rowGroupingEnabled = enabled;
return this;
}
// Appending Rows ********************************************************
/**
* Appends a row with this builder's line gap size.
*
* @see #lineGapSize(ConstantSize)
* @see #appendRow(String)
*/
public final void appendLineGapRow() {
appendRow(lineGapSpec);
}
// Filling Columns ******************************************************
/**
* Adds a component to the panel using the default constraints
* with a column span of 1. Then proceeds to the next data column.
*
* @param component the component to add
*/
public void append(Component component) {
append(component, 1);
}
/**
* Adds a component to the panel using the default constraints with
* the given columnSpan. Proceeds to the next data column.
*
* @param component the component to append
* @param columnSpan the column span used to add
*/
public void append(Component component, int columnSpan) {
ensureCursorColumnInGrid();
ensureHasGapRow(lineGapSpec);
ensureHasComponentLine();
add(component, createLeftAdjustedConstraints(columnSpan));
nextColumn(columnSpan + 1);
}
/**
* Adds two components to the panel; each component will span a single
* data column. Proceeds to the next data column.
*
* @param c1 the first component to add
* @param c2 the second component to add
*/
public void append(Component c1, Component c2) {
append(c1);
append(c2);
}
/**
* Adds three components to the panel; each component will span a single
* data column. Proceeds to the next data column.
*
* @param c1 the first component to add
* @param c2 the second component to add
* @param c3 the third component to add
*/
public void append(Component c1, Component c2, Component c3) {
append(c1);
append(c2);
append(c3);
}
// Appending Labels with optional components ------------------------------
/**
* Adds a text label to the panel and proceeds to the next column.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @return the added label
*/
public JLabel append(String textWithMnemonic) {
JLabel label = getComponentFactory().createLabel(textWithMnemonic);
append(label);
return label;
}
/**
* Adds a text label and component to the panel.
* Then proceeds to the next data column.
*
* The created label is labeling the given component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param component the component to add
* @return the added label
*/
public JLabel append(String textWithMnemonic, Component component) {
return append(textWithMnemonic, component, 1);
}
/**
* Adds a text label and component to the panel; the component will span
* the specified number columns. Proceeds to the next data column,
* and goes to the next line if the boolean flag is set.
*
* The created label is labeling the given component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param c the component to add
* @param nextLine true forces a next line
* @return the added label
* @see JLabel#setLabelFor(java.awt.Component)
*/
public JLabel append(String textWithMnemonic, Component c, boolean nextLine) {
JLabel label = append(textWithMnemonic, c);
if (nextLine) {
nextLine();
}
return label;
}
/**
* Adds a text label and component to the panel; the component will span
* the specified number columns. Proceeds to the next data column.
*
* The created label is labeling the given component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param c the component to add
* @param columnSpan number of columns the component shall span
* @return the added label
* @see JLabel#setLabelFor(java.awt.Component)
*/
public JLabel append(String textWithMnemonic, Component c, int columnSpan) {
JLabel label = append(textWithMnemonic);
label.setLabelFor(c);
append(c, columnSpan);
return label;
}
/**
* Adds a text label and two components to the panel; each component
* will span a single column. Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param c1 the first component to add
* @param c2 the second component to add
* @return the added label
*/
public JLabel append(String textWithMnemonic, Component c1, Component c2) {
JLabel label = append(textWithMnemonic, c1);
append(c2);
return label;
}
/**
* Adds a text label and two components to the panel; each component
* will span a single column. Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param c1 the first component to add
* @param c2 the second component to add
* @param colSpan the column span for the second component
* @return the created label
*/
public JLabel append(String textWithMnemonic, Component c1, Component c2, int colSpan) {
JLabel label = append(textWithMnemonic, c1);
append(c2, colSpan);
return label;
}
/**
* Adds a text label and three components to the panel; each component
* will span a single column. Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param c1 the first component to add
* @param c2 the second component to add
* @param c3 the third component to add
* @return the added label
*/
public JLabel append(String textWithMnemonic, Component c1, Component c2, Component c3) {
JLabel label = append(textWithMnemonic, c1, c2);
append(c3);
return label;
}
/**
* Adds a text label and four components to the panel; each component
* will span a single column. Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @param c1 the first component to add
* @param c2 the second component to add
* @param c3 the third component to add
* @param c4 the fourth component to add
* @return the added label
*/
public JLabel append(String textWithMnemonic, Component c1, Component c2, Component c3, Component c4) {
JLabel label = append(textWithMnemonic, c1, c2, c3);
append(c4);
return label;
}
// Appending internationalized labels with optional components ------------
/**
* Adds an internationalized (i15d) text label to the panel using
* the given resource key and proceeds to the next column.
*
* @param resourceKey the resource key for the the label's text
* @return the added label
*/
public JLabel appendI15d(String resourceKey) {
return append(getResourceString(resourceKey));
}
/**
* Adds an internationalized (i15d) text label and component
* to the panel. Then proceeds to the next data column.
*
* The created label is labeling the given component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param component the component to add
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component component) {
return append(getResourceString(resourceKey), component, 1);
}
/**
* Adds an internationalized (i15d) text label and component
* to the panel. Then proceeds to the next data column.
* Goes to the next line if the boolean flag is set.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param component the component to add
* @param nextLine true forces a next line
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component component, boolean nextLine) {
return append(getResourceString(resourceKey), component, nextLine);
}
/**
* Adds an internationalized (i15d) text label to the panel using
* the given resource key; then proceeds to the next data column
* and adds a component with the given column span.
* Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param c the component to add
* @param columnSpan number of columns the component shall span
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component c, int columnSpan) {
return append(getResourceString(resourceKey), c, columnSpan);
}
/**
* Adds an internationalized (i15d) text label and two components
* to the panel; each component will span a single column.
* Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param c1 the first component to add
* @param c2 the second component to add
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component c1, Component c2) {
return append(getResourceString(resourceKey), c1, c2);
}
/**
* Adds an internationalized (i15d) text label and two components
* to the panel; each component will span a single column.
* Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param c1 the first component to add
* @param c2 the second component to add
* @param colSpan the column span for the second component
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component c1, Component c2, int colSpan) {
return append(getResourceString(resourceKey), c1, c2, colSpan);
}
/**
* Adds an internationalized (i15d) text label and three components
* to the panel; each component will span a single column.
* Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param c1 the first component to add
* @param c2 the second component to add
* @param c3 the third component to add
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component c1, Component c2, Component c3) {
return append(getResourceString(resourceKey), c1, c2, c3);
}
/**
* Adds an internationalized (i15d) text label and four components
* to the panel; each component will span a single column.
* Proceeds to the next data column.
*
* The created label is labeling the first component; so the component
* gets the focus if the (optional) label mnemonic is pressed.
*
* @param resourceKey the resource key for the text to add
* @param c1 the first component to add
* @param c2 the second component to add
* @param c3 the third component to add
* @param c4 the third component to add
* @return the added label
*/
public JLabel appendI15d(String resourceKey, Component c1, Component c2, Component c3, Component c4) {
return append(getResourceString(resourceKey), c1, c2, c3, c4);
}
// Adding Titles ----------------------------------------------------------
/**
* Adds a title label to the panel and proceeds to the next column.
*
* @param textWithMnemonic the label's text - may mark a mnemonic
* @return the added title label
*/
public JLabel appendTitle(String textWithMnemonic) {
JLabel titleLabel = getComponentFactory().createTitle(textWithMnemonic);
append(titleLabel);
return titleLabel;
}
/**
* Adds an internationalized title label to the panel and
* proceeds to the next column.
*
* @param resourceKey the resource key for the title's text
* @return the added title label
*/
public JLabel appendI15dTitle(String resourceKey) {
return appendTitle(getResourceString(resourceKey));
}
// Appending Separators ---------------------------------------------------
/**
* Adds a separator without text that spans all columns.
*
* @return the added titled separator
*/
public JComponent appendSeparator() {
return appendSeparator("");
}
/**
* Adds a separator with the given text that spans all columns.
*
* @param text the separator title text
* @return the added titled separator
*/
public JComponent appendSeparator(String text) {
ensureCursorColumnInGrid();
ensureHasGapRow(paragraphGapSpec);
ensureHasComponentLine();
setColumn(super.getLeadingColumn());
int columnSpan = getColumnCount();
setColumnSpan(getColumnCount());
JComponent titledSeparator = addSeparator(text);
setColumnSpan(1);
nextColumn(columnSpan);
return titledSeparator;
}
/**
* Appends an internationalized titled separator for
* the given resource key that spans all columns.
*
* @param resourceKey the resource key for the separator title's text
* @return the added titled separator
*/
public JComponent appendI15dSeparator(String resourceKey) {
return appendSeparator(getResourceString(resourceKey));
}
// Overriding Superclass Behavior ***************************************
/**
* Returns the leading column. Unlike the superclass this method
* honors the column offset.
*
* @return the leading column
*/
@Override
protected int getLeadingColumn() {
int column = super.getLeadingColumn();
return column + leadingColumnOffset * getColumnIncrementSign();
}
// Adding Rows **********************************************************
/**
* Ensures that the cursor is in the grid. In case it's beyond the
* form's right hand side, the cursor is moved to the leading column
* of the next line.
*/
private void ensureCursorColumnInGrid() {
if ( isLeftToRight() && getColumn() > getColumnCount()
|| !isLeftToRight() && getColumn() < 1) {
nextLine();
}
}
/**
* Ensures that we have a gap row before the next component row.
* Checks if the current row is the given {@code RowSpec}
* and appends this row spec if necessary.
*
* @param gapRowSpec the row specification to check for
*/
private void ensureHasGapRow(RowSpec gapRowSpec) {
if (getRow() == 1 || getRow() <= getRowCount()) {
return;
}
if (getRow() <= getRowCount()) {
RowSpec rowSpec = getCursorRowSpec();
if (rowSpec == gapRowSpec) {
return;
}
}
appendRow(gapRowSpec);
nextLine();
}
/**
* Ensures that the form has a component row. Adds a component row
* if the cursor is beyond the form's bottom.
*/
private void ensureHasComponentLine() {
if (getRow() <= getRowCount()) {
return;
}
appendRow(defaultRowSpec);
if (rowGroupingEnabled) {
getLayout().addGroupedRow(getRow());
}
}
/**
* Looks up and returns the row specification of the current row.
*
* @return the row specification of the current row
*/
private RowSpec getCursorRowSpec() {
return getLayout().getRowSpec(getRow());
}
}