blob: 60ae3c16ba0b568b31d7f93a15ec03b4f25a0577 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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 */
25package java.awt;
26
27import java.util.Hashtable;
28import java.util.Arrays;
29
30/**
31 * The <code>GridBagLayout</code> class is a flexible layout
32 * manager that aligns components vertically, horizontally or along their
33 * baseline without requiring that the components be of the same size.
34 * Each <code>GridBagLayout</code> object maintains a dynamic,
35 * rectangular grid of cells, with each component occupying
36 * one or more cells, called its <em>display area</em>.
37 * <p>
38 * Each component managed by a <code>GridBagLayout</code> is associated with
39 * an instance of {@link GridBagConstraints}. The constraints object
40 * specifies where a component's display area should be located on the grid
41 * and how the component should be positioned within its display area. In
42 * addition to its constraints object, the <code>GridBagLayout</code> also
43 * considers each component's minimum and preferred sizes in order to
44 * determine a component's size.
45 * <p>
46 * The overall orientation of the grid depends on the container's
47 * {@link ComponentOrientation} property. For horizontal left-to-right
48 * orientations, grid coordinate (0,0) is in the upper left corner of the
49 * container with x increasing to the right and y increasing downward. For
50 * horizontal right-to-left orientations, grid coordinate (0,0) is in the upper
51 * right corner of the container with x increasing to the left and y
52 * increasing downward.
53 * <p>
54 * To use a grid bag layout effectively, you must customize one or more
55 * of the <code>GridBagConstraints</code> objects that are associated
56 * with its components. You customize a <code>GridBagConstraints</code>
57 * object by setting one or more of its instance variables:
58 * <p>
59 * <dl>
60 * <dt>{@link GridBagConstraints#gridx},
61 * {@link GridBagConstraints#gridy}
62 * <dd>Specifies the cell containing the leading corner of the component's
63 * display area, where the cell at the origin of the grid has address
64 * <code>gridx&nbsp;=&nbsp;0</code>,
65 * <code>gridy&nbsp;=&nbsp;0</code>. For horizontal left-to-right layout,
66 * a component's leading corner is its upper left. For horizontal
67 * right-to-left layout, a component's leading corner is its upper right.
68 * Use <code>GridBagConstraints.RELATIVE</code> (the default value)
69 * to specify that the component be placed immediately following
70 * (along the x axis for <code>gridx</code> or the y axis for
71 * <code>gridy</code>) the component that was added to the container
72 * just before this component was added.
73 * <dt>{@link GridBagConstraints#gridwidth},
74 * {@link GridBagConstraints#gridheight}
75 * <dd>Specifies the number of cells in a row (for <code>gridwidth</code>)
76 * or column (for <code>gridheight</code>)
77 * in the component's display area.
78 * The default value is 1.
79 * Use <code>GridBagConstraints.REMAINDER</code> to specify
80 * that the component's display area will be from <code>gridx</code>
81 * to the last cell in the row (for <code>gridwidth</code>)
82 * or from <code>gridy</code> to the last cell in the column
83 * (for <code>gridheight</code>).
84 *
85 * Use <code>GridBagConstraints.RELATIVE</code> to specify
86 * that the component's display area will be from <code>gridx</code>
87 * to the next to the last cell in its row (for <code>gridwidth</code>
88 * or from <code>gridy</code> to the next to the last cell in its
89 * column (for <code>gridheight</code>).
90 *
91 * <dt>{@link GridBagConstraints#fill}
92 * <dd>Used when the component's display area
93 * is larger than the component's requested size
94 * to determine whether (and how) to resize the component.
95 * Possible values are
96 * <code>GridBagConstraints.NONE</code> (the default),
97 * <code>GridBagConstraints.HORIZONTAL</code>
98 * (make the component wide enough to fill its display area
99 * horizontally, but don't change its height),
100 * <code>GridBagConstraints.VERTICAL</code>
101 * (make the component tall enough to fill its display area
102 * vertically, but don't change its width), and
103 * <code>GridBagConstraints.BOTH</code>
104 * (make the component fill its display area entirely).
105 * <dt>{@link GridBagConstraints#ipadx},
106 * {@link GridBagConstraints#ipady}
107 * <dd>Specifies the component's internal padding within the layout,
108 * how much to add to the minimum size of the component.
109 * The width of the component will be at least its minimum width
110 * plus <code>ipadx</code> pixels. Similarly, the height of
111 * the component will be at least the minimum height plus
112 * <code>ipady</code> pixels.
113 * <dt>{@link GridBagConstraints#insets}
114 * <dd>Specifies the component's external padding, the minimum
115 * amount of space between the component and the edges of its display area.
116 * <dt>{@link GridBagConstraints#anchor}
117 * <dd>Specifies where the component should be positioned in its display area.
118 * There are three kinds of possible values: absolute, orientation-relative,
119 * and baseline-relative
120 * Orientation relative values are interpreted relative to the container's
121 * <code>ComponentOrientation</code> property while absolute values
122 * are not. Baseline relative values are calculated relative to the
123 * baseline. Valid values are:</dd>
124 * <p>
125 * <center><table BORDER=0 COLS=3 WIDTH=800
126 * SUMMARY="absolute, relative and baseline values as described above">
127 * <tr>
128 * <th><P ALIGN="LEFT">Absolute Values</th>
129 * <th><P ALIGN="LEFT">Orientation Relative Values</th>
130 * <th><P ALIGN="LEFT">Baseline Relative Values</th>
131 * </tr>
132 * <tr>
133 * <td>
134 * <li><code>GridBagConstraints.NORTH</code></li>
135 * <li><code>GridBagConstraints.SOUTH</code></li>
136 * <li><code>GridBagConstraints.WEST</code></li>
137 * <li><code>GridBagConstraints.EAST</code></li>
138 * <li><code>GridBagConstraints.NORTHWEST</code></li>
139 * <li><code>GridBagConstraints.NORTHEAST</code></li>
140 * <li><code>GridBagConstraints.SOUTHWEST</code></li>
141 * <li><code>GridBagConstraints.SOUTHEAST</code></li>
142 * <li><code>GridBagConstraints.CENTER</code> (the default)</li>
143 * </td>
144 * <td>
145 * <li><code>GridBagConstraints.PAGE_START</code></li>
146 * <li><code>GridBagConstraints.PAGE_END</code></li>
147 * <li><code>GridBagConstraints.LINE_START</code></li>
148 * <li><code>GridBagConstraints.LINE_END</code></li>
149 * <li><code>GridBagConstraints.FIRST_LINE_START</code></li>
150 * <li><code>GridBagConstraints.FIRST_LINE_END</code></li>
151 * <li><code>GridBagConstraints.LAST_LINE_START</code></li>
152 * <li><code>GridBagConstraints.LAST_LINE_END</code></li>
153 * </td>
154 * <td>
155 * <li><code>GridBagConstraints.BASELINE</code></li>
156 * <li><code>GridBagConstraints.BASELINE_LEADING</code></li>
157 * <li><code>GridBagConstraints.BASELINE_TRAILING</code></li>
158 * <li><code>GridBagConstraints.ABOVE_BASELINE</code></li>
159 * <li><code>GridBagConstraints.ABOVE_BASELINE_LEADING</code></li>
160 * <li><code>GridBagConstraints.ABOVE_BASELINE_TRAILING</code></li>
161 * <li><code>GridBagConstraints.BELOW_BASELINE</code></li>
162 * <li><code>GridBagConstraints.BELOW_BASELINE_LEADING</code></li>
163 * <li><code>GridBagConstraints.BELOW_BASELINE_TRAILING</code></li>
164 * </td>
165 * </tr>
166 * </table></center><p>
167 * <dt>{@link GridBagConstraints#weightx},
168 * {@link GridBagConstraints#weighty}
169 * <dd>Used to determine how to distribute space, which is
170 * important for specifying resizing behavior.
171 * Unless you specify a weight for at least one component
172 * in a row (<code>weightx</code>) and column (<code>weighty</code>),
173 * all the components clump together in the center of their container.
174 * This is because when the weight is zero (the default),
175 * the <code>GridBagLayout</code> object puts any extra space
176 * between its grid of cells and the edges of the container.
177 * </dl>
178 * <p>
179 * Each row may have a baseline; the baseline is determined by the
180 * components in that row that have a valid baseline and are aligned
181 * along the baseline (the component's anchor value is one of {@code
182 * BASELINE}, {@code BASELINE_LEADING} or {@code BASELINE_TRAILING}).
183 * If none of the components in the row has a valid baseline, the row
184 * does not have a baseline.
185 * <p>
186 * If a component spans rows it is aligned either to the baseline of
187 * the start row (if the baseline-resize behavior is {@code
188 * CONSTANT_ASCENT}) or the end row (if the baseline-resize behavior
189 * is {@code CONSTANT_DESCENT}). The row that the component is
190 * aligned to is called the <em>prevailing row</em>.
191 * <p>
192 * The following figure shows a baseline layout and includes a
193 * component that spans rows:
194 * <center><table summary="Baseline Layout">
195 * <tr ALIGN=CENTER>
196 * <td>
197 * <img src="doc-files/GridBagLayout-baseline.png"
198 * alt="The following text describes this graphic (Figure 1)." ALIGN=center>
199 * </td>
200 * </table></center>
201 * This layout consists of three components:
202 * <ul><li>A panel that starts in row 0 and ends in row 1. The panel
203 * has a baseline-resize behavior of <code>CONSTANT_DESCENT</code> and has
204 * an anchor of <code>BASELINE</code>. As the baseline-resize behavior
205 * is <code>CONSTANT_DESCENT</code> the prevailing row for the panel is
206 * row 1.
207 * <li>Two buttons, each with a baseline-resize behavior of
208 * <code>CENTER_OFFSET</code> and an anchor of <code>BASELINE</code>.
209 * </ul>
210 * Because the second button and the panel share the same prevailing row,
211 * they are both aligned along their baseline.
212 * <p>
213 * Components positioned using one of the baseline-relative values resize
214 * differently than when positioned using an absolute or orientation-relative
215 * value. How components change is dictated by how the baseline of the
216 * prevailing row changes. The baseline is anchored to the
217 * bottom of the display area if any components with the same prevailing row
218 * have a baseline-resize behavior of <code>CONSTANT_DESCENT</code>,
219 * otherwise the baseline is anchored to the top of the display area.
220 * The following rules dictate the resize behavior:
221 * <ul>
222 * <li>Resizable components positioned above the baseline can only
223 * grow as tall as the baseline. For example, if the baseline is at 100
224 * and anchored at the top, a resizable component positioned above the
225 * baseline can never grow more than 100 units.
226 * <li>Similarly, resizable components positioned below the baseline can
227 * only grow as high as the difference between the display height and the
228 * baseline.
229 * <li>Resizable components positioned on the baseline with a
230 * baseline-resize behavior of <code>OTHER</code> are only resized if
231 * the baseline at the resized size fits within the display area. If
232 * the baseline is such that it does not fit within the display area
233 * the component is not resized.
234 * <li>Components positioned on the baseline that do not have a
235 * baseline-resize behavior of <code>OTHER</code>
236 * can only grow as tall as {@code display height - baseline + baseline of component}.
237 * </ul>
238 * If you position a component along the baseline, but the
239 * component does not have a valid baseline, it will be vertically centered
240 * in its space. Similarly if you have positioned a component relative
241 * to the baseline and none of the components in the row have a valid
242 * baseline the component is vertically centered.
243 * <p>
244 * The following figures show ten components (all buttons)
245 * managed by a grid bag layout. Figure 2 shows the layout for a horizontal,
246 * left-to-right container and Figure 3 shows the layout for a horizontal,
247 * right-to-left container.
248 * <p>
249 * <center><table COLS=2 WIDTH=600 summary="layout">
250 * <tr ALIGN=CENTER>
251 * <td>
252 * <img src="doc-files/GridBagLayout-1.gif" alt="The preceeding text describes this graphic (Figure 1)." ALIGN=center HSPACE=10 VSPACE=7>
253 * </td>
254 * <td>
255 * <img src="doc-files/GridBagLayout-2.gif" alt="The preceeding text describes this graphic (Figure 2)." ALIGN=center HSPACE=10 VSPACE=7>
256 * </td>
257 * <tr ALIGN=CENTER>
258 * <td>Figure 2: Horizontal, Left-to-Right</td>
259 * <td>Figure 3: Horizontal, Right-to-Left</td>
260 * </tr>
261 * </table></center>
262 * <p>
263 * Each of the ten components has the <code>fill</code> field
264 * of its associated <code>GridBagConstraints</code> object
265 * set to <code>GridBagConstraints.BOTH</code>.
266 * In addition, the components have the following non-default constraints:
267 * <p>
268 * <ul>
269 * <li>Button1, Button2, Button3: <code>weightx&nbsp;=&nbsp;1.0</code>
270 * <li>Button4: <code>weightx&nbsp;=&nbsp;1.0</code>,
271 * <code>gridwidth&nbsp;=&nbsp;GridBagConstraints.REMAINDER</code>
272 * <li>Button5: <code>gridwidth&nbsp;=&nbsp;GridBagConstraints.REMAINDER</code>
273 * <li>Button6: <code>gridwidth&nbsp;=&nbsp;GridBagConstraints.RELATIVE</code>
274 * <li>Button7: <code>gridwidth&nbsp;=&nbsp;GridBagConstraints.REMAINDER</code>
275 * <li>Button8: <code>gridheight&nbsp;=&nbsp;2</code>,
276 * <code>weighty&nbsp;=&nbsp;1.0</code>
277 * <li>Button9, Button 10:
278 * <code>gridwidth&nbsp;=&nbsp;GridBagConstraints.REMAINDER</code>
279 * </ul>
280 * <p>
281 * Here is the code that implements the example shown above:
282 * <p>
283 * <hr><blockquote><pre>
284 * import java.awt.*;
285 * import java.util.*;
286 * import java.applet.Applet;
287 *
288 * public class GridBagEx1 extends Applet {
289 *
290 * protected void makebutton(String name,
291 * GridBagLayout gridbag,
292 * GridBagConstraints c) {
293 * Button button = new Button(name);
294 * gridbag.setConstraints(button, c);
295 * add(button);
296 * }
297 *
298 * public void init() {
299 * GridBagLayout gridbag = new GridBagLayout();
300 * GridBagConstraints c = new GridBagConstraints();
301 *
302 * setFont(new Font("SansSerif", Font.PLAIN, 14));
303 * setLayout(gridbag);
304 *
305 * c.fill = GridBagConstraints.BOTH;
306 * c.weightx = 1.0;
307 * makebutton("Button1", gridbag, c);
308 * makebutton("Button2", gridbag, c);
309 * makebutton("Button3", gridbag, c);
310 *
311 * c.gridwidth = GridBagConstraints.REMAINDER; //end row
312 * makebutton("Button4", gridbag, c);
313 *
314 * c.weightx = 0.0; //reset to the default
315 * makebutton("Button5", gridbag, c); //another row
316 *
317 * c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row
318 * makebutton("Button6", gridbag, c);
319 *
320 * c.gridwidth = GridBagConstraints.REMAINDER; //end row
321 * makebutton("Button7", gridbag, c);
322 *
323 * c.gridwidth = 1; //reset to the default
324 * c.gridheight = 2;
325 * c.weighty = 1.0;
326 * makebutton("Button8", gridbag, c);
327 *
328 * c.weighty = 0.0; //reset to the default
329 * c.gridwidth = GridBagConstraints.REMAINDER; //end row
330 * c.gridheight = 1; //reset to the default
331 * makebutton("Button9", gridbag, c);
332 * makebutton("Button10", gridbag, c);
333 *
334 * setSize(300, 100);
335 * }
336 *
337 * public static void main(String args[]) {
338 * Frame f = new Frame("GridBag Layout Example");
339 * GridBagEx1 ex1 = new GridBagEx1();
340 *
341 * ex1.init();
342 *
343 * f.add("Center", ex1);
344 * f.pack();
345 * f.setSize(f.getPreferredSize());
346 * f.show();
347 * }
348 * }
349 * </pre></blockquote><hr>
350 * <p>
351 * @author Doug Stein
352 * @author Bill Spitzak (orignial NeWS & OLIT implementation)
353 * @see java.awt.GridBagConstraints
354 * @see java.awt.GridBagLayoutInfo
355 * @see java.awt.ComponentOrientation
356 * @since JDK1.0
357 */
358public class GridBagLayout implements LayoutManager2,
359java.io.Serializable {
360
361 static final int EMPIRICMULTIPLIER = 2;
362 /**
363 * This field is no longer used to reserve arrays and keeped for backward
364 * compatibility. Previously, this was
365 * the maximum number of grid positions (both horizontal and
366 * vertical) that could be laid out by the grid bag layout.
367 * Current implementation doesn't impose any limits
368 * on the size of a grid.
369 */
370 protected static final int MAXGRIDSIZE = 512;
371
372 /**
373 * The smallest grid that can be laid out by the grid bag layout.
374 */
375 protected static final int MINSIZE = 1;
376 /**
377 * The preferred grid size that can be laid out by the grid bag layout.
378 */
379 protected static final int PREFERREDSIZE = 2;
380
381 /**
382 * This hashtable maintains the association between
383 * a component and its gridbag constraints.
384 * The Keys in <code>comptable</code> are the components and the
385 * values are the instances of <code>GridBagConstraints</code>.
386 *
387 * @serial
388 * @see java.awt.GridBagConstraints
389 */
390 protected Hashtable<Component,GridBagConstraints> comptable;
391
392 /**
393 * This field holds a gridbag constraints instance
394 * containing the default values, so if a component
395 * does not have gridbag constraints associated with
396 * it, then the component will be assigned a
397 * copy of the <code>defaultConstraints</code>.
398 *
399 * @serial
400 * @see #getConstraints(Component)
401 * @see #setConstraints(Component, GridBagConstraints)
402 * @see #lookupConstraints(Component)
403 */
404 protected GridBagConstraints defaultConstraints;
405
406 /**
407 * This field holds the layout information
408 * for the gridbag. The information in this field
409 * is based on the most recent validation of the
410 * gridbag.
411 * If <code>layoutInfo</code> is <code>null</code>
412 * this indicates that there are no components in
413 * the gridbag or if there are components, they have
414 * not yet been validated.
415 *
416 * @serial
417 * @see #getLayoutInfo(Container, int)
418 */
419 protected GridBagLayoutInfo layoutInfo;
420
421 /**
422 * This field holds the overrides to the column minimum
423 * width. If this field is non-<code>null</code> the values are
424 * applied to the gridbag after all of the minimum columns
425 * widths have been calculated.
426 * If columnWidths has more elements than the number of
427 * columns, columns are added to the gridbag to match
428 * the number of elements in columnWidth.
429 *
430 * @serial
431 * @see #getLayoutDimensions()
432 */
433 public int columnWidths[];
434
435 /**
436 * This field holds the overrides to the row minimum
437 * heights. If this field is non-<code>null</code> the values are
438 * applied to the gridbag after all of the minimum row
439 * heights have been calculated.
440 * If <code>rowHeights</code> has more elements than the number of
441 * rows, rowa are added to the gridbag to match
442 * the number of elements in <code>rowHeights</code>.
443 *
444 * @serial
445 * @see #getLayoutDimensions()
446 */
447 public int rowHeights[];
448
449 /**
450 * This field holds the overrides to the column weights.
451 * If this field is non-<code>null</code> the values are
452 * applied to the gridbag after all of the columns
453 * weights have been calculated.
454 * If <code>columnWeights[i]</code> &gt; weight for column i, then
455 * column i is assigned the weight in <code>columnWeights[i]</code>.
456 * If <code>columnWeights</code> has more elements than the number
457 * of columns, the excess elements are ignored - they do
458 * not cause more columns to be created.
459 *
460 * @serial
461 */
462 public double columnWeights[];
463
464 /**
465 * This field holds the overrides to the row weights.
466 * If this field is non-<code>null</code> the values are
467 * applied to the gridbag after all of the rows
468 * weights have been calculated.
469 * If <code>rowWeights[i]</code> &gt; weight for row i, then
470 * row i is assigned the weight in <code>rowWeights[i]</code>.
471 * If <code>rowWeights</code> has more elements than the number
472 * of rows, the excess elements are ignored - they do
473 * not cause more rows to be created.
474 *
475 * @serial
476 */
477 public double rowWeights[];
478
479 /**
480 * The component being positioned. This is set before calling into
481 * <code>adjustForGravity</code>.
482 */
483 private Component componentAdjusting;
484
485 /**
486 * Creates a grid bag layout manager.
487 */
488 public GridBagLayout () {
489 comptable = new Hashtable<Component,GridBagConstraints>();
490 defaultConstraints = new GridBagConstraints();
491 }
492
493 /**
494 * Sets the constraints for the specified component in this layout.
495 * @param comp the component to be modified
496 * @param constraints the constraints to be applied
497 */
498 public void setConstraints(Component comp, GridBagConstraints constraints) {
499 comptable.put(comp, (GridBagConstraints)constraints.clone());
500 }
501
502 /**
503 * Gets the constraints for the specified component. A copy of
504 * the actual <code>GridBagConstraints</code> object is returned.
505 * @param comp the component to be queried
506 * @return the constraint for the specified component in this
507 * grid bag layout; a copy of the actual constraint
508 * object is returned
509 */
510 public GridBagConstraints getConstraints(Component comp) {
511 GridBagConstraints constraints = comptable.get(comp);
512 if (constraints == null) {
513 setConstraints(comp, defaultConstraints);
514 constraints = comptable.get(comp);
515 }
516 return (GridBagConstraints)constraints.clone();
517 }
518
519 /**
520 * Retrieves the constraints for the specified component.
521 * The return value is not a copy, but is the actual
522 * <code>GridBagConstraints</code> object used by the layout mechanism.
523 * <p>
524 * If <code>comp</code> is not in the <code>GridBagLayout</code>,
525 * a set of default <code>GridBagConstraints</code> are returned.
526 * A <code>comp</code> value of <code>null</code> is invalid
527 * and returns <code>null</code>.
528 *
529 * @param comp the component to be queried
530 * @return the contraints for the specified component
531 */
532 protected GridBagConstraints lookupConstraints(Component comp) {
533 GridBagConstraints constraints = comptable.get(comp);
534 if (constraints == null) {
535 setConstraints(comp, defaultConstraints);
536 constraints = comptable.get(comp);
537 }
538 return constraints;
539 }
540
541 /**
542 * Removes the constraints for the specified component in this layout
543 * @param comp the component to be modified
544 */
545 private void removeConstraints(Component comp) {
546 comptable.remove(comp);
547 }
548
549 /**
550 * Determines the origin of the layout area, in the graphics coordinate
551 * space of the target container. This value represents the pixel
552 * coordinates of the top-left corner of the layout area regardless of
553 * the <code>ComponentOrientation</code> value of the container. This
554 * is distinct from the grid origin given by the cell coordinates (0,0).
555 * Most applications do not call this method directly.
556 * @return the graphics origin of the cell in the top-left
557 * corner of the layout grid
558 * @see java.awt.ComponentOrientation
559 * @since JDK1.1
560 */
561 public Point getLayoutOrigin () {
562 Point origin = new Point(0,0);
563 if (layoutInfo != null) {
564 origin.x = layoutInfo.startx;
565 origin.y = layoutInfo.starty;
566 }
567 return origin;
568 }
569
570 /**
571 * Determines column widths and row heights for the layout grid.
572 * <p>
573 * Most applications do not call this method directly.
574 * @return an array of two arrays, containing the widths
575 * of the layout columns and
576 * the heights of the layout rows
577 * @since JDK1.1
578 */
579 public int [][] getLayoutDimensions () {
580 if (layoutInfo == null)
581 return new int[2][0];
582
583 int dim[][] = new int [2][];
584 dim[0] = new int[layoutInfo.width];
585 dim[1] = new int[layoutInfo.height];
586
587 System.arraycopy(layoutInfo.minWidth, 0, dim[0], 0, layoutInfo.width);
588 System.arraycopy(layoutInfo.minHeight, 0, dim[1], 0, layoutInfo.height);
589
590 return dim;
591 }
592
593 /**
594 * Determines the weights of the layout grid's columns and rows.
595 * Weights are used to calculate how much a given column or row
596 * stretches beyond its preferred size, if the layout has extra
597 * room to fill.
598 * <p>
599 * Most applications do not call this method directly.
600 * @return an array of two arrays, representing the
601 * horizontal weights of the layout columns
602 * and the vertical weights of the layout rows
603 * @since JDK1.1
604 */
605 public double [][] getLayoutWeights () {
606 if (layoutInfo == null)
607 return new double[2][0];
608
609 double weights[][] = new double [2][];
610 weights[0] = new double[layoutInfo.width];
611 weights[1] = new double[layoutInfo.height];
612
613 System.arraycopy(layoutInfo.weightX, 0, weights[0], 0, layoutInfo.width);
614 System.arraycopy(layoutInfo.weightY, 0, weights[1], 0, layoutInfo.height);
615
616 return weights;
617 }
618
619 /**
620 * Determines which cell in the layout grid contains the point
621 * specified by <code>(x,&nbsp;y)</code>. Each cell is identified
622 * by its column index (ranging from 0 to the number of columns
623 * minus 1) and its row index (ranging from 0 to the number of
624 * rows minus 1).
625 * <p>
626 * If the <code>(x,&nbsp;y)</code> point lies
627 * outside the grid, the following rules are used.
628 * The column index is returned as zero if <code>x</code> lies to the
629 * left of the layout for a left-to-right container or to the right of
630 * the layout for a right-to-left container. The column index is returned
631 * as the number of columns if <code>x</code> lies
632 * to the right of the layout in a left-to-right container or to the left
633 * in a right-to-left container.
634 * The row index is returned as zero if <code>y</code> lies above the
635 * layout, and as the number of rows if <code>y</code> lies
636 * below the layout. The orientation of a container is determined by its
637 * <code>ComponentOrientation</code> property.
638 * @param x the <i>x</i> coordinate of a point
639 * @param y the <i>y</i> coordinate of a point
640 * @return an ordered pair of indexes that indicate which cell
641 * in the layout grid contains the point
642 * (<i>x</i>,&nbsp;<i>y</i>).
643 * @see java.awt.ComponentOrientation
644 * @since JDK1.1
645 */
646 public Point location(int x, int y) {
647 Point loc = new Point(0,0);
648 int i, d;
649
650 if (layoutInfo == null)
651 return loc;
652
653 d = layoutInfo.startx;
654 if (!rightToLeft) {
655 for (i=0; i<layoutInfo.width; i++) {
656 d += layoutInfo.minWidth[i];
657 if (d > x)
658 break;
659 }
660 } else {
661 for (i=layoutInfo.width-1; i>=0; i--) {
662 if (d > x)
663 break;
664 d += layoutInfo.minWidth[i];
665 }
666 i++;
667 }
668 loc.x = i;
669
670 d = layoutInfo.starty;
671 for (i=0; i<layoutInfo.height; i++) {
672 d += layoutInfo.minHeight[i];
673 if (d > y)
674 break;
675 }
676 loc.y = i;
677
678 return loc;
679 }
680
681 /**
682 * Has no effect, since this layout manager does not use a per-component string.
683 */
684 public void addLayoutComponent(String name, Component comp) {
685 }
686
687 /**
688 * Adds the specified component to the layout, using the specified
689 * <code>constraints</code> object. Note that constraints
690 * are mutable and are, therefore, cloned when cached.
691 *
692 * @param comp the component to be added
693 * @param constraints an object that determines how
694 * the component is added to the layout
695 * @exception IllegalArgumentException if <code>constraints</code>
696 * is not a <code>GridBagConstraint</code>
697 */
698 public void addLayoutComponent(Component comp, Object constraints) {
699 if (constraints instanceof GridBagConstraints) {
700 setConstraints(comp, (GridBagConstraints)constraints);
701 } else if (constraints != null) {
702 throw new IllegalArgumentException("cannot add to layout: constraints must be a GridBagConstraint");
703 }
704 }
705
706 /**
707 * Removes the specified component from this layout.
708 * <p>
709 * Most applications do not call this method directly.
710 * @param comp the component to be removed.
711 * @see java.awt.Container#remove(java.awt.Component)
712 * @see java.awt.Container#removeAll()
713 */
714 public void removeLayoutComponent(Component comp) {
715 removeConstraints(comp);
716 }
717
718 /**
719 * Determines the preferred size of the <code>parent</code>
720 * container using this grid bag layout.
721 * <p>
722 * Most applications do not call this method directly.
723 *
724 * @param parent the container in which to do the layout
725 * @see java.awt.Container#getPreferredSize
726 * @return the preferred size of the <code>parent</code>
727 * container
728 */
729 public Dimension preferredLayoutSize(Container parent) {
730 GridBagLayoutInfo info = getLayoutInfo(parent, PREFERREDSIZE);
731 return getMinSize(parent, info);
732 }
733
734 /**
735 * Determines the minimum size of the <code>parent</code> container
736 * using this grid bag layout.
737 * <p>
738 * Most applications do not call this method directly.
739 * @param parent the container in which to do the layout
740 * @see java.awt.Container#doLayout
741 * @return the minimum size of the <code>parent</code> container
742 */
743 public Dimension minimumLayoutSize(Container parent) {
744 GridBagLayoutInfo info = getLayoutInfo(parent, MINSIZE);
745 return getMinSize(parent, info);
746 }
747
748 /**
749 * Returns the maximum dimensions for this layout given the components
750 * in the specified target container.
751 * @param target the container which needs to be laid out
752 * @see Container
753 * @see #minimumLayoutSize(Container)
754 * @see #preferredLayoutSize(Container)
755 * @return the maximum dimensions for this layout
756 */
757 public Dimension maximumLayoutSize(Container target) {
758 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
759 }
760
761 /**
762 * Returns the alignment along the x axis. This specifies how
763 * the component would like to be aligned relative to other
764 * components. The value should be a number between 0 and 1
765 * where 0 represents alignment along the origin, 1 is aligned
766 * the furthest away from the origin, 0.5 is centered, etc.
767 * <p>
768 * @return the value <code>0.5f</code> to indicate centered
769 */
770 public float getLayoutAlignmentX(Container parent) {
771 return 0.5f;
772 }
773
774 /**
775 * Returns the alignment along the y axis. This specifies how
776 * the component would like to be aligned relative to other
777 * components. The value should be a number between 0 and 1
778 * where 0 represents alignment along the origin, 1 is aligned
779 * the furthest away from the origin, 0.5 is centered, etc.
780 * <p>
781 * @return the value <code>0.5f</code> to indicate centered
782 */
783 public float getLayoutAlignmentY(Container parent) {
784 return 0.5f;
785 }
786
787 /**
788 * Invalidates the layout, indicating that if the layout manager
789 * has cached information it should be discarded.
790 */
791 public void invalidateLayout(Container target) {
792 }
793
794 /**
795 * Lays out the specified container using this grid bag layout.
796 * This method reshapes components in the specified container in
797 * order to satisfy the contraints of this <code>GridBagLayout</code>
798 * object.
799 * <p>
800 * Most applications do not call this method directly.
801 * @param parent the container in which to do the layout
802 * @see java.awt.Container
803 * @see java.awt.Container#doLayout
804 */
805 public void layoutContainer(Container parent) {
806 arrangeGrid(parent);
807 }
808
809 /**
810 * Returns a string representation of this grid bag layout's values.
811 * @return a string representation of this grid bag layout.
812 */
813 public String toString() {
814 return getClass().getName();
815 }
816
817 /**
818 * Print the layout information. Useful for debugging.
819 */
820
821 /* DEBUG
822 *
823 * protected void dumpLayoutInfo(GridBagLayoutInfo s) {
824 * int x;
825 *
826 * System.out.println("Col\tWidth\tWeight");
827 * for (x=0; x<s.width; x++) {
828 * System.out.println(x + "\t" +
829 * s.minWidth[x] + "\t" +
830 * s.weightX[x]);
831 * }
832 * System.out.println("Row\tHeight\tWeight");
833 * for (x=0; x<s.height; x++) {
834 * System.out.println(x + "\t" +
835 * s.minHeight[x] + "\t" +
836 * s.weightY[x]);
837 * }
838 * }
839 */
840
841 /**
842 * Print the layout constraints. Useful for debugging.
843 */
844
845 /* DEBUG
846 *
847 * protected void dumpConstraints(GridBagConstraints constraints) {
848 * System.out.println(
849 * "wt " +
850 * constraints.weightx +
851 * " " +
852 * constraints.weighty +
853 * ", " +
854 *
855 * "box " +
856 * constraints.gridx +
857 * " " +
858 * constraints.gridy +
859 * " " +
860 * constraints.gridwidth +
861 * " " +
862 * constraints.gridheight +
863 * ", " +
864 *
865 * "min " +
866 * constraints.minWidth +
867 * " " +
868 * constraints.minHeight +
869 * ", " +
870 *
871 * "pad " +
872 * constraints.insets.bottom +
873 * " " +
874 * constraints.insets.left +
875 * " " +
876 * constraints.insets.right +
877 * " " +
878 * constraints.insets.top +
879 * " " +
880 * constraints.ipadx +
881 * " " +
882 * constraints.ipady);
883 * }
884 */
885
886 /**
887 * Fills in an instance of <code>GridBagLayoutInfo</code> for the
888 * current set of managed children. This requires three passes through the
889 * set of children:
890 *
891 * <ol>
892 * <li>Figure out the dimensions of the layout grid.
893 * <li>Determine which cells the components occupy.
894 * <li>Distribute the weights and min sizes amoung the rows/columns.
895 * </ol>
896 *
897 * This also caches the minsizes for all the children when they are
898 * first encountered (so subsequent loops don't need to ask again).
899 * <p>
900 * This method should only be used internally by
901 * <code>GridBagLayout</code>.
902 *
903 * @param parent the layout container
904 * @param sizeflag either <code>PREFERREDSIZE</code> or
905 * <code>MINSIZE</code>
906 * @return the <code>GridBagLayoutInfo</code> for the set of children
907 * @since 1.4
908 */
909 protected GridBagLayoutInfo getLayoutInfo(Container parent, int sizeflag) {
910 return GetLayoutInfo(parent, sizeflag);
911 }
912
913 /*
914 * Calculate maximum array sizes to allocate arrays without ensureCapacity
915 * we may use preCalculated sizes in whole class because of upper estimation of
916 * maximumArrayXIndex and maximumArrayYIndex.
917 */
918
919 private long[] preInitMaximumArraySizes(Container parent){
920 Component components[] = parent.getComponents();
921 Component comp;
922 GridBagConstraints constraints;
923 int curX, curY;
924 int curWidth, curHeight;
925 int preMaximumArrayXIndex = 0;
926 int preMaximumArrayYIndex = 0;
927 long [] returnArray = new long[2];
928
929 for (int compId = 0 ; compId < components.length ; compId++) {
930 comp = components[compId];
931 if (!comp.isVisible()) {
932 continue;
933 }
934
935 constraints = lookupConstraints(comp);
936 curX = constraints.gridx;
937 curY = constraints.gridy;
938 curWidth = constraints.gridwidth;
939 curHeight = constraints.gridheight;
940
941 // -1==RELATIVE, means that column|row equals to previously added component,
942 // since each next Component with gridx|gridy == RELATIVE starts from
943 // previous position, so we should start from previous component which
944 // already used in maximumArray[X|Y]Index calculation. We could just increase
945 // maximum by 1 to handle situation when component with gridx=-1 was added.
946 if (curX < 0){
947 curX = ++preMaximumArrayYIndex;
948 }
949 if (curY < 0){
950 curY = ++preMaximumArrayXIndex;
951 }
952 // gridwidth|gridheight may be equal to RELATIVE (-1) or REMAINDER (0)
953 // in any case using 1 instead of 0 or -1 should be sufficient to for
954 // correct maximumArraySizes calculation
955 if (curWidth <= 0){
956 curWidth = 1;
957 }
958 if (curHeight <= 0){
959 curHeight = 1;
960 }
961
962 preMaximumArrayXIndex = Math.max(curY + curHeight, preMaximumArrayXIndex);
963 preMaximumArrayYIndex = Math.max(curX + curWidth, preMaximumArrayYIndex);
964 } //for (components) loop
965 // Must specify index++ to allocate well-working arrays.
966 /* fix for 4623196.
967 * now return long array instead of Point
968 */
969 returnArray[0] = preMaximumArrayXIndex;
970 returnArray[1] = preMaximumArrayYIndex;
971 return returnArray;
972 } //PreInitMaximumSizes
973
974 /**
975 * This method is obsolete and supplied for backwards
976 * compatability only; new code should call {@link
977 * #getLayoutInfo(java.awt.Container, int) getLayoutInfo} instead.
978 * This method is the same as <code>getLayoutInfo</code>;
979 * refer to <code>getLayoutInfo</code> for details on parameters
980 * and return value.
981 */
982 protected GridBagLayoutInfo GetLayoutInfo(Container parent, int sizeflag) {
983 synchronized (parent.getTreeLock()) {
984 GridBagLayoutInfo r;
985 Component comp;
986 GridBagConstraints constraints;
987 Dimension d;
988 Component components[] = parent.getComponents();
989 // Code below will address index curX+curWidth in the case of yMaxArray, weightY
990 // ( respectively curY+curHeight for xMaxArray, weightX ) where
991 // curX in 0 to preInitMaximumArraySizes.y
992 // Thus, the maximum index that could
993 // be calculated in the following code is curX+curX.
994 // EmpericMultier equals 2 because of this.
995
996 int layoutWidth, layoutHeight;
997 int []xMaxArray;
998 int []yMaxArray;
999 int compindex, i, k, px, py, pixels_diff, nextSize;
1000 int curX = 0; // constraints.gridx
1001 int curY = 0; // constraints.gridy
1002 int curWidth = 1; // constraints.gridwidth
1003 int curHeight = 1; // constraints.gridheight
1004 int curRow, curCol;
1005 double weight_diff, weight;
1006 int maximumArrayXIndex = 0;
1007 int maximumArrayYIndex = 0;
1008 int anchor;
1009
1010 /*
1011 * Pass #1
1012 *
1013 * Figure out the dimensions of the layout grid (use a value of 1 for
1014 * zero or negative widths and heights).
1015 */
1016
1017 layoutWidth = layoutHeight = 0;
1018 curRow = curCol = -1;
1019 long [] arraySizes = preInitMaximumArraySizes(parent);
1020
1021 /* fix for 4623196.
1022 * If user try to create a very big grid we can
1023 * get NegativeArraySizeException because of integer value
1024 * overflow (EMPIRICMULTIPLIER*gridSize might be more then Integer.MAX_VALUE).
1025 * We need to detect this situation and try to create a
1026 * grid with Integer.MAX_VALUE size instead.
1027 */
1028 maximumArrayXIndex = (EMPIRICMULTIPLIER * arraySizes[0] > Integer.MAX_VALUE )? Integer.MAX_VALUE : EMPIRICMULTIPLIER*(int)arraySizes[0];
1029 maximumArrayYIndex = (EMPIRICMULTIPLIER * arraySizes[1] > Integer.MAX_VALUE )? Integer.MAX_VALUE : EMPIRICMULTIPLIER*(int)arraySizes[1];
1030
1031 if (rowHeights != null){
1032 maximumArrayXIndex = Math.max(maximumArrayXIndex, rowHeights.length);
1033 }
1034 if (columnWidths != null){
1035 maximumArrayYIndex = Math.max(maximumArrayYIndex, columnWidths.length);
1036 }
1037
1038 xMaxArray = new int[maximumArrayXIndex];
1039 yMaxArray = new int[maximumArrayYIndex];
1040
1041 boolean hasBaseline = false;
1042 for (compindex = 0 ; compindex < components.length ; compindex++) {
1043 comp = components[compindex];
1044 if (!comp.isVisible())
1045 continue;
1046 constraints = lookupConstraints(comp);
1047
1048 curX = constraints.gridx;
1049 curY = constraints.gridy;
1050 curWidth = constraints.gridwidth;
1051 if (curWidth <= 0)
1052 curWidth = 1;
1053 curHeight = constraints.gridheight;
1054 if (curHeight <= 0)
1055 curHeight = 1;
1056
1057 /* If x or y is negative, then use relative positioning: */
1058 if (curX < 0 && curY < 0) {
1059 if (curRow >= 0)
1060 curY = curRow;
1061 else if (curCol >= 0)
1062 curX = curCol;
1063 else
1064 curY = 0;
1065 }
1066 if (curX < 0) {
1067 px = 0;
1068 for (i = curY; i < (curY + curHeight); i++) {
1069 px = Math.max(px, xMaxArray[i]);
1070 }
1071
1072 curX = px - curX - 1;
1073 if(curX < 0)
1074 curX = 0;
1075 }
1076 else if (curY < 0) {
1077 py = 0;
1078 for (i = curX; i < (curX + curWidth); i++) {
1079 py = Math.max(py, yMaxArray[i]);
1080 }
1081 curY = py - curY - 1;
1082 if(curY < 0)
1083 curY = 0;
1084 }
1085
1086 /* Adjust the grid width and height
1087 * fix for 5005945: unneccessary loops removed
1088 */
1089 px = curX + curWidth;
1090 if (layoutWidth < px) {
1091 layoutWidth = px;
1092 }
1093 py = curY + curHeight;
1094 if (layoutHeight < py) {
1095 layoutHeight = py;
1096 }
1097
1098 /* Adjust xMaxArray and yMaxArray */
1099 for (i = curX; i < (curX + curWidth); i++) {
1100 yMaxArray[i] =py;
1101 }
1102 for (i = curY; i < (curY + curHeight); i++) {
1103 xMaxArray[i] = px;
1104 }
1105
1106
1107 /* Cache the current slave's size. */
1108 if (sizeflag == PREFERREDSIZE)
1109 d = comp.getPreferredSize();
1110 else
1111 d = comp.getMinimumSize();
1112 constraints.minWidth = d.width;
1113 constraints.minHeight = d.height;
1114 if (calculateBaseline(comp, constraints, d)) {
1115 hasBaseline = true;
1116 }
1117
1118 /* Zero width and height must mean that this is the last item (or
1119 * else something is wrong). */
1120 if (constraints.gridheight == 0 && constraints.gridwidth == 0)
1121 curRow = curCol = -1;
1122
1123 /* Zero width starts a new row */
1124 if (constraints.gridheight == 0 && curRow < 0)
1125 curCol = curX + curWidth;
1126
1127 /* Zero height starts a new column */
1128 else if (constraints.gridwidth == 0 && curCol < 0)
1129 curRow = curY + curHeight;
1130 } //for (components) loop
1131
1132
1133 /*
1134 * Apply minimum row/column dimensions
1135 */
1136 if (columnWidths != null && layoutWidth < columnWidths.length)
1137 layoutWidth = columnWidths.length;
1138 if (rowHeights != null && layoutHeight < rowHeights.length)
1139 layoutHeight = rowHeights.length;
1140
1141 r = new GridBagLayoutInfo(layoutWidth, layoutHeight);
1142
1143 /*
1144 * Pass #2
1145 *
1146 * Negative values for gridX are filled in with the current x value.
1147 * Negative values for gridY are filled in with the current y value.
1148 * Negative or zero values for gridWidth and gridHeight end the current
1149 * row or column, respectively.
1150 */
1151
1152 curRow = curCol = -1;
1153
1154 Arrays.fill(xMaxArray, 0);
1155 Arrays.fill(yMaxArray, 0);
1156
1157 int[] maxAscent = null;
1158 int[] maxDescent = null;
1159 short[] baselineType = null;
1160
1161 if (hasBaseline) {
1162 r.maxAscent = maxAscent = new int[layoutHeight];
1163 r.maxDescent = maxDescent = new int[layoutHeight];
1164 r.baselineType = baselineType = new short[layoutHeight];
1165 r.hasBaseline = true;
1166 }
1167
1168
1169 for (compindex = 0 ; compindex < components.length ; compindex++) {
1170 comp = components[compindex];
1171 if (!comp.isVisible())
1172 continue;
1173 constraints = lookupConstraints(comp);
1174
1175 curX = constraints.gridx;
1176 curY = constraints.gridy;
1177 curWidth = constraints.gridwidth;
1178 curHeight = constraints.gridheight;
1179
1180 /* If x or y is negative, then use relative positioning: */
1181 if (curX < 0 && curY < 0) {
1182 if(curRow >= 0)
1183 curY = curRow;
1184 else if(curCol >= 0)
1185 curX = curCol;
1186 else
1187 curY = 0;
1188 }
1189
1190 if (curX < 0) {
1191 if (curHeight <= 0) {
1192 curHeight += r.height - curY;
1193 if (curHeight < 1)
1194 curHeight = 1;
1195 }
1196
1197 px = 0;
1198 for (i = curY; i < (curY + curHeight); i++)
1199 px = Math.max(px, xMaxArray[i]);
1200
1201 curX = px - curX - 1;
1202 if(curX < 0)
1203 curX = 0;
1204 }
1205 else if (curY < 0) {
1206 if (curWidth <= 0) {
1207 curWidth += r.width - curX;
1208 if (curWidth < 1)
1209 curWidth = 1;
1210 }
1211
1212 py = 0;
1213 for (i = curX; i < (curX + curWidth); i++){
1214 py = Math.max(py, yMaxArray[i]);
1215 }
1216
1217 curY = py - curY - 1;
1218 if(curY < 0)
1219 curY = 0;
1220 }
1221
1222 if (curWidth <= 0) {
1223 curWidth += r.width - curX;
1224 if (curWidth < 1)
1225 curWidth = 1;
1226 }
1227
1228 if (curHeight <= 0) {
1229 curHeight += r.height - curY;
1230 if (curHeight < 1)
1231 curHeight = 1;
1232 }
1233
1234 px = curX + curWidth;
1235 py = curY + curHeight;
1236
1237 for (i = curX; i < (curX + curWidth); i++) { yMaxArray[i] = py; }
1238 for (i = curY; i < (curY + curHeight); i++) { xMaxArray[i] = px; }
1239
1240 /* Make negative sizes start a new row/column */
1241 if (constraints.gridheight == 0 && constraints.gridwidth == 0)
1242 curRow = curCol = -1;
1243 if (constraints.gridheight == 0 && curRow < 0)
1244 curCol = curX + curWidth;
1245 else if (constraints.gridwidth == 0 && curCol < 0)
1246 curRow = curY + curHeight;
1247
1248 /* Assign the new values to the gridbag slave */
1249 constraints.tempX = curX;
1250 constraints.tempY = curY;
1251 constraints.tempWidth = curWidth;
1252 constraints.tempHeight = curHeight;
1253
1254 anchor = constraints.anchor;
1255 if (hasBaseline) {
1256 switch(anchor) {
1257 case GridBagConstraints.BASELINE:
1258 case GridBagConstraints.BASELINE_LEADING:
1259 case GridBagConstraints.BASELINE_TRAILING:
1260 if (constraints.ascent >= 0) {
1261 if (curHeight == 1) {
1262 maxAscent[curY] =
1263 Math.max(maxAscent[curY],
1264 constraints.ascent);
1265 maxDescent[curY] =
1266 Math.max(maxDescent[curY],
1267 constraints.descent);
1268 }
1269 else {
1270 if (constraints.baselineResizeBehavior ==
1271 Component.BaselineResizeBehavior.
1272 CONSTANT_DESCENT) {
1273 maxDescent[curY + curHeight - 1] =
1274 Math.max(maxDescent[curY + curHeight
1275 - 1],
1276 constraints.descent);
1277 }
1278 else {
1279 maxAscent[curY] = Math.max(maxAscent[curY],
1280 constraints.ascent);
1281 }
1282 }
1283 if (constraints.baselineResizeBehavior ==
1284 Component.BaselineResizeBehavior.CONSTANT_DESCENT) {
1285 baselineType[curY + curHeight - 1] |=
1286 (1 << constraints.
1287 baselineResizeBehavior.ordinal());
1288 }
1289 else {
1290 baselineType[curY] |= (1 << constraints.
1291 baselineResizeBehavior.ordinal());
1292 }
1293 }
1294 break;
1295 case GridBagConstraints.ABOVE_BASELINE:
1296 case GridBagConstraints.ABOVE_BASELINE_LEADING:
1297 case GridBagConstraints.ABOVE_BASELINE_TRAILING:
1298 // Component positioned above the baseline.
1299 // To make the bottom edge of the component aligned
1300 // with the baseline the bottom inset is
1301 // added to the descent, the rest to the ascent.
1302 pixels_diff = constraints.minHeight +
1303 constraints.insets.top +
1304 constraints.ipady;
1305 maxAscent[curY] = Math.max(maxAscent[curY],
1306 pixels_diff);
1307 maxDescent[curY] = Math.max(maxDescent[curY],
1308 constraints.insets.bottom);
1309 break;
1310 case GridBagConstraints.BELOW_BASELINE:
1311 case GridBagConstraints.BELOW_BASELINE_LEADING:
1312 case GridBagConstraints.BELOW_BASELINE_TRAILING:
1313 // Component positioned below the baseline.
1314 // To make the top edge of the component aligned
1315 // with the baseline the top inset is
1316 // added to the ascent, the rest to the descent.
1317 pixels_diff = constraints.minHeight +
1318 constraints.insets.bottom + constraints.ipady;
1319 maxDescent[curY] = Math.max(maxDescent[curY],
1320 pixels_diff);
1321 maxAscent[curY] = Math.max(maxAscent[curY],
1322 constraints.insets.top);
1323 break;
1324 }
1325 }
1326 }
1327
1328 r.weightX = new double[maximumArrayYIndex];
1329 r.weightY = new double[maximumArrayXIndex];
1330 r.minWidth = new int[maximumArrayYIndex];
1331 r.minHeight = new int[maximumArrayXIndex];
1332
1333
1334 /*
1335 * Apply minimum row/column dimensions and weights
1336 */
1337 if (columnWidths != null)
1338 System.arraycopy(columnWidths, 0, r.minWidth, 0, columnWidths.length);
1339 if (rowHeights != null)
1340 System.arraycopy(rowHeights, 0, r.minHeight, 0, rowHeights.length);
1341 if (columnWeights != null)
1342 System.arraycopy(columnWeights, 0, r.weightX, 0, Math.min(r.weightX.length, columnWeights.length));
1343 if (rowWeights != null)
1344 System.arraycopy(rowWeights, 0, r.weightY, 0, Math.min(r.weightY.length, rowWeights.length));
1345
1346 /*
1347 * Pass #3
1348 *
1349 * Distribute the minimun widths and weights:
1350 */
1351
1352 nextSize = Integer.MAX_VALUE;
1353
1354 for (i = 1;
1355 i != Integer.MAX_VALUE;
1356 i = nextSize, nextSize = Integer.MAX_VALUE) {
1357 for (compindex = 0 ; compindex < components.length ; compindex++) {
1358 comp = components[compindex];
1359 if (!comp.isVisible())
1360 continue;
1361 constraints = lookupConstraints(comp);
1362
1363 if (constraints.tempWidth == i) {
1364 px = constraints.tempX + constraints.tempWidth; /* right column */
1365
1366 /*
1367 * Figure out if we should use this slave\'s weight. If the weight
1368 * is less than the total weight spanned by the width of the cell,
1369 * then discard the weight. Otherwise split the difference
1370 * according to the existing weights.
1371 */
1372
1373 weight_diff = constraints.weightx;
1374 for (k = constraints.tempX; k < px; k++)
1375 weight_diff -= r.weightX[k];
1376 if (weight_diff > 0.0) {
1377 weight = 0.0;
1378 for (k = constraints.tempX; k < px; k++)
1379 weight += r.weightX[k];
1380 for (k = constraints.tempX; weight > 0.0 && k < px; k++) {
1381 double wt = r.weightX[k];
1382 double dx = (wt * weight_diff) / weight;
1383 r.weightX[k] += dx;
1384 weight_diff -= dx;
1385 weight -= wt;
1386 }
1387 /* Assign the remainder to the rightmost cell */
1388 r.weightX[px-1] += weight_diff;
1389 }
1390
1391 /*
1392 * Calculate the minWidth array values.
1393 * First, figure out how wide the current slave needs to be.
1394 * Then, see if it will fit within the current minWidth values.
1395 * If it will not fit, add the difference according to the
1396 * weightX array.
1397 */
1398
1399 pixels_diff =
1400 constraints.minWidth + constraints.ipadx +
1401 constraints.insets.left + constraints.insets.right;
1402
1403 for (k = constraints.tempX; k < px; k++)
1404 pixels_diff -= r.minWidth[k];
1405 if (pixels_diff > 0) {
1406 weight = 0.0;
1407 for (k = constraints.tempX; k < px; k++)
1408 weight += r.weightX[k];
1409 for (k = constraints.tempX; weight > 0.0 && k < px; k++) {
1410 double wt = r.weightX[k];
1411 int dx = (int)((wt * ((double)pixels_diff)) / weight);
1412 r.minWidth[k] += dx;
1413 pixels_diff -= dx;
1414 weight -= wt;
1415 }
1416 /* Any leftovers go into the rightmost cell */
1417 r.minWidth[px-1] += pixels_diff;
1418 }
1419 }
1420 else if (constraints.tempWidth > i && constraints.tempWidth < nextSize)
1421 nextSize = constraints.tempWidth;
1422
1423
1424 if (constraints.tempHeight == i) {
1425 py = constraints.tempY + constraints.tempHeight; /* bottom row */
1426
1427 /*
1428 * Figure out if we should use this slave's weight. If the weight
1429 * is less than the total weight spanned by the height of the cell,
1430 * then discard the weight. Otherwise split it the difference
1431 * according to the existing weights.
1432 */
1433
1434 weight_diff = constraints.weighty;
1435 for (k = constraints.tempY; k < py; k++)
1436 weight_diff -= r.weightY[k];
1437 if (weight_diff > 0.0) {
1438 weight = 0.0;
1439 for (k = constraints.tempY; k < py; k++)
1440 weight += r.weightY[k];
1441 for (k = constraints.tempY; weight > 0.0 && k < py; k++) {
1442 double wt = r.weightY[k];
1443 double dy = (wt * weight_diff) / weight;
1444 r.weightY[k] += dy;
1445 weight_diff -= dy;
1446 weight -= wt;
1447 }
1448 /* Assign the remainder to the bottom cell */
1449 r.weightY[py-1] += weight_diff;
1450 }
1451
1452 /*
1453 * Calculate the minHeight array values.
1454 * First, figure out how tall the current slave needs to be.
1455 * Then, see if it will fit within the current minHeight values.
1456 * If it will not fit, add the difference according to the
1457 * weightY array.
1458 */
1459
1460 pixels_diff = -1;
1461 if (hasBaseline) {
1462 switch(constraints.anchor) {
1463 case GridBagConstraints.BASELINE:
1464 case GridBagConstraints.BASELINE_LEADING:
1465 case GridBagConstraints.BASELINE_TRAILING:
1466 if (constraints.ascent >= 0) {
1467 if (constraints.tempHeight == 1) {
1468 pixels_diff =
1469 maxAscent[constraints.tempY] +
1470 maxDescent[constraints.tempY];
1471 }
1472 else if (constraints.baselineResizeBehavior !=
1473 Component.BaselineResizeBehavior.
1474 CONSTANT_DESCENT) {
1475 pixels_diff =
1476 maxAscent[constraints.tempY] +
1477 constraints.descent;
1478 }
1479 else {
1480 pixels_diff = constraints.ascent +
1481 maxDescent[constraints.tempY +
1482 constraints.tempHeight - 1];
1483 }
1484 }
1485 break;
1486 case GridBagConstraints.ABOVE_BASELINE:
1487 case GridBagConstraints.ABOVE_BASELINE_LEADING:
1488 case GridBagConstraints.ABOVE_BASELINE_TRAILING:
1489 pixels_diff = constraints.insets.top +
1490 constraints.minHeight +
1491 constraints.ipady +
1492 maxDescent[constraints.tempY];
1493 break;
1494 case GridBagConstraints.BELOW_BASELINE:
1495 case GridBagConstraints.BELOW_BASELINE_LEADING:
1496 case GridBagConstraints.BELOW_BASELINE_TRAILING:
1497 pixels_diff = maxAscent[constraints.tempY] +
1498 constraints.minHeight +
1499 constraints.insets.bottom +
1500 constraints.ipady;
1501 break;
1502 }
1503 }
1504 if (pixels_diff == -1) {
1505 pixels_diff =
1506 constraints.minHeight + constraints.ipady +
1507 constraints.insets.top +
1508 constraints.insets.bottom;
1509 }
1510 for (k = constraints.tempY; k < py; k++)
1511 pixels_diff -= r.minHeight[k];
1512 if (pixels_diff > 0) {
1513 weight = 0.0;
1514 for (k = constraints.tempY; k < py; k++)
1515 weight += r.weightY[k];
1516 for (k = constraints.tempY; weight > 0.0 && k < py; k++) {
1517 double wt = r.weightY[k];
1518 int dy = (int)((wt * ((double)pixels_diff)) / weight);
1519 r.minHeight[k] += dy;
1520 pixels_diff -= dy;
1521 weight -= wt;
1522 }
1523 /* Any leftovers go into the bottom cell */
1524 r.minHeight[py-1] += pixels_diff;
1525 }
1526 }
1527 else if (constraints.tempHeight > i &&
1528 constraints.tempHeight < nextSize)
1529 nextSize = constraints.tempHeight;
1530 }
1531 }
1532 return r;
1533 }
1534 } //getLayoutInfo()
1535
1536 /**
1537 * Calculate the baseline for the specified component.
1538 * If {@code c} is positioned along it's baseline, the baseline is
1539 * obtained and the {@code constraints} ascent, descent and
1540 * baseline resize behavior are set from the component; and true is
1541 * returned. Otherwise false is returned.
1542 */
1543 private boolean calculateBaseline(Component c,
1544 GridBagConstraints constraints,
1545 Dimension size) {
1546 int anchor = constraints.anchor;
1547 if (anchor == GridBagConstraints.BASELINE ||
1548 anchor == GridBagConstraints.BASELINE_LEADING ||
1549 anchor == GridBagConstraints.BASELINE_TRAILING) {
1550 // Apply the padding to the component, then ask for the baseline.
1551 int w = size.width + constraints.ipadx;
1552 int h = size.height + constraints.ipady;
1553 constraints.ascent = c.getBaseline(w, h);
1554 if (constraints.ascent >= 0) {
1555 // Component has a baseline
1556 int baseline = constraints.ascent;
1557 // Adjust the ascent and descent to include the insets.
1558 constraints.descent = h - constraints.ascent +
1559 constraints.insets.bottom;
1560 constraints.ascent += constraints.insets.top;
1561 constraints.baselineResizeBehavior =
1562 c.getBaselineResizeBehavior();
1563 constraints.centerPadding = 0;
1564 if (constraints.baselineResizeBehavior == Component.
1565 BaselineResizeBehavior.CENTER_OFFSET) {
1566 // Component has a baseline resize behavior of
1567 // CENTER_OFFSET, calculate centerPadding and
1568 // centerOffset (see the description of
1569 // CENTER_OFFSET in the enum for detais on this
1570 // algorithm).
1571 int nextBaseline = c.getBaseline(w, h + 1);
1572 constraints.centerOffset = baseline - h / 2;
1573 if (h % 2 == 0) {
1574 if (baseline != nextBaseline) {
1575 constraints.centerPadding = 1;
1576 }
1577 }
1578 else if (baseline == nextBaseline){
1579 constraints.centerOffset--;
1580 constraints.centerPadding = 1;
1581 }
1582 }
1583 }
1584 return true;
1585 }
1586 else {
1587 constraints.ascent = -1;
1588 return false;
1589 }
1590 }
1591
1592 /**
1593 * Adjusts the x, y, width, and height fields to the correct
1594 * values depending on the constraint geometry and pads.
1595 * This method should only be used internally by
1596 * <code>GridBagLayout</code>.
1597 *
1598 * @param constraints the constraints to be applied
1599 * @param r the <code>Rectangle</code> to be adjusted
1600 * @since 1.4
1601 */
1602 protected void adjustForGravity(GridBagConstraints constraints,
1603 Rectangle r) {
1604 AdjustForGravity(constraints, r);
1605 }
1606
1607 /**
1608 * This method is obsolete and supplied for backwards
1609 * compatability only; new code should call {@link
1610 * #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle)
1611 * adjustForGravity} instead.
1612 * This method is the same as <code>adjustForGravity</code>;
1613 * refer to <code>adjustForGravity</code> for details
1614 * on parameters.
1615 */
1616 protected void AdjustForGravity(GridBagConstraints constraints,
1617 Rectangle r) {
1618 int diffx, diffy;
1619 int cellY = r.y;
1620 int cellHeight = r.height;
1621
1622 if (!rightToLeft) {
1623 r.x += constraints.insets.left;
1624 } else {
1625 r.x -= r.width - constraints.insets.right;
1626 }
1627 r.width -= (constraints.insets.left + constraints.insets.right);
1628 r.y += constraints.insets.top;
1629 r.height -= (constraints.insets.top + constraints.insets.bottom);
1630
1631 diffx = 0;
1632 if ((constraints.fill != GridBagConstraints.HORIZONTAL &&
1633 constraints.fill != GridBagConstraints.BOTH)
1634 && (r.width > (constraints.minWidth + constraints.ipadx))) {
1635 diffx = r.width - (constraints.minWidth + constraints.ipadx);
1636 r.width = constraints.minWidth + constraints.ipadx;
1637 }
1638
1639 diffy = 0;
1640 if ((constraints.fill != GridBagConstraints.VERTICAL &&
1641 constraints.fill != GridBagConstraints.BOTH)
1642 && (r.height > (constraints.minHeight + constraints.ipady))) {
1643 diffy = r.height - (constraints.minHeight + constraints.ipady);
1644 r.height = constraints.minHeight + constraints.ipady;
1645 }
1646
1647 switch (constraints.anchor) {
1648 case GridBagConstraints.BASELINE:
1649 r.x += diffx/2;
1650 alignOnBaseline(constraints, r, cellY, cellHeight);
1651 break;
1652 case GridBagConstraints.BASELINE_LEADING:
1653 if (rightToLeft) {
1654 r.x += diffx;
1655 }
1656 alignOnBaseline(constraints, r, cellY, cellHeight);
1657 break;
1658 case GridBagConstraints.BASELINE_TRAILING:
1659 if (!rightToLeft) {
1660 r.x += diffx;
1661 }
1662 alignOnBaseline(constraints, r, cellY, cellHeight);
1663 break;
1664 case GridBagConstraints.ABOVE_BASELINE:
1665 r.x += diffx/2;
1666 alignAboveBaseline(constraints, r, cellY, cellHeight);
1667 break;
1668 case GridBagConstraints.ABOVE_BASELINE_LEADING:
1669 if (rightToLeft) {
1670 r.x += diffx;
1671 }
1672 alignAboveBaseline(constraints, r, cellY, cellHeight);
1673 break;
1674 case GridBagConstraints.ABOVE_BASELINE_TRAILING:
1675 if (!rightToLeft) {
1676 r.x += diffx;
1677 }
1678 alignAboveBaseline(constraints, r, cellY, cellHeight);
1679 break;
1680 case GridBagConstraints.BELOW_BASELINE:
1681 r.x += diffx/2;
1682 alignBelowBaseline(constraints, r, cellY, cellHeight);
1683 break;
1684 case GridBagConstraints.BELOW_BASELINE_LEADING:
1685 if (rightToLeft) {
1686 r.x += diffx;
1687 }
1688 alignBelowBaseline(constraints, r, cellY, cellHeight);
1689 break;
1690 case GridBagConstraints.BELOW_BASELINE_TRAILING:
1691 if (!rightToLeft) {
1692 r.x += diffx;
1693 }
1694 alignBelowBaseline(constraints, r, cellY, cellHeight);
1695 break;
1696 case GridBagConstraints.CENTER:
1697 r.x += diffx/2;
1698 r.y += diffy/2;
1699 break;
1700 case GridBagConstraints.PAGE_START:
1701 case GridBagConstraints.NORTH:
1702 r.x += diffx/2;
1703 break;
1704 case GridBagConstraints.NORTHEAST:
1705 r.x += diffx;
1706 break;
1707 case GridBagConstraints.EAST:
1708 r.x += diffx;
1709 r.y += diffy/2;
1710 break;
1711 case GridBagConstraints.SOUTHEAST:
1712 r.x += diffx;
1713 r.y += diffy;
1714 break;
1715 case GridBagConstraints.PAGE_END:
1716 case GridBagConstraints.SOUTH:
1717 r.x += diffx/2;
1718 r.y += diffy;
1719 break;
1720 case GridBagConstraints.SOUTHWEST:
1721 r.y += diffy;
1722 break;
1723 case GridBagConstraints.WEST:
1724 r.y += diffy/2;
1725 break;
1726 case GridBagConstraints.NORTHWEST:
1727 break;
1728 case GridBagConstraints.LINE_START:
1729 if (rightToLeft) {
1730 r.x += diffx;
1731 }
1732 r.y += diffy/2;
1733 break;
1734 case GridBagConstraints.LINE_END:
1735 if (!rightToLeft) {
1736 r.x += diffx;
1737 }
1738 r.y += diffy/2;
1739 break;
1740 case GridBagConstraints.FIRST_LINE_START:
1741 if (rightToLeft) {
1742 r.x += diffx;
1743 }
1744 break;
1745 case GridBagConstraints.FIRST_LINE_END:
1746 if (!rightToLeft) {
1747 r.x += diffx;
1748 }
1749 break;
1750 case GridBagConstraints.LAST_LINE_START:
1751 if (rightToLeft) {
1752 r.x += diffx;
1753 }
1754 r.y += diffy;
1755 break;
1756 case GridBagConstraints.LAST_LINE_END:
1757 if (!rightToLeft) {
1758 r.x += diffx;
1759 }
1760 r.y += diffy;
1761 break;
1762 default:
1763 throw new IllegalArgumentException("illegal anchor value");
1764 }
1765 }
1766
1767 /**
1768 * Positions on the baseline.
1769 *
1770 * @param cellY the location of the row, does not include insets
1771 * @param cellHeight the height of the row, does not take into account
1772 * insets
1773 * @param r available bounds for the component, is padded by insets and
1774 * ipady
1775 */
1776 private void alignOnBaseline(GridBagConstraints cons, Rectangle r,
1777 int cellY, int cellHeight) {
1778 if (cons.ascent >= 0) {
1779 if (cons.baselineResizeBehavior == Component.
1780 BaselineResizeBehavior.CONSTANT_DESCENT) {
1781 // Anchor to the bottom.
1782 // Baseline is at (cellY + cellHeight - maxDescent).
1783 // Bottom of component (maxY) is at baseline + descent
1784 // of component. We need to subtract the bottom inset here
1785 // as the descent in the constraints object includes the
1786 // bottom inset.
1787 int maxY = cellY + cellHeight -
1788 layoutInfo.maxDescent[cons.tempY + cons.tempHeight - 1] +
1789 cons.descent - cons.insets.bottom;
1790 if (!cons.isVerticallyResizable()) {
1791 // Component not resizable, calculate y location
1792 // from maxY - height.
1793 r.y = maxY - cons.minHeight;
1794 r.height = cons.minHeight;
1795 } else {
1796 // Component is resizable. As brb is constant descent,
1797 // can expand component to fill region above baseline.
1798 // Subtract out the top inset so that components insets
1799 // are honored.
1800 r.height = maxY - cellY - cons.insets.top;
1801 }
1802 }
1803 else {
1804 // BRB is not constant_descent
1805 int baseline; // baseline for the row, relative to cellY
1806 // Component baseline, includes insets.top
1807 int ascent = cons.ascent;
1808 if (layoutInfo.hasConstantDescent(cons.tempY)) {
1809 // Mixed ascent/descent in same row, calculate position
1810 // off maxDescent
1811 baseline = cellHeight - layoutInfo.maxDescent[cons.tempY];
1812 }
1813 else {
1814 // Only ascents/unknown in this row, anchor to top
1815 baseline = layoutInfo.maxAscent[cons.tempY];
1816 }
1817 if (cons.baselineResizeBehavior == Component.
1818 BaselineResizeBehavior.OTHER) {
1819 // BRB is other, which means we can only determine
1820 // the baseline by asking for it again giving the
1821 // size we plan on using for the component.
1822 boolean fits = false;
1823 ascent = componentAdjusting.getBaseline(r.width, r.height);
1824 if (ascent >= 0) {
1825 // Component has a baseline, pad with top inset
1826 // (this follows from calculateBaseline which
1827 // does the same).
1828 ascent += cons.insets.top;
1829 }
1830 if (ascent >= 0 && ascent <= baseline) {
1831 // Components baseline fits within rows baseline.
1832 // Make sure the descent fits within the space as well.
1833 if (baseline + (r.height - ascent - cons.insets.top) <=
1834 cellHeight - cons.insets.bottom) {
1835 // It fits, we're good.
1836 fits = true;
1837 }
1838 else if (cons.isVerticallyResizable()) {
1839 // Doesn't fit, but it's resizable. Try
1840 // again assuming we'll get ascent again.
1841 int ascent2 = componentAdjusting.getBaseline(
1842 r.width, cellHeight - cons.insets.bottom -
1843 baseline + ascent);
1844 if (ascent2 >= 0) {
1845 ascent2 += cons.insets.top;
1846 }
1847 if (ascent2 >= 0 && ascent2 <= ascent) {
1848 // It'll fit
1849 r.height = cellHeight - cons.insets.bottom -
1850 baseline + ascent;
1851 ascent = ascent2;
1852 fits = true;
1853 }
1854 }
1855 }
1856 if (!fits) {
1857 // Doesn't fit, use min size and original ascent
1858 ascent = cons.ascent;
1859 r.width = cons.minWidth;
1860 r.height = cons.minHeight;
1861 }
1862 }
1863 // Reset the components y location based on
1864 // components ascent and baseline for row. Because ascent
1865 // includes the baseline
1866 r.y = cellY + baseline - ascent + cons.insets.top;
1867 if (cons.isVerticallyResizable()) {
1868 switch(cons.baselineResizeBehavior) {
1869 case CONSTANT_ASCENT:
1870 r.height = Math.max(cons.minHeight,cellY + cellHeight -
1871 r.y - cons.insets.bottom);
1872 break;
1873 case CENTER_OFFSET:
1874 {
1875 int upper = r.y - cellY - cons.insets.top;
1876 int lower = cellY + cellHeight - r.y -
1877 cons.minHeight - cons.insets.bottom;
1878 int delta = Math.min(upper, lower);
1879 delta += delta;
1880 if (delta > 0 &&
1881 (cons.minHeight + cons.centerPadding +
1882 delta) / 2 + cons.centerOffset != baseline) {
1883 // Off by 1
1884 delta--;
1885 }
1886 r.height = cons.minHeight + delta;
1887 r.y = cellY + baseline -
1888 (r.height + cons.centerPadding) / 2 -
1889 cons.centerOffset;
1890 }
1891 break;
1892 case OTHER:
1893 // Handled above
1894 break;
1895 default:
1896 break;
1897 }
1898 }
1899 }
1900 }
1901 else {
1902 centerVertically(cons, r, cellHeight);
1903 }
1904 }
1905
1906 /**
1907 * Positions the specified component above the baseline. That is
1908 * the bottom edge of the component will be aligned along the baseline.
1909 * If the row does not have a baseline, this centers the component.
1910 */
1911 private void alignAboveBaseline(GridBagConstraints cons, Rectangle r,
1912 int cellY, int cellHeight) {
1913 if (layoutInfo.hasBaseline(cons.tempY)) {
1914 int maxY; // Baseline for the row
1915 if (layoutInfo.hasConstantDescent(cons.tempY)) {
1916 // Prefer descent
1917 maxY = cellY + cellHeight - layoutInfo.maxDescent[cons.tempY];
1918 }
1919 else {
1920 // Prefer ascent
1921 maxY = cellY + layoutInfo.maxAscent[cons.tempY];
1922 }
1923 if (cons.isVerticallyResizable()) {
1924 // Component is resizable. Top edge is offset by top
1925 // inset, bottom edge on baseline.
1926 r.y = cellY + cons.insets.top;
1927 r.height = maxY - r.y;
1928 }
1929 else {
1930 // Not resizable.
1931 r.height = cons.minHeight + cons.ipady;
1932 r.y = maxY - r.height;
1933 }
1934 }
1935 else {
1936 centerVertically(cons, r, cellHeight);
1937 }
1938 }
1939
1940 /**
1941 * Positions below the baseline.
1942 */
1943 private void alignBelowBaseline(GridBagConstraints cons, Rectangle r,
1944 int cellY, int cellHeight) {
1945 if (layoutInfo.hasBaseline(cons.tempY)) {
1946 if (layoutInfo.hasConstantDescent(cons.tempY)) {
1947 // Prefer descent
1948 r.y = cellY + cellHeight - layoutInfo.maxDescent[cons.tempY];
1949 }
1950 else {
1951 // Prefer ascent
1952 r.y = cellY + layoutInfo.maxAscent[cons.tempY];
1953 }
1954 if (cons.isVerticallyResizable()) {
1955 r.height = cellY + cellHeight - r.y - cons.insets.bottom;
1956 }
1957 }
1958 else {
1959 centerVertically(cons, r, cellHeight);
1960 }
1961 }
1962
1963 private void centerVertically(GridBagConstraints cons, Rectangle r,
1964 int cellHeight) {
1965 if (!cons.isVerticallyResizable()) {
1966 r.y += Math.max(0, (cellHeight - cons.insets.top -
1967 cons.insets.bottom - cons.minHeight -
1968 cons.ipady) / 2);
1969 }
1970 }
1971
1972 /**
1973 * Figures out the minimum size of the
1974 * master based on the information from <code>getLayoutInfo</code>.
1975 * This method should only be used internally by
1976 * <code>GridBagLayout</code>.
1977 *
1978 * @param parent the layout container
1979 * @param info the layout info for this parent
1980 * @return a <code>Dimension</code> object containing the
1981 * minimum size
1982 * @since 1.4
1983 */
1984 protected Dimension getMinSize(Container parent, GridBagLayoutInfo info) {
1985 return GetMinSize(parent, info);
1986 }
1987
1988 /**
1989 * This method is obsolete and supplied for backwards
1990 * compatability only; new code should call {@link
1991 * #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead.
1992 * This method is the same as <code>getMinSize</code>;
1993 * refer to <code>getMinSize</code> for details on parameters
1994 * and return value.
1995 */
1996 protected Dimension GetMinSize(Container parent, GridBagLayoutInfo info) {
1997 Dimension d = new Dimension();
1998 int i, t;
1999 Insets insets = parent.getInsets();
2000
2001 t = 0;
2002 for(i = 0; i < info.width; i++)
2003 t += info.minWidth[i];
2004 d.width = t + insets.left + insets.right;
2005
2006 t = 0;
2007 for(i = 0; i < info.height; i++)
2008 t += info.minHeight[i];
2009 d.height = t + insets.top + insets.bottom;
2010
2011 return d;
2012 }
2013
2014 transient boolean rightToLeft = false;
2015
2016 /**
2017 * Lays out the grid.
2018 * This method should only be used internally by
2019 * <code>GridBagLayout</code>.
2020 *
2021 * @param parent the layout container
2022 * @since 1.4
2023 */
2024 protected void arrangeGrid(Container parent) {
2025 ArrangeGrid(parent);
2026 }
2027
2028 /**
2029 * This method is obsolete and supplied for backwards
2030 * compatability only; new code should call {@link
2031 * #arrangeGrid(Container) arrangeGrid} instead.
2032 * This method is the same as <code>arrangeGrid</code>;
2033 * refer to <code>arrangeGrid</code> for details on the
2034 * parameter.
2035 */
2036 protected void ArrangeGrid(Container parent) {
2037 Component comp;
2038 int compindex;
2039 GridBagConstraints constraints;
2040 Insets insets = parent.getInsets();
2041 Component components[] = parent.getComponents();
2042 Dimension d;
2043 Rectangle r = new Rectangle();
2044 int i, diffw, diffh;
2045 double weight;
2046 GridBagLayoutInfo info;
2047
2048 rightToLeft = !parent.getComponentOrientation().isLeftToRight();
2049
2050 /*
2051 * If the parent has no slaves anymore, then don't do anything
2052 * at all: just leave the parent's size as-is.
2053 */
2054 if (components.length == 0 &&
2055 (columnWidths == null || columnWidths.length == 0) &&
2056 (rowHeights == null || rowHeights.length == 0)) {
2057 return;
2058 }
2059
2060 /*
2061 * Pass #1: scan all the slaves to figure out the total amount
2062 * of space needed.
2063 */
2064
2065 info = getLayoutInfo(parent, PREFERREDSIZE);
2066 d = getMinSize(parent, info);
2067
2068 if (parent.width < d.width || parent.height < d.height) {
2069 info = getLayoutInfo(parent, MINSIZE);
2070 d = getMinSize(parent, info);
2071 }
2072
2073 layoutInfo = info;
2074 r.width = d.width;
2075 r.height = d.height;
2076
2077 /*
2078 * DEBUG
2079 *
2080 * DumpLayoutInfo(info);
2081 * for (compindex = 0 ; compindex < components.length ; compindex++) {
2082 * comp = components[compindex];
2083 * if (!comp.isVisible())
2084 * continue;
2085 * constraints = lookupConstraints(comp);
2086 * DumpConstraints(constraints);
2087 * }
2088 * System.out.println("minSize " + r.width + " " + r.height);
2089 */
2090
2091 /*
2092 * If the current dimensions of the window don't match the desired
2093 * dimensions, then adjust the minWidth and minHeight arrays
2094 * according to the weights.
2095 */
2096
2097 diffw = parent.width - r.width;
2098 if (diffw != 0) {
2099 weight = 0.0;
2100 for (i = 0; i < info.width; i++)
2101 weight += info.weightX[i];
2102 if (weight > 0.0) {
2103 for (i = 0; i < info.width; i++) {
2104 int dx = (int)(( ((double)diffw) * info.weightX[i]) / weight);
2105 info.minWidth[i] += dx;
2106 r.width += dx;
2107 if (info.minWidth[i] < 0) {
2108 r.width -= info.minWidth[i];
2109 info.minWidth[i] = 0;
2110 }
2111 }
2112 }
2113 diffw = parent.width - r.width;
2114 }
2115
2116 else {
2117 diffw = 0;
2118 }
2119
2120 diffh = parent.height - r.height;
2121 if (diffh != 0) {
2122 weight = 0.0;
2123 for (i = 0; i < info.height; i++)
2124 weight += info.weightY[i];
2125 if (weight > 0.0) {
2126 for (i = 0; i < info.height; i++) {
2127 int dy = (int)(( ((double)diffh) * info.weightY[i]) / weight);
2128 info.minHeight[i] += dy;
2129 r.height += dy;
2130 if (info.minHeight[i] < 0) {
2131 r.height -= info.minHeight[i];
2132 info.minHeight[i] = 0;
2133 }
2134 }
2135 }
2136 diffh = parent.height - r.height;
2137 }
2138
2139 else {
2140 diffh = 0;
2141 }
2142
2143 /*
2144 * DEBUG
2145 *
2146 * System.out.println("Re-adjusted:");
2147 * DumpLayoutInfo(info);
2148 */
2149
2150 /*
2151 * Now do the actual layout of the slaves using the layout information
2152 * that has been collected.
2153 */
2154
2155 info.startx = diffw/2 + insets.left;
2156 info.starty = diffh/2 + insets.top;
2157
2158 for (compindex = 0 ; compindex < components.length ; compindex++) {
2159 comp = components[compindex];
2160 if (!comp.isVisible()){
2161 continue;
2162 }
2163 constraints = lookupConstraints(comp);
2164
2165 if (!rightToLeft) {
2166 r.x = info.startx;
2167 for(i = 0; i < constraints.tempX; i++)
2168 r.x += info.minWidth[i];
2169 } else {
2170 r.x = parent.width - (diffw/2 + insets.right);
2171 for(i = 0; i < constraints.tempX; i++)
2172 r.x -= info.minWidth[i];
2173 }
2174
2175 r.y = info.starty;
2176 for(i = 0; i < constraints.tempY; i++)
2177 r.y += info.minHeight[i];
2178
2179 r.width = 0;
2180 for(i = constraints.tempX;
2181 i < (constraints.tempX + constraints.tempWidth);
2182 i++) {
2183 r.width += info.minWidth[i];
2184 }
2185
2186 r.height = 0;
2187 for(i = constraints.tempY;
2188 i < (constraints.tempY + constraints.tempHeight);
2189 i++) {
2190 r.height += info.minHeight[i];
2191 }
2192
2193 componentAdjusting = comp;
2194 adjustForGravity(constraints, r);
2195
2196 /* fix for 4408108 - components were being created outside of the container */
2197 /* fix for 4969409 "-" replaced by "+" */
2198 if (r.x < 0) {
2199 r.width += r.x;
2200 r.x = 0;
2201 }
2202
2203 if (r.y < 0) {
2204 r.height += r.y;
2205 r.y = 0;
2206 }
2207
2208 /*
2209 * If the window is too small to be interesting then
2210 * unmap it. Otherwise configure it and then make sure
2211 * it's mapped.
2212 */
2213
2214 if ((r.width <= 0) || (r.height <= 0)) {
2215 comp.setBounds(0, 0, 0, 0);
2216 }
2217 else {
2218 if (comp.x != r.x || comp.y != r.y ||
2219 comp.width != r.width || comp.height != r.height) {
2220 comp.setBounds(r.x, r.y, r.width, r.height);
2221 }
2222 }
2223 }
2224 }
2225
2226 // Added for serial backwards compatability (4348425)
2227 static final long serialVersionUID = 8838754796412211005L;
2228}