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