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