Java tutorial
/* * 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); } } }