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