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