11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.util.Hashtable; 28 import java.util.Arrays; 29 30 /** 31 * The <code>GridBagLayout</code> class is a flexible layout 32 * manager that aligns components vertically, horizontally or along their 33 * baseline without requiring that the components be of the same size. 34 * Each <code>GridBagLayout</code> object maintains a dynamic, 35 * rectangular grid of cells, with each component occupying 36 * one or more cells, called its <em>display area</em>. 37 * <p> 38 * Each component managed by a <code>GridBagLayout</code> is associated with 39 * an instance of {@link GridBagConstraints}. The constraints object 40 * specifies where a component's display area should be located on the grid 41 * and how the component should be positioned within its display area. In 42 * addition to its constraints object, the <code>GridBagLayout</code> also 43 * considers each component's minimum and preferred sizes in order to 44 * determine a component's size. 45 * <p> 46 * The overall orientation of the grid depends on the container's 47 * {@link ComponentOrientation} property. For horizontal left-to-right 48 * orientations, grid coordinate (0,0) is in the upper left corner of the 49 * container with x increasing to the right and y increasing downward. For 50 * horizontal right-to-left orientations, grid coordinate (0,0) is in the upper 51 * right corner of the container with x increasing to the left and y 52 * increasing downward. 53 * <p> 54 * To use a grid bag layout effectively, you must customize one or more 55 * of the <code>GridBagConstraints</code> objects that are associated 56 * with its components. You customize a <code>GridBagConstraints</code> 57 * object by setting one or more of its instance variables: 58 * 59 * <dl> 60 * <dt>{@link GridBagConstraints#gridx}, 61 * {@link GridBagConstraints#gridy} 62 * <dd>Specifies the cell containing the leading corner of the component's 63 * display area, where the cell at the origin of the grid has address 64 * <code>gridx = 0</code>, 65 * <code>gridy = 0</code>. For horizontal left-to-right layout, 66 * a component's leading corner is its upper left. For horizontal 67 * right-to-left layout, a component's leading corner is its upper right. 68 * Use <code>GridBagConstraints.RELATIVE</code> (the default value) 69 * to specify that the component be placed immediately following 70 * (along the x axis for <code>gridx</code> or the y axis for 71 * <code>gridy</code>) the component that was added to the container 72 * just before this component was added. 73 * <dt>{@link GridBagConstraints#gridwidth}, 74 * {@link GridBagConstraints#gridheight} 75 * <dd>Specifies the number of cells in a row (for <code>gridwidth</code>) 76 * or column (for <code>gridheight</code>) 77 * in the component's display area. 78 * The default value is 1. 79 * Use <code>GridBagConstraints.REMAINDER</code> to specify 80 * that the component's display area will be from <code>gridx</code> 81 * to the last cell in the row (for <code>gridwidth</code>) 82 * or from <code>gridy</code> to the last cell in the column 83 * (for <code>gridheight</code>). 84 * 85 * Use <code>GridBagConstraints.RELATIVE</code> to specify 86 * that the component's display area will be from <code>gridx</code> 87 * to the next to the last cell in its row (for <code>gridwidth</code> 88 * or from <code>gridy</code> to the next to the last cell in its 89 * column (for <code>gridheight</code>). 90 * 91 * <dt>{@link GridBagConstraints#fill} 92 * <dd>Used when the component's display area 93 * is larger than the component's requested size 94 * to determine whether (and how) to resize the component. 95 * Possible values are 96 * <code>GridBagConstraints.NONE</code> (the default), 97 * <code>GridBagConstraints.HORIZONTAL</code> 98 * (make the component wide enough to fill its display area 99 * horizontally, but don't change its height), 100 * <code>GridBagConstraints.VERTICAL</code> 101 * (make the component tall enough to fill its display area 102 * vertically, but don't change its width), and 103 * <code>GridBagConstraints.BOTH</code> 104 * (make the component fill its display area entirely). 105 * <dt>{@link GridBagConstraints#ipadx}, 106 * {@link GridBagConstraints#ipady} 107 * <dd>Specifies the component's internal padding within the layout, 108 * how much to add to the minimum size of the component. 109 * The width of the component will be at least its minimum width 110 * plus <code>ipadx</code> pixels. Similarly, the height of 111 * the component will be at least the minimum height plus 112 * <code>ipady</code> pixels. 113 * <dt>{@link GridBagConstraints#insets} 114 * <dd>Specifies the component's external padding, the minimum 115 * amount of space between the component and the edges of its display area. 116 * <dt>{@link GridBagConstraints#anchor} 117 * <dd>Specifies where the component should be positioned in its display area. 118 * There are three kinds of possible values: absolute, orientation-relative, 119 * and baseline-relative 120 * Orientation relative values are interpreted relative to the container's 121 * <code>ComponentOrientation</code> property while absolute values 122 * are not. Baseline relative values are calculated relative to the 123 * baseline. Valid values are: 124 * 125 * <center><table BORDER=0 WIDTH=800 126 * SUMMARY="absolute, relative and baseline values as described above"> 127 * <tr> 128 * <th><P style="text-align:left">Absolute Values</th> 129 * <th><P style="text-align:left">Orientation Relative Values</th> 130 * <th><P style="text-align:left">Baseline Relative Values</th> 131 * </tr> 132 * <tr> 133 * <td> 134 * <ul style="list-style-type:none"> 135 * <li><code>GridBagConstraints.NORTH</code></li> 136 * <li><code>GridBagConstraints.SOUTH</code></li> 137 * <li><code>GridBagConstraints.WEST</code></li> 138 * <li><code>GridBagConstraints.EAST</code></li> 139 * <li><code>GridBagConstraints.NORTHWEST</code></li> 140 * <li><code>GridBagConstraints.NORTHEAST</code></li> 141 * <li><code>GridBagConstraints.SOUTHWEST</code></li> 142 * <li><code>GridBagConstraints.SOUTHEAST</code></li> 143 * <li><code>GridBagConstraints.CENTER</code> (the default)</li> 144 * </ul> 145 * </td> 146 * <td> 147 * <ul style="list-style-type:none"> 148 * <li><code>GridBagConstraints.PAGE_START</code></li> 149 * <li><code>GridBagConstraints.PAGE_END</code></li> 150 * <li><code>GridBagConstraints.LINE_START</code></li> 151 * <li><code>GridBagConstraints.LINE_END</code></li> 152 * <li><code>GridBagConstraints.FIRST_LINE_START</code></li> 153 * <li><code>GridBagConstraints.FIRST_LINE_END</code></li> 154 * <li><code>GridBagConstraints.LAST_LINE_START</code></li> 155 * <li><code>GridBagConstraints.LAST_LINE_END</code></li> 156 * </ul> 157 * </td> 158 * <td> 159 * <ul style="list-style-type:none"> 160 * <li><code>GridBagConstraints.BASELINE</code></li> 161 * <li><code>GridBagConstraints.BASELINE_LEADING</code></li> 162 * <li><code>GridBagConstraints.BASELINE_TRAILING</code></li> 163 * <li><code>GridBagConstraints.ABOVE_BASELINE</code></li> 164 * <li><code>GridBagConstraints.ABOVE_BASELINE_LEADING</code></li> 165 * <li><code>GridBagConstraints.ABOVE_BASELINE_TRAILING</code></li> 166 * <li><code>GridBagConstraints.BELOW_BASELINE</code></li> 167 * <li><code>GridBagConstraints.BELOW_BASELINE_LEADING</code></li> 168 * <li><code>GridBagConstraints.BELOW_BASELINE_TRAILING</code></li> 169 * </ul> 170 * </td> 171 * </tr> 172 * </table></center> 173 * <dt>{@link GridBagConstraints#weightx}, 174 * {@link GridBagConstraints#weighty} 175 * <dd>Used to determine how to distribute space, which is 176 * important for specifying resizing behavior. 177 * Unless you specify a weight for at least one component 178 * in a row (<code>weightx</code>) and column (<code>weighty</code>), 179 * all the components clump together in the center of their container. 180 * This is because when the weight is zero (the default), 181 * the <code>GridBagLayout</code> object puts any extra space 182 * between its grid of cells and the edges of the container. 183 * </dl> 184 * <p> 185 * Each row may have a baseline; the baseline is determined by the 186 * components in that row that have a valid baseline and are aligned 187 * along the baseline (the component's anchor value is one of {@code 188 * BASELINE}, {@code BASELINE_LEADING} or {@code BASELINE_TRAILING}). 189 * If none of the components in the row has a valid baseline, the row 190 * does not have a baseline. 191 * <p> 192 * If a component spans rows it is aligned either to the baseline of 193 * the start row (if the baseline-resize behavior is {@code 194 * CONSTANT_ASCENT}) or the end row (if the baseline-resize behavior 195 * is {@code CONSTANT_DESCENT}). The row that the component is 196 * aligned to is called the <em>prevailing row</em>. 197 * <p> 198 * The following figure shows a baseline layout and includes a 199 * component that spans rows: 200 * <center><table summary="Baseline Layout"> 201 * <tr ALIGN=CENTER> 202 * <td> 203 * <img src="doc-files/GridBagLayout-baseline.png" 204 * alt="The following text describes this graphic (Figure 1)." style="float:center"> 205 * </td> 206 * </table></center> 207 * This layout consists of three components: 208 * <ul><li>A panel that starts in row 0 and ends in row 1. The panel 209 * has a baseline-resize behavior of <code>CONSTANT_DESCENT</code> and has 210 * an anchor of <code>BASELINE</code>. As the baseline-resize behavior 211 * is <code>CONSTANT_DESCENT</code> the prevailing row for the panel is 212 * row 1. 213 * <li>Two buttons, each with a baseline-resize behavior of 214 * <code>CENTER_OFFSET</code> and an anchor of <code>BASELINE</code>. 215 * </ul> 216 * Because the second button and the panel share the same prevailing row, 217 * they are both aligned along their baseline. 218 * <p> 219 * Components positioned using one of the baseline-relative values resize 220 * differently than when positioned using an absolute or orientation-relative 221 * value. How components change is dictated by how the baseline of the 222 * prevailing row changes. The baseline is anchored to the 223 * bottom of the display area if any components with the same prevailing row 224 * have a baseline-resize behavior of <code>CONSTANT_DESCENT</code>, 225 * otherwise the baseline is anchored to the top of the display area. 226 * The following rules dictate the resize behavior: 227 * <ul> 228 * <li>Resizable components positioned above the baseline can only 229 * grow as tall as the baseline. For example, if the baseline is at 100 230 * and anchored at the top, a resizable component positioned above the 231 * baseline can never grow more than 100 units. 232 * <li>Similarly, resizable components positioned below the baseline can 233 * only grow as high as the difference between the display height and the 234 * baseline. 235 * <li>Resizable components positioned on the baseline with a 236 * baseline-resize behavior of <code>OTHER</code> are only resized if 237 * the baseline at the resized size fits within the display area. If 238 * the baseline is such that it does not fit within the display area 239 * the component is not resized. 240 * <li>Components positioned on the baseline that do not have a 241 * baseline-resize behavior of <code>OTHER</code> 242 * can only grow as tall as {@code display height - baseline + baseline of component}. 243 * </ul> 244 * If you position a component along the baseline, but the 245 * component does not have a valid baseline, it will be vertically centered 246 * in its space. Similarly if you have positioned a component relative 247 * to the baseline and none of the components in the row have a valid 248 * baseline the component is vertically centered. 249 * <p> 250 * The following figures show ten components (all buttons) 251 * managed by a grid bag layout. Figure 2 shows the layout for a horizontal, 252 * left-to-right container and Figure 3 shows the layout for a horizontal, 253 * right-to-left container. 254 * 255 * <center><table WIDTH=600 summary="layout"> 256 * <tr ALIGN=CENTER> 257 * <td> 258 * <img src="doc-files/GridBagLayout-1.gif" alt="The preceding text describes this graphic (Figure 1)." style="float:center; margin: 7px 10px;"> 259 * </td> 260 * <td> 261 * <img src="doc-files/GridBagLayout-2.gif" alt="The preceding text describes this graphic (Figure 2)." style="float:center; margin: 7px 10px;"> 262 * </td> 263 * <tr ALIGN=CENTER> 264 * <td>Figure 2: Horizontal, Left-to-Right</td> 265 * <td>Figure 3: Horizontal, Right-to-Left</td> 266 * </tr> 267 * </table></center> 268 * <p> 269 * Each of the ten components has the <code>fill</code> field 270 * of its associated <code>GridBagConstraints</code> object 271 * set to <code>GridBagConstraints.BOTH</code>. 272 * In addition, the components have the following non-default constraints: 273 * 274 * <ul> 275 * <li>Button1, Button2, Button3: <code>weightx = 1.0</code> 276 * <li>Button4: <code>weightx = 1.0</code>, 277 * <code>gridwidth = GridBagConstraints.REMAINDER</code> 278 * <li>Button5: <code>gridwidth = GridBagConstraints.REMAINDER</code> 279 * <li>Button6: <code>gridwidth = GridBagConstraints.RELATIVE</code> 280 * <li>Button7: <code>gridwidth = GridBagConstraints.REMAINDER</code> 281 * <li>Button8: <code>gridheight = 2</code>, 282 * <code>weighty = 1.0</code> 283 * <li>Button9, Button 10: 284 * <code>gridwidth = GridBagConstraints.REMAINDER</code> 285 * </ul> 286 * <p> 287 * Here is the code that implements the example shown above: 288 * 289 * <hr><blockquote><pre> 290 * import java.awt.*; 291 * import java.util.*; 370 * compatibility. Previously, this was 371 * the maximum number of grid positions (both horizontal and 372 * vertical) that could be laid out by the grid bag layout. 373 * Current implementation doesn't impose any limits 374 * on the size of a grid. 375 */ 376 protected static final int MAXGRIDSIZE = 512; 377 378 /** 379 * The smallest grid that can be laid out by the grid bag layout. 380 */ 381 protected static final int MINSIZE = 1; 382 /** 383 * The preferred grid size that can be laid out by the grid bag layout. 384 */ 385 protected static final int PREFERREDSIZE = 2; 386 387 /** 388 * This hashtable maintains the association between 389 * a component and its gridbag constraints. 390 * The Keys in <code>comptable</code> are the components and the 391 * values are the instances of <code>GridBagConstraints</code>. 392 * 393 * @serial 394 * @see java.awt.GridBagConstraints 395 */ 396 protected Hashtable<Component,GridBagConstraints> comptable; 397 398 /** 399 * This field holds a gridbag constraints instance 400 * containing the default values, so if a component 401 * does not have gridbag constraints associated with 402 * it, then the component will be assigned a 403 * copy of the <code>defaultConstraints</code>. 404 * 405 * @serial 406 * @see #getConstraints(Component) 407 * @see #setConstraints(Component, GridBagConstraints) 408 * @see #lookupConstraints(Component) 409 */ 410 protected GridBagConstraints defaultConstraints; 411 412 /** 413 * This field holds the layout information 414 * for the gridbag. The information in this field 415 * is based on the most recent validation of the 416 * gridbag. 417 * If <code>layoutInfo</code> is <code>null</code> 418 * this indicates that there are no components in 419 * the gridbag or if there are components, they have 420 * not yet been validated. 421 * 422 * @serial 423 * @see #getLayoutInfo(Container, int) 424 */ 425 protected GridBagLayoutInfo layoutInfo; 426 427 /** 428 * This field holds the overrides to the column minimum 429 * width. If this field is non-<code>null</code> the values are 430 * applied to the gridbag after all of the minimum columns 431 * widths have been calculated. 432 * If columnWidths has more elements than the number of 433 * columns, columns are added to the gridbag to match 434 * the number of elements in columnWidth. 435 * 436 * @serial 437 * @see #getLayoutDimensions() 438 */ 439 public int columnWidths[]; 440 441 /** 442 * This field holds the overrides to the row minimum 443 * heights. If this field is non-<code>null</code> the values are 444 * applied to the gridbag after all of the minimum row 445 * heights have been calculated. 446 * If <code>rowHeights</code> has more elements than the number of 447 * rows, rows are added to the gridbag to match 448 * the number of elements in <code>rowHeights</code>. 449 * 450 * @serial 451 * @see #getLayoutDimensions() 452 */ 453 public int rowHeights[]; 454 455 /** 456 * This field holds the overrides to the column weights. 457 * If this field is non-<code>null</code> the values are 458 * applied to the gridbag after all of the columns 459 * weights have been calculated. 460 * If <code>columnWeights[i]</code> > weight for column i, then 461 * column i is assigned the weight in <code>columnWeights[i]</code>. 462 * If <code>columnWeights</code> has more elements than the number 463 * of columns, the excess elements are ignored - they do 464 * not cause more columns to be created. 465 * 466 * @serial 467 */ 468 public double columnWeights[]; 469 470 /** 471 * This field holds the overrides to the row weights. 472 * If this field is non-<code>null</code> the values are 473 * applied to the gridbag after all of the rows 474 * weights have been calculated. 475 * If <code>rowWeights[i]</code> > weight for row i, then 476 * row i is assigned the weight in <code>rowWeights[i]</code>. 477 * If <code>rowWeights</code> has more elements than the number 478 * of rows, the excess elements are ignored - they do 479 * not cause more rows to be created. 480 * 481 * @serial 482 */ 483 public double rowWeights[]; 484 485 /** 486 * The component being positioned. This is set before calling into 487 * <code>adjustForGravity</code>. 488 */ 489 private Component componentAdjusting; 490 491 /** 492 * Creates a grid bag layout manager. 493 */ 494 public GridBagLayout () { 495 comptable = new Hashtable<Component,GridBagConstraints>(); 496 defaultConstraints = new GridBagConstraints(); 497 } 498 499 /** 500 * Sets the constraints for the specified component in this layout. 501 * @param comp the component to be modified 502 * @param constraints the constraints to be applied 503 */ 504 public void setConstraints(Component comp, GridBagConstraints constraints) { 505 comptable.put(comp, (GridBagConstraints)constraints.clone()); 506 } 507 508 /** 509 * Gets the constraints for the specified component. A copy of 510 * the actual <code>GridBagConstraints</code> object is returned. 511 * @param comp the component to be queried 512 * @return the constraint for the specified component in this 513 * grid bag layout; a copy of the actual constraint 514 * object is returned 515 */ 516 public GridBagConstraints getConstraints(Component comp) { 517 GridBagConstraints constraints = comptable.get(comp); 518 if (constraints == null) { 519 setConstraints(comp, defaultConstraints); 520 constraints = comptable.get(comp); 521 } 522 return (GridBagConstraints)constraints.clone(); 523 } 524 525 /** 526 * Retrieves the constraints for the specified component. 527 * The return value is not a copy, but is the actual 528 * <code>GridBagConstraints</code> object used by the layout mechanism. 529 * <p> 530 * If <code>comp</code> is not in the <code>GridBagLayout</code>, 531 * a set of default <code>GridBagConstraints</code> are returned. 532 * A <code>comp</code> value of <code>null</code> is invalid 533 * and returns <code>null</code>. 534 * 535 * @param comp the component to be queried 536 * @return the constraints for the specified component 537 */ 538 protected GridBagConstraints lookupConstraints(Component comp) { 539 GridBagConstraints constraints = comptable.get(comp); 540 if (constraints == null) { 541 setConstraints(comp, defaultConstraints); 542 constraints = comptable.get(comp); 543 } 544 return constraints; 545 } 546 547 /** 548 * Removes the constraints for the specified component in this layout 549 * @param comp the component to be modified 550 */ 551 private void removeConstraints(Component comp) { 552 comptable.remove(comp); 553 } 554 555 /** 556 * Determines the origin of the layout area, in the graphics coordinate 557 * space of the target container. This value represents the pixel 558 * coordinates of the top-left corner of the layout area regardless of 559 * the <code>ComponentOrientation</code> value of the container. This 560 * is distinct from the grid origin given by the cell coordinates (0,0). 561 * Most applications do not call this method directly. 562 * @return the graphics origin of the cell in the top-left 563 * corner of the layout grid 564 * @see java.awt.ComponentOrientation 565 * @since 1.1 566 */ 567 public Point getLayoutOrigin () { 568 Point origin = new Point(0,0); 569 if (layoutInfo != null) { 570 origin.x = layoutInfo.startx; 571 origin.y = layoutInfo.starty; 572 } 573 return origin; 574 } 575 576 /** 577 * Determines column widths and row heights for the layout grid. 578 * <p> 579 * Most applications do not call this method directly. 614 615 double weights[][] = new double [2][]; 616 weights[0] = new double[layoutInfo.width]; 617 weights[1] = new double[layoutInfo.height]; 618 619 System.arraycopy(layoutInfo.weightX, 0, weights[0], 0, layoutInfo.width); 620 System.arraycopy(layoutInfo.weightY, 0, weights[1], 0, layoutInfo.height); 621 622 return weights; 623 } 624 625 /** 626 * Determines which cell in the layout grid contains the point 627 * specified by <code>(x, y)</code>. Each cell is identified 628 * by its column index (ranging from 0 to the number of columns 629 * minus 1) and its row index (ranging from 0 to the number of 630 * rows minus 1). 631 * <p> 632 * If the <code>(x, y)</code> point lies 633 * outside the grid, the following rules are used. 634 * The column index is returned as zero if <code>x</code> lies to the 635 * left of the layout for a left-to-right container or to the right of 636 * the layout for a right-to-left container. The column index is returned 637 * as the number of columns if <code>x</code> lies 638 * to the right of the layout in a left-to-right container or to the left 639 * in a right-to-left container. 640 * The row index is returned as zero if <code>y</code> lies above the 641 * layout, and as the number of rows if <code>y</code> lies 642 * below the layout. The orientation of a container is determined by its 643 * <code>ComponentOrientation</code> property. 644 * @param x the <i>x</i> coordinate of a point 645 * @param y the <i>y</i> coordinate of a point 646 * @return an ordered pair of indexes that indicate which cell 647 * in the layout grid contains the point 648 * (<i>x</i>, <i>y</i>). 649 * @see java.awt.ComponentOrientation 650 * @since 1.1 651 */ 652 public Point location(int x, int y) { 653 Point loc = new Point(0,0); 654 int i, d; 655 656 if (layoutInfo == null) 657 return loc; 658 659 d = layoutInfo.startx; 660 if (!rightToLeft) { 661 for (i=0; i<layoutInfo.width; i++) { 662 d += layoutInfo.minWidth[i]; 663 if (d > x) 675 676 d = layoutInfo.starty; 677 for (i=0; i<layoutInfo.height; i++) { 678 d += layoutInfo.minHeight[i]; 679 if (d > y) 680 break; 681 } 682 loc.y = i; 683 684 return loc; 685 } 686 687 /** 688 * Has no effect, since this layout manager does not use a per-component string. 689 */ 690 public void addLayoutComponent(String name, Component comp) { 691 } 692 693 /** 694 * Adds the specified component to the layout, using the specified 695 * <code>constraints</code> object. Note that constraints 696 * are mutable and are, therefore, cloned when cached. 697 * 698 * @param comp the component to be added 699 * @param constraints an object that determines how 700 * the component is added to the layout 701 * @exception IllegalArgumentException if <code>constraints</code> 702 * is not a <code>GridBagConstraint</code> 703 */ 704 public void addLayoutComponent(Component comp, Object constraints) { 705 if (constraints instanceof GridBagConstraints) { 706 setConstraints(comp, (GridBagConstraints)constraints); 707 } else if (constraints != null) { 708 throw new IllegalArgumentException("cannot add to layout: constraints must be a GridBagConstraint"); 709 } 710 } 711 712 /** 713 * Removes the specified component from this layout. 714 * <p> 715 * Most applications do not call this method directly. 716 * @param comp the component to be removed. 717 * @see java.awt.Container#remove(java.awt.Component) 718 * @see java.awt.Container#removeAll() 719 */ 720 public void removeLayoutComponent(Component comp) { 721 removeConstraints(comp); 722 } 723 724 /** 725 * Determines the preferred size of the <code>parent</code> 726 * container using this grid bag layout. 727 * <p> 728 * Most applications do not call this method directly. 729 * 730 * @param parent the container in which to do the layout 731 * @see java.awt.Container#getPreferredSize 732 * @return the preferred size of the <code>parent</code> 733 * container 734 */ 735 public Dimension preferredLayoutSize(Container parent) { 736 GridBagLayoutInfo info = getLayoutInfo(parent, PREFERREDSIZE); 737 return getMinSize(parent, info); 738 } 739 740 /** 741 * Determines the minimum size of the <code>parent</code> container 742 * using this grid bag layout. 743 * <p> 744 * Most applications do not call this method directly. 745 * @param parent the container in which to do the layout 746 * @see java.awt.Container#doLayout 747 * @return the minimum size of the <code>parent</code> container 748 */ 749 public Dimension minimumLayoutSize(Container parent) { 750 GridBagLayoutInfo info = getLayoutInfo(parent, MINSIZE); 751 return getMinSize(parent, info); 752 } 753 754 /** 755 * Returns the maximum dimensions for this layout given the components 756 * in the specified target container. 757 * @param target the container which needs to be laid out 758 * @see Container 759 * @see #minimumLayoutSize(Container) 760 * @see #preferredLayoutSize(Container) 761 * @return the maximum dimensions for this layout 762 */ 763 public Dimension maximumLayoutSize(Container target) { 764 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 765 } 766 767 /** 768 * Returns the alignment along the x axis. This specifies how 769 * the component would like to be aligned relative to other 770 * components. The value should be a number between 0 and 1 771 * where 0 represents alignment along the origin, 1 is aligned 772 * the furthest away from the origin, 0.5 is centered, etc. 773 * 774 * @return the value <code>0.5f</code> to indicate centered 775 */ 776 public float getLayoutAlignmentX(Container parent) { 777 return 0.5f; 778 } 779 780 /** 781 * Returns the alignment along the y axis. This specifies how 782 * the component would like to be aligned relative to other 783 * components. The value should be a number between 0 and 1 784 * where 0 represents alignment along the origin, 1 is aligned 785 * the furthest away from the origin, 0.5 is centered, etc. 786 * 787 * @return the value <code>0.5f</code> to indicate centered 788 */ 789 public float getLayoutAlignmentY(Container parent) { 790 return 0.5f; 791 } 792 793 /** 794 * Invalidates the layout, indicating that if the layout manager 795 * has cached information it should be discarded. 796 */ 797 public void invalidateLayout(Container target) { 798 } 799 800 /** 801 * Lays out the specified container using this grid bag layout. 802 * This method reshapes components in the specified container in 803 * order to satisfy the constraints of this <code>GridBagLayout</code> 804 * object. 805 * <p> 806 * Most applications do not call this method directly. 807 * @param parent the container in which to do the layout 808 * @see java.awt.Container 809 * @see java.awt.Container#doLayout 810 */ 811 public void layoutContainer(Container parent) { 812 arrangeGrid(parent); 813 } 814 815 /** 816 * Returns a string representation of this grid bag layout's values. 817 * @return a string representation of this grid bag layout. 818 */ 819 public String toString() { 820 return getClass().getName(); 821 } 822 823 /** 873 * " " + 874 * constraints.minHeight + 875 * ", " + 876 * 877 * "pad " + 878 * constraints.insets.bottom + 879 * " " + 880 * constraints.insets.left + 881 * " " + 882 * constraints.insets.right + 883 * " " + 884 * constraints.insets.top + 885 * " " + 886 * constraints.ipadx + 887 * " " + 888 * constraints.ipady); 889 * } 890 */ 891 892 /** 893 * Fills in an instance of <code>GridBagLayoutInfo</code> for the 894 * current set of managed children. This requires three passes through the 895 * set of children: 896 * 897 * <ol> 898 * <li>Figure out the dimensions of the layout grid. 899 * <li>Determine which cells the components occupy. 900 * <li>Distribute the weights and min sizes among the rows/columns. 901 * </ol> 902 * 903 * This also caches the minsizes for all the children when they are 904 * first encountered (so subsequent loops don't need to ask again). 905 * <p> 906 * This method should only be used internally by 907 * <code>GridBagLayout</code>. 908 * 909 * @param parent the layout container 910 * @param sizeflag either <code>PREFERREDSIZE</code> or 911 * <code>MINSIZE</code> 912 * @return the <code>GridBagLayoutInfo</code> for the set of children 913 * @since 1.4 914 */ 915 protected GridBagLayoutInfo getLayoutInfo(Container parent, int sizeflag) { 916 return GetLayoutInfo(parent, sizeflag); 917 } 918 919 /* 920 * Calculate maximum array sizes to allocate arrays without ensureCapacity 921 * we may use preCalculated sizes in whole class because of upper estimation of 922 * maximumArrayXIndex and maximumArrayYIndex. 923 */ 924 925 private long[] preInitMaximumArraySizes(Container parent){ 926 Component components[] = parent.getComponents(); 927 Component comp; 928 GridBagConstraints constraints; 929 int curX, curY; 930 int curWidth, curHeight; 931 int preMaximumArrayXIndex = 0; 932 int preMaximumArrayYIndex = 0; 1588 } 1589 } 1590 else if (baseline == nextBaseline){ 1591 constraints.centerOffset--; 1592 constraints.centerPadding = 1; 1593 } 1594 } 1595 } 1596 return true; 1597 } 1598 else { 1599 constraints.ascent = -1; 1600 return false; 1601 } 1602 } 1603 1604 /** 1605 * Adjusts the x, y, width, and height fields to the correct 1606 * values depending on the constraint geometry and pads. 1607 * This method should only be used internally by 1608 * <code>GridBagLayout</code>. 1609 * 1610 * @param constraints the constraints to be applied 1611 * @param r the <code>Rectangle</code> to be adjusted 1612 * @since 1.4 1613 */ 1614 protected void adjustForGravity(GridBagConstraints constraints, 1615 Rectangle r) { 1616 AdjustForGravity(constraints, r); 1617 } 1618 1619 /** 1620 * Adjusts the x, y, width, and height fields to the correct 1621 * values depending on the constraint geometry and pads. 1622 * <p> 1623 * This method is obsolete and supplied for backwards 1624 * compatibility only; new code should call {@link 1625 * #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle) 1626 * adjustForGravity} instead. 1627 * This method is the same as <code>adjustForGravity</code> 1628 * 1629 * @param constraints the constraints to be applied 1630 * @param r the {@code Rectangle} to be adjusted 1631 */ 1632 protected void AdjustForGravity(GridBagConstraints constraints, 1633 Rectangle r) { 1634 int diffx, diffy; 1635 int cellY = r.y; 1636 int cellHeight = r.height; 1637 1638 if (!rightToLeft) { 1639 r.x += constraints.insets.left; 1640 } else { 1641 r.x -= r.width - constraints.insets.right; 1642 } 1643 r.width -= (constraints.insets.left + constraints.insets.right); 1644 r.y += constraints.insets.top; 1645 r.height -= (constraints.insets.top + constraints.insets.bottom); 1646 1647 diffx = 0; 1970 if (cons.isVerticallyResizable()) { 1971 r.height = cellY + cellHeight - r.y - cons.insets.bottom; 1972 } 1973 } 1974 else { 1975 centerVertically(cons, r, cellHeight); 1976 } 1977 } 1978 1979 private void centerVertically(GridBagConstraints cons, Rectangle r, 1980 int cellHeight) { 1981 if (!cons.isVerticallyResizable()) { 1982 r.y += Math.max(0, (cellHeight - cons.insets.top - 1983 cons.insets.bottom - cons.minHeight - 1984 cons.ipady) / 2); 1985 } 1986 } 1987 1988 /** 1989 * Figures out the minimum size of the 1990 * master based on the information from <code>getLayoutInfo</code>. 1991 * This method should only be used internally by 1992 * <code>GridBagLayout</code>. 1993 * 1994 * @param parent the layout container 1995 * @param info the layout info for this parent 1996 * @return a <code>Dimension</code> object containing the 1997 * minimum size 1998 * @since 1.4 1999 */ 2000 protected Dimension getMinSize(Container parent, GridBagLayoutInfo info) { 2001 return GetMinSize(parent, info); 2002 } 2003 2004 /** 2005 * This method is obsolete and supplied for backwards 2006 * compatibility only; new code should call {@link 2007 * #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead. 2008 * This method is the same as <code>getMinSize</code> 2009 * 2010 * @param parent the layout container 2011 * @param info the layout info for this parent 2012 * @return a <code>Dimension</code> object containing the 2013 * minimum size 2014 */ 2015 protected Dimension GetMinSize(Container parent, GridBagLayoutInfo info) { 2016 Dimension d = new Dimension(); 2017 int i, t; 2018 Insets insets = parent.getInsets(); 2019 2020 t = 0; 2021 for(i = 0; i < info.width; i++) 2022 t += info.minWidth[i]; 2023 d.width = t + insets.left + insets.right; 2024 2025 t = 0; 2026 for(i = 0; i < info.height; i++) 2027 t += info.minHeight[i]; 2028 d.height = t + insets.top + insets.bottom; 2029 2030 return d; 2031 } 2032 2033 transient boolean rightToLeft = false; 2034 2035 /** 2036 * Lays out the grid. 2037 * This method should only be used internally by 2038 * <code>GridBagLayout</code>. 2039 * 2040 * @param parent the layout container 2041 * @since 1.4 2042 */ 2043 protected void arrangeGrid(Container parent) { 2044 ArrangeGrid(parent); 2045 } 2046 2047 /** 2048 * This method is obsolete and supplied for backwards 2049 * compatibility only; new code should call {@link 2050 * #arrangeGrid(Container) arrangeGrid} instead. 2051 * This method is the same as <code>arrangeGrid</code> 2052 * 2053 * @param parent the layout container 2054 */ 2055 protected void ArrangeGrid(Container parent) { 2056 Component comp; 2057 int compindex; 2058 GridBagConstraints constraints; 2059 Insets insets = parent.getInsets(); 2060 Component components[] = parent.getComponents(); 2061 Dimension d; 2062 Rectangle r = new Rectangle(); 2063 int i, diffw, diffh; 2064 double weight; 2065 GridBagLayoutInfo info; 2066 2067 rightToLeft = !parent.getComponentOrientation().isLeftToRight(); 2068 2069 /* 2070 * If the parent has no slaves anymore, then don't do anything 2071 * at all: just leave the parent's size as-is. | 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.util.Hashtable; 28 import java.util.Arrays; 29 30 /** 31 * The {@code GridBagLayout} class is a flexible layout 32 * manager that aligns components vertically, horizontally or along their 33 * baseline without requiring that the components be of the same size. 34 * Each {@code GridBagLayout} object maintains a dynamic, 35 * rectangular grid of cells, with each component occupying 36 * one or more cells, called its <em>display area</em>. 37 * <p> 38 * Each component managed by a {@code GridBagLayout} is associated with 39 * an instance of {@link GridBagConstraints}. The constraints object 40 * specifies where a component's display area should be located on the grid 41 * and how the component should be positioned within its display area. In 42 * addition to its constraints object, the {@code GridBagLayout} also 43 * considers each component's minimum and preferred sizes in order to 44 * determine a component's size. 45 * <p> 46 * The overall orientation of the grid depends on the container's 47 * {@link ComponentOrientation} property. For horizontal left-to-right 48 * orientations, grid coordinate (0,0) is in the upper left corner of the 49 * container with x increasing to the right and y increasing downward. For 50 * horizontal right-to-left orientations, grid coordinate (0,0) is in the upper 51 * right corner of the container with x increasing to the left and y 52 * increasing downward. 53 * <p> 54 * To use a grid bag layout effectively, you must customize one or more 55 * of the {@code GridBagConstraints} objects that are associated 56 * with its components. You customize a {@code GridBagConstraints} 57 * object by setting one or more of its instance variables: 58 * 59 * <dl> 60 * <dt>{@link GridBagConstraints#gridx}, 61 * {@link GridBagConstraints#gridy} 62 * <dd>Specifies the cell containing the leading corner of the component's 63 * display area, where the cell at the origin of the grid has address 64 * <code>gridx = 0</code>, 65 * <code>gridy = 0</code>. For horizontal left-to-right layout, 66 * a component's leading corner is its upper left. For horizontal 67 * right-to-left layout, a component's leading corner is its upper right. 68 * Use {@code GridBagConstraints.RELATIVE} (the default value) 69 * to specify that the component be placed immediately following 70 * (along the x axis for {@code gridx} or the y axis for 71 * {@code gridy}) the component that was added to the container 72 * just before this component was added. 73 * <dt>{@link GridBagConstraints#gridwidth}, 74 * {@link GridBagConstraints#gridheight} 75 * <dd>Specifies the number of cells in a row (for {@code gridwidth}) 76 * or column (for {@code gridheight}) 77 * in the component's display area. 78 * The default value is 1. 79 * Use {@code GridBagConstraints.REMAINDER} to specify 80 * that the component's display area will be from {@code gridx} 81 * to the last cell in the row (for {@code gridwidth}) 82 * or from {@code gridy} to the last cell in the column 83 * (for {@code gridheight}). 84 * 85 * Use {@code GridBagConstraints.RELATIVE} to specify 86 * that the component's display area will be from {@code gridx} 87 * to the next to the last cell in its row (for {@code gridwidth} 88 * or from {@code gridy} to the next to the last cell in its 89 * column (for {@code gridheight}). 90 * 91 * <dt>{@link GridBagConstraints#fill} 92 * <dd>Used when the component's display area 93 * is larger than the component's requested size 94 * to determine whether (and how) to resize the component. 95 * Possible values are 96 * {@code GridBagConstraints.NONE} (the default), 97 * {@code GridBagConstraints.HORIZONTAL} 98 * (make the component wide enough to fill its display area 99 * horizontally, but don't change its height), 100 * {@code GridBagConstraints.VERTICAL} 101 * (make the component tall enough to fill its display area 102 * vertically, but don't change its width), and 103 * {@code GridBagConstraints.BOTH} 104 * (make the component fill its display area entirely). 105 * <dt>{@link GridBagConstraints#ipadx}, 106 * {@link GridBagConstraints#ipady} 107 * <dd>Specifies the component's internal padding within the layout, 108 * how much to add to the minimum size of the component. 109 * The width of the component will be at least its minimum width 110 * plus {@code ipadx} pixels. Similarly, the height of 111 * the component will be at least the minimum height plus 112 * {@code ipady} pixels. 113 * <dt>{@link GridBagConstraints#insets} 114 * <dd>Specifies the component's external padding, the minimum 115 * amount of space between the component and the edges of its display area. 116 * <dt>{@link GridBagConstraints#anchor} 117 * <dd>Specifies where the component should be positioned in its display area. 118 * There are three kinds of possible values: absolute, orientation-relative, 119 * and baseline-relative 120 * Orientation relative values are interpreted relative to the container's 121 * {@code ComponentOrientation} property while absolute values 122 * are not. Baseline relative values are calculated relative to the 123 * baseline. Valid values are: 124 * 125 * <center><table BORDER=0 WIDTH=800 126 * SUMMARY="absolute, relative and baseline values as described above"> 127 * <tr> 128 * <th><P style="text-align:left">Absolute Values</th> 129 * <th><P style="text-align:left">Orientation Relative Values</th> 130 * <th><P style="text-align:left">Baseline Relative Values</th> 131 * </tr> 132 * <tr> 133 * <td> 134 * <ul style="list-style-type:none"> 135 * <li>{@code GridBagConstraints.NORTH}</li> 136 * <li>{@code GridBagConstraints.SOUTH}</li> 137 * <li>{@code GridBagConstraints.WEST}</li> 138 * <li>{@code GridBagConstraints.EAST}</li> 139 * <li>{@code GridBagConstraints.NORTHWEST}</li> 140 * <li>{@code GridBagConstraints.NORTHEAST}</li> 141 * <li>{@code GridBagConstraints.SOUTHWEST}</li> 142 * <li>{@code GridBagConstraints.SOUTHEAST}</li> 143 * <li>{@code GridBagConstraints.CENTER} (the default)</li> 144 * </ul> 145 * </td> 146 * <td> 147 * <ul style="list-style-type:none"> 148 * <li>{@code GridBagConstraints.PAGE_START}</li> 149 * <li>{@code GridBagConstraints.PAGE_END}</li> 150 * <li>{@code GridBagConstraints.LINE_START}</li> 151 * <li>{@code GridBagConstraints.LINE_END}</li> 152 * <li>{@code GridBagConstraints.FIRST_LINE_START}</li> 153 * <li>{@code GridBagConstraints.FIRST_LINE_END}</li> 154 * <li>{@code GridBagConstraints.LAST_LINE_START}</li> 155 * <li>{@code GridBagConstraints.LAST_LINE_END}</li> 156 * </ul> 157 * </td> 158 * <td> 159 * <ul style="list-style-type:none"> 160 * <li>{@code GridBagConstraints.BASELINE}</li> 161 * <li>{@code GridBagConstraints.BASELINE_LEADING}</li> 162 * <li>{@code GridBagConstraints.BASELINE_TRAILING}</li> 163 * <li>{@code GridBagConstraints.ABOVE_BASELINE}</li> 164 * <li>{@code GridBagConstraints.ABOVE_BASELINE_LEADING}</li> 165 * <li>{@code GridBagConstraints.ABOVE_BASELINE_TRAILING}</li> 166 * <li>{@code GridBagConstraints.BELOW_BASELINE}</li> 167 * <li>{@code GridBagConstraints.BELOW_BASELINE_LEADING}</li> 168 * <li>{@code GridBagConstraints.BELOW_BASELINE_TRAILING}</li> 169 * </ul> 170 * </td> 171 * </tr> 172 * </table></center> 173 * <dt>{@link GridBagConstraints#weightx}, 174 * {@link GridBagConstraints#weighty} 175 * <dd>Used to determine how to distribute space, which is 176 * important for specifying resizing behavior. 177 * Unless you specify a weight for at least one component 178 * in a row ({@code weightx}) and column ({@code weighty}), 179 * all the components clump together in the center of their container. 180 * This is because when the weight is zero (the default), 181 * the {@code GridBagLayout} object puts any extra space 182 * between its grid of cells and the edges of the container. 183 * </dl> 184 * <p> 185 * Each row may have a baseline; the baseline is determined by the 186 * components in that row that have a valid baseline and are aligned 187 * along the baseline (the component's anchor value is one of {@code 188 * BASELINE}, {@code BASELINE_LEADING} or {@code BASELINE_TRAILING}). 189 * If none of the components in the row has a valid baseline, the row 190 * does not have a baseline. 191 * <p> 192 * If a component spans rows it is aligned either to the baseline of 193 * the start row (if the baseline-resize behavior is {@code 194 * CONSTANT_ASCENT}) or the end row (if the baseline-resize behavior 195 * is {@code CONSTANT_DESCENT}). The row that the component is 196 * aligned to is called the <em>prevailing row</em>. 197 * <p> 198 * The following figure shows a baseline layout and includes a 199 * component that spans rows: 200 * <center><table summary="Baseline Layout"> 201 * <tr ALIGN=CENTER> 202 * <td> 203 * <img src="doc-files/GridBagLayout-baseline.png" 204 * alt="The following text describes this graphic (Figure 1)." style="float:center"> 205 * </td> 206 * </table></center> 207 * This layout consists of three components: 208 * <ul><li>A panel that starts in row 0 and ends in row 1. The panel 209 * has a baseline-resize behavior of {@code CONSTANT_DESCENT} and has 210 * an anchor of {@code BASELINE}. As the baseline-resize behavior 211 * is {@code CONSTANT_DESCENT} the prevailing row for the panel is 212 * row 1. 213 * <li>Two buttons, each with a baseline-resize behavior of 214 * {@code CENTER_OFFSET} and an anchor of {@code BASELINE}. 215 * </ul> 216 * Because the second button and the panel share the same prevailing row, 217 * they are both aligned along their baseline. 218 * <p> 219 * Components positioned using one of the baseline-relative values resize 220 * differently than when positioned using an absolute or orientation-relative 221 * value. How components change is dictated by how the baseline of the 222 * prevailing row changes. The baseline is anchored to the 223 * bottom of the display area if any components with the same prevailing row 224 * have a baseline-resize behavior of {@code CONSTANT_DESCENT}, 225 * otherwise the baseline is anchored to the top of the display area. 226 * The following rules dictate the resize behavior: 227 * <ul> 228 * <li>Resizable components positioned above the baseline can only 229 * grow as tall as the baseline. For example, if the baseline is at 100 230 * and anchored at the top, a resizable component positioned above the 231 * baseline can never grow more than 100 units. 232 * <li>Similarly, resizable components positioned below the baseline can 233 * only grow as high as the difference between the display height and the 234 * baseline. 235 * <li>Resizable components positioned on the baseline with a 236 * baseline-resize behavior of {@code OTHER} are only resized if 237 * the baseline at the resized size fits within the display area. If 238 * the baseline is such that it does not fit within the display area 239 * the component is not resized. 240 * <li>Components positioned on the baseline that do not have a 241 * baseline-resize behavior of {@code OTHER} 242 * can only grow as tall as {@code display height - baseline + baseline of component}. 243 * </ul> 244 * If you position a component along the baseline, but the 245 * component does not have a valid baseline, it will be vertically centered 246 * in its space. Similarly if you have positioned a component relative 247 * to the baseline and none of the components in the row have a valid 248 * baseline the component is vertically centered. 249 * <p> 250 * The following figures show ten components (all buttons) 251 * managed by a grid bag layout. Figure 2 shows the layout for a horizontal, 252 * left-to-right container and Figure 3 shows the layout for a horizontal, 253 * right-to-left container. 254 * 255 * <center><table WIDTH=600 summary="layout"> 256 * <tr ALIGN=CENTER> 257 * <td> 258 * <img src="doc-files/GridBagLayout-1.gif" alt="The preceding text describes this graphic (Figure 1)." style="float:center; margin: 7px 10px;"> 259 * </td> 260 * <td> 261 * <img src="doc-files/GridBagLayout-2.gif" alt="The preceding text describes this graphic (Figure 2)." style="float:center; margin: 7px 10px;"> 262 * </td> 263 * <tr ALIGN=CENTER> 264 * <td>Figure 2: Horizontal, Left-to-Right</td> 265 * <td>Figure 3: Horizontal, Right-to-Left</td> 266 * </tr> 267 * </table></center> 268 * <p> 269 * Each of the ten components has the {@code fill} field 270 * of its associated {@code GridBagConstraints} object 271 * set to {@code GridBagConstraints.BOTH}. 272 * In addition, the components have the following non-default constraints: 273 * 274 * <ul> 275 * <li>Button1, Button2, Button3: <code>weightx = 1.0</code> 276 * <li>Button4: <code>weightx = 1.0</code>, 277 * <code>gridwidth = GridBagConstraints.REMAINDER</code> 278 * <li>Button5: <code>gridwidth = GridBagConstraints.REMAINDER</code> 279 * <li>Button6: <code>gridwidth = GridBagConstraints.RELATIVE</code> 280 * <li>Button7: <code>gridwidth = GridBagConstraints.REMAINDER</code> 281 * <li>Button8: <code>gridheight = 2</code>, 282 * <code>weighty = 1.0</code> 283 * <li>Button9, Button 10: 284 * <code>gridwidth = GridBagConstraints.REMAINDER</code> 285 * </ul> 286 * <p> 287 * Here is the code that implements the example shown above: 288 * 289 * <hr><blockquote><pre> 290 * import java.awt.*; 291 * import java.util.*; 370 * compatibility. Previously, this was 371 * the maximum number of grid positions (both horizontal and 372 * vertical) that could be laid out by the grid bag layout. 373 * Current implementation doesn't impose any limits 374 * on the size of a grid. 375 */ 376 protected static final int MAXGRIDSIZE = 512; 377 378 /** 379 * The smallest grid that can be laid out by the grid bag layout. 380 */ 381 protected static final int MINSIZE = 1; 382 /** 383 * The preferred grid size that can be laid out by the grid bag layout. 384 */ 385 protected static final int PREFERREDSIZE = 2; 386 387 /** 388 * This hashtable maintains the association between 389 * a component and its gridbag constraints. 390 * The Keys in {@code comptable} are the components and the 391 * values are the instances of {@code GridBagConstraints}. 392 * 393 * @serial 394 * @see java.awt.GridBagConstraints 395 */ 396 protected Hashtable<Component,GridBagConstraints> comptable; 397 398 /** 399 * This field holds a gridbag constraints instance 400 * containing the default values, so if a component 401 * does not have gridbag constraints associated with 402 * it, then the component will be assigned a 403 * copy of the {@code defaultConstraints}. 404 * 405 * @serial 406 * @see #getConstraints(Component) 407 * @see #setConstraints(Component, GridBagConstraints) 408 * @see #lookupConstraints(Component) 409 */ 410 protected GridBagConstraints defaultConstraints; 411 412 /** 413 * This field holds the layout information 414 * for the gridbag. The information in this field 415 * is based on the most recent validation of the 416 * gridbag. 417 * If {@code layoutInfo} is {@code null} 418 * this indicates that there are no components in 419 * the gridbag or if there are components, they have 420 * not yet been validated. 421 * 422 * @serial 423 * @see #getLayoutInfo(Container, int) 424 */ 425 protected GridBagLayoutInfo layoutInfo; 426 427 /** 428 * This field holds the overrides to the column minimum 429 * width. If this field is non-{@code null} the values are 430 * applied to the gridbag after all of the minimum columns 431 * widths have been calculated. 432 * If columnWidths has more elements than the number of 433 * columns, columns are added to the gridbag to match 434 * the number of elements in columnWidth. 435 * 436 * @serial 437 * @see #getLayoutDimensions() 438 */ 439 public int columnWidths[]; 440 441 /** 442 * This field holds the overrides to the row minimum 443 * heights. If this field is non-{@code null} the values are 444 * applied to the gridbag after all of the minimum row 445 * heights have been calculated. 446 * If {@code rowHeights} has more elements than the number of 447 * rows, rows are added to the gridbag to match 448 * the number of elements in {@code rowHeights}. 449 * 450 * @serial 451 * @see #getLayoutDimensions() 452 */ 453 public int rowHeights[]; 454 455 /** 456 * This field holds the overrides to the column weights. 457 * If this field is non-{@code null} the values are 458 * applied to the gridbag after all of the columns 459 * weights have been calculated. 460 * If {@code columnWeights[i] >} weight for column i, then 461 * column i is assigned the weight in {@code columnWeights[i]}. 462 * If {@code columnWeights} has more elements than the number 463 * of columns, the excess elements are ignored - they do 464 * not cause more columns to be created. 465 * 466 * @serial 467 */ 468 public double columnWeights[]; 469 470 /** 471 * This field holds the overrides to the row weights. 472 * If this field is non-{@code null} the values are 473 * applied to the gridbag after all of the rows 474 * weights have been calculated. 475 * If {@code rowWeights[i] > } weight for row i, then 476 * row i is assigned the weight in {@code rowWeights[i]}. 477 * If {@code rowWeights} has more elements than the number 478 * of rows, the excess elements are ignored - they do 479 * not cause more rows to be created. 480 * 481 * @serial 482 */ 483 public double rowWeights[]; 484 485 /** 486 * The component being positioned. This is set before calling into 487 * {@code adjustForGravity}. 488 */ 489 private Component componentAdjusting; 490 491 /** 492 * Creates a grid bag layout manager. 493 */ 494 public GridBagLayout () { 495 comptable = new Hashtable<Component,GridBagConstraints>(); 496 defaultConstraints = new GridBagConstraints(); 497 } 498 499 /** 500 * Sets the constraints for the specified component in this layout. 501 * @param comp the component to be modified 502 * @param constraints the constraints to be applied 503 */ 504 public void setConstraints(Component comp, GridBagConstraints constraints) { 505 comptable.put(comp, (GridBagConstraints)constraints.clone()); 506 } 507 508 /** 509 * Gets the constraints for the specified component. A copy of 510 * the actual {@code GridBagConstraints} object is returned. 511 * @param comp the component to be queried 512 * @return the constraint for the specified component in this 513 * grid bag layout; a copy of the actual constraint 514 * object is returned 515 */ 516 public GridBagConstraints getConstraints(Component comp) { 517 GridBagConstraints constraints = comptable.get(comp); 518 if (constraints == null) { 519 setConstraints(comp, defaultConstraints); 520 constraints = comptable.get(comp); 521 } 522 return (GridBagConstraints)constraints.clone(); 523 } 524 525 /** 526 * Retrieves the constraints for the specified component. 527 * The return value is not a copy, but is the actual 528 * {@code GridBagConstraints} object used by the layout mechanism. 529 * <p> 530 * If {@code comp} is not in the {@code GridBagLayout}, 531 * a set of default {@code GridBagConstraints} are returned. 532 * A {@code comp} value of {@code null} is invalid 533 * and returns {@code null}. 534 * 535 * @param comp the component to be queried 536 * @return the constraints for the specified component 537 */ 538 protected GridBagConstraints lookupConstraints(Component comp) { 539 GridBagConstraints constraints = comptable.get(comp); 540 if (constraints == null) { 541 setConstraints(comp, defaultConstraints); 542 constraints = comptable.get(comp); 543 } 544 return constraints; 545 } 546 547 /** 548 * Removes the constraints for the specified component in this layout 549 * @param comp the component to be modified 550 */ 551 private void removeConstraints(Component comp) { 552 comptable.remove(comp); 553 } 554 555 /** 556 * Determines the origin of the layout area, in the graphics coordinate 557 * space of the target container. This value represents the pixel 558 * coordinates of the top-left corner of the layout area regardless of 559 * the {@code ComponentOrientation} value of the container. This 560 * is distinct from the grid origin given by the cell coordinates (0,0). 561 * Most applications do not call this method directly. 562 * @return the graphics origin of the cell in the top-left 563 * corner of the layout grid 564 * @see java.awt.ComponentOrientation 565 * @since 1.1 566 */ 567 public Point getLayoutOrigin () { 568 Point origin = new Point(0,0); 569 if (layoutInfo != null) { 570 origin.x = layoutInfo.startx; 571 origin.y = layoutInfo.starty; 572 } 573 return origin; 574 } 575 576 /** 577 * Determines column widths and row heights for the layout grid. 578 * <p> 579 * Most applications do not call this method directly. 614 615 double weights[][] = new double [2][]; 616 weights[0] = new double[layoutInfo.width]; 617 weights[1] = new double[layoutInfo.height]; 618 619 System.arraycopy(layoutInfo.weightX, 0, weights[0], 0, layoutInfo.width); 620 System.arraycopy(layoutInfo.weightY, 0, weights[1], 0, layoutInfo.height); 621 622 return weights; 623 } 624 625 /** 626 * Determines which cell in the layout grid contains the point 627 * specified by <code>(x, y)</code>. Each cell is identified 628 * by its column index (ranging from 0 to the number of columns 629 * minus 1) and its row index (ranging from 0 to the number of 630 * rows minus 1). 631 * <p> 632 * If the <code>(x, y)</code> point lies 633 * outside the grid, the following rules are used. 634 * The column index is returned as zero if {@code x} lies to the 635 * left of the layout for a left-to-right container or to the right of 636 * the layout for a right-to-left container. The column index is returned 637 * as the number of columns if {@code x} lies 638 * to the right of the layout in a left-to-right container or to the left 639 * in a right-to-left container. 640 * The row index is returned as zero if {@code y} lies above the 641 * layout, and as the number of rows if {@code y} lies 642 * below the layout. The orientation of a container is determined by its 643 * {@code ComponentOrientation} property. 644 * @param x the <i>x</i> coordinate of a point 645 * @param y the <i>y</i> coordinate of a point 646 * @return an ordered pair of indexes that indicate which cell 647 * in the layout grid contains the point 648 * (<i>x</i>, <i>y</i>). 649 * @see java.awt.ComponentOrientation 650 * @since 1.1 651 */ 652 public Point location(int x, int y) { 653 Point loc = new Point(0,0); 654 int i, d; 655 656 if (layoutInfo == null) 657 return loc; 658 659 d = layoutInfo.startx; 660 if (!rightToLeft) { 661 for (i=0; i<layoutInfo.width; i++) { 662 d += layoutInfo.minWidth[i]; 663 if (d > x) 675 676 d = layoutInfo.starty; 677 for (i=0; i<layoutInfo.height; i++) { 678 d += layoutInfo.minHeight[i]; 679 if (d > y) 680 break; 681 } 682 loc.y = i; 683 684 return loc; 685 } 686 687 /** 688 * Has no effect, since this layout manager does not use a per-component string. 689 */ 690 public void addLayoutComponent(String name, Component comp) { 691 } 692 693 /** 694 * Adds the specified component to the layout, using the specified 695 * {@code constraints} object. Note that constraints 696 * are mutable and are, therefore, cloned when cached. 697 * 698 * @param comp the component to be added 699 * @param constraints an object that determines how 700 * the component is added to the layout 701 * @exception IllegalArgumentException if {@code constraints} 702 * is not a {@code GridBagConstraint} 703 */ 704 public void addLayoutComponent(Component comp, Object constraints) { 705 if (constraints instanceof GridBagConstraints) { 706 setConstraints(comp, (GridBagConstraints)constraints); 707 } else if (constraints != null) { 708 throw new IllegalArgumentException("cannot add to layout: constraints must be a GridBagConstraint"); 709 } 710 } 711 712 /** 713 * Removes the specified component from this layout. 714 * <p> 715 * Most applications do not call this method directly. 716 * @param comp the component to be removed. 717 * @see java.awt.Container#remove(java.awt.Component) 718 * @see java.awt.Container#removeAll() 719 */ 720 public void removeLayoutComponent(Component comp) { 721 removeConstraints(comp); 722 } 723 724 /** 725 * Determines the preferred size of the {@code parent} 726 * container using this grid bag layout. 727 * <p> 728 * Most applications do not call this method directly. 729 * 730 * @param parent the container in which to do the layout 731 * @see java.awt.Container#getPreferredSize 732 * @return the preferred size of the {@code parent} 733 * container 734 */ 735 public Dimension preferredLayoutSize(Container parent) { 736 GridBagLayoutInfo info = getLayoutInfo(parent, PREFERREDSIZE); 737 return getMinSize(parent, info); 738 } 739 740 /** 741 * Determines the minimum size of the {@code parent} container 742 * using this grid bag layout. 743 * <p> 744 * Most applications do not call this method directly. 745 * @param parent the container in which to do the layout 746 * @see java.awt.Container#doLayout 747 * @return the minimum size of the {@code parent} container 748 */ 749 public Dimension minimumLayoutSize(Container parent) { 750 GridBagLayoutInfo info = getLayoutInfo(parent, MINSIZE); 751 return getMinSize(parent, info); 752 } 753 754 /** 755 * Returns the maximum dimensions for this layout given the components 756 * in the specified target container. 757 * @param target the container which needs to be laid out 758 * @see Container 759 * @see #minimumLayoutSize(Container) 760 * @see #preferredLayoutSize(Container) 761 * @return the maximum dimensions for this layout 762 */ 763 public Dimension maximumLayoutSize(Container target) { 764 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 765 } 766 767 /** 768 * Returns the alignment along the x axis. This specifies how 769 * the component would like to be aligned relative to other 770 * components. The value should be a number between 0 and 1 771 * where 0 represents alignment along the origin, 1 is aligned 772 * the furthest away from the origin, 0.5 is centered, etc. 773 * 774 * @return the value {@code 0.5f} to indicate centered 775 */ 776 public float getLayoutAlignmentX(Container parent) { 777 return 0.5f; 778 } 779 780 /** 781 * Returns the alignment along the y axis. This specifies how 782 * the component would like to be aligned relative to other 783 * components. The value should be a number between 0 and 1 784 * where 0 represents alignment along the origin, 1 is aligned 785 * the furthest away from the origin, 0.5 is centered, etc. 786 * 787 * @return the value {@code 0.5f} to indicate centered 788 */ 789 public float getLayoutAlignmentY(Container parent) { 790 return 0.5f; 791 } 792 793 /** 794 * Invalidates the layout, indicating that if the layout manager 795 * has cached information it should be discarded. 796 */ 797 public void invalidateLayout(Container target) { 798 } 799 800 /** 801 * Lays out the specified container using this grid bag layout. 802 * This method reshapes components in the specified container in 803 * order to satisfy the constraints of this {@code GridBagLayout} 804 * object. 805 * <p> 806 * Most applications do not call this method directly. 807 * @param parent the container in which to do the layout 808 * @see java.awt.Container 809 * @see java.awt.Container#doLayout 810 */ 811 public void layoutContainer(Container parent) { 812 arrangeGrid(parent); 813 } 814 815 /** 816 * Returns a string representation of this grid bag layout's values. 817 * @return a string representation of this grid bag layout. 818 */ 819 public String toString() { 820 return getClass().getName(); 821 } 822 823 /** 873 * " " + 874 * constraints.minHeight + 875 * ", " + 876 * 877 * "pad " + 878 * constraints.insets.bottom + 879 * " " + 880 * constraints.insets.left + 881 * " " + 882 * constraints.insets.right + 883 * " " + 884 * constraints.insets.top + 885 * " " + 886 * constraints.ipadx + 887 * " " + 888 * constraints.ipady); 889 * } 890 */ 891 892 /** 893 * Fills in an instance of {@code GridBagLayoutInfo} for the 894 * current set of managed children. This requires three passes through the 895 * set of children: 896 * 897 * <ol> 898 * <li>Figure out the dimensions of the layout grid. 899 * <li>Determine which cells the components occupy. 900 * <li>Distribute the weights and min sizes among the rows/columns. 901 * </ol> 902 * 903 * This also caches the minsizes for all the children when they are 904 * first encountered (so subsequent loops don't need to ask again). 905 * <p> 906 * This method should only be used internally by 907 * {@code GridBagLayout}. 908 * 909 * @param parent the layout container 910 * @param sizeflag either {@code PREFERREDSIZE} or 911 * {@code MINSIZE} 912 * @return the {@code GridBagLayoutInfo} for the set of children 913 * @since 1.4 914 */ 915 protected GridBagLayoutInfo getLayoutInfo(Container parent, int sizeflag) { 916 return GetLayoutInfo(parent, sizeflag); 917 } 918 919 /* 920 * Calculate maximum array sizes to allocate arrays without ensureCapacity 921 * we may use preCalculated sizes in whole class because of upper estimation of 922 * maximumArrayXIndex and maximumArrayYIndex. 923 */ 924 925 private long[] preInitMaximumArraySizes(Container parent){ 926 Component components[] = parent.getComponents(); 927 Component comp; 928 GridBagConstraints constraints; 929 int curX, curY; 930 int curWidth, curHeight; 931 int preMaximumArrayXIndex = 0; 932 int preMaximumArrayYIndex = 0; 1588 } 1589 } 1590 else if (baseline == nextBaseline){ 1591 constraints.centerOffset--; 1592 constraints.centerPadding = 1; 1593 } 1594 } 1595 } 1596 return true; 1597 } 1598 else { 1599 constraints.ascent = -1; 1600 return false; 1601 } 1602 } 1603 1604 /** 1605 * Adjusts the x, y, width, and height fields to the correct 1606 * values depending on the constraint geometry and pads. 1607 * This method should only be used internally by 1608 * {@code GridBagLayout}. 1609 * 1610 * @param constraints the constraints to be applied 1611 * @param r the {@code Rectangle} to be adjusted 1612 * @since 1.4 1613 */ 1614 protected void adjustForGravity(GridBagConstraints constraints, 1615 Rectangle r) { 1616 AdjustForGravity(constraints, r); 1617 } 1618 1619 /** 1620 * Adjusts the x, y, width, and height fields to the correct 1621 * values depending on the constraint geometry and pads. 1622 * <p> 1623 * This method is obsolete and supplied for backwards 1624 * compatibility only; new code should call {@link 1625 * #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle) 1626 * adjustForGravity} instead. 1627 * This method is the same as {@code adjustForGravity} 1628 * 1629 * @param constraints the constraints to be applied 1630 * @param r the {@code Rectangle} to be adjusted 1631 */ 1632 protected void AdjustForGravity(GridBagConstraints constraints, 1633 Rectangle r) { 1634 int diffx, diffy; 1635 int cellY = r.y; 1636 int cellHeight = r.height; 1637 1638 if (!rightToLeft) { 1639 r.x += constraints.insets.left; 1640 } else { 1641 r.x -= r.width - constraints.insets.right; 1642 } 1643 r.width -= (constraints.insets.left + constraints.insets.right); 1644 r.y += constraints.insets.top; 1645 r.height -= (constraints.insets.top + constraints.insets.bottom); 1646 1647 diffx = 0; 1970 if (cons.isVerticallyResizable()) { 1971 r.height = cellY + cellHeight - r.y - cons.insets.bottom; 1972 } 1973 } 1974 else { 1975 centerVertically(cons, r, cellHeight); 1976 } 1977 } 1978 1979 private void centerVertically(GridBagConstraints cons, Rectangle r, 1980 int cellHeight) { 1981 if (!cons.isVerticallyResizable()) { 1982 r.y += Math.max(0, (cellHeight - cons.insets.top - 1983 cons.insets.bottom - cons.minHeight - 1984 cons.ipady) / 2); 1985 } 1986 } 1987 1988 /** 1989 * Figures out the minimum size of the 1990 * master based on the information from {@code getLayoutInfo}. 1991 * This method should only be used internally by 1992 * {@code GridBagLayout}. 1993 * 1994 * @param parent the layout container 1995 * @param info the layout info for this parent 1996 * @return a {@code Dimension} object containing the 1997 * minimum size 1998 * @since 1.4 1999 */ 2000 protected Dimension getMinSize(Container parent, GridBagLayoutInfo info) { 2001 return GetMinSize(parent, info); 2002 } 2003 2004 /** 2005 * This method is obsolete and supplied for backwards 2006 * compatibility only; new code should call {@link 2007 * #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead. 2008 * This method is the same as {@code getMinSize} 2009 * 2010 * @param parent the layout container 2011 * @param info the layout info for this parent 2012 * @return a {@code Dimension} object containing the 2013 * minimum size 2014 */ 2015 protected Dimension GetMinSize(Container parent, GridBagLayoutInfo info) { 2016 Dimension d = new Dimension(); 2017 int i, t; 2018 Insets insets = parent.getInsets(); 2019 2020 t = 0; 2021 for(i = 0; i < info.width; i++) 2022 t += info.minWidth[i]; 2023 d.width = t + insets.left + insets.right; 2024 2025 t = 0; 2026 for(i = 0; i < info.height; i++) 2027 t += info.minHeight[i]; 2028 d.height = t + insets.top + insets.bottom; 2029 2030 return d; 2031 } 2032 2033 transient boolean rightToLeft = false; 2034 2035 /** 2036 * Lays out the grid. 2037 * This method should only be used internally by 2038 * {@code GridBagLayout}. 2039 * 2040 * @param parent the layout container 2041 * @since 1.4 2042 */ 2043 protected void arrangeGrid(Container parent) { 2044 ArrangeGrid(parent); 2045 } 2046 2047 /** 2048 * This method is obsolete and supplied for backwards 2049 * compatibility only; new code should call {@link 2050 * #arrangeGrid(Container) arrangeGrid} instead. 2051 * This method is the same as {@code arrangeGrid} 2052 * 2053 * @param parent the layout container 2054 */ 2055 protected void ArrangeGrid(Container parent) { 2056 Component comp; 2057 int compindex; 2058 GridBagConstraints constraints; 2059 Insets insets = parent.getInsets(); 2060 Component components[] = parent.getComponents(); 2061 Dimension d; 2062 Rectangle r = new Rectangle(); 2063 int i, diffw, diffh; 2064 double weight; 2065 GridBagLayoutInfo info; 2066 2067 rightToLeft = !parent.getComponentOrientation().isLeftToRight(); 2068 2069 /* 2070 * If the parent has no slaves anymore, then don't do anything 2071 * at all: just leave the parent's size as-is. |