0001 /*
0002 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025 package java.awt;
0026
0027 import java.util.Hashtable;
0028 import java.util.Arrays;
0029
0030 /**
0031 * The <code>GridBagLayout</code> class is a flexible layout
0032 * manager that aligns components vertically, horizontally or along their
0033 * baseline without requiring that the components be of the same size.
0034 * Each <code>GridBagLayout</code> object maintains a dynamic,
0035 * rectangular grid of cells, with each component occupying
0036 * one or more cells, called its <em>display area</em>.
0037 * <p>
0038 * Each component managed by a <code>GridBagLayout</code> is associated with
0039 * an instance of {@link GridBagConstraints}. The constraints object
0040 * specifies where a component's display area should be located on the grid
0041 * and how the component should be positioned within its display area. In
0042 * addition to its constraints object, the <code>GridBagLayout</code> also
0043 * considers each component's minimum and preferred sizes in order to
0044 * determine a component's size.
0045 * <p>
0046 * The overall orientation of the grid depends on the container's
0047 * {@link ComponentOrientation} property. For horizontal left-to-right
0048 * orientations, grid coordinate (0,0) is in the upper left corner of the
0049 * container with x increasing to the right and y increasing downward. For
0050 * horizontal right-to-left orientations, grid coordinate (0,0) is in the upper
0051 * right corner of the container with x increasing to the left and y
0052 * increasing downward.
0053 * <p>
0054 * To use a grid bag layout effectively, you must customize one or more
0055 * of the <code>GridBagConstraints</code> objects that are associated
0056 * with its components. You customize a <code>GridBagConstraints</code>
0057 * object by setting one or more of its instance variables:
0058 * <p>
0059 * <dl>
0060 * <dt>{@link GridBagConstraints#gridx},
0061 * {@link GridBagConstraints#gridy}
0062 * <dd>Specifies the cell containing the leading corner of the component's
0063 * display area, where the cell at the origin of the grid has address
0064 * <code>gridx = 0</code>,
0065 * <code>gridy = 0</code>. For horizontal left-to-right layout,
0066 * a component's leading corner is its upper left. For horizontal
0067 * right-to-left layout, a component's leading corner is its upper right.
0068 * Use <code>GridBagConstraints.RELATIVE</code> (the default value)
0069 * to specify that the component be placed immediately following
0070 * (along the x axis for <code>gridx</code> or the y axis for
0071 * <code>gridy</code>) the component that was added to the container
0072 * just before this component was added.
0073 * <dt>{@link GridBagConstraints#gridwidth},
0074 * {@link GridBagConstraints#gridheight}
0075 * <dd>Specifies the number of cells in a row (for <code>gridwidth</code>)
0076 * or column (for <code>gridheight</code>)
0077 * in the component's display area.
0078 * The default value is 1.
0079 * Use <code>GridBagConstraints.REMAINDER</code> to specify
0080 * that the component's display area will be from <code>gridx</code>
0081 * to the last cell in the row (for <code>gridwidth</code>)
0082 * or from <code>gridy</code> to the last cell in the column
0083 * (for <code>gridheight</code>).
0084 *
0085 * Use <code>GridBagConstraints.RELATIVE</code> to specify
0086 * that the component's display area will be from <code>gridx</code>
0087 * to the next to the last cell in its row (for <code>gridwidth</code>
0088 * or from <code>gridy</code> to the next to the last cell in its
0089 * column (for <code>gridheight</code>).
0090 *
0091 * <dt>{@link GridBagConstraints#fill}
0092 * <dd>Used when the component's display area
0093 * is larger than the component's requested size
0094 * to determine whether (and how) to resize the component.
0095 * Possible values are
0096 * <code>GridBagConstraints.NONE</code> (the default),
0097 * <code>GridBagConstraints.HORIZONTAL</code>
0098 * (make the component wide enough to fill its display area
0099 * horizontally, but don't change its height),
0100 * <code>GridBagConstraints.VERTICAL</code>
0101 * (make the component tall enough to fill its display area
0102 * vertically, but don't change its width), and
0103 * <code>GridBagConstraints.BOTH</code>
0104 * (make the component fill its display area entirely).
0105 * <dt>{@link GridBagConstraints#ipadx},
0106 * {@link GridBagConstraints#ipady}
0107 * <dd>Specifies the component's internal padding within the layout,
0108 * how much to add to the minimum size of the component.
0109 * The width of the component will be at least its minimum width
0110 * plus <code>ipadx</code> pixels. Similarly, the height of
0111 * the component will be at least the minimum height plus
0112 * <code>ipady</code> pixels.
0113 * <dt>{@link GridBagConstraints#insets}
0114 * <dd>Specifies the component's external padding, the minimum
0115 * amount of space between the component and the edges of its display area.
0116 * <dt>{@link GridBagConstraints#anchor}
0117 * <dd>Specifies where the component should be positioned in its display area.
0118 * There are three kinds of possible values: absolute, orientation-relative,
0119 * and baseline-relative
0120 * Orientation relative values are interpreted relative to the container's
0121 * <code>ComponentOrientation</code> property while absolute values
0122 * are not. Baseline relative values are calculated relative to the
0123 * baseline. Valid values are:</dd>
0124 * <p>
0125 * <center><table BORDER=0 COLS=3 WIDTH=800
0126 * SUMMARY="absolute, relative and baseline values as described above">
0127 * <tr>
0128 * <th><P ALIGN="LEFT">Absolute Values</th>
0129 * <th><P ALIGN="LEFT">Orientation Relative Values</th>
0130 * <th><P ALIGN="LEFT">Baseline Relative Values</th>
0131 * </tr>
0132 * <tr>
0133 * <td>
0134 * <li><code>GridBagConstraints.NORTH</code></li>
0135 * <li><code>GridBagConstraints.SOUTH</code></li>
0136 * <li><code>GridBagConstraints.WEST</code></li>
0137 * <li><code>GridBagConstraints.EAST</code></li>
0138 * <li><code>GridBagConstraints.NORTHWEST</code></li>
0139 * <li><code>GridBagConstraints.NORTHEAST</code></li>
0140 * <li><code>GridBagConstraints.SOUTHWEST</code></li>
0141 * <li><code>GridBagConstraints.SOUTHEAST</code></li>
0142 * <li><code>GridBagConstraints.CENTER</code> (the default)</li>
0143 * </td>
0144 * <td>
0145 * <li><code>GridBagConstraints.PAGE_START</code></li>
0146 * <li><code>GridBagConstraints.PAGE_END</code></li>
0147 * <li><code>GridBagConstraints.LINE_START</code></li>
0148 * <li><code>GridBagConstraints.LINE_END</code></li>
0149 * <li><code>GridBagConstraints.FIRST_LINE_START</code></li>
0150 * <li><code>GridBagConstraints.FIRST_LINE_END</code></li>
0151 * <li><code>GridBagConstraints.LAST_LINE_START</code></li>
0152 * <li><code>GridBagConstraints.LAST_LINE_END</code></li>
0153 * </td>
0154 * <td>
0155 * <li><code>GridBagConstraints.BASELINE</code></li>
0156 * <li><code>GridBagConstraints.BASELINE_LEADING</code></li>
0157 * <li><code>GridBagConstraints.BASELINE_TRAILING</code></li>
0158 * <li><code>GridBagConstraints.ABOVE_BASELINE</code></li>
0159 * <li><code>GridBagConstraints.ABOVE_BASELINE_LEADING</code></li>
0160 * <li><code>GridBagConstraints.ABOVE_BASELINE_TRAILING</code></li>
0161 * <li><code>GridBagConstraints.BELOW_BASELINE</code></li>
0162 * <li><code>GridBagConstraints.BELOW_BASELINE_LEADING</code></li>
0163 * <li><code>GridBagConstraints.BELOW_BASELINE_TRAILING</code></li>
0164 * </td>
0165 * </tr>
0166 * </table></center><p>
0167 * <dt>{@link GridBagConstraints#weightx},
0168 * {@link GridBagConstraints#weighty}
0169 * <dd>Used to determine how to distribute space, which is
0170 * important for specifying resizing behavior.
0171 * Unless you specify a weight for at least one component
0172 * in a row (<code>weightx</code>) and column (<code>weighty</code>),
0173 * all the components clump together in the center of their container.
0174 * This is because when the weight is zero (the default),
0175 * the <code>GridBagLayout</code> object puts any extra space
0176 * between its grid of cells and the edges of the container.
0177 * </dl>
0178 * <p>
0179 * Each row may have a baseline; the baseline is determined by the
0180 * components in that row that have a valid baseline and are aligned
0181 * along the baseline (the component's anchor value is one of {@code
0182 * BASELINE}, {@code BASELINE_LEADING} or {@code BASELINE_TRAILING}).
0183 * If none of the components in the row has a valid baseline, the row
0184 * does not have a baseline.
0185 * <p>
0186 * If a component spans rows it is aligned either to the baseline of
0187 * the start row (if the baseline-resize behavior is {@code
0188 * CONSTANT_ASCENT}) or the end row (if the baseline-resize behavior
0189 * is {@code CONSTANT_DESCENT}). The row that the component is
0190 * aligned to is called the <em>prevailing row</em>.
0191 * <p>
0192 * The following figure shows a baseline layout and includes a
0193 * component that spans rows:
0194 * <center><table summary="Baseline Layout">
0195 * <tr ALIGN=CENTER>
0196 * <td>
0197 * <img src="doc-files/GridBagLayout-baseline.png"
0198 * alt="The following text describes this graphic (Figure 1)." ALIGN=center>
0199 * </td>
0200 * </table></center>
0201 * This layout consists of three components:
0202 * <ul><li>A panel that starts in row 0 and ends in row 1. The panel
0203 * has a baseline-resize behavior of <code>CONSTANT_DESCENT</code> and has
0204 * an anchor of <code>BASELINE</code>. As the baseline-resize behavior
0205 * is <code>CONSTANT_DESCENT</code> the prevailing row for the panel is
0206 * row 1.
0207 * <li>Two buttons, each with a baseline-resize behavior of
0208 * <code>CENTER_OFFSET</code> and an anchor of <code>BASELINE</code>.
0209 * </ul>
0210 * Because the second button and the panel share the same prevailing row,
0211 * they are both aligned along their baseline.
0212 * <p>
0213 * Components positioned using one of the baseline-relative values resize
0214 * differently than when positioned using an absolute or orientation-relative
0215 * value. How components change is dictated by how the baseline of the
0216 * prevailing row changes. The baseline is anchored to the
0217 * bottom of the display area if any components with the same prevailing row
0218 * have a baseline-resize behavior of <code>CONSTANT_DESCENT</code>,
0219 * otherwise the baseline is anchored to the top of the display area.
0220 * The following rules dictate the resize behavior:
0221 * <ul>
0222 * <li>Resizable components positioned above the baseline can only
0223 * grow as tall as the baseline. For example, if the baseline is at 100
0224 * and anchored at the top, a resizable component positioned above the
0225 * baseline can never grow more than 100 units.
0226 * <li>Similarly, resizable components positioned below the baseline can
0227 * only grow as high as the difference between the display height and the
0228 * baseline.
0229 * <li>Resizable components positioned on the baseline with a
0230 * baseline-resize behavior of <code>OTHER</code> are only resized if
0231 * the baseline at the resized size fits within the display area. If
0232 * the baseline is such that it does not fit within the display area
0233 * the component is not resized.
0234 * <li>Components positioned on the baseline that do not have a
0235 * baseline-resize behavior of <code>OTHER</code>
0236 * can only grow as tall as {@code display height - baseline + baseline of component}.
0237 * </ul>
0238 * If you position a component along the baseline, but the
0239 * component does not have a valid baseline, it will be vertically centered
0240 * in its space. Similarly if you have positioned a component relative
0241 * to the baseline and none of the components in the row have a valid
0242 * baseline the component is vertically centered.
0243 * <p>
0244 * The following figures show ten components (all buttons)
0245 * managed by a grid bag layout. Figure 2 shows the layout for a horizontal,
0246 * left-to-right container and Figure 3 shows the layout for a horizontal,
0247 * right-to-left container.
0248 * <p>
0249 * <center><table COLS=2 WIDTH=600 summary="layout">
0250 * <tr ALIGN=CENTER>
0251 * <td>
0252 * <img src="doc-files/GridBagLayout-1.gif" alt="The preceeding text describes this graphic (Figure 1)." ALIGN=center HSPACE=10 VSPACE=7>
0253 * </td>
0254 * <td>
0255 * <img src="doc-files/GridBagLayout-2.gif" alt="The preceeding text describes this graphic (Figure 2)." ALIGN=center HSPACE=10 VSPACE=7>
0256 * </td>
0257 * <tr ALIGN=CENTER>
0258 * <td>Figure 2: Horizontal, Left-to-Right</td>
0259 * <td>Figure 3: Horizontal, Right-to-Left</td>
0260 * </tr>
0261 * </table></center>
0262 * <p>
0263 * Each of the ten components has the <code>fill</code> field
0264 * of its associated <code>GridBagConstraints</code> object
0265 * set to <code>GridBagConstraints.BOTH</code>.
0266 * In addition, the components have the following non-default constraints:
0267 * <p>
0268 * <ul>
0269 * <li>Button1, Button2, Button3: <code>weightx = 1.0</code>
0270 * <li>Button4: <code>weightx = 1.0</code>,
0271 * <code>gridwidth = GridBagConstraints.REMAINDER</code>
0272 * <li>Button5: <code>gridwidth = GridBagConstraints.REMAINDER</code>
0273 * <li>Button6: <code>gridwidth = GridBagConstraints.RELATIVE</code>
0274 * <li>Button7: <code>gridwidth = GridBagConstraints.REMAINDER</code>
0275 * <li>Button8: <code>gridheight = 2</code>,
0276 * <code>weighty = 1.0</code>
0277 * <li>Button9, Button 10:
0278 * <code>gridwidth = GridBagConstraints.REMAINDER</code>
0279 * </ul>
0280 * <p>
0281 * Here is the code that implements the example shown above:
0282 * <p>
0283 * <hr><blockquote><pre>
0284 * import java.awt.*;
0285 * import java.util.*;
0286 * import java.applet.Applet;
0287 *
0288 * public class GridBagEx1 extends Applet {
0289 *
0290 * protected void makebutton(String name,
0291 * GridBagLayout gridbag,
0292 * GridBagConstraints c) {
0293 * Button button = new Button(name);
0294 * gridbag.setConstraints(button, c);
0295 * add(button);
0296 * }
0297 *
0298 * public void init() {
0299 * GridBagLayout gridbag = new GridBagLayout();
0300 * GridBagConstraints c = new GridBagConstraints();
0301 *
0302 * setFont(new Font("SansSerif", Font.PLAIN, 14));
0303 * setLayout(gridbag);
0304 *
0305 * c.fill = GridBagConstraints.BOTH;
0306 * c.weightx = 1.0;
0307 * makebutton("Button1", gridbag, c);
0308 * makebutton("Button2", gridbag, c);
0309 * makebutton("Button3", gridbag, c);
0310 *
0311 * c.gridwidth = GridBagConstraints.REMAINDER; //end row
0312 * makebutton("Button4", gridbag, c);
0313 *
0314 * c.weightx = 0.0; //reset to the default
0315 * makebutton("Button5", gridbag, c); //another row
0316 *
0317 * c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row
0318 * makebutton("Button6", gridbag, c);
0319 *
0320 * c.gridwidth = GridBagConstraints.REMAINDER; //end row
0321 * makebutton("Button7", gridbag, c);
0322 *
0323 * c.gridwidth = 1; //reset to the default
0324 * c.gridheight = 2;
0325 * c.weighty = 1.0;
0326 * makebutton("Button8", gridbag, c);
0327 *
0328 * c.weighty = 0.0; //reset to the default
0329 * c.gridwidth = GridBagConstraints.REMAINDER; //end row
0330 * c.gridheight = 1; //reset to the default
0331 * makebutton("Button9", gridbag, c);
0332 * makebutton("Button10", gridbag, c);
0333 *
0334 * setSize(300, 100);
0335 * }
0336 *
0337 * public static void main(String args[]) {
0338 * Frame f = new Frame("GridBag Layout Example");
0339 * GridBagEx1 ex1 = new GridBagEx1();
0340 *
0341 * ex1.init();
0342 *
0343 * f.add("Center", ex1);
0344 * f.pack();
0345 * f.setSize(f.getPreferredSize());
0346 * f.show();
0347 * }
0348 * }
0349 * </pre></blockquote><hr>
0350 * <p>
0351 * @version 1.85, 05/05/07
0352 * @author Doug Stein
0353 * @author Bill Spitzak (orignial NeWS & OLIT implementation)
0354 * @see java.awt.GridBagConstraints
0355 * @see java.awt.GridBagLayoutInfo
0356 * @see java.awt.ComponentOrientation
0357 * @since JDK1.0
0358 */
0359 public class GridBagLayout implements LayoutManager2,
0360 java.io.Serializable {
0361
0362 static final int EMPIRICMULTIPLIER = 2;
0363 /**
0364 * This field is no longer used to reserve arrays and keeped for backward
0365 * compatibility. Previously, this was
0366 * the maximum number of grid positions (both horizontal and
0367 * vertical) that could be laid out by the grid bag layout.
0368 * Current implementation doesn't impose any limits
0369 * on the size of a grid.
0370 */
0371 protected static final int MAXGRIDSIZE = 512;
0372
0373 /**
0374 * The smallest grid that can be laid out by the grid bag layout.
0375 */
0376 protected static final int MINSIZE = 1;
0377 /**
0378 * The preferred grid size that can be laid out by the grid bag layout.
0379 */
0380 protected static final int PREFERREDSIZE = 2;
0381
0382 /**
0383 * This hashtable maintains the association between
0384 * a component and its gridbag constraints.
0385 * The Keys in <code>comptable</code> are the components and the
0386 * values are the instances of <code>GridBagConstraints</code>.
0387 *
0388 * @serial
0389 * @see java.awt.GridBagConstraints
0390 */
0391 protected Hashtable<Component, GridBagConstraints> comptable;
0392
0393 /**
0394 * This field holds a gridbag constraints instance
0395 * containing the default values, so if a component
0396 * does not have gridbag constraints associated with
0397 * it, then the component will be assigned a
0398 * copy of the <code>defaultConstraints</code>.
0399 *
0400 * @serial
0401 * @see #getConstraints(Component)
0402 * @see #setConstraints(Component, GridBagConstraints)
0403 * @see #lookupConstraints(Component)
0404 */
0405 protected GridBagConstraints defaultConstraints;
0406
0407 /**
0408 * This field holds the layout information
0409 * for the gridbag. The information in this field
0410 * is based on the most recent validation of the
0411 * gridbag.
0412 * If <code>layoutInfo</code> is <code>null</code>
0413 * this indicates that there are no components in
0414 * the gridbag or if there are components, they have
0415 * not yet been validated.
0416 *
0417 * @serial
0418 * @see #getLayoutInfo(Container, int)
0419 */
0420 protected GridBagLayoutInfo layoutInfo;
0421
0422 /**
0423 * This field holds the overrides to the column minimum
0424 * width. If this field is non-<code>null</code> the values are
0425 * applied to the gridbag after all of the minimum columns
0426 * widths have been calculated.
0427 * If columnWidths has more elements than the number of
0428 * columns, columns are added to the gridbag to match
0429 * the number of elements in columnWidth.
0430 *
0431 * @serial
0432 * @see #getLayoutDimensions()
0433 */
0434 public int columnWidths[];
0435
0436 /**
0437 * This field holds the overrides to the row minimum
0438 * heights. If this field is non-<code>null</code> the values are
0439 * applied to the gridbag after all of the minimum row
0440 * heights have been calculated.
0441 * If <code>rowHeights</code> has more elements than the number of
0442 * rows, rowa are added to the gridbag to match
0443 * the number of elements in <code>rowHeights</code>.
0444 *
0445 * @serial
0446 * @see #getLayoutDimensions()
0447 */
0448 public int rowHeights[];
0449
0450 /**
0451 * This field holds the overrides to the column weights.
0452 * If this field is non-<code>null</code> the values are
0453 * applied to the gridbag after all of the columns
0454 * weights have been calculated.
0455 * If <code>columnWeights[i]</code> > weight for column i, then
0456 * column i is assigned the weight in <code>columnWeights[i]</code>.
0457 * If <code>columnWeights</code> has more elements than the number
0458 * of columns, the excess elements are ignored - they do
0459 * not cause more columns to be created.
0460 *
0461 * @serial
0462 */
0463 public double columnWeights[];
0464
0465 /**
0466 * This field holds the overrides to the row weights.
0467 * If this field is non-<code>null</code> the values are
0468 * applied to the gridbag after all of the rows
0469 * weights have been calculated.
0470 * If <code>rowWeights[i]</code> > weight for row i, then
0471 * row i is assigned the weight in <code>rowWeights[i]</code>.
0472 * If <code>rowWeights</code> has more elements than the number
0473 * of rows, the excess elements are ignored - they do
0474 * not cause more rows to be created.
0475 *
0476 * @serial
0477 */
0478 public double rowWeights[];
0479
0480 /**
0481 * The component being positioned. This is set before calling into
0482 * <code>adjustForGravity</code>.
0483 */
0484 private Component componentAdjusting;
0485
0486 /**
0487 * Creates a grid bag layout manager.
0488 */
0489 public GridBagLayout() {
0490 comptable = new Hashtable<Component, GridBagConstraints>();
0491 defaultConstraints = new GridBagConstraints();
0492 }
0493
0494 /**
0495 * Sets the constraints for the specified component in this layout.
0496 * @param comp the component to be modified
0497 * @param constraints the constraints to be applied
0498 */
0499 public void setConstraints(Component comp,
0500 GridBagConstraints constraints) {
0501 comptable.put(comp, (GridBagConstraints) constraints.clone());
0502 }
0503
0504 /**
0505 * Gets the constraints for the specified component. A copy of
0506 * the actual <code>GridBagConstraints</code> object is returned.
0507 * @param comp the component to be queried
0508 * @return the constraint for the specified component in this
0509 * grid bag layout; a copy of the actual constraint
0510 * object is returned
0511 */
0512 public GridBagConstraints getConstraints(Component comp) {
0513 GridBagConstraints constraints = comptable.get(comp);
0514 if (constraints == null) {
0515 setConstraints(comp, defaultConstraints);
0516 constraints = comptable.get(comp);
0517 }
0518 return (GridBagConstraints) constraints.clone();
0519 }
0520
0521 /**
0522 * Retrieves the constraints for the specified component.
0523 * The return value is not a copy, but is the actual
0524 * <code>GridBagConstraints</code> object used by the layout mechanism.
0525 * <p>
0526 * If <code>comp</code> is not in the <code>GridBagLayout</code>,
0527 * a set of default <code>GridBagConstraints</code> are returned.
0528 * A <code>comp</code> value of <code>null</code> is invalid
0529 * and returns <code>null</code>.
0530 *
0531 * @param comp the component to be queried
0532 * @return the contraints for the specified component
0533 */
0534 protected GridBagConstraints lookupConstraints(Component comp) {
0535 GridBagConstraints constraints = comptable.get(comp);
0536 if (constraints == null) {
0537 setConstraints(comp, defaultConstraints);
0538 constraints = comptable.get(comp);
0539 }
0540 return constraints;
0541 }
0542
0543 /**
0544 * Removes the constraints for the specified component in this layout
0545 * @param comp the component to be modified
0546 */
0547 private void removeConstraints(Component comp) {
0548 comptable.remove(comp);
0549 }
0550
0551 /**
0552 * Determines the origin of the layout area, in the graphics coordinate
0553 * space of the target container. This value represents the pixel
0554 * coordinates of the top-left corner of the layout area regardless of
0555 * the <code>ComponentOrientation</code> value of the container. This
0556 * is distinct from the grid origin given by the cell coordinates (0,0).
0557 * Most applications do not call this method directly.
0558 * @return the graphics origin of the cell in the top-left
0559 * corner of the layout grid
0560 * @see java.awt.ComponentOrientation
0561 * @since JDK1.1
0562 */
0563 public Point getLayoutOrigin() {
0564 Point origin = new Point(0, 0);
0565 if (layoutInfo != null) {
0566 origin.x = layoutInfo.startx;
0567 origin.y = layoutInfo.starty;
0568 }
0569 return origin;
0570 }
0571
0572 /**
0573 * Determines column widths and row heights for the layout grid.
0574 * <p>
0575 * Most applications do not call this method directly.
0576 * @return an array of two arrays, containing the widths
0577 * of the layout columns and
0578 * the heights of the layout rows
0579 * @since JDK1.1
0580 */
0581 public int[][] getLayoutDimensions() {
0582 if (layoutInfo == null)
0583 return new int[2][0];
0584
0585 int dim[][] = new int[2][];
0586 dim[0] = new int[layoutInfo.width];
0587 dim[1] = new int[layoutInfo.height];
0588
0589 System.arraycopy(layoutInfo.minWidth, 0, dim[0], 0,
0590 layoutInfo.width);
0591 System.arraycopy(layoutInfo.minHeight, 0, dim[1], 0,
0592 layoutInfo.height);
0593
0594 return dim;
0595 }
0596
0597 /**
0598 * Determines the weights of the layout grid's columns and rows.
0599 * Weights are used to calculate how much a given column or row
0600 * stretches beyond its preferred size, if the layout has extra
0601 * room to fill.
0602 * <p>
0603 * Most applications do not call this method directly.
0604 * @return an array of two arrays, representing the
0605 * horizontal weights of the layout columns
0606 * and the vertical weights of the layout rows
0607 * @since JDK1.1
0608 */
0609 public double[][] getLayoutWeights() {
0610 if (layoutInfo == null)
0611 return new double[2][0];
0612
0613 double weights[][] = new double[2][];
0614 weights[0] = new double[layoutInfo.width];
0615 weights[1] = new double[layoutInfo.height];
0616
0617 System.arraycopy(layoutInfo.weightX, 0, weights[0], 0,
0618 layoutInfo.width);
0619 System.arraycopy(layoutInfo.weightY, 0, weights[1], 0,
0620 layoutInfo.height);
0621
0622 return weights;
0623 }
0624
0625 /**
0626 * Determines which cell in the layout grid contains the point
0627 * specified by <code>(x, y)</code>. Each cell is identified
0628 * by its column index (ranging from 0 to the number of columns
0629 * minus 1) and its row index (ranging from 0 to the number of
0630 * rows minus 1).
0631 * <p>
0632 * If the <code>(x, y)</code> point lies
0633 * outside the grid, the following rules are used.
0634 * The column index is returned as zero if <code>x</code> lies to the
0635 * left of the layout for a left-to-right container or to the right of
0636 * the layout for a right-to-left container. The column index is returned
0637 * as the number of columns if <code>x</code> lies
0638 * to the right of the layout in a left-to-right container or to the left
0639 * in a right-to-left container.
0640 * The row index is returned as zero if <code>y</code> lies above the
0641 * layout, and as the number of rows if <code>y</code> lies
0642 * below the layout. The orientation of a container is determined by its
0643 * <code>ComponentOrientation</code> property.
0644 * @param x the <i>x</i> coordinate of a point
0645 * @param y the <i>y</i> coordinate of a point
0646 * @return an ordered pair of indexes that indicate which cell
0647 * in the layout grid contains the point
0648 * (<i>x</i>, <i>y</i>).
0649 * @see java.awt.ComponentOrientation
0650 * @since JDK1.1
0651 */
0652 public Point location(int x, int y) {
0653 Point loc = new Point(0, 0);
0654 int i, d;
0655
0656 if (layoutInfo == null)
0657 return loc;
0658
0659 d = layoutInfo.startx;
0660 if (!rightToLeft) {
0661 for (i = 0; i < layoutInfo.width; i++) {
0662 d += layoutInfo.minWidth[i];
0663 if (d > x)
0664 break;
0665 }
0666 } else {
0667 for (i = layoutInfo.width - 1; i >= 0; i--) {
0668 if (d > x)
0669 break;
0670 d += layoutInfo.minWidth[i];
0671 }
0672 i++;
0673 }
0674 loc.x = i;
0675
0676 d = layoutInfo.starty;
0677 for (i = 0; i < layoutInfo.height; i++) {
0678 d += layoutInfo.minHeight[i];
0679 if (d > y)
0680 break;
0681 }
0682 loc.y = i;
0683
0684 return loc;
0685 }
0686
0687 /**
0688 * Has no effect, since this layout manager does not use a per-component string.
0689 */
0690 public void addLayoutComponent(String name, Component comp) {
0691 }
0692
0693 /**
0694 * Adds the specified component to the layout, using the specified
0695 * <code>constraints</code> object. Note that constraints
0696 * are mutable and are, therefore, cloned when cached.
0697 *
0698 * @param comp the component to be added
0699 * @param constraints an object that determines how
0700 * the component is added to the layout
0701 * @exception IllegalArgumentException if <code>constraints</code>
0702 * is not a <code>GridBagConstraint</code>
0703 */
0704 public void addLayoutComponent(Component comp, Object constraints) {
0705 if (constraints instanceof GridBagConstraints) {
0706 setConstraints(comp, (GridBagConstraints) constraints);
0707 } else if (constraints != null) {
0708 throw new IllegalArgumentException(
0709 "cannot add to layout: constraints must be a GridBagConstraint");
0710 }
0711 }
0712
0713 /**
0714 * Removes the specified component from this layout.
0715 * <p>
0716 * Most applications do not call this method directly.
0717 * @param comp the component to be removed.
0718 * @see java.awt.Container#remove(java.awt.Component)
0719 * @see java.awt.Container#removeAll()
0720 */
0721 public void removeLayoutComponent(Component comp) {
0722 removeConstraints(comp);
0723 }
0724
0725 /**
0726 * Determines the preferred size of the <code>parent</code>
0727 * container using this grid bag layout.
0728 * <p>
0729 * Most applications do not call this method directly.
0730 *
0731 * @param parent the container in which to do the layout
0732 * @see java.awt.Container#getPreferredSize
0733 * @return the preferred size of the <code>parent</code>
0734 * container
0735 */
0736 public Dimension preferredLayoutSize(Container parent) {
0737 GridBagLayoutInfo info = getLayoutInfo(parent, PREFERREDSIZE);
0738 return getMinSize(parent, info);
0739 }
0740
0741 /**
0742 * Determines the minimum size of the <code>parent</code> container
0743 * using this grid bag layout.
0744 * <p>
0745 * Most applications do not call this method directly.
0746 * @param parent the container in which to do the layout
0747 * @see java.awt.Container#doLayout
0748 * @return the minimum size of the <code>parent</code> container
0749 */
0750 public Dimension minimumLayoutSize(Container parent) {
0751 GridBagLayoutInfo info = getLayoutInfo(parent, MINSIZE);
0752 return getMinSize(parent, info);
0753 }
0754
0755 /**
0756 * Returns the maximum dimensions for this layout given the components
0757 * in the specified target container.
0758 * @param target the container which needs to be laid out
0759 * @see Container
0760 * @see #minimumLayoutSize(Container)
0761 * @see #preferredLayoutSize(Container)
0762 * @return the maximum dimensions for this layout
0763 */
0764 public Dimension maximumLayoutSize(Container target) {
0765 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
0766 }
0767
0768 /**
0769 * Returns the alignment along the x axis. This specifies how
0770 * the component would like to be aligned relative to other
0771 * components. The value should be a number between 0 and 1
0772 * where 0 represents alignment along the origin, 1 is aligned
0773 * the furthest away from the origin, 0.5 is centered, etc.
0774 * <p>
0775 * @return the value <code>0.5f</code> to indicate centered
0776 */
0777 public float getLayoutAlignmentX(Container parent) {
0778 return 0.5f;
0779 }
0780
0781 /**
0782 * Returns the alignment along the y axis. This specifies how
0783 * the component would like to be aligned relative to other
0784 * components. The value should be a number between 0 and 1
0785 * where 0 represents alignment along the origin, 1 is aligned
0786 * the furthest away from the origin, 0.5 is centered, etc.
0787 * <p>
0788 * @return the value <code>0.5f</code> to indicate centered
0789 */
0790 public float getLayoutAlignmentY(Container parent) {
0791 return 0.5f;
0792 }
0793
0794 /**
0795 * Invalidates the layout, indicating that if the layout manager
0796 * has cached information it should be discarded.
0797 */
0798 public void invalidateLayout(Container target) {
0799 }
0800
0801 /**
0802 * Lays out the specified container using this grid bag layout.
0803 * This method reshapes components in the specified container in
0804 * order to satisfy the contraints of this <code>GridBagLayout</code>
0805 * object.
0806 * <p>
0807 * Most applications do not call this method directly.
0808 * @param parent the container in which to do the layout
0809 * @see java.awt.Container
0810 * @see java.awt.Container#doLayout
0811 */
0812 public void layoutContainer(Container parent) {
0813 arrangeGrid(parent);
0814 }
0815
0816 /**
0817 * Returns a string representation of this grid bag layout's values.
0818 * @return a string representation of this grid bag layout.
0819 */
0820 public String toString() {
0821 return getClass().getName();
0822 }
0823
0824 /**
0825 * Print the layout information. Useful for debugging.
0826 */
0827
0828 /* DEBUG
0829 *
0830 * protected void dumpLayoutInfo(GridBagLayoutInfo s) {
0831 * int x;
0832 *
0833 * System.out.println("Col\tWidth\tWeight");
0834 * for (x=0; x<s.width; x++) {
0835 * System.out.println(x + "\t" +
0836 * s.minWidth[x] + "\t" +
0837 * s.weightX[x]);
0838 * }
0839 * System.out.println("Row\tHeight\tWeight");
0840 * for (x=0; x<s.height; x++) {
0841 * System.out.println(x + "\t" +
0842 * s.minHeight[x] + "\t" +
0843 * s.weightY[x]);
0844 * }
0845 * }
0846 */
0847
0848 /**
0849 * Print the layout constraints. Useful for debugging.
0850 */
0851
0852 /* DEBUG
0853 *
0854 * protected void dumpConstraints(GridBagConstraints constraints) {
0855 * System.out.println(
0856 * "wt " +
0857 * constraints.weightx +
0858 * " " +
0859 * constraints.weighty +
0860 * ", " +
0861 *
0862 * "box " +
0863 * constraints.gridx +
0864 * " " +
0865 * constraints.gridy +
0866 * " " +
0867 * constraints.gridwidth +
0868 * " " +
0869 * constraints.gridheight +
0870 * ", " +
0871 *
0872 * "min " +
0873 * constraints.minWidth +
0874 * " " +
0875 * constraints.minHeight +
0876 * ", " +
0877 *
0878 * "pad " +
0879 * constraints.insets.bottom +
0880 * " " +
0881 * constraints.insets.left +
0882 * " " +
0883 * constraints.insets.right +
0884 * " " +
0885 * constraints.insets.top +
0886 * " " +
0887 * constraints.ipadx +
0888 * " " +
0889 * constraints.ipady);
0890 * }
0891 */
0892
0893 /**
0894 * Fills in an instance of <code>GridBagLayoutInfo</code> for the
0895 * current set of managed children. This requires three passes through the
0896 * set of children:
0897 *
0898 * <ol>
0899 * <li>Figure out the dimensions of the layout grid.
0900 * <li>Determine which cells the components occupy.
0901 * <li>Distribute the weights and min sizes amoung the rows/columns.
0902 * </ol>
0903 *
0904 * This also caches the minsizes for all the children when they are
0905 * first encountered (so subsequent loops don't need to ask again).
0906 * <p>
0907 * This method should only be used internally by
0908 * <code>GridBagLayout</code>.
0909 *
0910 * @param parent the layout container
0911 * @param sizeflag either <code>PREFERREDSIZE</code> or
0912 * <code>MINSIZE</code>
0913 * @return the <code>GridBagLayoutInfo</code> for the set of children
0914 * @since 1.4
0915 */
0916 protected GridBagLayoutInfo getLayoutInfo(Container parent,
0917 int sizeflag) {
0918 return GetLayoutInfo(parent, sizeflag);
0919 }
0920
0921 /*
0922 * Calculate maximum array sizes to allocate arrays without ensureCapacity
0923 * we may use preCalculated sizes in whole class because of upper estimation of
0924 * maximumArrayXIndex and maximumArrayYIndex.
0925 */
0926
0927 private long[] preInitMaximumArraySizes(Container parent) {
0928 Component components[] = parent.getComponents();
0929 Component comp;
0930 GridBagConstraints constraints;
0931 int curX, curY;
0932 int curWidth, curHeight;
0933 int preMaximumArrayXIndex = 0;
0934 int preMaximumArrayYIndex = 0;
0935 long[] returnArray = new long[2];
0936
0937 for (int compId = 0; compId < components.length; compId++) {
0938 comp = components[compId];
0939 if (!comp.isVisible()) {
0940 continue;
0941 }
0942
0943 constraints = lookupConstraints(comp);
0944 curX = constraints.gridx;
0945 curY = constraints.gridy;
0946 curWidth = constraints.gridwidth;
0947 curHeight = constraints.gridheight;
0948
0949 // -1==RELATIVE, means that column|row equals to previously added component,
0950 // since each next Component with gridx|gridy == RELATIVE starts from
0951 // previous position, so we should start from previous component which
0952 // already used in maximumArray[X|Y]Index calculation. We could just increase
0953 // maximum by 1 to handle situation when component with gridx=-1 was added.
0954 if (curX < 0) {
0955 curX = ++preMaximumArrayYIndex;
0956 }
0957 if (curY < 0) {
0958 curY = ++preMaximumArrayXIndex;
0959 }
0960 // gridwidth|gridheight may be equal to RELATIVE (-1) or REMAINDER (0)
0961 // in any case using 1 instead of 0 or -1 should be sufficient to for
0962 // correct maximumArraySizes calculation
0963 if (curWidth <= 0) {
0964 curWidth = 1;
0965 }
0966 if (curHeight <= 0) {
0967 curHeight = 1;
0968 }
0969
0970 preMaximumArrayXIndex = Math.max(curY + curHeight,
0971 preMaximumArrayXIndex);
0972 preMaximumArrayYIndex = Math.max(curX + curWidth,
0973 preMaximumArrayYIndex);
0974 } //for (components) loop
0975 // Must specify index++ to allocate well-working arrays.
0976 /* fix for 4623196.
0977 * now return long array instead of Point
0978 */
0979 returnArray[0] = preMaximumArrayXIndex;
0980 returnArray[1] = preMaximumArrayYIndex;
0981 return returnArray;
0982 } //PreInitMaximumSizes
0983
0984 /**
0985 * This method is obsolete and supplied for backwards
0986 * compatability only; new code should call {@link
0987 * #getLayoutInfo(java.awt.Container, int) getLayoutInfo} instead.
0988 * This method is the same as <code>getLayoutInfo</code>;
0989 * refer to <code>getLayoutInfo</code> for details on parameters
0990 * and return value.
0991 */
0992 protected GridBagLayoutInfo GetLayoutInfo(Container parent,
0993 int sizeflag) {
0994 synchronized (parent.getTreeLock()) {
0995 GridBagLayoutInfo r;
0996 Component comp;
0997 GridBagConstraints constraints;
0998 Dimension d;
0999 Component components[] = parent.getComponents();
1000 // Code below will address index curX+curWidth in the case of yMaxArray, weightY
1001 // ( respectively curY+curHeight for xMaxArray, weightX ) where
1002 // curX in 0 to preInitMaximumArraySizes.y
1003 // Thus, the maximum index that could
1004 // be calculated in the following code is curX+curX.
1005 // EmpericMultier equals 2 because of this.
1006
1007 int layoutWidth, layoutHeight;
1008 int[] xMaxArray;
1009 int[] yMaxArray;
1010 int compindex, i, k, px, py, pixels_diff, nextSize;
1011 int curX = 0; // constraints.gridx
1012 int curY = 0; // constraints.gridy
1013 int curWidth = 1; // constraints.gridwidth
1014 int curHeight = 1; // constraints.gridheight
1015 int curRow, curCol;
1016 double weight_diff, weight;
1017 int maximumArrayXIndex = 0;
1018 int maximumArrayYIndex = 0;
1019 int anchor;
1020
1021 /*
1022 * Pass #1
1023 *
1024 * Figure out the dimensions of the layout grid (use a value of 1 for
1025 * zero or negative widths and heights).
1026 */
1027
1028 layoutWidth = layoutHeight = 0;
1029 curRow = curCol = -1;
1030 long[] arraySizes = preInitMaximumArraySizes(parent);
1031
1032 /* fix for 4623196.
1033 * If user try to create a very big grid we can
1034 * get NegativeArraySizeException because of integer value
1035 * overflow (EMPIRICMULTIPLIER*gridSize might be more then Integer.MAX_VALUE).
1036 * We need to detect this situation and try to create a
1037 * grid with Integer.MAX_VALUE size instead.
1038 */
1039 maximumArrayXIndex = (EMPIRICMULTIPLIER * arraySizes[0] > Integer.MAX_VALUE) ? Integer.MAX_VALUE
1040 : EMPIRICMULTIPLIER * (int) arraySizes[0];
1041 maximumArrayYIndex = (EMPIRICMULTIPLIER * arraySizes[1] > Integer.MAX_VALUE) ? Integer.MAX_VALUE
1042 : EMPIRICMULTIPLIER * (int) arraySizes[1];
1043
1044 if (rowHeights != null) {
1045 maximumArrayXIndex = Math.max(maximumArrayXIndex,
1046 rowHeights.length);
1047 }
1048 if (columnWidths != null) {
1049 maximumArrayYIndex = Math.max(maximumArrayYIndex,
1050 columnWidths.length);
1051 }
1052
1053 xMaxArray = new int[maximumArrayXIndex];
1054 yMaxArray = new int[maximumArrayYIndex];
1055
1056 boolean hasBaseline = false;
1057 for (compindex = 0; compindex < components.length; compindex++) {
1058 comp = components[compindex];
1059 if (!comp.isVisible())
1060 continue;
1061 constraints = lookupConstraints(comp);
1062
1063 curX = constraints.gridx;
1064 curY = constraints.gridy;
1065 curWidth = constraints.gridwidth;
1066 if (curWidth <= 0)
1067 curWidth = 1;
1068 curHeight = constraints.gridheight;
1069 if (curHeight <= 0)
1070 curHeight = 1;
1071
1072 /* If x or y is negative, then use relative positioning: */
1073 if (curX < 0 && curY < 0) {
1074 if (curRow >= 0)
1075 curY = curRow;
1076 else if (curCol >= 0)
1077 curX = curCol;
1078 else
1079 curY = 0;
1080 }
1081 if (curX < 0) {
1082 px = 0;
1083 for (i = curY; i < (curY + curHeight); i++) {
1084 px = Math.max(px, xMaxArray[i]);
1085 }
1086
1087 curX = px - curX - 1;
1088 if (curX < 0)
1089 curX = 0;
1090 } else if (curY < 0) {
1091 py = 0;
1092 for (i = curX; i < (curX + curWidth); i++) {
1093 py = Math.max(py, yMaxArray[i]);
1094 }
1095 curY = py - curY - 1;
1096 if (curY < 0)
1097 curY = 0;
1098 }
1099
1100 /* Adjust the grid width and height
1101 * fix for 5005945: unneccessary loops removed
1102 */
1103 px = curX + curWidth;
1104 if (layoutWidth < px) {
1105 layoutWidth = px;
1106 }
1107 py = curY + curHeight;
1108 if (layoutHeight < py) {
1109 layoutHeight = py;
1110 }
1111
1112 /* Adjust xMaxArray and yMaxArray */
1113 for (i = curX; i < (curX + curWidth); i++) {
1114 yMaxArray[i] = py;
1115 }
1116 for (i = curY; i < (curY + curHeight); i++) {
1117 xMaxArray[i] = px;
1118 }
1119
1120 /* Cache the current slave's size. */
1121 if (sizeflag == PREFERREDSIZE)
1122 d = comp.getPreferredSize();
1123 else
1124 d = comp.getMinimumSize();
1125 constraints.minWidth = d.width;
1126 constraints.minHeight = d.height;
1127 if (calculateBaseline(comp, constraints, d)) {
1128 hasBaseline = true;
1129 }
1130
1131 /* Zero width and height must mean that this is the last item (or
1132 * else something is wrong). */
1133 if (constraints.gridheight == 0
1134 && constraints.gridwidth == 0)
1135 curRow = curCol = -1;
1136
1137 /* Zero width starts a new row */
1138 if (constraints.gridheight == 0 && curRow < 0)
1139 curCol = curX + curWidth;
1140
1141 /* Zero height starts a new column */
1142 else if (constraints.gridwidth == 0 && curCol < 0)
1143 curRow = curY + curHeight;
1144 } //for (components) loop
1145
1146 /*
1147 * Apply minimum row/column dimensions
1148 */
1149 if (columnWidths != null
1150 && layoutWidth < columnWidths.length)
1151 layoutWidth = columnWidths.length;
1152 if (rowHeights != null && layoutHeight < rowHeights.length)
1153 layoutHeight = rowHeights.length;
1154
1155 r = new GridBagLayoutInfo(layoutWidth, layoutHeight);
1156
1157 /*
1158 * Pass #2
1159 *
1160 * Negative values for gridX are filled in with the current x value.
1161 * Negative values for gridY are filled in with the current y value.
1162 * Negative or zero values for gridWidth and gridHeight end the current
1163 * row or column, respectively.
1164 */
1165
1166 curRow = curCol = -1;
1167
1168 Arrays.fill(xMaxArray, 0);
1169 Arrays.fill(yMaxArray, 0);
1170
1171 int[] maxAscent = null;
1172 int[] maxDescent = null;
1173 short[] baselineType = null;
1174
1175 if (hasBaseline) {
1176 r.maxAscent = maxAscent = new int[layoutHeight];
1177 r.maxDescent = maxDescent = new int[layoutHeight];
1178 r.baselineType = baselineType = new short[layoutHeight];
1179 r.hasBaseline = true;
1180 }
1181
1182 for (compindex = 0; compindex < components.length; compindex++) {
1183 comp = components[compindex];
1184 if (!comp.isVisible())
1185 continue;
1186 constraints = lookupConstraints(comp);
1187
1188 curX = constraints.gridx;
1189 curY = constraints.gridy;
1190 curWidth = constraints.gridwidth;
1191 curHeight = constraints.gridheight;
1192
1193 /* If x or y is negative, then use relative positioning: */
1194 if (curX < 0 && curY < 0) {
1195 if (curRow >= 0)
1196 curY = curRow;
1197 else if (curCol >= 0)
1198 curX = curCol;
1199 else
1200 curY = 0;
1201 }
1202
1203 if (curX < 0) {
1204 if (curHeight <= 0) {
1205 curHeight += r.height - curY;
1206 if (curHeight < 1)
1207 curHeight = 1;
1208 }
1209
1210 px = 0;
1211 for (i = curY; i < (curY + curHeight); i++)
1212 px = Math.max(px, xMaxArray[i]);
1213
1214 curX = px - curX - 1;
1215 if (curX < 0)
1216 curX = 0;
1217 } else if (curY < 0) {
1218 if (curWidth <= 0) {
1219 curWidth += r.width - curX;
1220 if (curWidth < 1)
1221 curWidth = 1;
1222 }
1223
1224 py = 0;
1225 for (i = curX; i < (curX + curWidth); i++) {
1226 py = Math.max(py, yMaxArray[i]);
1227 }
1228
1229 curY = py - curY - 1;
1230 if (curY < 0)
1231 curY = 0;
1232 }
1233
1234 if (curWidth <= 0) {
1235 curWidth += r.width - curX;
1236 if (curWidth < 1)
1237 curWidth = 1;
1238 }
1239
1240 if (curHeight <= 0) {
1241 curHeight += r.height - curY;
1242 if (curHeight < 1)
1243 curHeight = 1;
1244 }
1245
1246 px = curX + curWidth;
1247 py = curY + curHeight;
1248
1249 for (i = curX; i < (curX + curWidth); i++) {
1250 yMaxArray[i] = py;
1251 }
1252 for (i = curY; i < (curY + curHeight); i++) {
1253 xMaxArray[i] = px;
1254 }
1255
1256 /* Make negative sizes start a new row/column */
1257 if (constraints.gridheight == 0
1258 && constraints.gridwidth == 0)
1259 curRow = curCol = -1;
1260 if (constraints.gridheight == 0 && curRow < 0)
1261 curCol = curX + curWidth;
1262 else if (constraints.gridwidth == 0 && curCol < 0)
1263 curRow = curY + curHeight;
1264
1265 /* Assign the new values to the gridbag slave */
1266 constraints.tempX = curX;
1267 constraints.tempY = curY;
1268 constraints.tempWidth = curWidth;
1269 constraints.tempHeight = curHeight;
1270
1271 anchor = constraints.anchor;
1272 if (hasBaseline) {
1273 switch (anchor) {
1274 case GridBagConstraints.BASELINE:
1275 case GridBagConstraints.BASELINE_LEADING:
1276 case GridBagConstraints.BASELINE_TRAILING:
1277 if (constraints.ascent >= 0) {
1278 if (curHeight == 1) {
1279 maxAscent[curY] = Math.max(
1280 maxAscent[curY],
1281 constraints.ascent);
1282 maxDescent[curY] = Math.max(
1283 maxDescent[curY],
1284 constraints.descent);
1285 } else {
1286 if (constraints.baselineResizeBehavior == Component.BaselineResizeBehavior.CONSTANT_DESCENT) {
1287 maxDescent[curY + curHeight - 1] = Math
1288 .max(maxDescent[curY
1289 + curHeight - 1],
1290 constraints.descent);
1291 } else {
1292 maxAscent[curY] = Math.max(
1293 maxAscent[curY],
1294 constraints.ascent);
1295 }
1296 }
1297 if (constraints.baselineResizeBehavior == Component.BaselineResizeBehavior.CONSTANT_DESCENT) {
1298 baselineType[curY + curHeight - 1] |= (1 << constraints.baselineResizeBehavior
1299 .ordinal());
1300 } else {
1301 baselineType[curY] |= (1 << constraints.baselineResizeBehavior
1302 .ordinal());
1303 }
1304 }
1305 break;
1306 case GridBagConstraints.ABOVE_BASELINE:
1307 case GridBagConstraints.ABOVE_BASELINE_LEADING:
1308 case GridBagConstraints.ABOVE_BASELINE_TRAILING:
1309 // Component positioned above the baseline.
1310 // To make the bottom edge of the component aligned
1311 // with the baseline the bottom inset is
1312 // added to the descent, the rest to the ascent.
1313 pixels_diff = constraints.minHeight
1314 + constraints.insets.top
1315 + constraints.ipady;
1316 maxAscent[curY] = Math.max(maxAscent[curY],
1317 pixels_diff);
1318 maxDescent[curY] = Math.max(maxDescent[curY],
1319 constraints.insets.bottom);
1320 break;
1321 case GridBagConstraints.BELOW_BASELINE:
1322 case GridBagConstraints.BELOW_BASELINE_LEADING:
1323 case GridBagConstraints.BELOW_BASELINE_TRAILING:
1324 // Component positioned below the baseline.
1325 // To make the top edge of the component aligned
1326 // with the baseline the top inset is
1327 // added to the ascent, the rest to the descent.
1328 pixels_diff = constraints.minHeight
1329 + constraints.insets.bottom
1330 + constraints.ipady;
1331 maxDescent[curY] = Math.max(maxDescent[curY],
1332 pixels_diff);
1333 maxAscent[curY] = Math.max(maxAscent[curY],
1334 constraints.insets.top);
1335 break;
1336 }
1337 }
1338 }
1339
1340 r.weightX = new double[maximumArrayYIndex];
1341 r.weightY = new double[maximumArrayXIndex];
1342 r.minWidth = new int[maximumArrayYIndex];
1343 r.minHeight = new int[maximumArrayXIndex];
1344
1345 /*
1346 * Apply minimum row/column dimensions and weights
1347 */
1348 if (columnWidths != null)
1349 System.arraycopy(columnWidths, 0, r.minWidth, 0,
1350 columnWidths.length);
1351 if (rowHeights != null)
1352 System.arraycopy(rowHeights, 0, r.minHeight, 0,
1353 rowHeights.length);
1354 if (columnWeights != null)
1355 System.arraycopy(columnWeights, 0, r.weightX, 0, Math
1356 .min(r.weightX.length, columnWeights.length));
1357 if (rowWeights != null)
1358 System.arraycopy(rowWeights, 0, r.weightY, 0, Math.min(
1359 r.weightY.length, rowWeights.length));
1360
1361 /*
1362 * Pass #3
1363 *
1364 * Distribute the minimun widths and weights:
1365 */
1366
1367 nextSize = Integer.MAX_VALUE;
1368
1369 for (i = 1; i != Integer.MAX_VALUE; i = nextSize, nextSize = Integer.MAX_VALUE) {
1370 for (compindex = 0; compindex < components.length; compindex++) {
1371 comp = components[compindex];
1372 if (!comp.isVisible())
1373 continue;
1374 constraints = lookupConstraints(comp);
1375
1376 if (constraints.tempWidth == i) {
1377 px = constraints.tempX + constraints.tempWidth; /* right column */
1378
1379 /*
1380 * Figure out if we should use this slave\'s weight. If the weight
1381 * is less than the total weight spanned by the width of the cell,
1382 * then discard the weight. Otherwise split the difference
1383 * according to the existing weights.
1384 */
1385
1386 weight_diff = constraints.weightx;
1387 for (k = constraints.tempX; k < px; k++)
1388 weight_diff -= r.weightX[k];
1389 if (weight_diff > 0.0) {
1390 weight = 0.0;
1391 for (k = constraints.tempX; k < px; k++)
1392 weight += r.weightX[k];
1393 for (k = constraints.tempX; weight > 0.0
1394 && k < px; k++) {
1395 double wt = r.weightX[k];
1396 double dx = (wt * weight_diff) / weight;
1397 r.weightX[k] += dx;
1398 weight_diff -= dx;
1399 weight -= wt;
1400 }
1401 /* Assign the remainder to the rightmost cell */
1402 r.weightX[px - 1] += weight_diff;
1403 }
1404
1405 /*
1406 * Calculate the minWidth array values.
1407 * First, figure out how wide the current slave needs to be.
1408 * Then, see if it will fit within the current minWidth values.
1409 * If it will not fit, add the difference according to the
1410 * weightX array.
1411 */
1412
1413 pixels_diff = constraints.minWidth
1414 + constraints.ipadx
1415 + constraints.insets.left
1416 + constraints.insets.right;
1417
1418 for (k = constraints.tempX; k < px; k++)
1419 pixels_diff -= r.minWidth[k];
1420 if (pixels_diff > 0) {
1421 weight = 0.0;
1422 for (k = constraints.tempX; k < px; k++)
1423 weight += r.weightX[k];
1424 for (k = constraints.tempX; weight > 0.0
1425 && k < px; k++) {
1426 double wt = r.weightX[k];
1427 int dx = (int) ((wt * ((double) pixels_diff)) / weight);
1428 r.minWidth[k] += dx;
1429 pixels_diff -= dx;
1430 weight -= wt;
1431 }
1432 /* Any leftovers go into the rightmost cell */
1433 r.minWidth[px - 1] += pixels_diff;
1434 }
1435 } else if (constraints.tempWidth > i
1436 && constraints.tempWidth < nextSize)
1437 nextSize = constraints.tempWidth;
1438
1439 if (constraints.tempHeight == i) {
1440 py = constraints.tempY + constraints.tempHeight; /* bottom row */
1441
1442 /*
1443 * Figure out if we should use this slave's weight. If the weight
1444 * is less than the total weight spanned by the height of the cell,
1445 * then discard the weight. Otherwise split it the difference
1446 * according to the existing weights.
1447 */
1448
1449 weight_diff = constraints.weighty;
1450 for (k = constraints.tempY; k < py; k++)
1451 weight_diff -= r.weightY[k];
1452 if (weight_diff > 0.0) {
1453 weight = 0.0;
1454 for (k = constraints.tempY; k < py; k++)
1455 weight += r.weightY[k];
1456 for (k = constraints.tempY; weight > 0.0
1457 && k < py; k++) {
1458 double wt = r.weightY[k];
1459 double dy = (wt * weight_diff) / weight;
1460 r.weightY[k] += dy;
1461 weight_diff -= dy;
1462 weight -= wt;
1463 }
1464 /* Assign the remainder to the bottom cell */
1465 r.weightY[py - 1] += weight_diff;
1466 }
1467
1468 /*
1469 * Calculate the minHeight array values.
1470 * First, figure out how tall the current slave needs to be.
1471 * Then, see if it will fit within the current minHeight values.
1472 * If it will not fit, add the difference according to the
1473 * weightY array.
1474 */
1475
1476 pixels_diff = -1;
1477 if (hasBaseline) {
1478 switch (constraints.anchor) {
1479 case GridBagConstraints.BASELINE:
1480 case GridBagConstraints.BASELINE_LEADING:
1481 case GridBagConstraints.BASELINE_TRAILING:
1482 if (constraints.ascent >= 0) {
1483 if (constraints.tempHeight == 1) {
1484 pixels_diff = maxAscent[constraints.tempY]
1485 + maxDescent[constraints.tempY];
1486 } else if (constraints.baselineResizeBehavior != Component.BaselineResizeBehavior.CONSTANT_DESCENT) {
1487 pixels_diff = maxAscent[constraints.tempY]
1488 + constraints.descent;
1489 } else {
1490 pixels_diff = constraints.ascent
1491 + maxDescent[constraints.tempY
1492 + constraints.tempHeight
1493 - 1];
1494 }
1495 }
1496 break;
1497 case GridBagConstraints.ABOVE_BASELINE:
1498 case GridBagConstraints.ABOVE_BASELINE_LEADING:
1499 case GridBagConstraints.ABOVE_BASELINE_TRAILING:
1500 pixels_diff = constraints.insets.top
1501 + constraints.minHeight
1502 + constraints.ipady
1503 + maxDescent[constraints.tempY];
1504 break;
1505 case GridBagConstraints.BELOW_BASELINE:
1506 case GridBagConstraints.BELOW_BASELINE_LEADING:
1507 case GridBagConstraints.BELOW_BASELINE_TRAILING:
1508 pixels_diff = maxAscent[constraints.tempY]
1509 + constraints.minHeight
1510 + constraints.insets.bottom
1511 + constraints.ipady;
1512 break;
1513 }
1514 }
1515 if (pixels_diff == -1) {
1516 pixels_diff = constraints.minHeight
1517 + constraints.ipady
1518 + constraints.insets.top
1519 + constraints.insets.bottom;
1520 }
1521 for (k = constraints.tempY; k < py; k++)
1522 pixels_diff -= r.minHeight[k];
1523 if (pixels_diff > 0) {
1524 weight = 0.0;
1525 for (k = constraints.tempY; k < py; k++)
1526 weight += r.weightY[k];
1527 for (k = constraints.tempY; weight > 0.0
1528 && k < py; k++) {
1529 double wt = r.weightY[k];
1530 int dy = (int) ((wt * ((double) pixels_diff)) / weight);
1531 r.minHeight[k] += dy;
1532 pixels_diff -= dy;
1533 weight -= wt;
1534 }
1535 /* Any leftovers go into the bottom cell */
1536 r.minHeight[py - 1] += pixels_diff;
1537 }
1538 } else if (constraints.tempHeight > i
1539 && constraints.tempHeight < nextSize)
1540 nextSize = constraints.tempHeight;
1541 }
1542 }
1543 return r;
1544 }
1545 } //getLayoutInfo()
1546
1547 /**
1548 * Calculate the baseline for the specified component.
1549 * If {@code c} is positioned along it's baseline, the baseline is
1550 * obtained and the {@code constraints} ascent, descent and
1551 * baseline resize behavior are set from the component; and true is
1552 * returned. Otherwise false is returned.
1553 */
1554 private boolean calculateBaseline(Component c,
1555 GridBagConstraints constraints, Dimension size) {
1556 int anchor = constraints.anchor;
1557 if (anchor == GridBagConstraints.BASELINE
1558 || anchor == GridBagConstraints.BASELINE_LEADING
1559 || anchor == GridBagConstraints.BASELINE_TRAILING) {
1560 // Apply the padding to the component, then ask for the baseline.
1561 int w = size.width + constraints.ipadx;
1562 int h = size.height + constraints.ipady;
1563 constraints.ascent = c.getBaseline(w, h);
1564 if (constraints.ascent >= 0) {
1565 // Component has a baseline
1566 int baseline = constraints.ascent;
1567 // Adjust the ascent and descent to include the insets.
1568 constraints.descent = h - constraints.ascent
1569 + constraints.insets.bottom;
1570 constraints.ascent += constraints.insets.top;
1571 constraints.baselineResizeBehavior = c
1572 .getBaselineResizeBehavior();
1573 constraints.centerPadding = 0;
1574 if (constraints.baselineResizeBehavior == Component.BaselineResizeBehavior.CENTER_OFFSET) {
1575 // Component has a baseline resize behavior of
1576 // CENTER_OFFSET, calculate centerPadding and
1577 // centerOffset (see the description of
1578 // CENTER_OFFSET in the enum for detais on this
1579 // algorithm).
1580 int nextBaseline = c.getBaseline(w, h + 1);
1581 constraints.centerOffset = baseline - h / 2;
1582 if (h % 2 == 0) {
1583 if (baseline != nextBaseline) {
1584 constraints.centerPadding = 1;
1585 }
1586 } else if (baseline == nextBaseline) {
1587 constraints.centerOffset--;
1588 constraints.centerPadding = 1;
1589 }
1590 }
1591 }
1592 return true;
1593 } else {
1594 constraints.ascent = -1;
1595 return false;
1596 }
1597 }
1598
1599 /**
1600 * Adjusts the x, y, width, and height fields to the correct
1601 * values depending on the constraint geometry and pads.
1602 * This method should only be used internally by
1603 * <code>GridBagLayout</code>.
1604 *
1605 * @param constraints the constraints to be applied
1606 * @param r the <code>Rectangle</code> to be adjusted
1607 * @since 1.4
1608 */
1609 protected void adjustForGravity(GridBagConstraints constraints,
1610 Rectangle r) {
1611 AdjustForGravity(constraints, r);
1612 }
1613
1614 /**
1615 * This method is obsolete and supplied for backwards
1616 * compatability only; new code should call {@link
1617 * #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle)
1618 * adjustForGravity} instead.
1619 * This method is the same as <code>adjustForGravity</code>;
1620 * refer to <code>adjustForGravity</code> for details
1621 * on parameters.
1622 */
1623 protected void AdjustForGravity(GridBagConstraints constraints,
1624 Rectangle r) {
1625 int diffx, diffy;
1626 int cellY = r.y;
1627 int cellHeight = r.height;
1628
1629 if (!rightToLeft) {
1630 r.x += constraints.insets.left;
1631 } else {
1632 r.x -= r.width - constraints.insets.right;
1633 }
1634 r.width -= (constraints.insets.left + constraints.insets.right);
1635 r.y += constraints.insets.top;
1636 r.height -= (constraints.insets.top + constraints.insets.bottom);
1637
1638 diffx = 0;
1639 if ((constraints.fill != GridBagConstraints.HORIZONTAL && constraints.fill != GridBagConstraints.BOTH)
1640 && (r.width > (constraints.minWidth + constraints.ipadx))) {
1641 diffx = r.width
1642 - (constraints.minWidth + constraints.ipadx);
1643 r.width = constraints.minWidth + constraints.ipadx;
1644 }
1645
1646 diffy = 0;
1647 if ((constraints.fill != GridBagConstraints.VERTICAL && constraints.fill != GridBagConstraints.BOTH)
1648 && (r.height > (constraints.minHeight + constraints.ipady))) {
1649 diffy = r.height
1650 - (constraints.minHeight + constraints.ipady);
1651 r.height = constraints.minHeight + constraints.ipady;
1652 }
1653
1654 switch (constraints.anchor) {
1655 case GridBagConstraints.BASELINE:
1656 r.x += diffx / 2;
1657 alignOnBaseline(constraints, r, cellY, cellHeight);
1658 break;
1659 case GridBagConstraints.BASELINE_LEADING:
1660 if (rightToLeft) {
1661 r.x += diffx;
1662 }
1663 alignOnBaseline(constraints, r, cellY, cellHeight);
1664 break;
1665 case GridBagConstraints.BASELINE_TRAILING:
1666 if (!rightToLeft) {
1667 r.x += diffx;
1668 }
1669 alignOnBaseline(constraints, r, cellY, cellHeight);
1670 break;
1671 case GridBagConstraints.ABOVE_BASELINE:
1672 r.x += diffx / 2;
1673 alignAboveBaseline(constraints, r, cellY, cellHeight);
1674 break;
1675 case GridBagConstraints.ABOVE_BASELINE_LEADING:
1676 if (rightToLeft) {
1677 r.x += diffx;
1678 }
1679 alignAboveBaseline(constraints, r, cellY, cellHeight);
1680 break;
1681 case GridBagConstraints.ABOVE_BASELINE_TRAILING:
1682 if (!rightToLeft) {
1683 r.x += diffx;
1684 }
1685 alignAboveBaseline(constraints, r, cellY, cellHeight);
1686 break;
1687 case GridBagConstraints.BELOW_BASELINE:
1688 r.x += diffx / 2;
1689 alignBelowBaseline(constraints, r, cellY, cellHeight);
1690 break;
1691 case GridBagConstraints.BELOW_BASELINE_LEADING:
1692 if (rightToLeft) {
1693 r.x += diffx;
1694 }
1695 alignBelowBaseline(constraints, r, cellY, cellHeight);
1696 break;
1697 case GridBagConstraints.BELOW_BASELINE_TRAILING:
1698 if (!rightToLeft) {
1699 r.x += diffx;
1700 }
1701 alignBelowBaseline(constraints, r, cellY, cellHeight);
1702 break;
1703 case GridBagConstraints.CENTER:
1704 r.x += diffx / 2;
1705 r.y += diffy / 2;
1706 break;
1707 case GridBagConstraints.PAGE_START:
1708 case GridBagConstraints.NORTH:
1709 r.x += diffx / 2;
1710 break;
1711 case GridBagConstraints.NORTHEAST:
1712 r.x += diffx;
1713 break;
1714 case GridBagConstraints.EAST:
1715 r.x += diffx;
1716 r.y += diffy / 2;
1717 break;
1718 case GridBagConstraints.SOUTHEAST:
1719 r.x += diffx;
1720 r.y += diffy;
1721 break;
1722 case GridBagConstraints.PAGE_END:
1723 case GridBagConstraints.SOUTH:
1724 r.x += diffx / 2;
1725 r.y += diffy;
1726 break;
1727 case GridBagConstraints.SOUTHWEST:
1728 r.y += diffy;
1729 break;
1730 case GridBagConstraints.WEST:
1731 r.y += diffy / 2;
1732 break;
1733 case GridBagConstraints.NORTHWEST:
1734 break;
1735 case GridBagConstraints.LINE_START:
1736 if (rightToLeft) {
1737 r.x += diffx;
1738 }
1739 r.y += diffy / 2;
1740 break;
1741 case GridBagConstraints.LINE_END:
1742 if (!rightToLeft) {
1743 r.x += diffx;
1744 }
1745 r.y += diffy / 2;
1746 break;
1747 case GridBagConstraints.FIRST_LINE_START:
1748 if (rightToLeft) {
1749 r.x += diffx;
1750 }
1751 break;
1752 case GridBagConstraints.FIRST_LINE_END:
1753 if (!rightToLeft) {
1754 r.x += diffx;
1755 }
1756 break;
1757 case GridBagConstraints.LAST_LINE_START:
1758 if (rightToLeft) {
1759 r.x += diffx;
1760 }
1761 r.y += diffy;
1762 break;
1763 case GridBagConstraints.LAST_LINE_END:
1764 if (!rightToLeft) {
1765 r.x += diffx;
1766 }
1767 r.y += diffy;
1768 break;
1769 default:
1770 throw new IllegalArgumentException("illegal anchor value");
1771 }
1772 }
1773
1774 /**
1775 * Positions on the baseline.
1776 *
1777 * @param cellY the location of the row, does not include insets
1778 * @param cellHeight the height of the row, does not take into account
1779 * insets
1780 * @param r available bounds for the component, is padded by insets and
1781 * ipady
1782 */
1783 private void alignOnBaseline(GridBagConstraints cons, Rectangle r,
1784 int cellY, int cellHeight) {
1785 if (cons.ascent >= 0) {
1786 if (cons.baselineResizeBehavior == Component.BaselineResizeBehavior.CONSTANT_DESCENT) {
1787 // Anchor to the bottom.
1788 // Baseline is at (cellY + cellHeight - maxDescent).
1789 // Bottom of component (maxY) is at baseline + descent
1790 // of component. We need to subtract the bottom inset here
1791 // as the descent in the constraints object includes the
1792 // bottom inset.
1793 int maxY = cellY
1794 + cellHeight
1795 - layoutInfo.maxDescent[cons.tempY
1796 + cons.tempHeight - 1] + cons.descent
1797 - cons.insets.bottom;
1798 if (!cons.isVerticallyResizable()) {
1799 // Component not resizable, calculate y location
1800 // from maxY - height.
1801 r.y = maxY - cons.minHeight;
1802 r.height = cons.minHeight;
1803 } else {
1804 // Component is resizable. As brb is constant descent,
1805 // can expand component to fill region above baseline.
1806 // Subtract out the top inset so that components insets
1807 // are honored.
1808 r.height = maxY - cellY - cons.insets.top;
1809 }
1810 } else {
1811 // BRB is not constant_descent
1812 int baseline; // baseline for the row, relative to cellY
1813 // Component baseline, includes insets.top
1814 int ascent = cons.ascent;
1815 if (layoutInfo.hasConstantDescent(cons.tempY)) {
1816 // Mixed ascent/descent in same row, calculate position
1817 // off maxDescent
1818 baseline = cellHeight
1819 - layoutInfo.maxDescent[cons.tempY];
1820 } else {
1821 // Only ascents/unknown in this row, anchor to top
1822 baseline = layoutInfo.maxAscent[cons.tempY];
1823 }
1824 if (cons.baselineResizeBehavior == Component.BaselineResizeBehavior.OTHER) {
1825 // BRB is other, which means we can only determine
1826 // the baseline by asking for it again giving the
1827 // size we plan on using for the component.
1828 boolean fits = false;
1829 ascent = componentAdjusting.getBaseline(r.width,
1830 r.height);
1831 if (ascent >= 0) {
1832 // Component has a baseline, pad with top inset
1833 // (this follows from calculateBaseline which
1834 // does the same).
1835 ascent += cons.insets.top;
1836 }
1837 if (ascent >= 0 && ascent <= baseline) {
1838 // Components baseline fits within rows baseline.
1839 // Make sure the descent fits within the space as well.
1840 if (baseline
1841 + (r.height - ascent - cons.insets.top) <= cellHeight
1842 - cons.insets.bottom) {
1843 // It fits, we're good.
1844 fits = true;
1845 } else if (cons.isVerticallyResizable()) {
1846 // Doesn't fit, but it's resizable. Try
1847 // again assuming we'll get ascent again.
1848 int ascent2 = componentAdjusting
1849 .getBaseline(r.width, cellHeight
1850 - cons.insets.bottom
1851 - baseline + ascent);
1852 if (ascent2 >= 0) {
1853 ascent2 += cons.insets.top;
1854 }
1855 if (ascent2 >= 0 && ascent2 <= ascent) {
1856 // It'll fit
1857 r.height = cellHeight
1858 - cons.insets.bottom - baseline
1859 + ascent;
1860 ascent = ascent2;
1861 fits = true;
1862 }
1863 }
1864 }
1865 if (!fits) {
1866 // Doesn't fit, use min size and original ascent
1867 ascent = cons.ascent;
1868 r.width = cons.minWidth;
1869 r.height = cons.minHeight;
1870 }
1871 }
1872 // Reset the components y location based on
1873 // components ascent and baseline for row. Because ascent
1874 // includes the baseline
1875 r.y = cellY + baseline - ascent + cons.insets.top;
1876 if (cons.isVerticallyResizable()) {
1877 switch (cons.baselineResizeBehavior) {
1878 case CONSTANT_ASCENT:
1879 r.height = Math
1880 .max(cons.minHeight, cellY + cellHeight
1881 - r.y - cons.insets.bottom);
1882 break;
1883 case CENTER_OFFSET: {
1884 int upper = r.y - cellY - cons.insets.top;
1885 int lower = cellY + cellHeight - r.y
1886 - cons.minHeight - cons.insets.bottom;
1887 int delta = Math.min(upper, lower);
1888 delta += delta;
1889 if (delta > 0
1890 && (cons.minHeight + cons.centerPadding + delta)
1891 / 2 + cons.centerOffset != baseline) {
1892 // Off by 1
1893 delta--;
1894 }
1895 r.height = cons.minHeight + delta;
1896 r.y = cellY + baseline
1897 - (r.height + cons.centerPadding) / 2
1898 - cons.centerOffset;
1899 }
1900 break;
1901 case OTHER:
1902 // Handled above
1903 break;
1904 default:
1905 break;
1906 }
1907 }
1908 }
1909 } else {
1910 centerVertically(cons, r, cellHeight);
1911 }
1912 }
1913
1914 /**
1915 * Positions the specified component above the baseline. That is
1916 * the bottom edge of the component will be aligned along the baseline.
1917 * If the row does not have a baseline, this centers the component.
1918 */
1919 private void alignAboveBaseline(GridBagConstraints cons,
1920 Rectangle r, int cellY, int cellHeight) {
1921 if (layoutInfo.hasBaseline(cons.tempY)) {
1922 int maxY; // Baseline for the row
1923 if (layoutInfo.hasConstantDescent(cons.tempY)) {
1924 // Prefer descent
1925 maxY = cellY + cellHeight
1926 - layoutInfo.maxDescent[cons.tempY];
1927 } else {
1928 // Prefer ascent
1929 maxY = cellY + layoutInfo.maxAscent[cons.tempY];
1930 }
1931 if (cons.isVerticallyResizable()) {
1932 // Component is resizable. Top edge is offset by top
1933 // inset, bottom edge on baseline.
1934 r.y = cellY + cons.insets.top;
1935 r.height = maxY - r.y;
1936 } else {
1937 // Not resizable.
1938 r.height = cons.minHeight + cons.ipady;
1939 r.y = maxY - r.height;
1940 }
1941 } else {
1942 centerVertically(cons, r, cellHeight);
1943 }
1944 }
1945
1946 /**
1947 * Positions below the baseline.
1948 */
1949 private void alignBelowBaseline(GridBagConstraints cons,
1950 Rectangle r, int cellY, int cellHeight) {
1951 if (layoutInfo.hasBaseline(cons.tempY)) {
1952 if (layoutInfo.hasConstantDescent(cons.tempY)) {
1953 // Prefer descent
1954 r.y = cellY + cellHeight
1955 - layoutInfo.maxDescent[cons.tempY];
1956 } else {
1957 // Prefer ascent
1958 r.y = cellY + layoutInfo.maxAscent[cons.tempY];
1959 }
1960 if (cons.isVerticallyResizable()) {
1961 r.height = cellY + cellHeight - r.y
1962 - cons.insets.bottom;
1963 }
1964 } else {
1965 centerVertically(cons, r, cellHeight);
1966 }
1967 }
1968
1969 private void centerVertically(GridBagConstraints cons, Rectangle r,
1970 int cellHeight) {
1971 if (!cons.isVerticallyResizable()) {
1972 r.y += Math.max(0,
1973 (cellHeight - cons.insets.top - cons.insets.bottom
1974 - cons.minHeight - cons.ipady) / 2);
1975 }
1976 }
1977
1978 /**
1979 * Figures out the minimum size of the
1980 * master based on the information from <code>getLayoutInfo</code>.
1981 * This method should only be used internally by
1982 * <code>GridBagLayout</code>.
1983 *
1984 * @param parent the layout container
1985 * @param info the layout info for this parent
1986 * @return a <code>Dimension</code> object containing the
1987 * minimum size
1988 * @since 1.4
1989 */
1990 protected Dimension getMinSize(Container parent,
1991 GridBagLayoutInfo info) {
1992 return GetMinSize(parent, info);
1993 }
1994
1995 /**
1996 * This method is obsolete and supplied for backwards
1997 * compatability only; new code should call {@link
1998 * #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead.
1999 * This method is the same as <code>getMinSize</code>;
2000 * refer to <code>getMinSize</code> for details on parameters
2001 * and return value.
2002 */
2003 protected Dimension GetMinSize(Container parent,
2004 GridBagLayoutInfo info) {
2005 Dimension d = new Dimension();
2006 int i, t;
2007 Insets insets = parent.getInsets();
2008
2009 t = 0;
2010 for (i = 0; i < info.width; i++)
2011 t += info.minWidth[i];
2012 d.width = t + insets.left + insets.right;
2013
2014 t = 0;
2015 for (i = 0; i < info.height; i++)
2016 t += info.minHeight[i];
2017 d.height = t + insets.top + insets.bottom;
2018
2019 return d;
2020 }
2021
2022 transient boolean rightToLeft = false;
2023
2024 /**
2025 * Lays out the grid.
2026 * This method should only be used internally by
2027 * <code>GridBagLayout</code>.
2028 *
2029 * @param parent the layout container
2030 * @since 1.4
2031 */
2032 protected void arrangeGrid(Container parent) {
2033 ArrangeGrid(parent);
2034 }
2035
2036 /**
2037 * This method is obsolete and supplied for backwards
2038 * compatability only; new code should call {@link
2039 * #arrangeGrid(Container) arrangeGrid} instead.
2040 * This method is the same as <code>arrangeGrid</code>;
2041 * refer to <code>arrangeGrid</code> for details on the
2042 * parameter.
2043 */
2044 protected void ArrangeGrid(Container parent) {
2045 Component comp;
2046 int compindex;
2047 GridBagConstraints constraints;
2048 Insets insets = parent.getInsets();
2049 Component components[] = parent.getComponents();
2050 Dimension d;
2051 Rectangle r = new Rectangle();
2052 int i, diffw, diffh;
2053 double weight;
2054 GridBagLayoutInfo info;
2055
2056 rightToLeft = !parent.getComponentOrientation().isLeftToRight();
2057
2058 /*
2059 * If the parent has no slaves anymore, then don't do anything
2060 * at all: just leave the parent's size as-is.
2061 */
2062 if (components.length == 0
2063 && (columnWidths == null || columnWidths.length == 0)
2064 && (rowHeights == null || rowHeights.length == 0)) {
2065 return;
2066 }
2067
2068 /*
2069 * Pass #1: scan all the slaves to figure out the total amount
2070 * of space needed.
2071 */
2072
2073 info = getLayoutInfo(parent, PREFERREDSIZE);
2074 d = getMinSize(parent, info);
2075
2076 if (parent.width < d.width || parent.height < d.height) {
2077 info = getLayoutInfo(parent, MINSIZE);
2078 d = getMinSize(parent, info);
2079 }
2080
2081 layoutInfo = info;
2082 r.width = d.width;
2083 r.height = d.height;
2084
2085 /*
2086 * DEBUG
2087 *
2088 * DumpLayoutInfo(info);
2089 * for (compindex = 0 ; compindex < components.length ; compindex++) {
2090 * comp = components[compindex];
2091 * if (!comp.isVisible())
2092 * continue;
2093 * constraints = lookupConstraints(comp);
2094 * DumpConstraints(constraints);
2095 * }
2096 * System.out.println("minSize " + r.width + " " + r.height);
2097 */
2098
2099 /*
2100 * If the current dimensions of the window don't match the desired
2101 * dimensions, then adjust the minWidth and minHeight arrays
2102 * according to the weights.
2103 */
2104
2105 diffw = parent.width - r.width;
2106 if (diffw != 0) {
2107 weight = 0.0;
2108 for (i = 0; i < info.width; i++)
2109 weight += info.weightX[i];
2110 if (weight > 0.0) {
2111 for (i = 0; i < info.width; i++) {
2112 int dx = (int) ((((double) diffw) * info.weightX[i]) / weight);
2113 info.minWidth[i] += dx;
2114 r.width += dx;
2115 if (info.minWidth[i] < 0) {
2116 r.width -= info.minWidth[i];
2117 info.minWidth[i] = 0;
2118 }
2119 }
2120 }
2121 diffw = parent.width - r.width;
2122 }
2123
2124 else {
2125 diffw = 0;
2126 }
2127
2128 diffh = parent.height - r.height;
2129 if (diffh != 0) {
2130 weight = 0.0;
2131 for (i = 0; i < info.height; i++)
2132 weight += info.weightY[i];
2133 if (weight > 0.0) {
2134 for (i = 0; i < info.height; i++) {
2135 int dy = (int) ((((double) diffh) * info.weightY[i]) / weight);
2136 info.minHeight[i] += dy;
2137 r.height += dy;
2138 if (info.minHeight[i] < 0) {
2139 r.height -= info.minHeight[i];
2140 info.minHeight[i] = 0;
2141 }
2142 }
2143 }
2144 diffh = parent.height - r.height;
2145 }
2146
2147 else {
2148 diffh = 0;
2149 }
2150
2151 /*
2152 * DEBUG
2153 *
2154 * System.out.println("Re-adjusted:");
2155 * DumpLayoutInfo(info);
2156 */
2157
2158 /*
2159 * Now do the actual layout of the slaves using the layout information
2160 * that has been collected.
2161 */
2162
2163 info.startx = diffw / 2 + insets.left;
2164 info.starty = diffh / 2 + insets.top;
2165
2166 for (compindex = 0; compindex < components.length; compindex++) {
2167 comp = components[compindex];
2168 if (!comp.isVisible()) {
2169 continue;
2170 }
2171 constraints = lookupConstraints(comp);
2172
2173 if (!rightToLeft) {
2174 r.x = info.startx;
2175 for (i = 0; i < constraints.tempX; i++)
2176 r.x += info.minWidth[i];
2177 } else {
2178 r.x = parent.width - (diffw / 2 + insets.right);
2179 for (i = 0; i < constraints.tempX; i++)
2180 r.x -= info.minWidth[i];
2181 }
2182
2183 r.y = info.starty;
2184 for (i = 0; i < constraints.tempY; i++)
2185 r.y += info.minHeight[i];
2186
2187 r.width = 0;
2188 for (i = constraints.tempX; i < (constraints.tempX + constraints.tempWidth); i++) {
2189 r.width += info.minWidth[i];
2190 }
2191
2192 r.height = 0;
2193 for (i = constraints.tempY; i < (constraints.tempY + constraints.tempHeight); i++) {
2194 r.height += info.minHeight[i];
2195 }
2196
2197 componentAdjusting = comp;
2198 adjustForGravity(constraints, r);
2199
2200 /* fix for 4408108 - components were being created outside of the container */
2201 /* fix for 4969409 "-" replaced by "+" */
2202 if (r.x < 0) {
2203 r.width += r.x;
2204 r.x = 0;
2205 }
2206
2207 if (r.y < 0) {
2208 r.height += r.y;
2209 r.y = 0;
2210 }
2211
2212 /*
2213 * If the window is too small to be interesting then
2214 * unmap it. Otherwise configure it and then make sure
2215 * it's mapped.
2216 */
2217
2218 if ((r.width <= 0) || (r.height <= 0)) {
2219 comp.setBounds(0, 0, 0, 0);
2220 } else {
2221 if (comp.x != r.x || comp.y != r.y
2222 || comp.width != r.width
2223 || comp.height != r.height) {
2224 comp.setBounds(r.x, r.y, r.width, r.height);
2225 }
2226 }
2227 }
2228 }
2229
2230 // Added for serial backwards compatability (4348425)
2231 static final long serialVersionUID = 8838754796412211005L;
2232 }
|