|
1 /* |
|
2 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 package java.awt; |
|
27 |
|
28 /** |
|
29 * The <code>GridLayout</code> class is a layout manager that |
|
30 * lays out a container's components in a rectangular grid. |
|
31 * The container is divided into equal-sized rectangles, |
|
32 * and one component is placed in each rectangle. |
|
33 * For example, the following is an applet that lays out six buttons |
|
34 * into three rows and two columns: |
|
35 * <p> |
|
36 * <hr><blockquote> |
|
37 * <pre> |
|
38 * import java.awt.*; |
|
39 * import java.applet.Applet; |
|
40 * public class ButtonGrid extends Applet { |
|
41 * public void init() { |
|
42 * setLayout(new GridLayout(3,2)); |
|
43 * add(new Button("1")); |
|
44 * add(new Button("2")); |
|
45 * add(new Button("3")); |
|
46 * add(new Button("4")); |
|
47 * add(new Button("5")); |
|
48 * add(new Button("6")); |
|
49 * } |
|
50 * } |
|
51 * </pre></blockquote><hr> |
|
52 * <p> |
|
53 * If the container's <code>ComponentOrientation</code> property is horizontal |
|
54 * and left-to-right, the above example produces the output shown in Figure 1. |
|
55 * If the container's <code>ComponentOrientation</code> property is horizontal |
|
56 * and right-to-left, the example produces the output shown in Figure 2. |
|
57 * <p> |
|
58 * <center><table COLS=2 WIDTH=600 summary="layout"> |
|
59 * <tr ALIGN=CENTER> |
|
60 * <td><img SRC="doc-files/GridLayout-1.gif" |
|
61 * alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2. |
|
62 * Row 2 shows buttons 3 then 4. Row 3 shows buttons 5 then 6."> |
|
63 * </td> |
|
64 * |
|
65 * <td ALIGN=CENTER><img SRC="doc-files/GridLayout-2.gif" |
|
66 * alt="Shows 6 buttons in rows of 2. Row 1 shows buttons 2 then 1. |
|
67 * Row 2 shows buttons 4 then 3. Row 3 shows buttons 6 then 5."> |
|
68 * </td> |
|
69 * </tr> |
|
70 * |
|
71 * <tr ALIGN=CENTER> |
|
72 * <td>Figure 1: Horizontal, Left-to-Right</td> |
|
73 * |
|
74 * <td>Figure 2: Horizontal, Right-to-Left</td> |
|
75 * </tr> |
|
76 * </table></center> |
|
77 * <p> |
|
78 * When both the number of rows and the number of columns have |
|
79 * been set to non-zero values, either by a constructor or |
|
80 * by the <tt>setRows</tt> and <tt>setColumns</tt> methods, the number of |
|
81 * columns specified is ignored. Instead, the number of |
|
82 * columns is determined from the specified number of rows |
|
83 * and the total number of components in the layout. So, for |
|
84 * example, if three rows and two columns have been specified |
|
85 * and nine components are added to the layout, they will |
|
86 * be displayed as three rows of three columns. Specifying |
|
87 * the number of columns affects the layout only when the |
|
88 * number of rows is set to zero. |
|
89 * |
|
90 * @author Arthur van Hoff |
|
91 * @since JDK1.0 |
|
92 */ |
|
93 public class GridLayout implements LayoutManager, java.io.Serializable { |
|
94 /* |
|
95 * serialVersionUID |
|
96 */ |
|
97 private static final long serialVersionUID = -7411804673224730901L; |
|
98 |
|
99 /** |
|
100 * This is the horizontal gap (in pixels) which specifies the space |
|
101 * between columns. They can be changed at any time. |
|
102 * This should be a non-negative integer. |
|
103 * |
|
104 * @serial |
|
105 * @see #getHgap() |
|
106 * @see #setHgap(int) |
|
107 */ |
|
108 int hgap; |
|
109 /** |
|
110 * This is the vertical gap (in pixels) which specifies the space |
|
111 * between rows. They can be changed at any time. |
|
112 * This should be a non negative integer. |
|
113 * |
|
114 * @serial |
|
115 * @see #getVgap() |
|
116 * @see #setVgap(int) |
|
117 */ |
|
118 int vgap; |
|
119 /** |
|
120 * This is the number of rows specified for the grid. The number |
|
121 * of rows can be changed at any time. |
|
122 * This should be a non negative integer, where '0' means |
|
123 * 'any number' meaning that the number of Rows in that |
|
124 * dimension depends on the other dimension. |
|
125 * |
|
126 * @serial |
|
127 * @see #getRows() |
|
128 * @see #setRows(int) |
|
129 */ |
|
130 int rows; |
|
131 /** |
|
132 * This is the number of columns specified for the grid. The number |
|
133 * of columns can be changed at any time. |
|
134 * This should be a non negative integer, where '0' means |
|
135 * 'any number' meaning that the number of Columns in that |
|
136 * dimension depends on the other dimension. |
|
137 * |
|
138 * @serial |
|
139 * @see #getColumns() |
|
140 * @see #setColumns(int) |
|
141 */ |
|
142 int cols; |
|
143 |
|
144 /** |
|
145 * Creates a grid layout with a default of one column per component, |
|
146 * in a single row. |
|
147 * @since JDK1.1 |
|
148 */ |
|
149 public GridLayout() { |
|
150 this(1, 0, 0, 0); |
|
151 } |
|
152 |
|
153 /** |
|
154 * Creates a grid layout with the specified number of rows and |
|
155 * columns. All components in the layout are given equal size. |
|
156 * <p> |
|
157 * One, but not both, of <code>rows</code> and <code>cols</code> can |
|
158 * be zero, which means that any number of objects can be placed in a |
|
159 * row or in a column. |
|
160 * @param rows the rows, with the value zero meaning |
|
161 * any number of rows. |
|
162 * @param cols the columns, with the value zero meaning |
|
163 * any number of columns. |
|
164 */ |
|
165 public GridLayout(int rows, int cols) { |
|
166 this(rows, cols, 0, 0); |
|
167 } |
|
168 |
|
169 /** |
|
170 * Creates a grid layout with the specified number of rows and |
|
171 * columns. All components in the layout are given equal size. |
|
172 * <p> |
|
173 * In addition, the horizontal and vertical gaps are set to the |
|
174 * specified values. Horizontal gaps are placed between each |
|
175 * of the columns. Vertical gaps are placed between each of |
|
176 * the rows. |
|
177 * <p> |
|
178 * One, but not both, of <code>rows</code> and <code>cols</code> can |
|
179 * be zero, which means that any number of objects can be placed in a |
|
180 * row or in a column. |
|
181 * <p> |
|
182 * All <code>GridLayout</code> constructors defer to this one. |
|
183 * @param rows the rows, with the value zero meaning |
|
184 * any number of rows |
|
185 * @param cols the columns, with the value zero meaning |
|
186 * any number of columns |
|
187 * @param hgap the horizontal gap |
|
188 * @param vgap the vertical gap |
|
189 * @exception IllegalArgumentException if the value of both |
|
190 * <code>rows</code> and <code>cols</code> is |
|
191 * set to zero |
|
192 */ |
|
193 public GridLayout(int rows, int cols, int hgap, int vgap) { |
|
194 if ((rows == 0) && (cols == 0)) { |
|
195 throw new IllegalArgumentException("rows and cols cannot both be zero"); |
|
196 } |
|
197 this.rows = rows; |
|
198 this.cols = cols; |
|
199 this.hgap = hgap; |
|
200 this.vgap = vgap; |
|
201 } |
|
202 |
|
203 /** |
|
204 * Gets the number of rows in this layout. |
|
205 * @return the number of rows in this layout |
|
206 * @since JDK1.1 |
|
207 */ |
|
208 public int getRows() { |
|
209 return rows; |
|
210 } |
|
211 |
|
212 /** |
|
213 * Sets the number of rows in this layout to the specified value. |
|
214 * @param rows the number of rows in this layout |
|
215 * @exception IllegalArgumentException if the value of both |
|
216 * <code>rows</code> and <code>cols</code> is set to zero |
|
217 * @since JDK1.1 |
|
218 */ |
|
219 public void setRows(int rows) { |
|
220 if ((rows == 0) && (this.cols == 0)) { |
|
221 throw new IllegalArgumentException("rows and cols cannot both be zero"); |
|
222 } |
|
223 this.rows = rows; |
|
224 } |
|
225 |
|
226 /** |
|
227 * Gets the number of columns in this layout. |
|
228 * @return the number of columns in this layout |
|
229 * @since JDK1.1 |
|
230 */ |
|
231 public int getColumns() { |
|
232 return cols; |
|
233 } |
|
234 |
|
235 /** |
|
236 * Sets the number of columns in this layout to the specified value. |
|
237 * Setting the number of columns has no affect on the layout |
|
238 * if the number of rows specified by a constructor or by |
|
239 * the <tt>setRows</tt> method is non-zero. In that case, the number |
|
240 * of columns displayed in the layout is determined by the total |
|
241 * number of components and the number of rows specified. |
|
242 * @param cols the number of columns in this layout |
|
243 * @exception IllegalArgumentException if the value of both |
|
244 * <code>rows</code> and <code>cols</code> is set to zero |
|
245 * @since JDK1.1 |
|
246 */ |
|
247 public void setColumns(int cols) { |
|
248 if ((cols == 0) && (this.rows == 0)) { |
|
249 throw new IllegalArgumentException("rows and cols cannot both be zero"); |
|
250 } |
|
251 this.cols = cols; |
|
252 } |
|
253 |
|
254 /** |
|
255 * Gets the horizontal gap between components. |
|
256 * @return the horizontal gap between components |
|
257 * @since JDK1.1 |
|
258 */ |
|
259 public int getHgap() { |
|
260 return hgap; |
|
261 } |
|
262 |
|
263 /** |
|
264 * Sets the horizontal gap between components to the specified value. |
|
265 * @param hgap the horizontal gap between components |
|
266 * @since JDK1.1 |
|
267 */ |
|
268 public void setHgap(int hgap) { |
|
269 this.hgap = hgap; |
|
270 } |
|
271 |
|
272 /** |
|
273 * Gets the vertical gap between components. |
|
274 * @return the vertical gap between components |
|
275 * @since JDK1.1 |
|
276 */ |
|
277 public int getVgap() { |
|
278 return vgap; |
|
279 } |
|
280 |
|
281 /** |
|
282 * Sets the vertical gap between components to the specified value. |
|
283 * @param vgap the vertical gap between components |
|
284 * @since JDK1.1 |
|
285 */ |
|
286 public void setVgap(int vgap) { |
|
287 this.vgap = vgap; |
|
288 } |
|
289 |
|
290 /** |
|
291 * Adds the specified component with the specified name to the layout. |
|
292 * @param name the name of the component |
|
293 * @param comp the component to be added |
|
294 */ |
|
295 public void addLayoutComponent(String name, Component comp) { |
|
296 } |
|
297 |
|
298 /** |
|
299 * Removes the specified component from the layout. |
|
300 * @param comp the component to be removed |
|
301 */ |
|
302 public void removeLayoutComponent(Component comp) { |
|
303 } |
|
304 |
|
305 /** |
|
306 * Determines the preferred size of the container argument using |
|
307 * this grid layout. |
|
308 * <p> |
|
309 * The preferred width of a grid layout is the largest preferred |
|
310 * width of all of the components in the container times the number of |
|
311 * columns, plus the horizontal padding times the number of columns |
|
312 * minus one, plus the left and right insets of the target container. |
|
313 * <p> |
|
314 * The preferred height of a grid layout is the largest preferred |
|
315 * height of all of the components in the container times the number of |
|
316 * rows, plus the vertical padding times the number of rows minus one, |
|
317 * plus the top and bottom insets of the target container. |
|
318 * |
|
319 * @param parent the container in which to do the layout |
|
320 * @return the preferred dimensions to lay out the |
|
321 * subcomponents of the specified container |
|
322 * @see java.awt.GridLayout#minimumLayoutSize |
|
323 * @see java.awt.Container#getPreferredSize() |
|
324 */ |
|
325 public Dimension preferredLayoutSize(Container parent) { |
|
326 synchronized (parent.getTreeLock()) { |
|
327 Insets insets = parent.getInsets(); |
|
328 int ncomponents = parent.getComponentCount(); |
|
329 int nrows = rows; |
|
330 int ncols = cols; |
|
331 |
|
332 if (nrows > 0) { |
|
333 ncols = (ncomponents + nrows - 1) / nrows; |
|
334 } else { |
|
335 nrows = (ncomponents + ncols - 1) / ncols; |
|
336 } |
|
337 int w = 0; |
|
338 int h = 0; |
|
339 for (int i = 0 ; i < ncomponents ; i++) { |
|
340 Component comp = parent.getComponent(i); |
|
341 Dimension d = comp.getPreferredSize(); |
|
342 if (w < d.width) { |
|
343 w = d.width; |
|
344 } |
|
345 if (h < d.height) { |
|
346 h = d.height; |
|
347 } |
|
348 } |
|
349 return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap, |
|
350 insets.top + insets.bottom + nrows*h + (nrows-1)*vgap); |
|
351 } |
|
352 } |
|
353 |
|
354 /** |
|
355 * Determines the minimum size of the container argument using this |
|
356 * grid layout. |
|
357 * <p> |
|
358 * The minimum width of a grid layout is the largest minimum width |
|
359 * of all of the components in the container times the number of columns, |
|
360 * plus the horizontal padding times the number of columns minus one, |
|
361 * plus the left and right insets of the target container. |
|
362 * <p> |
|
363 * The minimum height of a grid layout is the largest minimum height |
|
364 * of all of the components in the container times the number of rows, |
|
365 * plus the vertical padding times the number of rows minus one, plus |
|
366 * the top and bottom insets of the target container. |
|
367 * |
|
368 * @param parent the container in which to do the layout |
|
369 * @return the minimum dimensions needed to lay out the |
|
370 * subcomponents of the specified container |
|
371 * @see java.awt.GridLayout#preferredLayoutSize |
|
372 * @see java.awt.Container#doLayout |
|
373 */ |
|
374 public Dimension minimumLayoutSize(Container parent) { |
|
375 synchronized (parent.getTreeLock()) { |
|
376 Insets insets = parent.getInsets(); |
|
377 int ncomponents = parent.getComponentCount(); |
|
378 int nrows = rows; |
|
379 int ncols = cols; |
|
380 |
|
381 if (nrows > 0) { |
|
382 ncols = (ncomponents + nrows - 1) / nrows; |
|
383 } else { |
|
384 nrows = (ncomponents + ncols - 1) / ncols; |
|
385 } |
|
386 int w = 0; |
|
387 int h = 0; |
|
388 for (int i = 0 ; i < ncomponents ; i++) { |
|
389 Component comp = parent.getComponent(i); |
|
390 Dimension d = comp.getMinimumSize(); |
|
391 if (w < d.width) { |
|
392 w = d.width; |
|
393 } |
|
394 if (h < d.height) { |
|
395 h = d.height; |
|
396 } |
|
397 } |
|
398 return new Dimension(insets.left + insets.right + ncols*w + (ncols-1)*hgap, |
|
399 insets.top + insets.bottom + nrows*h + (nrows-1)*vgap); |
|
400 } |
|
401 } |
|
402 |
|
403 /** |
|
404 * Lays out the specified container using this layout. |
|
405 * <p> |
|
406 * This method reshapes the components in the specified target |
|
407 * container in order to satisfy the constraints of the |
|
408 * <code>GridLayout</code> object. |
|
409 * <p> |
|
410 * The grid layout manager determines the size of individual |
|
411 * components by dividing the free space in the container into |
|
412 * equal-sized portions according to the number of rows and columns |
|
413 * in the layout. The container's free space equals the container's |
|
414 * size minus any insets and any specified horizontal or vertical |
|
415 * gap. All components in a grid layout are given the same size. |
|
416 * |
|
417 * @param parent the container in which to do the layout |
|
418 * @see java.awt.Container |
|
419 * @see java.awt.Container#doLayout |
|
420 */ |
|
421 public void layoutContainer(Container parent) { |
|
422 synchronized (parent.getTreeLock()) { |
|
423 Insets insets = parent.getInsets(); |
|
424 int ncomponents = parent.getComponentCount(); |
|
425 int nrows = rows; |
|
426 int ncols = cols; |
|
427 boolean ltr = parent.getComponentOrientation().isLeftToRight(); |
|
428 |
|
429 if (ncomponents == 0) { |
|
430 return; |
|
431 } |
|
432 if (nrows > 0) { |
|
433 ncols = (ncomponents + nrows - 1) / nrows; |
|
434 } else { |
|
435 nrows = (ncomponents + ncols - 1) / ncols; |
|
436 } |
|
437 // 4370316. To position components in the center we should: |
|
438 // 1. get an amount of extra space within Container |
|
439 // 2. incorporate half of that value to the left/top position |
|
440 // Note that we use trancating division for widthOnComponent |
|
441 // The reminder goes to extraWidthAvailable |
|
442 int totalGapsWidth = (ncols - 1) * hgap; |
|
443 int widthWOInsets = parent.width - (insets.left + insets.right); |
|
444 int widthOnComponent = (widthWOInsets - totalGapsWidth) / ncols; |
|
445 int extraWidthAvailable = (widthWOInsets - (widthOnComponent * ncols + totalGapsWidth)) / 2; |
|
446 |
|
447 int totalGapsHeight = (nrows - 1) * vgap; |
|
448 int heightWOInsets = parent.height - (insets.top + insets.bottom); |
|
449 int heightOnComponent = (heightWOInsets - totalGapsHeight) / nrows; |
|
450 int extraHeightAvailable = (heightWOInsets - (heightOnComponent * nrows + totalGapsHeight)) / 2; |
|
451 if (ltr) { |
|
452 for (int c = 0, x = insets.left + extraWidthAvailable; c < ncols ; c++, x += widthOnComponent + hgap) { |
|
453 for (int r = 0, y = insets.top + extraHeightAvailable; r < nrows ; r++, y += heightOnComponent + vgap) { |
|
454 int i = r * ncols + c; |
|
455 if (i < ncomponents) { |
|
456 parent.getComponent(i).setBounds(x, y, widthOnComponent, heightOnComponent); |
|
457 } |
|
458 } |
|
459 } |
|
460 } else { |
|
461 for (int c = 0, x = (parent.width - insets.right - widthOnComponent) - extraWidthAvailable; c < ncols ; c++, x -= widthOnComponent + hgap) { |
|
462 for (int r = 0, y = insets.top + extraHeightAvailable; r < nrows ; r++, y += heightOnComponent + vgap) { |
|
463 int i = r * ncols + c; |
|
464 if (i < ncomponents) { |
|
465 parent.getComponent(i).setBounds(x, y, widthOnComponent, heightOnComponent); |
|
466 } |
|
467 } |
|
468 } |
|
469 } |
|
470 } |
|
471 } |
|
472 |
|
473 /** |
|
474 * Returns the string representation of this grid layout's values. |
|
475 * @return a string representation of this grid layout |
|
476 */ |
|
477 public String toString() { |
|
478 return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + |
|
479 ",rows=" + rows + ",cols=" + cols + "]"; |
|
480 } |
|
481 } |