// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: BBFormBuilder.java,v 1.12 2008/02/28 07:47:52 spyromus Exp $
//
package com.salas.bb.utils.uif;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.Sizes;
import javax.swing.*;
import java.awt.*;
import java.util.ResourceBundle;
/**
* Enhanced builder of forms. This class helps build JGoodies forms incrementally. You need
* to understand JGoodies Forms to use this class. Note that this is not a general users guide for
* this class just practical notes. If you want to add more information as you learn to use this, feel free!
*
* Some key ideas to help you get going:
*
* When constructed, a a JGoodies "columns definition" string is supplied which establishes
* the number of columns, and the constraints on the widths of the columns
*
* From that point, a series of "append" methods are called, each supplying one or more components,
* and indicating whether the components should span more than one column.
*
* When you use this class you need to keep track of where you are, what column and what row, because
* by default this 'cursor' will wrap from the end of one row to the beginning of the next one, automatically.
*
* If you want to override this, you can for example call one of the nextColumn() and/or nextLine() related methods.
*
* What does nextline() do? nextLine() moves the cursor down several lines. It doesn't
* create rows.
*
* If you have just filled some row the cursor at the end of this row and
* there are no rows below it.
*
* If you continue with append(someComponent) it will see that cursor points to the column after the
* last defined. Consequentially, it will move cursor one line down and to the very left. If there's
* a row present, it will use this row to add component.
* If there's no row it will:
* a. create gap row
* b. move cursor one more line down
* c. create content row (with preferred height)
* d. add your component
* Now what happens when you do nextline() after filling the row. You tell
* that you wish to move cursor one line down. It is actually what the
* engine does implicitly and the only case when you need to use it
* explicitly is when you don't wish to fill the row to the end. You have
* more columns to the right, but you wish to break to the next line, so
* you tell nextLine().
* What happens when you tell nextLine(2). You jump two rows down. In other
* words, you jump over one row. This row doesn't exist and engine fails to
* create the second row after that missing... that's an exception.
* Having all this in mind, if you want to create a big gap, dont do nextLine(2). Instead:
*
* appendUnrelatedComponentsRow() -- it's a big fixed-height gap.
* go to the next line
* and go to the next line again, or you will end up with components
* placed on this gap row.
* The shorter recording of this (thanks to my builder) is appendUnrelatedComponentsRow(2).
*/
public class BBFormBuilder
{
private DefaultFormBuilder builder;
/**
* Constructs an instance of builder for given columns layout. Users and instance of
* <code>JPanel</code> as layout container.
*
* @param columnsDefinition columns layout.
*/
public BBFormBuilder(String columnsDefinition)
{
this(new FormLayout(columnsDefinition));
}
/**
* Constructs an instance of builder for the given layout. Uses an instance of
* <code>JPanel</code> as layout container.
*
* @param layout the form layout used to layout the container
*/
public BBFormBuilder(FormLayout layout)
{
this(layout, null, new JPanel(null));
}
/**
* Constructs an instance of builder for the given layout. Uses an instance of
* <code>JPanel</code> as layout container.
*
* @param layout the form layout used to layout the container
* @param bundle the resource bundle used to lookup i15d strings
*/
public BBFormBuilder(FormLayout layout, ResourceBundle bundle)
{
this(layout, bundle, new JPanel(null));
}
/**
* Constructs an instance of builder for the given layout. Uses an instance of
* <code>JPanel</code> as layout container.
*
* @param columnsDefinition columns layout.
* @param panel layout container.
*/
public BBFormBuilder(String columnsDefinition, JPanel panel)
{
this(new FormLayout(columnsDefinition), panel);
}
/**
* Constructs an instance of builder for the given FormLayout and layout container.
*
* @param layout the <code>FormLayout</code> used to layout the container
* @param panel the layout container
*/
public BBFormBuilder(FormLayout layout, JPanel panel)
{
this(layout, null, panel);
}
/**
* Sets the offset of the leading column, often 0 or 1.
*
* @param columnOffset the new offset of the leading column
*/
public void setLeadingColumnOffset(int columnOffset)
{
builder.setLeadingColumnOffset(columnOffset);
}
/**
* Constructs an instance of builder for the given FormLayout and layout container.
*
* @param layout the <code>FormLayout</code> used to layout the container
* @param bundle the <code>ResourceBundle</code> used to lookup i15d strings
* @param panel the layout container
*/
public BBFormBuilder(FormLayout layout, ResourceBundle bundle, JPanel panel)
{
builder = new DefaultFormBuilder(layout, bundle, panel);
builder.setLineGapSize(Sizes.DLUY2);
builder.setParagraphGapSize(Sizes.DLUY7);
}
/**
* Adds a string label.
*
* @param str string.
*/
public void append(String str)
{
append(new JLabel(str));
}
/**
* 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)
{
builder.append(component, columnSpan);
}
/**
* Appends two components one after another.
*
* @param c1 first component.
* @param c2 second component.
*/
public void append(Component c1, Component c2)
{
append(c1);
append(c2);
}
/**
* Appends labeled component.
*
* @param textWithMnemonic text with mnemonic mark.
* @param c component.
*/
public void append(String textWithMnemonic, Component c)
{
append(textWithMnemonic, 1, c, 1, null, 1);
}
/**
* Adds a text label to the panel and proceeds to the next column.
*
* @param textWithMnemonic the label's text - may mark a mnemonic.
* @param columnSpan number of columns to span this label onto.
*
* @return the added label.
*/
public JLabel append(String textWithMnemonic, int columnSpan)
{
JLabel label = ComponentsFactory.createLabel(textWithMnemonic);
append(label, columnSpan);
return label;
}
/**
* Appends a text label with two components. The label is
* linked with the first component.
*
* @param textWithMnemonic text for label with optional mnemonic.
* @param c1 first component (label is linked to).
* @param c2 second component.
*/
public void append(String textWithMnemonic, Component c1, Component c2)
{
append(textWithMnemonic, 1, c1, 1, c2, 1);
}
/**
* Appends a text label spanning across several columns with two components. The label is
* linked with the first component.
*
* @param textWithMnemonic text for label with optional mnemonic.
* @param c component (label is linked to).
* @param columnSpan component column span.
*
* @return a label object.
*/
public JLabel append(String textWithMnemonic, Component c, int columnSpan)
{
return append(textWithMnemonic, 1, c, columnSpan, null, 1);
}
/**
* Appends a text label spanning across several columns with two components. The label is
* linked with the first component.
*
* @param textWithMnemonic text for label with optional mnemonic.
* @param labelSpan number of columns for label to span.
* @param c1 first component (label is linked to).
* @param c2 second component.
*/
public void append(String textWithMnemonic, int labelSpan, Component c1, Component c2)
{
append(textWithMnemonic, labelSpan, c1, 1, c2, 1);
}
/**
* Appends a text label spanning across several columns with component. The label is
* linked with the component.
*
* @param textWithMnemonic text for label with optional mnemonic.
* @param labelSpan number of columns for label to span.
* @param c component (label is linked to).
* @param colSpan number of columns to span the component.
*
* @return label.
*/
public JLabel append(String textWithMnemonic, int labelSpan, Component c, int colSpan)
{
return append(textWithMnemonic, labelSpan, c, colSpan, null, 1);
}
/**
* Appends a text label spanning acros several columns with two components. The label is
* linked with the first component.
*
* @param textWithMnemonic text for label with optional mnemonic.
* @param labelSpan number of columns for label to span.
* @param c1 first component (label is linked to).
* @param columnSpan1 columns to span first component on to.
* @param c2 second component.
* @param columnSpan2 columns to span second component on to.
*
* @return label.
*/
public JLabel append(String textWithMnemonic, int labelSpan, Component c1, int columnSpan1,
Component c2, int columnSpan2)
{
JLabel label = append(textWithMnemonic, labelSpan);
if (c1 != null)
{
append(c1, columnSpan1);
label.setLabelFor(c1);
}
if (c2 != null) append(c2, columnSpan2);
return label;
}
/**
* Appends component with defined column span and aligning properties.
*
* @param c component.
* @param columnSpan column span.
* @param horiz horizontal alignment.
* @param vert vertical alignment.
*/
public void append(Component c, int columnSpan,
CellConstraints.Alignment horiz, CellConstraints.Alignment vert)
{
builder.append("");
int column = builder.getColumn() - 2;
builder.setColumn(column);
CellConstraints cc = new CellConstraints(column, builder.getRow(), columnSpan, 1,
horiz, vert);
builder.add(c, cc);
builder.nextColumn(columnSpan + 1);
}
/**
* Appends label with defined column span and aligning properties.
*
* @param textWithMnemonic text with mnemonic chars.
* @param columnSpan column span.
* @param horiz horizontal alignment.
* @param vert vertical alignment.
*
* @return label.
*/
public JLabel append(String textWithMnemonic, int columnSpan,
CellConstraints.Alignment horiz, CellConstraints.Alignment vert)
{
JLabel label = ComponentsFactory.createLabel(textWithMnemonic);
append(label, columnSpan, horiz, vert);
return label;
}
/**
* Appends row between related components.
*/
public void appendRelatedComponentsGapRow()
{
builder.appendRelatedComponentsGapRow();
}
/**
* Appends row between related components and moves cursor to the next <code>lines</code>.
*
* @param lines number of lines to move down.
*/
public void appendRelatedComponentsGapRow(int lines)
{
appendRelatedComponentsGapRow();
if (lines > 0) builder.nextLine(lines);
}
/**
* Appends row between unrelated components.
*/
public void appendUnrelatedComponentsGapRow()
{
builder.appendUnrelatedComponentsGapRow();
}
/**
* Appends row between unrelated components and moves cursor to the next <code>lines</code>.
*
* @param lines number of lines to move down.
*/
public void appendUnrelatedComponentsGapRow(int lines)
{
appendUnrelatedComponentsGapRow();
if (lines > 0) builder.nextLine(lines);
}
/**
* Appends row with arbitrary specs.
*
* @param encodedSpecs specs.
*/
public void appendRow(String encodedSpecs)
{
builder.appendRow(encodedSpecs);
}
/**
* Moves cursor to the next line.
*
* @return this builder.
*/
public BBFormBuilder nextLine()
{
return nextLine(1);
}
/**
* Moves cursor <code>lines</code> below.
*
* @param lines lines.
*
* @return this builder.
*/
public BBFormBuilder nextLine(int lines)
{
builder.nextLine(lines);
return this;
}
/**
* Moves cursor to the next column.
*
* @return this builder.
*/
public BBFormBuilder nextColumn()
{
return nextColumn(1);
}
/**
* Moves cursor <code>columns</code> columns to the right.
*
* @param columns number of columns to shift.
*
* @return this builder.
*/
public BBFormBuilder nextColumn(int columns)
{
builder.nextColumn(columns);
return this;
}
/**
* Returns the panel being constructed.
*
* @return panel.
*/
public JPanel getPanel()
{
return builder.getPanel();
}
/**
* Sets default dialog border around the panel.
*/
public void setDefaultDialogBorder()
{
builder.setDefaultDialogBorder();
}
/**
* Appends separator.
*
* @param text separator text.
*/
public void appendSeparator(String text)
{
builder.appendSeparator(text);
}
}