/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.awt.*;
/**
* A simple layout manager, for "Entry" areas ith e.g., a list of labels and
* their corresponding JTextFields. These typically look like:
*
* <PRE>
*
* Login: _______________
* Password: _______________
*
* </PRE>
*
* Basically two (or more) columns of different, but constant, widths. <b>Note:
* all columns must be the same height! </b>.
* <P>
* Construct instances by passing an array of the column width percentages (as
* doubles, fractions from 0.1 to 0.9, so 40%,60% would be {0.4, 0.6}). The
* length of this array uniquely determines the number of columns. Columns are
* forced to be the relevant widths. <b>Note: </b> As with GridLayout, the
* number of items added <B>must </B> be an even multiple of the number of
* columns. If not, exceptions may be thrown!
*
* @author Ian F. Darwin, http://www.darwinsys.com/
* @version $Id: EntryLayout.java,v 1.11 2004/06/01 02:51:37 ian Exp $
*/
public class EntryLayout implements LayoutManager {
/** The array of widths, as decimal fractions (0.4 == 40%, etc.). */
protected final double[] widthPercentages;
/** The number of columns. */
protected final int COLUMNS;
/** The default padding */
protected final static int HPAD = 5, VPAD = 5;
/** The actual padding */
protected final int hpad, vpad;
/** True if the list of widths was valid. */
protected boolean validWidths = false;
/**
* Construct an EntryLayout with widths and padding specified.
*
* @param relWidths
* Array of doubles specifying relative column widths.
* @param h
* Horizontal padding between items
* @param v
* Vertical padding between items
*/
public EntryLayout(double[] relWidths, int h, int v) {
COLUMNS = relWidths.length;
widthPercentages = new double[COLUMNS];
for (int i = 0; i < relWidths.length; i++) {
if (relWidths[i] >= 1.0)
throw new IllegalArgumentException(
"EntryLayout: widths must be fractions < 1");
widthPercentages[i] = relWidths[i];
}
validWidths = true;
hpad = h;
vpad = v;
}
/**
* Construct an EntryLayout with widths and with default padding amounts.
*
* @param relWidths
* Array of doubles specifying column widths.
*/
public EntryLayout(double[] relWidths) {
this(relWidths, HPAD, VPAD);
}
/**
* Adds the specified component with the specified constraint to the layout;
* required by LayoutManager but not used.
*/
public void addLayoutComponent(String name, Component comp) {
// nothing to do
}
/**
* Removes the specified component from the layout; required by
* LayoutManager, but does nothing.
*/
public void removeLayoutComponent(Component comp) {
// nothing to do
}
/**
* Calculates the preferred size dimensions for the specified panel given
* the components in the specified parent container.
*/
public Dimension preferredLayoutSize(Container parent) {
// System.out.println("preferredLayoutSize");
return computeLayoutSize(parent, hpad, vpad);
}
/**
* Find the minimum Dimension for the specified container given the
* components therein.
*/
public Dimension minimumLayoutSize(Container parent) {
// System.out.println("minimumLayoutSize");
return computeLayoutSize(parent, 0, 0);
}
/** The width of each column, as found by computLayoutSize(). */
int[] widths;
/** The height of each row, as found by computLayoutSize(). */
int[] heights;
/**
* Compute the size of the whole mess. Serves as the guts of
* preferredLayoutSize() and minimumLayoutSize().
*
* @param parent
* The container in which to do the layout.
* @param hp
* The horizontal padding (may be zero)
* @param vp
* The Vertical Padding (may be zero).
*/
protected Dimension computeLayoutSize(Container parent, int hp, int vp) {
if (!validWidths)
return null;
Component[] components = parent.getComponents();
Dimension contSize = parent.getSize();
int preferredWidth = 0, preferredHeight = 0;
widths = new int[COLUMNS];
heights = new int[components.length / COLUMNS];
// System.out.println("Grid: " + widths.length + ", " + heights.length);
int i;
// Pass One: Compute largest widths and heights.
for (i = 0; i < components.length; i++) {
int row = i / widthPercentages.length;
int col = i % widthPercentages.length;
Component c = components[i];
Dimension d = c.getPreferredSize();
widths[col] = Math.max(widths[col], d.width);
heights[row] = Math.max(heights[row], d.height);
}
// Pass two: agregate them.
for (i = 0; i < widths.length; i++)
preferredWidth += widths[i] + hp;
for (i = 0; i < heights.length; i++)
preferredHeight += heights[i] + vp;
// Finally, pass the sums back as the actual size.
return new Dimension(preferredWidth, preferredHeight);
}
/**
* Lays out the container in the specified panel. This is a row-column type
* layout; find x, y, width and height of each Component.
*
* @param parent
* The Container whose children we are laying out.
*/
public void layoutContainer(Container parent) {
if (!validWidths)
return;
Component[] components = parent.getComponents();
Dimension contSize = parent.getSize();
int x = 0;
for (int i = 0; i < components.length; i++) {
int row = i / COLUMNS;
int col = i % COLUMNS;
Component c = components[i];
Dimension d = c.getPreferredSize();
int colWidth = (int) (contSize.width * widthPercentages[col]);
if (col == 0) {
x = hpad;
} else {
x += hpad * (col - 1)
+ (int) (contSize.width * widthPercentages[col - 1]);
}
int y = vpad * (row) + (row * heights[row])
+ (heights[row] - d.height);
Rectangle r = new Rectangle(x, y, colWidth, d.height);
c.setBounds(r);
}
}
}
|