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: }
|