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