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 26 package java.awt; 27 28 import java.util.Hashtable; 29 30 /** 31 * A border layout lays out a container, arranging and resizing 32 * its components to fit in five regions: 33 * north, south, east, west, and center. 34 * Each region may contain no more than one component, and 35 * is identified by a corresponding constant: 36 * {@code NORTH}, {@code SOUTH}, {@code EAST}, 37 * {@code WEST}, and {@code CENTER}. When adding a 38 * component to a container with a border layout, use one of these 39 * five constants, for example: 40 * <pre> 41 * Panel p = new Panel(); 42 * p.setLayout(new BorderLayout()); 43 * p.add(new Button("Okay"), BorderLayout.SOUTH); 44 * </pre> 45 * As a convenience, {@code BorderLayout} interprets the 46 * absence of a string specification the same as the constant 47 * {@code CENTER}: 48 * <pre> 49 * Panel p2 = new Panel(); 50 * p2.setLayout(new BorderLayout()); 51 * p2.add(new TextArea()); // Same as p.add(new TextArea(), BorderLayout.CENTER); 52 * </pre> 53 * <p> 54 * In addition, {@code BorderLayout} supports the relative 55 * positioning constants, {@code PAGE_START}, {@code PAGE_END}, 56 * {@code LINE_START}, and {@code LINE_END}. 57 * In a container whose {@code ComponentOrientation} is set to 58 * {@code ComponentOrientation.LEFT_TO_RIGHT}, these constants map to 59 * {@code NORTH}, {@code SOUTH}, {@code WEST}, and 60 * {@code EAST}, respectively. 61 * <p> 62 * For compatibility with previous releases, {@code BorderLayout} 63 * also includes the relative positioning constants {@code BEFORE_FIRST_LINE}, 64 * {@code AFTER_LAST_LINE}, {@code BEFORE_LINE_BEGINS} and 65 * {@code AFTER_LINE_ENDS}. These are equivalent to 66 * {@code PAGE_START}, {@code PAGE_END}, {@code LINE_START} 67 * and {@code LINE_END} respectively. For 68 * consistency with the relative positioning constants used by other 69 * components, the latter constants are preferred. 70 * <p> 71 * Mixing both absolute and relative positioning constants can lead to 72 * unpredictable results. If 73 * you use both types, the relative constants will take precedence. 74 * For example, if you add components using both the {@code NORTH} 75 * and {@code PAGE_START} constants in a container whose 76 * orientation is {@code LEFT_TO_RIGHT}, only the 77 * {@code PAGE_START} will be laid out. 78 * <p> 79 * NOTE: Currently, 80 * {@code BorderLayout} does not support vertical 81 * orientations. The {@code isVertical} setting on the container's 82 * {@code ComponentOrientation} is not respected. 83 * <p> 84 * The components are laid out according to their 85 * preferred sizes and the constraints of the container's size. 86 * The {@code NORTH} and {@code SOUTH} components may 87 * be stretched horizontally; the {@code EAST} and 88 * {@code WEST} components may be stretched vertically; 89 * the {@code CENTER} component may stretch both horizontally 90 * and vertically to fill any space left over. 91 * <p> 92 * Here is an example of five buttons in an applet laid out using 93 * the {@code BorderLayout} layout manager: 94 * <p> 95 * <img src="doc-files/BorderLayout-1.gif" alt="Diagram of an applet 96 * demonstrating BorderLayout. Each section of the BorderLayout contains a 97 * Button corresponding to its position in the layout, one of: North, West, 98 * Center, East, or South." style="margin: 7px 10px;"> 99 * <p> 100 * The code for this applet is as follows: 101 * 102 * <hr><blockquote><pre> 103 * import java.awt.*; 104 * import java.applet.Applet; 105 * 106 * public class buttonDir extends Applet { 107 * public void init() { 108 * setLayout(new BorderLayout()); 109 * add(new Button("North"), BorderLayout.NORTH); 110 * add(new Button("South"), BorderLayout.SOUTH); 111 * add(new Button("East"), BorderLayout.EAST); 112 * add(new Button("West"), BorderLayout.WEST); 113 * add(new Button("Center"), BorderLayout.CENTER); 114 * } 115 * } 116 * </pre></blockquote><hr> 117 * 118 * @author Arthur van Hoff 119 * @see java.awt.Container#add(String, Component) 120 * @see java.awt.ComponentOrientation 121 * @since 1.0 122 */ 123 public class BorderLayout implements LayoutManager2, 124 java.io.Serializable { 125 /** 126 * Constructs a border layout with the horizontal gaps 127 * between components. 128 * The horizontal gap is specified by {@code hgap}. 129 * 130 * @see #getHgap() 131 * @see #setHgap(int) 132 * 133 * @serial 134 */ 135 int hgap; 136 137 /** 138 * Constructs a border layout with the vertical gaps 139 * between components. 140 * The vertical gap is specified by {@code vgap}. 141 * 142 * @see #getVgap() 143 * @see #setVgap(int) 144 * @serial 145 */ 146 int vgap; 147 148 /** 149 * Constant to specify components location to be the 150 * north portion of the border layout. 151 * @serial 152 * @see #getChild(String, boolean) 153 * @see #addLayoutComponent 154 * @see #getLayoutAlignmentX 155 * @see #getLayoutAlignmentY 156 * @see #removeLayoutComponent 157 */ 158 Component north; 159 /** 160 * Constant to specify components location to be the 161 * west portion of the border layout. 162 * @serial 163 * @see #getChild(String, boolean) 164 * @see #addLayoutComponent 165 * @see #getLayoutAlignmentX 166 * @see #getLayoutAlignmentY 167 * @see #removeLayoutComponent 168 */ 169 Component west; 170 /** 171 * Constant to specify components location to be the 172 * east portion of the border layout. 173 * @serial 174 * @see #getChild(String, boolean) 175 * @see #addLayoutComponent 176 * @see #getLayoutAlignmentX 177 * @see #getLayoutAlignmentY 178 * @see #removeLayoutComponent 179 */ 180 Component east; 181 /** 182 * Constant to specify components location to be the 183 * south portion of the border layout. 184 * @serial 185 * @see #getChild(String, boolean) 186 * @see #addLayoutComponent 187 * @see #getLayoutAlignmentX 188 * @see #getLayoutAlignmentY 189 * @see #removeLayoutComponent 190 */ 191 Component south; 192 /** 193 * Constant to specify components location to be the 194 * center portion of the border layout. 195 * @serial 196 * @see #getChild(String, boolean) 197 * @see #addLayoutComponent 198 * @see #getLayoutAlignmentX 199 * @see #getLayoutAlignmentY 200 * @see #removeLayoutComponent 201 */ 202 Component center; 203 204 /** 205 * 206 * A relative positioning constant, that can be used instead of 207 * north, south, east, west or center. 208 * mixing the two types of constants can lead to unpredictable results. If 209 * you use both types, the relative constants will take precedence. 210 * For example, if you add components using both the {@code NORTH} 211 * and {@code BEFORE_FIRST_LINE} constants in a container whose 212 * orientation is {@code LEFT_TO_RIGHT}, only the 213 * {@code BEFORE_FIRST_LINE} will be laid out. 214 * This will be the same for lastLine, firstItem, lastItem. 215 * @serial 216 */ 217 Component firstLine; 218 /** 219 * A relative positioning constant, that can be used instead of 220 * north, south, east, west or center. 221 * Please read Description for firstLine. 222 * @serial 223 */ 224 Component lastLine; 225 /** 226 * A relative positioning constant, that can be used instead of 227 * north, south, east, west or center. 228 * Please read Description for firstLine. 229 * @serial 230 */ 231 Component firstItem; 232 /** 233 * A relative positioning constant, that can be used instead of 234 * north, south, east, west or center. 235 * Please read Description for firstLine. 236 * @serial 237 */ 238 Component lastItem; 239 240 /** 241 * The north layout constraint (top of container). 242 */ 243 public static final String NORTH = "North"; 244 245 /** 246 * The south layout constraint (bottom of container). 247 */ 248 public static final String SOUTH = "South"; 249 250 /** 251 * The east layout constraint (right side of container). 252 */ 253 public static final String EAST = "East"; 254 255 /** 256 * The west layout constraint (left side of container). 257 */ 258 public static final String WEST = "West"; 259 260 /** 261 * The center layout constraint (middle of container). 262 */ 263 public static final String CENTER = "Center"; 264 265 /** 266 * Synonym for PAGE_START. Exists for compatibility with previous 267 * versions. PAGE_START is preferred. 268 * 269 * @see #PAGE_START 270 * @since 1.2 271 */ 272 public static final String BEFORE_FIRST_LINE = "First"; 273 274 /** 275 * Synonym for PAGE_END. Exists for compatibility with previous 276 * versions. PAGE_END is preferred. 277 * 278 * @see #PAGE_END 279 * @since 1.2 280 */ 281 public static final String AFTER_LAST_LINE = "Last"; 282 283 /** 284 * Synonym for LINE_START. Exists for compatibility with previous 285 * versions. LINE_START is preferred. 286 * 287 * @see #LINE_START 288 * @since 1.2 289 */ 290 public static final String BEFORE_LINE_BEGINS = "Before"; 291 292 /** 293 * Synonym for LINE_END. Exists for compatibility with previous 294 * versions. LINE_END is preferred. 295 * 296 * @see #LINE_END 297 * @since 1.2 298 */ 299 public static final String AFTER_LINE_ENDS = "After"; 300 301 /** 302 * The component comes before the first line of the layout's content. 303 * For Western, left-to-right and top-to-bottom orientations, this is 304 * equivalent to NORTH. 305 * 306 * @see java.awt.Component#getComponentOrientation 307 * @since 1.4 308 */ 309 public static final String PAGE_START = BEFORE_FIRST_LINE; 310 311 /** 312 * The component comes after the last line of the layout's content. 313 * For Western, left-to-right and top-to-bottom orientations, this is 314 * equivalent to SOUTH. 315 * 316 * @see java.awt.Component#getComponentOrientation 317 * @since 1.4 318 */ 319 public static final String PAGE_END = AFTER_LAST_LINE; 320 321 /** 322 * The component goes at the beginning of the line direction for the 323 * layout. For Western, left-to-right and top-to-bottom orientations, 324 * this is equivalent to WEST. 325 * 326 * @see java.awt.Component#getComponentOrientation 327 * @since 1.4 328 */ 329 public static final String LINE_START = BEFORE_LINE_BEGINS; 330 331 /** 332 * The component goes at the end of the line direction for the 333 * layout. For Western, left-to-right and top-to-bottom orientations, 334 * this is equivalent to EAST. 335 * 336 * @see java.awt.Component#getComponentOrientation 337 * @since 1.4 338 */ 339 public static final String LINE_END = AFTER_LINE_ENDS; 340 341 /* 342 * JDK 1.1 serialVersionUID 343 */ 344 private static final long serialVersionUID = -8658291919501921765L; 345 346 /** 347 * Constructs a new border layout with 348 * no gaps between components. 349 */ 350 public BorderLayout() { 351 this(0, 0); 352 } 353 354 /** 355 * Constructs a border layout with the specified gaps 356 * between components. 357 * The horizontal gap is specified by {@code hgap} 358 * and the vertical gap is specified by {@code vgap}. 359 * @param hgap the horizontal gap. 360 * @param vgap the vertical gap. 361 */ 362 public BorderLayout(int hgap, int vgap) { 363 this.hgap = hgap; 364 this.vgap = vgap; 365 } 366 367 /** 368 * Returns the horizontal gap between components. 369 * 370 * @return the horizontal gap between components 371 * @since 1.1 372 */ 373 public int getHgap() { 374 return hgap; 375 } 376 377 /** 378 * Sets the horizontal gap between components. 379 * 380 * @param hgap the horizontal gap between components 381 * @since 1.1 382 */ 383 public void setHgap(int hgap) { 384 this.hgap = hgap; 385 } 386 387 /** 388 * Returns the vertical gap between components. 389 * 390 * @return the vertical gap between components 391 * @since 1.1 392 */ 393 public int getVgap() { 394 return vgap; 395 } 396 397 /** 398 * Sets the vertical gap between components. 399 * 400 * @param vgap the vertical gap between components 401 * @since 1.1 402 */ 403 public void setVgap(int vgap) { 404 this.vgap = vgap; 405 } 406 407 /** 408 * Adds the specified component to the layout, using the specified 409 * constraint object. For border layouts, the constraint must be 410 * one of the following constants: {@code NORTH}, 411 * {@code SOUTH}, {@code EAST}, 412 * {@code WEST}, or {@code CENTER}. 413 * <p> 414 * Most applications do not call this method directly. This method 415 * is called when a component is added to a container using the 416 * {@code Container.add} method with the same argument types. 417 * @param comp the component to be added. 418 * @param constraints an object that specifies how and where 419 * the component is added to the layout. 420 * @see java.awt.Container#add(java.awt.Component, java.lang.Object) 421 * @exception IllegalArgumentException if the constraint object is not 422 * a string, or if it not one of the five specified constants. 423 * @since 1.1 424 */ 425 public void addLayoutComponent(Component comp, Object constraints) { 426 synchronized (comp.getTreeLock()) { 427 if ((constraints == null) || (constraints instanceof String)) { 428 addLayoutComponent((String)constraints, comp); 429 } else { 430 throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)"); 431 } 432 } 433 } 434 435 /** 436 * @deprecated replaced by {@code addLayoutComponent(Component, Object)}. 437 */ 438 @Deprecated 439 public void addLayoutComponent(String name, Component comp) { 440 synchronized (comp.getTreeLock()) { 441 /* Special case: treat null the same as "Center". */ 442 if (name == null) { 443 name = "Center"; 444 } 445 446 /* Assign the component to one of the known regions of the layout. 447 */ 448 if ("Center".equals(name)) { 449 center = comp; 450 } else if ("North".equals(name)) { 451 north = comp; 452 } else if ("South".equals(name)) { 453 south = comp; 454 } else if ("East".equals(name)) { 455 east = comp; 456 } else if ("West".equals(name)) { 457 west = comp; 458 } else if (BEFORE_FIRST_LINE.equals(name)) { 459 firstLine = comp; 460 } else if (AFTER_LAST_LINE.equals(name)) { 461 lastLine = comp; 462 } else if (BEFORE_LINE_BEGINS.equals(name)) { 463 firstItem = comp; 464 } else if (AFTER_LINE_ENDS.equals(name)) { 465 lastItem = comp; 466 } else { 467 throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name); 468 } 469 } 470 } 471 472 /** 473 * Removes the specified component from this border layout. This 474 * method is called when a container calls its {@code remove} or 475 * {@code removeAll} methods. Most applications do not call this 476 * method directly. 477 * @param comp the component to be removed. 478 * @see java.awt.Container#remove(java.awt.Component) 479 * @see java.awt.Container#removeAll() 480 */ 481 public void removeLayoutComponent(Component comp) { 482 synchronized (comp.getTreeLock()) { 483 if (comp == center) { 484 center = null; 485 } else if (comp == north) { 486 north = null; 487 } else if (comp == south) { 488 south = null; 489 } else if (comp == east) { 490 east = null; 491 } else if (comp == west) { 492 west = null; 493 } 494 if (comp == firstLine) { 495 firstLine = null; 496 } else if (comp == lastLine) { 497 lastLine = null; 498 } else if (comp == firstItem) { 499 firstItem = null; 500 } else if (comp == lastItem) { 501 lastItem = null; 502 } 503 } 504 } 505 506 /** 507 * Gets the component that was added using the given constraint 508 * 509 * @param constraints the desired constraint, one of {@code CENTER}, 510 * {@code NORTH}, {@code SOUTH}, 511 * {@code WEST}, {@code EAST}, 512 * {@code PAGE_START}, {@code PAGE_END}, 513 * {@code LINE_START}, {@code LINE_END} 514 * @return the component at the given location, or {@code null} if 515 * the location is empty 516 * @exception IllegalArgumentException if the constraint object is 517 * not one of the nine specified constants 518 * @see #addLayoutComponent(java.awt.Component, java.lang.Object) 519 * @since 1.5 520 */ 521 public Component getLayoutComponent(Object constraints) { 522 if (CENTER.equals(constraints)) { 523 return center; 524 } else if (NORTH.equals(constraints)) { 525 return north; 526 } else if (SOUTH.equals(constraints)) { 527 return south; 528 } else if (WEST.equals(constraints)) { 529 return west; 530 } else if (EAST.equals(constraints)) { 531 return east; 532 } else if (PAGE_START.equals(constraints)) { 533 return firstLine; 534 } else if (PAGE_END.equals(constraints)) { 535 return lastLine; 536 } else if (LINE_START.equals(constraints)) { 537 return firstItem; 538 } else if (LINE_END.equals(constraints)) { 539 return lastItem; 540 } else { 541 throw new IllegalArgumentException("cannot get component: unknown constraint: " + constraints); 542 } 543 } 544 545 546 /** 547 * Returns the component that corresponds to the given constraint location 548 * based on the target {@code Container}'s component orientation. 549 * Components added with the relative constraints {@code PAGE_START}, 550 * {@code PAGE_END}, {@code LINE_START}, and {@code LINE_END} 551 * take precedence over components added with the explicit constraints 552 * {@code NORTH}, {@code SOUTH}, {@code WEST}, and {@code EAST}. 553 * The {@code Container}'s component orientation is used to determine the location of components 554 * added with {@code LINE_START} and {@code LINE_END}. 555 * 556 * @param constraints the desired absolute position, one of {@code CENTER}, 557 * {@code NORTH}, {@code SOUTH}, 558 * {@code EAST}, {@code WEST} 559 * @param target the {@code Container} used to obtain 560 * the constraint location based on the target 561 * {@code Container}'s component orientation. 562 * @return the component at the given location, or {@code null} if 563 * the location is empty 564 * @exception IllegalArgumentException if the constraint object is 565 * not one of the five specified constants 566 * @exception NullPointerException if the target parameter is null 567 * @see #addLayoutComponent(java.awt.Component, java.lang.Object) 568 * @since 1.5 569 */ 570 public Component getLayoutComponent(Container target, Object constraints) { 571 boolean ltr = target.getComponentOrientation().isLeftToRight(); 572 Component result = null; 573 574 if (NORTH.equals(constraints)) { 575 result = (firstLine != null) ? firstLine : north; 576 } else if (SOUTH.equals(constraints)) { 577 result = (lastLine != null) ? lastLine : south; 578 } else if (WEST.equals(constraints)) { 579 result = ltr ? firstItem : lastItem; 580 if (result == null) { 581 result = west; 582 } 583 } else if (EAST.equals(constraints)) { 584 result = ltr ? lastItem : firstItem; 585 if (result == null) { 586 result = east; 587 } 588 } else if (CENTER.equals(constraints)) { 589 result = center; 590 } else { 591 throw new IllegalArgumentException("cannot get component: invalid constraint: " + constraints); 592 } 593 594 return result; 595 } 596 597 598 /** 599 * Gets the constraints for the specified component 600 * 601 * @param comp the component to be queried 602 * @return the constraint for the specified component, 603 * or null if component is null or is not present 604 * in this layout 605 * @see #addLayoutComponent(java.awt.Component, java.lang.Object) 606 * @since 1.5 607 */ 608 public Object getConstraints(Component comp) { 609 //fix for 6242148 : API method java.awt.BorderLayout.getConstraints(null) should return null 610 if (comp == null){ 611 return null; 612 } 613 if (comp == center) { 614 return CENTER; 615 } else if (comp == north) { 616 return NORTH; 617 } else if (comp == south) { 618 return SOUTH; 619 } else if (comp == west) { 620 return WEST; 621 } else if (comp == east) { 622 return EAST; 623 } else if (comp == firstLine) { 624 return PAGE_START; 625 } else if (comp == lastLine) { 626 return PAGE_END; 627 } else if (comp == firstItem) { 628 return LINE_START; 629 } else if (comp == lastItem) { 630 return LINE_END; 631 } 632 return null; 633 } 634 635 /** 636 * Determines the minimum size of the {@code target} container 637 * using this layout manager. 638 * <p> 639 * This method is called when a container calls its 640 * {@code getMinimumSize} method. Most applications do not call 641 * this method directly. 642 * @param target the container in which to do the layout. 643 * @return the minimum dimensions needed to lay out the subcomponents 644 * of the specified container. 645 * @see java.awt.Container 646 * @see java.awt.BorderLayout#preferredLayoutSize 647 * @see java.awt.Container#getMinimumSize() 648 */ 649 public Dimension minimumLayoutSize(Container target) { 650 synchronized (target.getTreeLock()) { 651 Dimension dim = new Dimension(0, 0); 652 653 boolean ltr = target.getComponentOrientation().isLeftToRight(); 654 Component c = null; 655 656 if ((c=getChild(EAST,ltr)) != null) { 657 Dimension d = c.getMinimumSize(); 658 dim.width += d.width + hgap; 659 dim.height = Math.max(d.height, dim.height); 660 } 661 if ((c=getChild(WEST,ltr)) != null) { 662 Dimension d = c.getMinimumSize(); 663 dim.width += d.width + hgap; 664 dim.height = Math.max(d.height, dim.height); 665 } 666 if ((c=getChild(CENTER,ltr)) != null) { 667 Dimension d = c.getMinimumSize(); 668 dim.width += d.width; 669 dim.height = Math.max(d.height, dim.height); 670 } 671 if ((c=getChild(NORTH,ltr)) != null) { 672 Dimension d = c.getMinimumSize(); 673 dim.width = Math.max(d.width, dim.width); 674 dim.height += d.height + vgap; 675 } 676 if ((c=getChild(SOUTH,ltr)) != null) { 677 Dimension d = c.getMinimumSize(); 678 dim.width = Math.max(d.width, dim.width); 679 dim.height += d.height + vgap; 680 } 681 682 Insets insets = target.getInsets(); 683 dim.width += insets.left + insets.right; 684 dim.height += insets.top + insets.bottom; 685 686 return dim; 687 } 688 } 689 690 /** 691 * Determines the preferred size of the {@code target} 692 * container using this layout manager, based on the components 693 * in the container. 694 * <p> 695 * Most applications do not call this method directly. This method 696 * is called when a container calls its {@code getPreferredSize} 697 * method. 698 * @param target the container in which to do the layout. 699 * @return the preferred dimensions to lay out the subcomponents 700 * of the specified container. 701 * @see java.awt.Container 702 * @see java.awt.BorderLayout#minimumLayoutSize 703 * @see java.awt.Container#getPreferredSize() 704 */ 705 public Dimension preferredLayoutSize(Container target) { 706 synchronized (target.getTreeLock()) { 707 Dimension dim = new Dimension(0, 0); 708 709 boolean ltr = target.getComponentOrientation().isLeftToRight(); 710 Component c = null; 711 712 if ((c=getChild(EAST,ltr)) != null) { 713 Dimension d = c.getPreferredSize(); 714 dim.width += d.width + hgap; 715 dim.height = Math.max(d.height, dim.height); 716 } 717 if ((c=getChild(WEST,ltr)) != null) { 718 Dimension d = c.getPreferredSize(); 719 dim.width += d.width + hgap; 720 dim.height = Math.max(d.height, dim.height); 721 } 722 if ((c=getChild(CENTER,ltr)) != null) { 723 Dimension d = c.getPreferredSize(); 724 dim.width += d.width; 725 dim.height = Math.max(d.height, dim.height); 726 } 727 if ((c=getChild(NORTH,ltr)) != null) { 728 Dimension d = c.getPreferredSize(); 729 dim.width = Math.max(d.width, dim.width); 730 dim.height += d.height + vgap; 731 } 732 if ((c=getChild(SOUTH,ltr)) != null) { 733 Dimension d = c.getPreferredSize(); 734 dim.width = Math.max(d.width, dim.width); 735 dim.height += d.height + vgap; 736 } 737 738 Insets insets = target.getInsets(); 739 dim.width += insets.left + insets.right; 740 dim.height += insets.top + insets.bottom; 741 742 return dim; 743 } 744 } 745 746 /** 747 * Returns the maximum dimensions for this layout given the components 748 * in the specified target container. 749 * @param target the component which needs to be laid out 750 * @see Container 751 * @see #minimumLayoutSize 752 * @see #preferredLayoutSize 753 */ 754 public Dimension maximumLayoutSize(Container target) { 755 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 756 } 757 758 /** 759 * Returns the alignment along the x axis. This specifies how 760 * the component would like to be aligned relative to other 761 * components. The value should be a number between 0 and 1 762 * where 0 represents alignment along the origin, 1 is aligned 763 * the furthest away from the origin, 0.5 is centered, etc. 764 */ 765 public float getLayoutAlignmentX(Container parent) { 766 return 0.5f; 767 } 768 769 /** 770 * Returns the alignment along the y axis. This specifies how 771 * the component would like to be aligned relative to other 772 * components. The value should be a number between 0 and 1 773 * where 0 represents alignment along the origin, 1 is aligned 774 * the furthest away from the origin, 0.5 is centered, etc. 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 container argument using this border layout. 789 * <p> 790 * This method actually reshapes the components in the specified 791 * container in order to satisfy the constraints of this 792 * {@code BorderLayout} object. The {@code NORTH} 793 * and {@code SOUTH} components, if any, are placed at 794 * the top and bottom of the container, respectively. The 795 * {@code WEST} and {@code EAST} components are 796 * then placed on the left and right, respectively. Finally, 797 * the {@code CENTER} object is placed in any remaining 798 * space in the middle. 799 * <p> 800 * Most applications do not call this method directly. This method 801 * is called when a container calls its {@code doLayout} method. 802 * @param target the container in which to do the layout. 803 * @see java.awt.Container 804 * @see java.awt.Container#doLayout() 805 */ 806 public void layoutContainer(Container target) { 807 synchronized (target.getTreeLock()) { 808 Insets insets = target.getInsets(); 809 int top = insets.top; 810 int bottom = target.height - insets.bottom; 811 int left = insets.left; 812 int right = target.width - insets.right; 813 814 boolean ltr = target.getComponentOrientation().isLeftToRight(); 815 Component c = null; 816 817 if ((c=getChild(NORTH,ltr)) != null) { 818 c.setSize(right - left, c.height); 819 Dimension d = c.getPreferredSize(); 820 c.setBounds(left, top, right - left, d.height); 821 top += d.height + vgap; 822 } 823 if ((c=getChild(SOUTH,ltr)) != null) { 824 c.setSize(right - left, c.height); 825 Dimension d = c.getPreferredSize(); 826 c.setBounds(left, bottom - d.height, right - left, d.height); 827 bottom -= d.height + vgap; 828 } 829 if ((c=getChild(EAST,ltr)) != null) { 830 c.setSize(c.width, bottom - top); 831 Dimension d = c.getPreferredSize(); 832 c.setBounds(right - d.width, top, d.width, bottom - top); 833 right -= d.width + hgap; 834 } 835 if ((c=getChild(WEST,ltr)) != null) { 836 c.setSize(c.width, bottom - top); 837 Dimension d = c.getPreferredSize(); 838 c.setBounds(left, top, d.width, bottom - top); 839 left += d.width + hgap; 840 } 841 if ((c=getChild(CENTER,ltr)) != null) { 842 c.setBounds(left, top, right - left, bottom - top); 843 } 844 } 845 } 846 847 /** 848 * Get the component that corresponds to the given constraint location 849 * 850 * @param key The desired absolute position, 851 * either NORTH, SOUTH, EAST, or WEST. 852 * @param ltr Is the component line direction left-to-right? 853 */ 854 private Component getChild(String key, boolean ltr) { 855 Component result = null; 856 857 if (key == NORTH) { 858 result = (firstLine != null) ? firstLine : north; 859 } 860 else if (key == SOUTH) { 861 result = (lastLine != null) ? lastLine : south; 862 } 863 else if (key == WEST) { 864 result = ltr ? firstItem : lastItem; 865 if (result == null) { 866 result = west; 867 } 868 } 869 else if (key == EAST) { 870 result = ltr ? lastItem : firstItem; 871 if (result == null) { 872 result = east; 873 } 874 } 875 else if (key == CENTER) { 876 result = center; 877 } 878 if (result != null && !result.visible) { 879 result = null; 880 } 881 return result; 882 } 883 884 /** 885 * Returns a string representation of the state of this border layout. 886 * @return a string representation of this border layout. 887 */ 888 public String toString() { 889 return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; 890 } 891 }