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