001: /*
002: * @(#)GridLayout.java 1.12 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.awt;
029:
030: /**
031: * The <code>GridLayout</code> class is a layout manager that
032: * lays out a container's components in a rectangular grid.
033: * <p>
034: * The container is divided into equal-sized rectangles,
035: * and one component is placed in each rectangle.
036: * <p>
037: * For example, the following is an applet that lays out six buttons
038: * into three rows and two columns:
039: * <p>
040: * <hr><blockquote><pre>
041: * import java.awt.*;
042: * import java.applet.Applet;
043: * public class ButtonGrid extends Applet {
044: * public void init() {
045: * setLayout(new GridLayout(3,2));
046: * add(new Button("1"));
047: * add(new Button("2"));
048: * add(new Button("3"));
049: * add(new Button("4"));
050: * add(new Button("5"));
051: * add(new Button("6"));
052: * }
053: * }
054: * </pre></blockquote><hr>
055: * <p>
056: * It produces the following output:
057: * <p>
058: * <img src="images-awt/GridLayout-1.gif"
059: * ALIGN=center HSPACE=10 VSPACE=7>
060: * <p>
061: * When both the number of rows and the number of columns have
062: * been set to non-zero values, either by a constructor or
063: * by the <tt>setRows</tt> and <tt>setColumns</tt> methods, the number of
064: * columns specified is ignored. Instead, the number of
065: * columns is determined from the specified number or rows
066: * and the total number of components in the layout. So, for
067: * example, if three rows and two columns have been specified
068: * and nine components are added to the layout, then they will
069: * be displayed as three rows of three columns. Specifying
070: * the number of columns affects the layout only when the
071: * number of rows is set to zero.
072: *
073: * @version 1.21, 03/01/01
074: * @since JDK1.0
075: */
076: public class GridLayout implements LayoutManager, java.io.Serializable {
077: int hgap;
078: int vgap;
079: int rows;
080: int cols;
081:
082: /**
083: * Creates a grid layout with a default of one column per component,
084: * in a single row.
085: * @since JDK1.1
086: */
087: public GridLayout() {
088: this (1, 0, 0, 0);
089: }
090:
091: /**
092: * Creates a grid layout with the specified number of rows and
093: * columns. All components in the layout are given equal size.
094: * <p>
095: * One, but not both, of <code>rows</code> and <code>cols</code> can
096: * be zero, which means that any number of objects can be placed in a
097: * row or in a column.
098: * @param rows the rows, with the value zero meaning
099: * any number of rows.
100: * @param cols the columns, with the value zero meaning
101: * any number of columns.
102: * @since JDK1.0
103: */
104: public GridLayout(int rows, int cols) {
105: this (rows, cols, 0, 0);
106: }
107:
108: /**
109: * Creates a grid layout with the specified number of rows and
110: * columns. All components in the layout are given equal size.
111: * <p>
112: * In addition, the horizontal and vertical gaps are set to the
113: * specified values. Horizontal gaps are placed at the left and
114: * right edges, and between each of the columns. Vertical gaps are
115: * placed at the top and bottom edges, and between each of the rows.
116: * <p>
117: * One, but not both, of <code>rows</code> and <code>cols</code> can
118: * be zero, which means that any number of objects can be placed in a
119: * row or in a column.
120: * @param rows the rows, with the value zero meaning
121: * any number of rows.
122: * @param cols the columns, with the value zero meaning
123: * any number of columns.
124: * @param hgap the horizontal gap.
125: * @param vgap the vertical gap.
126: * @exception IllegalArgumentException if the of <code>rows</code>
127: * or <code>cols</code> is invalid.
128: * @since JDK1.0
129: */
130: public GridLayout(int rows, int cols, int hgap, int vgap) {
131: if ((rows == 0) && (cols == 0)) {
132: throw new IllegalArgumentException(
133: "rows and cols cannot both be zero");
134: }
135: this .rows = rows;
136: this .cols = cols;
137: this .hgap = hgap;
138: this .vgap = vgap;
139: }
140:
141: /**
142: * Gets the number of rows in this layout.
143: * @return the number of rows in this layout.
144: * @since JDK1.1
145: */
146: public int getRows() {
147: return rows;
148: }
149:
150: /**
151: * Sets the number of rows in this layout to the specified value.
152: * @param rows the number of rows in this layout.
153: * @exception IllegalArgumentException if the value of both
154: * <code>rows</code> and <code>cols</code> is set to zero.
155: * @since JDK1.1
156: */
157: public void setRows(int rows) {
158: if ((rows == 0) && (this .cols == 0)) {
159: throw new IllegalArgumentException(
160: "rows and cols cannot both be zero");
161: }
162: this .rows = rows;
163: }
164:
165: /**
166: * Gets the number of columns in this layout.
167: * @return the number of columns in this layout.
168: * @since JDK1.1
169: */
170: public int getColumns() {
171: return cols;
172: }
173:
174: /**
175: * Sets the number of columns in this layout to the specified value.
176: * Setting the number of columns has no affect on the layout
177: * if the number of rows specified by a constructor or by
178: * the <tt>setRows</tt> method is non-zero. In that case, the number
179: * of columns displayed in the layout is determined by the total
180: * number of components and the number of rows specified.
181: * @param cols the number of columns in this layout.
182: * @exception IllegalArgumentException if the value of both
183: * <code>rows</code> and <code>cols</code> is set to zero.
184: * @since JDK1.1
185: */
186: public void setColumns(int cols) {
187: if ((cols == 0) && (this .rows == 0)) {
188: throw new IllegalArgumentException(
189: "rows and cols cannot both be zero");
190: }
191: this .cols = cols;
192: }
193:
194: /**
195: * Gets the horizontal gap between components.
196: * @return the horizontal gap between components.
197: * @since JDK1.1
198: */
199: public int getHgap() {
200: return hgap;
201: }
202:
203: /**
204: * Sets the horizontal gap between components to the specified value.
205: * @param hgap the horizontal gap between components.
206: * @since JDK1.1
207: */
208: public void setHgap(int hgap) {
209: this .hgap = hgap;
210: }
211:
212: /**
213: * Gets the vertical gap between components.
214: * @return the vertical gap between components.
215: * @since JDK1.1
216: */
217: public int getVgap() {
218: return vgap;
219: }
220:
221: /**
222: * Sets the vertical gap between components to the specified value.
223: * @param vgap the vertical gap between components.
224: * @since JDK1.1
225: */
226: public void setVgap(int vgap) {
227: this .vgap = vgap;
228: }
229:
230: /**
231: * Adds the specified component with the specified name to the layout.
232: * @param name the name of the component.
233: * @param comp the component to be added.
234: * @since JDK1.0
235: */
236: public void addLayoutComponent(String name, Component comp) {
237: }
238:
239: /**
240: * Removes the specified component from the layout.
241: * @param comp the component to be removed.
242: * @since JDK1.0
243: */
244: public void removeLayoutComponent(Component comp) {
245: }
246:
247: /**
248: * Determines the preferred size of the container argument using
249: * this grid layout.
250: * <p>
251: * The preferred width of a grid layout is the largest preferred
252: * width of any of the widths in the container times the number of
253: * columns, plus the horizontal padding times the number of columns
254: * plus one, plus the left and right insets of the target container.
255: * <p>
256: * The preferred height of a grid layout is the largest preferred
257: * height of any of the widths in the container times the number of
258: * rows, plus the vertical padding times the number of rows plus one,
259: * plus the top and left insets of the target container.
260: *
261: * @param target the container in which to do the layout.
262: * @return the preferred dimensions to lay out the
263: * subcomponents of the specified container.
264: * @see java.awt.GridLayout#minimumLayoutSize
265: * @see java.awt.Container#getPreferredSize()
266: * @since JDK1.0
267: */
268: public Dimension preferredLayoutSize(Container parent) {
269: synchronized (parent.getTreeLock()) {
270: Insets insets = parent.getInsets();
271: int ncomponents = parent.getComponentCount();
272: int nrows = rows;
273: int ncols = cols;
274: if (nrows > 0) {
275: ncols = (ncomponents + nrows - 1) / nrows;
276: } else {
277: nrows = (ncomponents + ncols - 1) / ncols;
278: }
279: int w = 0;
280: int h = 0;
281: for (int i = 0; i < ncomponents; i++) {
282: Component comp = parent.getComponent(i);
283: Dimension d = comp.getPreferredSize();
284: if (w < d.width) {
285: w = d.width;
286: }
287: if (h < d.height) {
288: h = d.height;
289: }
290: }
291: return new Dimension(insets.left + insets.right + ncols * w
292: + (ncols - 1) * hgap, insets.top + insets.bottom
293: + nrows * h + (nrows - 1) * vgap);
294: }
295: }
296:
297: /**
298: * Determines the minimum size of the container argument using this
299: * grid layout.
300: * <p>
301: * The minimum width of a grid layout is the largest minimum width
302: * of any of the widths in the container times the number of columns,
303: * plus the horizontal padding times the number of columns plus one,
304: * plus the left and right insets of the target container.
305: * <p>
306: * The minimum height of a grid layout is the largest minimum height
307: * of any of the widths in the container times the number of rows,
308: * plus the vertical padding times the number of rows plus one, plus
309: * the top and left insets of the target container.
310: *
311: * @param target the container in which to do the layout.
312: * @return the minimum dimensions needed to lay out the
313: * subcomponents of the specified container.
314: * @see java.awt.GridLayout#preferredLayoutSize
315: * @see java.awt.Container#doLayout
316: * @since JDK1.0
317: */
318: public Dimension minimumLayoutSize(Container parent) {
319: synchronized (parent.getTreeLock()) {
320: Insets insets = parent.getInsets();
321: int ncomponents = parent.getComponentCount();
322: int nrows = rows;
323: int ncols = cols;
324: if (nrows > 0) {
325: ncols = (ncomponents + nrows - 1) / nrows;
326: } else {
327: nrows = (ncomponents + ncols - 1) / ncols;
328: }
329: int w = 0;
330: int h = 0;
331: for (int i = 0; i < ncomponents; i++) {
332: Component comp = parent.getComponent(i);
333: Dimension d = comp.getMinimumSize();
334: if (w < d.width) {
335: w = d.width;
336: }
337: if (h < d.height) {
338: h = d.height;
339: }
340: }
341: return new Dimension(insets.left + insets.right + ncols * w
342: + (ncols - 1) * hgap, insets.top + insets.bottom
343: + nrows * h + (nrows - 1) * vgap);
344: }
345: }
346:
347: /**
348: * Lays out the specified container using this layout.
349: * <p>
350: * This method reshapes the components in the specified target
351: * container in order to satisfy the constraints of the
352: * <code>GridLayout</code> object.
353: * <p>
354: * The grid layout manager determines the size of individual
355: * components by dividing the free space in the container into
356: * equal-sized portions according to the number of rows and columns
357: * in the layout. The container's free space equals the container's
358: * size minus any insets and any specified horizontal or vertical
359: * gap. All components in a grid layout are given the same size.
360: *
361: * @param target the container in which to do the layout.
362: * @see java.awt.Container
363: * @see java.awt.Container#doLayout
364: * @since JDK1.0
365: */
366: public void layoutContainer(Container parent) {
367: synchronized (parent.getTreeLock()) {
368: Insets insets = parent.getInsets();
369: int ncomponents = parent.getComponentCount();
370: int nrows = rows;
371: int ncols = cols;
372: if (ncomponents == 0) {
373: return;
374: }
375: if (nrows > 0) {
376: ncols = (ncomponents + nrows - 1) / nrows;
377: } else {
378: nrows = (ncomponents + ncols - 1) / ncols;
379: }
380: int w = parent.width - (insets.left + insets.right);
381: int h = parent.height - (insets.top + insets.bottom);
382: w = (w - (ncols - 1) * hgap) / ncols;
383: h = (h - (nrows - 1) * vgap) / nrows;
384: for (int c = 0, x = insets.left; c < ncols; c++, x += w
385: + hgap) {
386: for (int r = 0, y = insets.top; r < nrows; r++, y += h
387: + vgap) {
388: int i = r * ncols + c;
389: if (i < ncomponents) {
390: parent.getComponent(i).setBounds(x, y, w, h);
391: }
392: }
393: }
394: }
395: }
396:
397: /**
398: * Returns the string representation of this grid layout's values.
399: * @return a string representation of this grid layout.
400: * @since JDK1.0
401: */
402: public String toString() {
403: return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap
404: + ",rows=" + rows + ",cols=" + cols + "]";
405: }
406: }
|