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