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: 124 * <p> 125 * <center><table BORDER=0 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 * <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)." ALIGN=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 * <p> 255 * <center><table WIDTH=600 summary="layout"> 256 * <tr ALIGN=CENTER> 257 * <td> 258 * <img src="doc-files/GridBagLayout-1.gif" alt="The preceeding text describes this graphic (Figure 1)." ALIGN=center HSPACE=10 VSPACE=7> 259 * </td> 260 * <td> 261 * <img src="doc-files/GridBagLayout-2.gif" alt="The preceeding text describes this graphic (Figure 2)." ALIGN=center HSPACE=10 VSPACE=7> 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 * <p> 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 * <p> 289 * <hr><blockquote><pre> 290 * import java.awt.*; 291 * import java.util.*; 292 * import java.applet.Applet; 293 * 294 * public class GridBagEx1 extends Applet { 295 * 296 * protected void makebutton(String name, 297 * GridBagLayout gridbag, 298 * GridBagConstraints c) { 299 * Button button = new Button(name); 300 * gridbag.setConstraints(button, c); 301 * add(button); 302 * } 303 * 304 * public void init() { 305 * GridBagLayout gridbag = new GridBagLayout(); 306 * GridBagConstraints c = new GridBagConstraints(); 307 * 308 * setFont(new Font("SansSerif", Font.PLAIN, 14)); 309 * setLayout(gridbag); 310 * 311 * c.fill = GridBagConstraints.BOTH; 312 * c.weightx = 1.0; 313 * makebutton("Button1", gridbag, c); 314 * makebutton("Button2", gridbag, c); 315 * makebutton("Button3", gridbag, c); 316 * 317 * c.gridwidth = GridBagConstraints.REMAINDER; //end row 318 * makebutton("Button4", gridbag, c); 319 * 320 * c.weightx = 0.0; //reset to the default 321 * makebutton("Button5", gridbag, c); //another row 322 * 323 * c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row 324 * makebutton("Button6", gridbag, c); 325 * 326 * c.gridwidth = GridBagConstraints.REMAINDER; //end row 327 * makebutton("Button7", gridbag, c); 328 * 329 * c.gridwidth = 1; //reset to the default 330 * c.gridheight = 2; 331 * c.weighty = 1.0; 332 * makebutton("Button8", gridbag, c); 333 * 334 * c.weighty = 0.0; //reset to the default 335 * c.gridwidth = GridBagConstraints.REMAINDER; //end row 336 * c.gridheight = 1; //reset to the default 337 * makebutton("Button9", gridbag, c); 338 * makebutton("Button10", gridbag, c); 339 * 340 * setSize(300, 100); 341 * } 342 * 343 * public static void main(String args[]) { 344 * Frame f = new Frame("GridBag Layout Example"); 345 * GridBagEx1 ex1 = new GridBagEx1(); 346 * 347 * ex1.init(); 348 * 349 * f.add("Center", ex1); 350 * f.pack(); 351 * f.setSize(f.getPreferredSize()); 352 * f.show(); 353 * } 354 * } 355 * </pre></blockquote><hr> 356 * <p> 357 * @author Doug Stein 358 * @author Bill Spitzak (orignial NeWS & OLIT implementation) 359 * @see java.awt.GridBagConstraints 360 * @see java.awt.GridBagLayoutInfo 361 * @see java.awt.ComponentOrientation 362 * @since JDK1.0 363 */ 364 public class GridBagLayout implements LayoutManager2, 365 java.io.Serializable { 366 367 static final int EMPIRICMULTIPLIER = 2; 368 /** 369 * This field is no longer used to reserve arrays and keeped for backward 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, rowa 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 contraints 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 JDK1.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. 580 * @return an array of two arrays, containing the widths 581 * of the layout columns and 582 * the heights of the layout rows 583 * @since JDK1.1 584 */ 585 public int [][] getLayoutDimensions () { 586 if (layoutInfo == null) 587 return new int[2][0]; 588 589 int dim[][] = new int [2][]; 590 dim[0] = new int[layoutInfo.width]; 591 dim[1] = new int[layoutInfo.height]; 592 593 System.arraycopy(layoutInfo.minWidth, 0, dim[0], 0, layoutInfo.width); 594 System.arraycopy(layoutInfo.minHeight, 0, dim[1], 0, layoutInfo.height); 595 596 return dim; 597 } 598 599 /** 600 * Determines the weights of the layout grid's columns and rows. 601 * Weights are used to calculate how much a given column or row 602 * stretches beyond its preferred size, if the layout has extra 603 * room to fill. 604 * <p> 605 * Most applications do not call this method directly. 606 * @return an array of two arrays, representing the 607 * horizontal weights of the layout columns 608 * and the vertical weights of the layout rows 609 * @since JDK1.1 610 */ 611 public double [][] getLayoutWeights () { 612 if (layoutInfo == null) 613 return new double[2][0]; 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 JDK1.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) 664 break; 665 } 666 } else { 667 for (i=layoutInfo.width-1; i>=0; i--) { 668 if (d > x) 669 break; 670 d += layoutInfo.minWidth[i]; 671 } 672 i++; 673 } 674 loc.x = i; 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 * <p> 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 * <p> 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 contraints 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 /** 824 * Print the layout information. Useful for debugging. 825 */ 826 827 /* DEBUG 828 * 829 * protected void dumpLayoutInfo(GridBagLayoutInfo s) { 830 * int x; 831 * 832 * System.out.println("Col\tWidth\tWeight"); 833 * for (x=0; x<s.width; x++) { 834 * System.out.println(x + "\t" + 835 * s.minWidth[x] + "\t" + 836 * s.weightX[x]); 837 * } 838 * System.out.println("Row\tHeight\tWeight"); 839 * for (x=0; x<s.height; x++) { 840 * System.out.println(x + "\t" + 841 * s.minHeight[x] + "\t" + 842 * s.weightY[x]); 843 * } 844 * } 845 */ 846 847 /** 848 * Print the layout constraints. Useful for debugging. 849 */ 850 851 /* DEBUG 852 * 853 * protected void dumpConstraints(GridBagConstraints constraints) { 854 * System.out.println( 855 * "wt " + 856 * constraints.weightx + 857 * " " + 858 * constraints.weighty + 859 * ", " + 860 * 861 * "box " + 862 * constraints.gridx + 863 * " " + 864 * constraints.gridy + 865 * " " + 866 * constraints.gridwidth + 867 * " " + 868 * constraints.gridheight + 869 * ", " + 870 * 871 * "min " + 872 * constraints.minWidth + 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 amoung 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; 933 long [] returnArray = new long[2]; 934 935 for (int compId = 0 ; compId < components.length ; compId++) { 936 comp = components[compId]; 937 if (!comp.isVisible()) { 938 continue; 939 } 940 941 constraints = lookupConstraints(comp); 942 curX = constraints.gridx; 943 curY = constraints.gridy; 944 curWidth = constraints.gridwidth; 945 curHeight = constraints.gridheight; 946 947 // -1==RELATIVE, means that column|row equals to previously added component, 948 // since each next Component with gridx|gridy == RELATIVE starts from 949 // previous position, so we should start from previous component which 950 // already used in maximumArray[X|Y]Index calculation. We could just increase 951 // maximum by 1 to handle situation when component with gridx=-1 was added. 952 if (curX < 0){ 953 curX = ++preMaximumArrayYIndex; 954 } 955 if (curY < 0){ 956 curY = ++preMaximumArrayXIndex; 957 } 958 // gridwidth|gridheight may be equal to RELATIVE (-1) or REMAINDER (0) 959 // in any case using 1 instead of 0 or -1 should be sufficient to for 960 // correct maximumArraySizes calculation 961 if (curWidth <= 0){ 962 curWidth = 1; 963 } 964 if (curHeight <= 0){ 965 curHeight = 1; 966 } 967 968 preMaximumArrayXIndex = Math.max(curY + curHeight, preMaximumArrayXIndex); 969 preMaximumArrayYIndex = Math.max(curX + curWidth, preMaximumArrayYIndex); 970 } //for (components) loop 971 // Must specify index++ to allocate well-working arrays. 972 /* fix for 4623196. 973 * now return long array instead of Point 974 */ 975 returnArray[0] = preMaximumArrayXIndex; 976 returnArray[1] = preMaximumArrayYIndex; 977 return returnArray; 978 } //PreInitMaximumSizes 979 980 /** 981 * This method is obsolete and supplied for backwards 982 * compatability only; new code should call {@link 983 * #getLayoutInfo(java.awt.Container, int) getLayoutInfo} instead. 984 * This method is the same as <code>getLayoutInfo</code>; 985 * refer to <code>getLayoutInfo</code> for details on parameters 986 * and return value. 987 */ 988 protected GridBagLayoutInfo GetLayoutInfo(Container parent, int sizeflag) { 989 synchronized (parent.getTreeLock()) { 990 GridBagLayoutInfo r; 991 Component comp; 992 GridBagConstraints constraints; 993 Dimension d; 994 Component components[] = parent.getComponents(); 995 // Code below will address index curX+curWidth in the case of yMaxArray, weightY 996 // ( respectively curY+curHeight for xMaxArray, weightX ) where 997 // curX in 0 to preInitMaximumArraySizes.y 998 // Thus, the maximum index that could 999 // be calculated in the following code is curX+curX. 1000 // EmpericMultier equals 2 because of this. 1001 1002 int layoutWidth, layoutHeight; 1003 int []xMaxArray; 1004 int []yMaxArray; 1005 int compindex, i, k, px, py, pixels_diff, nextSize; 1006 int curX = 0; // constraints.gridx 1007 int curY = 0; // constraints.gridy 1008 int curWidth = 1; // constraints.gridwidth 1009 int curHeight = 1; // constraints.gridheight 1010 int curRow, curCol; 1011 double weight_diff, weight; 1012 int maximumArrayXIndex = 0; 1013 int maximumArrayYIndex = 0; 1014 int anchor; 1015 1016 /* 1017 * Pass #1 1018 * 1019 * Figure out the dimensions of the layout grid (use a value of 1 for 1020 * zero or negative widths and heights). 1021 */ 1022 1023 layoutWidth = layoutHeight = 0; 1024 curRow = curCol = -1; 1025 long [] arraySizes = preInitMaximumArraySizes(parent); 1026 1027 /* fix for 4623196. 1028 * If user try to create a very big grid we can 1029 * get NegativeArraySizeException because of integer value 1030 * overflow (EMPIRICMULTIPLIER*gridSize might be more then Integer.MAX_VALUE). 1031 * We need to detect this situation and try to create a 1032 * grid with Integer.MAX_VALUE size instead. 1033 */ 1034 maximumArrayXIndex = (EMPIRICMULTIPLIER * arraySizes[0] > Integer.MAX_VALUE )? Integer.MAX_VALUE : EMPIRICMULTIPLIER*(int)arraySizes[0]; 1035 maximumArrayYIndex = (EMPIRICMULTIPLIER * arraySizes[1] > Integer.MAX_VALUE )? Integer.MAX_VALUE : EMPIRICMULTIPLIER*(int)arraySizes[1]; 1036 1037 if (rowHeights != null){ 1038 maximumArrayXIndex = Math.max(maximumArrayXIndex, rowHeights.length); 1039 } 1040 if (columnWidths != null){ 1041 maximumArrayYIndex = Math.max(maximumArrayYIndex, columnWidths.length); 1042 } 1043 1044 xMaxArray = new int[maximumArrayXIndex]; 1045 yMaxArray = new int[maximumArrayYIndex]; 1046 1047 boolean hasBaseline = false; 1048 for (compindex = 0 ; compindex < components.length ; compindex++) { 1049 comp = components[compindex]; 1050 if (!comp.isVisible()) 1051 continue; 1052 constraints = lookupConstraints(comp); 1053 1054 curX = constraints.gridx; 1055 curY = constraints.gridy; 1056 curWidth = constraints.gridwidth; 1057 if (curWidth <= 0) 1058 curWidth = 1; 1059 curHeight = constraints.gridheight; 1060 if (curHeight <= 0) 1061 curHeight = 1; 1062 1063 /* If x or y is negative, then use relative positioning: */ 1064 if (curX < 0 && curY < 0) { 1065 if (curRow >= 0) 1066 curY = curRow; 1067 else if (curCol >= 0) 1068 curX = curCol; 1069 else 1070 curY = 0; 1071 } 1072 if (curX < 0) { 1073 px = 0; 1074 for (i = curY; i < (curY + curHeight); i++) { 1075 px = Math.max(px, xMaxArray[i]); 1076 } 1077 1078 curX = px - curX - 1; 1079 if(curX < 0) 1080 curX = 0; 1081 } 1082 else if (curY < 0) { 1083 py = 0; 1084 for (i = curX; i < (curX + curWidth); i++) { 1085 py = Math.max(py, yMaxArray[i]); 1086 } 1087 curY = py - curY - 1; 1088 if(curY < 0) 1089 curY = 0; 1090 } 1091 1092 /* Adjust the grid width and height 1093 * fix for 5005945: unneccessary loops removed 1094 */ 1095 px = curX + curWidth; 1096 if (layoutWidth < px) { 1097 layoutWidth = px; 1098 } 1099 py = curY + curHeight; 1100 if (layoutHeight < py) { 1101 layoutHeight = py; 1102 } 1103 1104 /* Adjust xMaxArray and yMaxArray */ 1105 for (i = curX; i < (curX + curWidth); i++) { 1106 yMaxArray[i] =py; 1107 } 1108 for (i = curY; i < (curY + curHeight); i++) { 1109 xMaxArray[i] = px; 1110 } 1111 1112 1113 /* Cache the current slave's size. */ 1114 if (sizeflag == PREFERREDSIZE) 1115 d = comp.getPreferredSize(); 1116 else 1117 d = comp.getMinimumSize(); 1118 constraints.minWidth = d.width; 1119 constraints.minHeight = d.height; 1120 if (calculateBaseline(comp, constraints, d)) { 1121 hasBaseline = true; 1122 } 1123 1124 /* Zero width and height must mean that this is the last item (or 1125 * else something is wrong). */ 1126 if (constraints.gridheight == 0 && constraints.gridwidth == 0) 1127 curRow = curCol = -1; 1128 1129 /* Zero width starts a new row */ 1130 if (constraints.gridheight == 0 && curRow < 0) 1131 curCol = curX + curWidth; 1132 1133 /* Zero height starts a new column */ 1134 else if (constraints.gridwidth == 0 && curCol < 0) 1135 curRow = curY + curHeight; 1136 } //for (components) loop 1137 1138 1139 /* 1140 * Apply minimum row/column dimensions 1141 */ 1142 if (columnWidths != null && layoutWidth < columnWidths.length) 1143 layoutWidth = columnWidths.length; 1144 if (rowHeights != null && layoutHeight < rowHeights.length) 1145 layoutHeight = rowHeights.length; 1146 1147 r = new GridBagLayoutInfo(layoutWidth, layoutHeight); 1148 1149 /* 1150 * Pass #2 1151 * 1152 * Negative values for gridX are filled in with the current x value. 1153 * Negative values for gridY are filled in with the current y value. 1154 * Negative or zero values for gridWidth and gridHeight end the current 1155 * row or column, respectively. 1156 */ 1157 1158 curRow = curCol = -1; 1159 1160 Arrays.fill(xMaxArray, 0); 1161 Arrays.fill(yMaxArray, 0); 1162 1163 int[] maxAscent = null; 1164 int[] maxDescent = null; 1165 short[] baselineType = null; 1166 1167 if (hasBaseline) { 1168 r.maxAscent = maxAscent = new int[layoutHeight]; 1169 r.maxDescent = maxDescent = new int[layoutHeight]; 1170 r.baselineType = baselineType = new short[layoutHeight]; 1171 r.hasBaseline = true; 1172 } 1173 1174 1175 for (compindex = 0 ; compindex < components.length ; compindex++) { 1176 comp = components[compindex]; 1177 if (!comp.isVisible()) 1178 continue; 1179 constraints = lookupConstraints(comp); 1180 1181 curX = constraints.gridx; 1182 curY = constraints.gridy; 1183 curWidth = constraints.gridwidth; 1184 curHeight = constraints.gridheight; 1185 1186 /* If x or y is negative, then use relative positioning: */ 1187 if (curX < 0 && curY < 0) { 1188 if(curRow >= 0) 1189 curY = curRow; 1190 else if(curCol >= 0) 1191 curX = curCol; 1192 else 1193 curY = 0; 1194 } 1195 1196 if (curX < 0) { 1197 if (curHeight <= 0) { 1198 curHeight += r.height - curY; 1199 if (curHeight < 1) 1200 curHeight = 1; 1201 } 1202 1203 px = 0; 1204 for (i = curY; i < (curY + curHeight); i++) 1205 px = Math.max(px, xMaxArray[i]); 1206 1207 curX = px - curX - 1; 1208 if(curX < 0) 1209 curX = 0; 1210 } 1211 else if (curY < 0) { 1212 if (curWidth <= 0) { 1213 curWidth += r.width - curX; 1214 if (curWidth < 1) 1215 curWidth = 1; 1216 } 1217 1218 py = 0; 1219 for (i = curX; i < (curX + curWidth); i++){ 1220 py = Math.max(py, yMaxArray[i]); 1221 } 1222 1223 curY = py - curY - 1; 1224 if(curY < 0) 1225 curY = 0; 1226 } 1227 1228 if (curWidth <= 0) { 1229 curWidth += r.width - curX; 1230 if (curWidth < 1) 1231 curWidth = 1; 1232 } 1233 1234 if (curHeight <= 0) { 1235 curHeight += r.height - curY; 1236 if (curHeight < 1) 1237 curHeight = 1; 1238 } 1239 1240 px = curX + curWidth; 1241 py = curY + curHeight; 1242 1243 for (i = curX; i < (curX + curWidth); i++) { yMaxArray[i] = py; } 1244 for (i = curY; i < (curY + curHeight); i++) { xMaxArray[i] = px; } 1245 1246 /* Make negative sizes start a new row/column */ 1247 if (constraints.gridheight == 0 && constraints.gridwidth == 0) 1248 curRow = curCol = -1; 1249 if (constraints.gridheight == 0 && curRow < 0) 1250 curCol = curX + curWidth; 1251 else if (constraints.gridwidth == 0 && curCol < 0) 1252 curRow = curY + curHeight; 1253 1254 /* Assign the new values to the gridbag slave */ 1255 constraints.tempX = curX; 1256 constraints.tempY = curY; 1257 constraints.tempWidth = curWidth; 1258 constraints.tempHeight = curHeight; 1259 1260 anchor = constraints.anchor; 1261 if (hasBaseline) { 1262 switch(anchor) { 1263 case GridBagConstraints.BASELINE: 1264 case GridBagConstraints.BASELINE_LEADING: 1265 case GridBagConstraints.BASELINE_TRAILING: 1266 if (constraints.ascent >= 0) { 1267 if (curHeight == 1) { 1268 maxAscent[curY] = 1269 Math.max(maxAscent[curY], 1270 constraints.ascent); 1271 maxDescent[curY] = 1272 Math.max(maxDescent[curY], 1273 constraints.descent); 1274 } 1275 else { 1276 if (constraints.baselineResizeBehavior == 1277 Component.BaselineResizeBehavior. 1278 CONSTANT_DESCENT) { 1279 maxDescent[curY + curHeight - 1] = 1280 Math.max(maxDescent[curY + curHeight 1281 - 1], 1282 constraints.descent); 1283 } 1284 else { 1285 maxAscent[curY] = Math.max(maxAscent[curY], 1286 constraints.ascent); 1287 } 1288 } 1289 if (constraints.baselineResizeBehavior == 1290 Component.BaselineResizeBehavior.CONSTANT_DESCENT) { 1291 baselineType[curY + curHeight - 1] |= 1292 (1 << constraints. 1293 baselineResizeBehavior.ordinal()); 1294 } 1295 else { 1296 baselineType[curY] |= (1 << constraints. 1297 baselineResizeBehavior.ordinal()); 1298 } 1299 } 1300 break; 1301 case GridBagConstraints.ABOVE_BASELINE: 1302 case GridBagConstraints.ABOVE_BASELINE_LEADING: 1303 case GridBagConstraints.ABOVE_BASELINE_TRAILING: 1304 // Component positioned above the baseline. 1305 // To make the bottom edge of the component aligned 1306 // with the baseline the bottom inset is 1307 // added to the descent, the rest to the ascent. 1308 pixels_diff = constraints.minHeight + 1309 constraints.insets.top + 1310 constraints.ipady; 1311 maxAscent[curY] = Math.max(maxAscent[curY], 1312 pixels_diff); 1313 maxDescent[curY] = Math.max(maxDescent[curY], 1314 constraints.insets.bottom); 1315 break; 1316 case GridBagConstraints.BELOW_BASELINE: 1317 case GridBagConstraints.BELOW_BASELINE_LEADING: 1318 case GridBagConstraints.BELOW_BASELINE_TRAILING: 1319 // Component positioned below the baseline. 1320 // To make the top edge of the component aligned 1321 // with the baseline the top inset is 1322 // added to the ascent, the rest to the descent. 1323 pixels_diff = constraints.minHeight + 1324 constraints.insets.bottom + constraints.ipady; 1325 maxDescent[curY] = Math.max(maxDescent[curY], 1326 pixels_diff); 1327 maxAscent[curY] = Math.max(maxAscent[curY], 1328 constraints.insets.top); 1329 break; 1330 } 1331 } 1332 } 1333 1334 r.weightX = new double[maximumArrayYIndex]; 1335 r.weightY = new double[maximumArrayXIndex]; 1336 r.minWidth = new int[maximumArrayYIndex]; 1337 r.minHeight = new int[maximumArrayXIndex]; 1338 1339 1340 /* 1341 * Apply minimum row/column dimensions and weights 1342 */ 1343 if (columnWidths != null) 1344 System.arraycopy(columnWidths, 0, r.minWidth, 0, columnWidths.length); 1345 if (rowHeights != null) 1346 System.arraycopy(rowHeights, 0, r.minHeight, 0, rowHeights.length); 1347 if (columnWeights != null) 1348 System.arraycopy(columnWeights, 0, r.weightX, 0, Math.min(r.weightX.length, columnWeights.length)); 1349 if (rowWeights != null) 1350 System.arraycopy(rowWeights, 0, r.weightY, 0, Math.min(r.weightY.length, rowWeights.length)); 1351 1352 /* 1353 * Pass #3 1354 * 1355 * Distribute the minimun widths and weights: 1356 */ 1357 1358 nextSize = Integer.MAX_VALUE; 1359 1360 for (i = 1; 1361 i != Integer.MAX_VALUE; 1362 i = nextSize, nextSize = Integer.MAX_VALUE) { 1363 for (compindex = 0 ; compindex < components.length ; compindex++) { 1364 comp = components[compindex]; 1365 if (!comp.isVisible()) 1366 continue; 1367 constraints = lookupConstraints(comp); 1368 1369 if (constraints.tempWidth == i) { 1370 px = constraints.tempX + constraints.tempWidth; /* right column */ 1371 1372 /* 1373 * Figure out if we should use this slave\'s weight. If the weight 1374 * is less than the total weight spanned by the width of the cell, 1375 * then discard the weight. Otherwise split the difference 1376 * according to the existing weights. 1377 */ 1378 1379 weight_diff = constraints.weightx; 1380 for (k = constraints.tempX; k < px; k++) 1381 weight_diff -= r.weightX[k]; 1382 if (weight_diff > 0.0) { 1383 weight = 0.0; 1384 for (k = constraints.tempX; k < px; k++) 1385 weight += r.weightX[k]; 1386 for (k = constraints.tempX; weight > 0.0 && k < px; k++) { 1387 double wt = r.weightX[k]; 1388 double dx = (wt * weight_diff) / weight; 1389 r.weightX[k] += dx; 1390 weight_diff -= dx; 1391 weight -= wt; 1392 } 1393 /* Assign the remainder to the rightmost cell */ 1394 r.weightX[px-1] += weight_diff; 1395 } 1396 1397 /* 1398 * Calculate the minWidth array values. 1399 * First, figure out how wide the current slave needs to be. 1400 * Then, see if it will fit within the current minWidth values. 1401 * If it will not fit, add the difference according to the 1402 * weightX array. 1403 */ 1404 1405 pixels_diff = 1406 constraints.minWidth + constraints.ipadx + 1407 constraints.insets.left + constraints.insets.right; 1408 1409 for (k = constraints.tempX; k < px; k++) 1410 pixels_diff -= r.minWidth[k]; 1411 if (pixels_diff > 0) { 1412 weight = 0.0; 1413 for (k = constraints.tempX; k < px; k++) 1414 weight += r.weightX[k]; 1415 for (k = constraints.tempX; weight > 0.0 && k < px; k++) { 1416 double wt = r.weightX[k]; 1417 int dx = (int)((wt * ((double)pixels_diff)) / weight); 1418 r.minWidth[k] += dx; 1419 pixels_diff -= dx; 1420 weight -= wt; 1421 } 1422 /* Any leftovers go into the rightmost cell */ 1423 r.minWidth[px-1] += pixels_diff; 1424 } 1425 } 1426 else if (constraints.tempWidth > i && constraints.tempWidth < nextSize) 1427 nextSize = constraints.tempWidth; 1428 1429 1430 if (constraints.tempHeight == i) { 1431 py = constraints.tempY + constraints.tempHeight; /* bottom row */ 1432 1433 /* 1434 * Figure out if we should use this slave's weight. If the weight 1435 * is less than the total weight spanned by the height of the cell, 1436 * then discard the weight. Otherwise split it the difference 1437 * according to the existing weights. 1438 */ 1439 1440 weight_diff = constraints.weighty; 1441 for (k = constraints.tempY; k < py; k++) 1442 weight_diff -= r.weightY[k]; 1443 if (weight_diff > 0.0) { 1444 weight = 0.0; 1445 for (k = constraints.tempY; k < py; k++) 1446 weight += r.weightY[k]; 1447 for (k = constraints.tempY; weight > 0.0 && k < py; k++) { 1448 double wt = r.weightY[k]; 1449 double dy = (wt * weight_diff) / weight; 1450 r.weightY[k] += dy; 1451 weight_diff -= dy; 1452 weight -= wt; 1453 } 1454 /* Assign the remainder to the bottom cell */ 1455 r.weightY[py-1] += weight_diff; 1456 } 1457 1458 /* 1459 * Calculate the minHeight array values. 1460 * First, figure out how tall the current slave needs to be. 1461 * Then, see if it will fit within the current minHeight values. 1462 * If it will not fit, add the difference according to the 1463 * weightY array. 1464 */ 1465 1466 pixels_diff = -1; 1467 if (hasBaseline) { 1468 switch(constraints.anchor) { 1469 case GridBagConstraints.BASELINE: 1470 case GridBagConstraints.BASELINE_LEADING: 1471 case GridBagConstraints.BASELINE_TRAILING: 1472 if (constraints.ascent >= 0) { 1473 if (constraints.tempHeight == 1) { 1474 pixels_diff = 1475 maxAscent[constraints.tempY] + 1476 maxDescent[constraints.tempY]; 1477 } 1478 else if (constraints.baselineResizeBehavior != 1479 Component.BaselineResizeBehavior. 1480 CONSTANT_DESCENT) { 1481 pixels_diff = 1482 maxAscent[constraints.tempY] + 1483 constraints.descent; 1484 } 1485 else { 1486 pixels_diff = constraints.ascent + 1487 maxDescent[constraints.tempY + 1488 constraints.tempHeight - 1]; 1489 } 1490 } 1491 break; 1492 case GridBagConstraints.ABOVE_BASELINE: 1493 case GridBagConstraints.ABOVE_BASELINE_LEADING: 1494 case GridBagConstraints.ABOVE_BASELINE_TRAILING: 1495 pixels_diff = constraints.insets.top + 1496 constraints.minHeight + 1497 constraints.ipady + 1498 maxDescent[constraints.tempY]; 1499 break; 1500 case GridBagConstraints.BELOW_BASELINE: 1501 case GridBagConstraints.BELOW_BASELINE_LEADING: 1502 case GridBagConstraints.BELOW_BASELINE_TRAILING: 1503 pixels_diff = maxAscent[constraints.tempY] + 1504 constraints.minHeight + 1505 constraints.insets.bottom + 1506 constraints.ipady; 1507 break; 1508 } 1509 } 1510 if (pixels_diff == -1) { 1511 pixels_diff = 1512 constraints.minHeight + constraints.ipady + 1513 constraints.insets.top + 1514 constraints.insets.bottom; 1515 } 1516 for (k = constraints.tempY; k < py; k++) 1517 pixels_diff -= r.minHeight[k]; 1518 if (pixels_diff > 0) { 1519 weight = 0.0; 1520 for (k = constraints.tempY; k < py; k++) 1521 weight += r.weightY[k]; 1522 for (k = constraints.tempY; weight > 0.0 && k < py; k++) { 1523 double wt = r.weightY[k]; 1524 int dy = (int)((wt * ((double)pixels_diff)) / weight); 1525 r.minHeight[k] += dy; 1526 pixels_diff -= dy; 1527 weight -= wt; 1528 } 1529 /* Any leftovers go into the bottom cell */ 1530 r.minHeight[py-1] += pixels_diff; 1531 } 1532 } 1533 else if (constraints.tempHeight > i && 1534 constraints.tempHeight < nextSize) 1535 nextSize = constraints.tempHeight; 1536 } 1537 } 1538 return r; 1539 } 1540 } //getLayoutInfo() 1541 1542 /** 1543 * Calculate the baseline for the specified component. 1544 * If {@code c} is positioned along it's baseline, the baseline is 1545 * obtained and the {@code constraints} ascent, descent and 1546 * baseline resize behavior are set from the component; and true is 1547 * returned. Otherwise false is returned. 1548 */ 1549 private boolean calculateBaseline(Component c, 1550 GridBagConstraints constraints, 1551 Dimension size) { 1552 int anchor = constraints.anchor; 1553 if (anchor == GridBagConstraints.BASELINE || 1554 anchor == GridBagConstraints.BASELINE_LEADING || 1555 anchor == GridBagConstraints.BASELINE_TRAILING) { 1556 // Apply the padding to the component, then ask for the baseline. 1557 int w = size.width + constraints.ipadx; 1558 int h = size.height + constraints.ipady; 1559 constraints.ascent = c.getBaseline(w, h); 1560 if (constraints.ascent >= 0) { 1561 // Component has a baseline 1562 int baseline = constraints.ascent; 1563 // Adjust the ascent and descent to include the insets. 1564 constraints.descent = h - constraints.ascent + 1565 constraints.insets.bottom; 1566 constraints.ascent += constraints.insets.top; 1567 constraints.baselineResizeBehavior = 1568 c.getBaselineResizeBehavior(); 1569 constraints.centerPadding = 0; 1570 if (constraints.baselineResizeBehavior == Component. 1571 BaselineResizeBehavior.CENTER_OFFSET) { 1572 // Component has a baseline resize behavior of 1573 // CENTER_OFFSET, calculate centerPadding and 1574 // centerOffset (see the description of 1575 // CENTER_OFFSET in the enum for detais on this 1576 // algorithm). 1577 int nextBaseline = c.getBaseline(w, h + 1); 1578 constraints.centerOffset = baseline - h / 2; 1579 if (h % 2 == 0) { 1580 if (baseline != nextBaseline) { 1581 constraints.centerPadding = 1; 1582 } 1583 } 1584 else if (baseline == nextBaseline){ 1585 constraints.centerOffset--; 1586 constraints.centerPadding = 1; 1587 } 1588 } 1589 } 1590 return true; 1591 } 1592 else { 1593 constraints.ascent = -1; 1594 return false; 1595 } 1596 } 1597 1598 /** 1599 * Adjusts the x, y, width, and height fields to the correct 1600 * values depending on the constraint geometry and pads. 1601 * This method should only be used internally by 1602 * <code>GridBagLayout</code>. 1603 * 1604 * @param constraints the constraints to be applied 1605 * @param r the <code>Rectangle</code> to be adjusted 1606 * @since 1.4 1607 */ 1608 protected void adjustForGravity(GridBagConstraints constraints, 1609 Rectangle r) { 1610 AdjustForGravity(constraints, r); 1611 } 1612 1613 /** 1614 * This method is obsolete and supplied for backwards 1615 * compatability only; new code should call {@link 1616 * #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle) 1617 * adjustForGravity} instead. 1618 * This method is the same as <code>adjustForGravity</code>; 1619 * refer to <code>adjustForGravity</code> for details 1620 * on parameters. 1621 */ 1622 protected void AdjustForGravity(GridBagConstraints constraints, 1623 Rectangle r) { 1624 int diffx, diffy; 1625 int cellY = r.y; 1626 int cellHeight = r.height; 1627 1628 if (!rightToLeft) { 1629 r.x += constraints.insets.left; 1630 } else { 1631 r.x -= r.width - constraints.insets.right; 1632 } 1633 r.width -= (constraints.insets.left + constraints.insets.right); 1634 r.y += constraints.insets.top; 1635 r.height -= (constraints.insets.top + constraints.insets.bottom); 1636 1637 diffx = 0; 1638 if ((constraints.fill != GridBagConstraints.HORIZONTAL && 1639 constraints.fill != GridBagConstraints.BOTH) 1640 && (r.width > (constraints.minWidth + constraints.ipadx))) { 1641 diffx = r.width - (constraints.minWidth + constraints.ipadx); 1642 r.width = constraints.minWidth + constraints.ipadx; 1643 } 1644 1645 diffy = 0; 1646 if ((constraints.fill != GridBagConstraints.VERTICAL && 1647 constraints.fill != GridBagConstraints.BOTH) 1648 && (r.height > (constraints.minHeight + constraints.ipady))) { 1649 diffy = r.height - (constraints.minHeight + constraints.ipady); 1650 r.height = constraints.minHeight + constraints.ipady; 1651 } 1652 1653 switch (constraints.anchor) { 1654 case GridBagConstraints.BASELINE: 1655 r.x += diffx/2; 1656 alignOnBaseline(constraints, r, cellY, cellHeight); 1657 break; 1658 case GridBagConstraints.BASELINE_LEADING: 1659 if (rightToLeft) { 1660 r.x += diffx; 1661 } 1662 alignOnBaseline(constraints, r, cellY, cellHeight); 1663 break; 1664 case GridBagConstraints.BASELINE_TRAILING: 1665 if (!rightToLeft) { 1666 r.x += diffx; 1667 } 1668 alignOnBaseline(constraints, r, cellY, cellHeight); 1669 break; 1670 case GridBagConstraints.ABOVE_BASELINE: 1671 r.x += diffx/2; 1672 alignAboveBaseline(constraints, r, cellY, cellHeight); 1673 break; 1674 case GridBagConstraints.ABOVE_BASELINE_LEADING: 1675 if (rightToLeft) { 1676 r.x += diffx; 1677 } 1678 alignAboveBaseline(constraints, r, cellY, cellHeight); 1679 break; 1680 case GridBagConstraints.ABOVE_BASELINE_TRAILING: 1681 if (!rightToLeft) { 1682 r.x += diffx; 1683 } 1684 alignAboveBaseline(constraints, r, cellY, cellHeight); 1685 break; 1686 case GridBagConstraints.BELOW_BASELINE: 1687 r.x += diffx/2; 1688 alignBelowBaseline(constraints, r, cellY, cellHeight); 1689 break; 1690 case GridBagConstraints.BELOW_BASELINE_LEADING: 1691 if (rightToLeft) { 1692 r.x += diffx; 1693 } 1694 alignBelowBaseline(constraints, r, cellY, cellHeight); 1695 break; 1696 case GridBagConstraints.BELOW_BASELINE_TRAILING: 1697 if (!rightToLeft) { 1698 r.x += diffx; 1699 } 1700 alignBelowBaseline(constraints, r, cellY, cellHeight); 1701 break; 1702 case GridBagConstraints.CENTER: 1703 r.x += diffx/2; 1704 r.y += diffy/2; 1705 break; 1706 case GridBagConstraints.PAGE_START: 1707 case GridBagConstraints.NORTH: 1708 r.x += diffx/2; 1709 break; 1710 case GridBagConstraints.NORTHEAST: 1711 r.x += diffx; 1712 break; 1713 case GridBagConstraints.EAST: 1714 r.x += diffx; 1715 r.y += diffy/2; 1716 break; 1717 case GridBagConstraints.SOUTHEAST: 1718 r.x += diffx; 1719 r.y += diffy; 1720 break; 1721 case GridBagConstraints.PAGE_END: 1722 case GridBagConstraints.SOUTH: 1723 r.x += diffx/2; 1724 r.y += diffy; 1725 break; 1726 case GridBagConstraints.SOUTHWEST: 1727 r.y += diffy; 1728 break; 1729 case GridBagConstraints.WEST: 1730 r.y += diffy/2; 1731 break; 1732 case GridBagConstraints.NORTHWEST: 1733 break; 1734 case GridBagConstraints.LINE_START: 1735 if (rightToLeft) { 1736 r.x += diffx; 1737 } 1738 r.y += diffy/2; 1739 break; 1740 case GridBagConstraints.LINE_END: 1741 if (!rightToLeft) { 1742 r.x += diffx; 1743 } 1744 r.y += diffy/2; 1745 break; 1746 case GridBagConstraints.FIRST_LINE_START: 1747 if (rightToLeft) { 1748 r.x += diffx; 1749 } 1750 break; 1751 case GridBagConstraints.FIRST_LINE_END: 1752 if (!rightToLeft) { 1753 r.x += diffx; 1754 } 1755 break; 1756 case GridBagConstraints.LAST_LINE_START: 1757 if (rightToLeft) { 1758 r.x += diffx; 1759 } 1760 r.y += diffy; 1761 break; 1762 case GridBagConstraints.LAST_LINE_END: 1763 if (!rightToLeft) { 1764 r.x += diffx; 1765 } 1766 r.y += diffy; 1767 break; 1768 default: 1769 throw new IllegalArgumentException("illegal anchor value"); 1770 } 1771 } 1772 1773 /** 1774 * Positions on the baseline. 1775 * 1776 * @param cellY the location of the row, does not include insets 1777 * @param cellHeight the height of the row, does not take into account 1778 * insets 1779 * @param r available bounds for the component, is padded by insets and 1780 * ipady 1781 */ 1782 private void alignOnBaseline(GridBagConstraints cons, Rectangle r, 1783 int cellY, int cellHeight) { 1784 if (cons.ascent >= 0) { 1785 if (cons.baselineResizeBehavior == Component. 1786 BaselineResizeBehavior.CONSTANT_DESCENT) { 1787 // Anchor to the bottom. 1788 // Baseline is at (cellY + cellHeight - maxDescent). 1789 // Bottom of component (maxY) is at baseline + descent 1790 // of component. We need to subtract the bottom inset here 1791 // as the descent in the constraints object includes the 1792 // bottom inset. 1793 int maxY = cellY + cellHeight - 1794 layoutInfo.maxDescent[cons.tempY + cons.tempHeight - 1] + 1795 cons.descent - cons.insets.bottom; 1796 if (!cons.isVerticallyResizable()) { 1797 // Component not resizable, calculate y location 1798 // from maxY - height. 1799 r.y = maxY - cons.minHeight; 1800 r.height = cons.minHeight; 1801 } else { 1802 // Component is resizable. As brb is constant descent, 1803 // can expand component to fill region above baseline. 1804 // Subtract out the top inset so that components insets 1805 // are honored. 1806 r.height = maxY - cellY - cons.insets.top; 1807 } 1808 } 1809 else { 1810 // BRB is not constant_descent 1811 int baseline; // baseline for the row, relative to cellY 1812 // Component baseline, includes insets.top 1813 int ascent = cons.ascent; 1814 if (layoutInfo.hasConstantDescent(cons.tempY)) { 1815 // Mixed ascent/descent in same row, calculate position 1816 // off maxDescent 1817 baseline = cellHeight - layoutInfo.maxDescent[cons.tempY]; 1818 } 1819 else { 1820 // Only ascents/unknown in this row, anchor to top 1821 baseline = layoutInfo.maxAscent[cons.tempY]; 1822 } 1823 if (cons.baselineResizeBehavior == Component. 1824 BaselineResizeBehavior.OTHER) { 1825 // BRB is other, which means we can only determine 1826 // the baseline by asking for it again giving the 1827 // size we plan on using for the component. 1828 boolean fits = false; 1829 ascent = componentAdjusting.getBaseline(r.width, r.height); 1830 if (ascent >= 0) { 1831 // Component has a baseline, pad with top inset 1832 // (this follows from calculateBaseline which 1833 // does the same). 1834 ascent += cons.insets.top; 1835 } 1836 if (ascent >= 0 && ascent <= baseline) { 1837 // Components baseline fits within rows baseline. 1838 // Make sure the descent fits within the space as well. 1839 if (baseline + (r.height - ascent - cons.insets.top) <= 1840 cellHeight - cons.insets.bottom) { 1841 // It fits, we're good. 1842 fits = true; 1843 } 1844 else if (cons.isVerticallyResizable()) { 1845 // Doesn't fit, but it's resizable. Try 1846 // again assuming we'll get ascent again. 1847 int ascent2 = componentAdjusting.getBaseline( 1848 r.width, cellHeight - cons.insets.bottom - 1849 baseline + ascent); 1850 if (ascent2 >= 0) { 1851 ascent2 += cons.insets.top; 1852 } 1853 if (ascent2 >= 0 && ascent2 <= ascent) { 1854 // It'll fit 1855 r.height = cellHeight - cons.insets.bottom - 1856 baseline + ascent; 1857 ascent = ascent2; 1858 fits = true; 1859 } 1860 } 1861 } 1862 if (!fits) { 1863 // Doesn't fit, use min size and original ascent 1864 ascent = cons.ascent; 1865 r.width = cons.minWidth; 1866 r.height = cons.minHeight; 1867 } 1868 } 1869 // Reset the components y location based on 1870 // components ascent and baseline for row. Because ascent 1871 // includes the baseline 1872 r.y = cellY + baseline - ascent + cons.insets.top; 1873 if (cons.isVerticallyResizable()) { 1874 switch(cons.baselineResizeBehavior) { 1875 case CONSTANT_ASCENT: 1876 r.height = Math.max(cons.minHeight,cellY + cellHeight - 1877 r.y - cons.insets.bottom); 1878 break; 1879 case CENTER_OFFSET: 1880 { 1881 int upper = r.y - cellY - cons.insets.top; 1882 int lower = cellY + cellHeight - r.y - 1883 cons.minHeight - cons.insets.bottom; 1884 int delta = Math.min(upper, lower); 1885 delta += delta; 1886 if (delta > 0 && 1887 (cons.minHeight + cons.centerPadding + 1888 delta) / 2 + cons.centerOffset != baseline) { 1889 // Off by 1 1890 delta--; 1891 } 1892 r.height = cons.minHeight + delta; 1893 r.y = cellY + baseline - 1894 (r.height + cons.centerPadding) / 2 - 1895 cons.centerOffset; 1896 } 1897 break; 1898 case OTHER: 1899 // Handled above 1900 break; 1901 default: 1902 break; 1903 } 1904 } 1905 } 1906 } 1907 else { 1908 centerVertically(cons, r, cellHeight); 1909 } 1910 } 1911 1912 /** 1913 * Positions the specified component above the baseline. That is 1914 * the bottom edge of the component will be aligned along the baseline. 1915 * If the row does not have a baseline, this centers the component. 1916 */ 1917 private void alignAboveBaseline(GridBagConstraints cons, Rectangle r, 1918 int cellY, int cellHeight) { 1919 if (layoutInfo.hasBaseline(cons.tempY)) { 1920 int maxY; // Baseline for the row 1921 if (layoutInfo.hasConstantDescent(cons.tempY)) { 1922 // Prefer descent 1923 maxY = cellY + cellHeight - layoutInfo.maxDescent[cons.tempY]; 1924 } 1925 else { 1926 // Prefer ascent 1927 maxY = cellY + layoutInfo.maxAscent[cons.tempY]; 1928 } 1929 if (cons.isVerticallyResizable()) { 1930 // Component is resizable. Top edge is offset by top 1931 // inset, bottom edge on baseline. 1932 r.y = cellY + cons.insets.top; 1933 r.height = maxY - r.y; 1934 } 1935 else { 1936 // Not resizable. 1937 r.height = cons.minHeight + cons.ipady; 1938 r.y = maxY - r.height; 1939 } 1940 } 1941 else { 1942 centerVertically(cons, r, cellHeight); 1943 } 1944 } 1945 1946 /** 1947 * Positions below the baseline. 1948 */ 1949 private void alignBelowBaseline(GridBagConstraints cons, Rectangle r, 1950 int cellY, int cellHeight) { 1951 if (layoutInfo.hasBaseline(cons.tempY)) { 1952 if (layoutInfo.hasConstantDescent(cons.tempY)) { 1953 // Prefer descent 1954 r.y = cellY + cellHeight - layoutInfo.maxDescent[cons.tempY]; 1955 } 1956 else { 1957 // Prefer ascent 1958 r.y = cellY + layoutInfo.maxAscent[cons.tempY]; 1959 } 1960 if (cons.isVerticallyResizable()) { 1961 r.height = cellY + cellHeight - r.y - cons.insets.bottom; 1962 } 1963 } 1964 else { 1965 centerVertically(cons, r, cellHeight); 1966 } 1967 } 1968 1969 private void centerVertically(GridBagConstraints cons, Rectangle r, 1970 int cellHeight) { 1971 if (!cons.isVerticallyResizable()) { 1972 r.y += Math.max(0, (cellHeight - cons.insets.top - 1973 cons.insets.bottom - cons.minHeight - 1974 cons.ipady) / 2); 1975 } 1976 } 1977 1978 /** 1979 * Figures out the minimum size of the 1980 * master based on the information from <code>getLayoutInfo</code>. 1981 * This method should only be used internally by 1982 * <code>GridBagLayout</code>. 1983 * 1984 * @param parent the layout container 1985 * @param info the layout info for this parent 1986 * @return a <code>Dimension</code> object containing the 1987 * minimum size 1988 * @since 1.4 1989 */ 1990 protected Dimension getMinSize(Container parent, GridBagLayoutInfo info) { 1991 return GetMinSize(parent, info); 1992 } 1993 1994 /** 1995 * This method is obsolete and supplied for backwards 1996 * compatability only; new code should call {@link 1997 * #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead. 1998 * This method is the same as <code>getMinSize</code>; 1999 * refer to <code>getMinSize</code> for details on parameters 2000 * and return value. 2001 */ 2002 protected Dimension GetMinSize(Container parent, GridBagLayoutInfo info) { 2003 Dimension d = new Dimension(); 2004 int i, t; 2005 Insets insets = parent.getInsets(); 2006 2007 t = 0; 2008 for(i = 0; i < info.width; i++) 2009 t += info.minWidth[i]; 2010 d.width = t + insets.left + insets.right; 2011 2012 t = 0; 2013 for(i = 0; i < info.height; i++) 2014 t += info.minHeight[i]; 2015 d.height = t + insets.top + insets.bottom; 2016 2017 return d; 2018 } 2019 2020 transient boolean rightToLeft = false; 2021 2022 /** 2023 * Lays out the grid. 2024 * This method should only be used internally by 2025 * <code>GridBagLayout</code>. 2026 * 2027 * @param parent the layout container 2028 * @since 1.4 2029 */ 2030 protected void arrangeGrid(Container parent) { 2031 ArrangeGrid(parent); 2032 } 2033 2034 /** 2035 * This method is obsolete and supplied for backwards 2036 * compatability only; new code should call {@link 2037 * #arrangeGrid(Container) arrangeGrid} instead. 2038 * This method is the same as <code>arrangeGrid</code>; 2039 * refer to <code>arrangeGrid</code> for details on the 2040 * parameter. 2041 */ 2042 protected void ArrangeGrid(Container parent) { 2043 Component comp; 2044 int compindex; 2045 GridBagConstraints constraints; 2046 Insets insets = parent.getInsets(); 2047 Component components[] = parent.getComponents(); 2048 Dimension d; 2049 Rectangle r = new Rectangle(); 2050 int i, diffw, diffh; 2051 double weight; 2052 GridBagLayoutInfo info; 2053 2054 rightToLeft = !parent.getComponentOrientation().isLeftToRight(); 2055 2056 /* 2057 * If the parent has no slaves anymore, then don't do anything 2058 * at all: just leave the parent's size as-is. 2059 */ 2060 if (components.length == 0 && 2061 (columnWidths == null || columnWidths.length == 0) && 2062 (rowHeights == null || rowHeights.length == 0)) { 2063 return; 2064 } 2065 2066 /* 2067 * Pass #1: scan all the slaves to figure out the total amount 2068 * of space needed. 2069 */ 2070 2071 info = getLayoutInfo(parent, PREFERREDSIZE); 2072 d = getMinSize(parent, info); 2073 2074 if (parent.width < d.width || parent.height < d.height) { 2075 info = getLayoutInfo(parent, MINSIZE); 2076 d = getMinSize(parent, info); 2077 } 2078 2079 layoutInfo = info; 2080 r.width = d.width; 2081 r.height = d.height; 2082 2083 /* 2084 * DEBUG 2085 * 2086 * DumpLayoutInfo(info); 2087 * for (compindex = 0 ; compindex < components.length ; compindex++) { 2088 * comp = components[compindex]; 2089 * if (!comp.isVisible()) 2090 * continue; 2091 * constraints = lookupConstraints(comp); 2092 * DumpConstraints(constraints); 2093 * } 2094 * System.out.println("minSize " + r.width + " " + r.height); 2095 */ 2096 2097 /* 2098 * If the current dimensions of the window don't match the desired 2099 * dimensions, then adjust the minWidth and minHeight arrays 2100 * according to the weights. 2101 */ 2102 2103 diffw = parent.width - r.width; 2104 if (diffw != 0) { 2105 weight = 0.0; 2106 for (i = 0; i < info.width; i++) 2107 weight += info.weightX[i]; 2108 if (weight > 0.0) { 2109 for (i = 0; i < info.width; i++) { 2110 int dx = (int)(( ((double)diffw) * info.weightX[i]) / weight); 2111 info.minWidth[i] += dx; 2112 r.width += dx; 2113 if (info.minWidth[i] < 0) { 2114 r.width -= info.minWidth[i]; 2115 info.minWidth[i] = 0; 2116 } 2117 } 2118 } 2119 diffw = parent.width - r.width; 2120 } 2121 2122 else { 2123 diffw = 0; 2124 } 2125 2126 diffh = parent.height - r.height; 2127 if (diffh != 0) { 2128 weight = 0.0; 2129 for (i = 0; i < info.height; i++) 2130 weight += info.weightY[i]; 2131 if (weight > 0.0) { 2132 for (i = 0; i < info.height; i++) { 2133 int dy = (int)(( ((double)diffh) * info.weightY[i]) / weight); 2134 info.minHeight[i] += dy; 2135 r.height += dy; 2136 if (info.minHeight[i] < 0) { 2137 r.height -= info.minHeight[i]; 2138 info.minHeight[i] = 0; 2139 } 2140 } 2141 } 2142 diffh = parent.height - r.height; 2143 } 2144 2145 else { 2146 diffh = 0; 2147 } 2148 2149 /* 2150 * DEBUG 2151 * 2152 * System.out.println("Re-adjusted:"); 2153 * DumpLayoutInfo(info); 2154 */ 2155 2156 /* 2157 * Now do the actual layout of the slaves using the layout information 2158 * that has been collected. 2159 */ 2160 2161 info.startx = diffw/2 + insets.left; 2162 info.starty = diffh/2 + insets.top; 2163 2164 for (compindex = 0 ; compindex < components.length ; compindex++) { 2165 comp = components[compindex]; 2166 if (!comp.isVisible()){ 2167 continue; 2168 } 2169 constraints = lookupConstraints(comp); 2170 2171 if (!rightToLeft) { 2172 r.x = info.startx; 2173 for(i = 0; i < constraints.tempX; i++) 2174 r.x += info.minWidth[i]; 2175 } else { 2176 r.x = parent.width - (diffw/2 + insets.right); 2177 for(i = 0; i < constraints.tempX; i++) 2178 r.x -= info.minWidth[i]; 2179 } 2180 2181 r.y = info.starty; 2182 for(i = 0; i < constraints.tempY; i++) 2183 r.y += info.minHeight[i]; 2184 2185 r.width = 0; 2186 for(i = constraints.tempX; 2187 i < (constraints.tempX + constraints.tempWidth); 2188 i++) { 2189 r.width += info.minWidth[i]; 2190 } 2191 2192 r.height = 0; 2193 for(i = constraints.tempY; 2194 i < (constraints.tempY + constraints.tempHeight); 2195 i++) { 2196 r.height += info.minHeight[i]; 2197 } 2198 2199 componentAdjusting = comp; 2200 adjustForGravity(constraints, r); 2201 2202 /* fix for 4408108 - components were being created outside of the container */ 2203 /* fix for 4969409 "-" replaced by "+" */ 2204 if (r.x < 0) { 2205 r.width += r.x; 2206 r.x = 0; 2207 } 2208 2209 if (r.y < 0) { 2210 r.height += r.y; 2211 r.y = 0; 2212 } 2213 2214 /* 2215 * If the window is too small to be interesting then 2216 * unmap it. Otherwise configure it and then make sure 2217 * it's mapped. 2218 */ 2219 2220 if ((r.width <= 0) || (r.height <= 0)) { 2221 comp.setBounds(0, 0, 0, 0); 2222 } 2223 else { 2224 if (comp.x != r.x || comp.y != r.y || 2225 comp.width != r.width || comp.height != r.height) { 2226 comp.setBounds(r.x, r.y, r.width, r.height); 2227 } 2228 } 2229 } 2230 } 2231 2232 // Added for serial backwards compatability (4348425) 2233 static final long serialVersionUID = 8838754796412211005L; 2234 }