GNU Classpath (0.17) | ||
Frames | No Frames |
1: /* BorderLayout.java -- A layout manager class 2: Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.awt; 40: 41: /** 42: * This class implements a layout manager that positions components 43: * in certain sectors of the parent container. 44: * 45: * @author Aaron M. Renn (arenn@urbanophile.com) 46: * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) 47: */ 48: public class BorderLayout implements LayoutManager2, java.io.Serializable 49: { 50: 51: /* 52: * Static Variables 53: */ 54: 55: /** 56: * Constant indicating the top of the container 57: */ 58: public static final String NORTH = "North"; 59: 60: /** 61: * Constant indicating the bottom of the container 62: */ 63: public static final String SOUTH = "South"; 64: 65: /** 66: * Constant indicating the right side of the container 67: */ 68: public static final String EAST = "East"; 69: 70: /** 71: * Constant indicating the left side of the container 72: */ 73: public static final String WEST = "West"; 74: 75: /** 76: * Constant indicating the center of the container 77: */ 78: public static final String CENTER = "Center"; 79: 80: 81: /** 82: * The constant indicating the position before the first line of the 83: * layout. The exact position depends on the writing system: For a 84: * top-to-bottom orientation, it is the same as {@link #NORTH}, for 85: * a bottom-to-top orientation, it is the same as {@link #SOUTH}. 86: * 87: * <p>This constant is an older name for {@link #PAGE_START} which 88: * has exactly the same value. 89: * 90: * @since 1.2 91: */ 92: public static final String BEFORE_FIRST_LINE = "First"; 93: 94: 95: /** 96: * The constant indicating the position after the last line of the 97: * layout. The exact position depends on the writing system: For a 98: * top-to-bottom orientation, it is the same as {@link #SOUTH}, for 99: * a bottom-to-top orientation, it is the same as {@link #NORTH}. 100: * 101: * <p>This constant is an older name for {@link #PAGE_END} which 102: * has exactly the same value. 103: * 104: * @since 1.2 105: */ 106: public static final String AFTER_LAST_LINE = "Last"; 107: 108: 109: /** 110: * The constant indicating the position before the first item of the 111: * layout. The exact position depends on the writing system: For a 112: * left-to-right orientation, it is the same as {@link #WEST}, for 113: * a right-to-left orientation, it is the same as {@link #EAST}. 114: * 115: * <p>This constant is an older name for {@link #LINE_START} which 116: * has exactly the same value. 117: * 118: * @since 1.2 119: */ 120: public static final String BEFORE_LINE_BEGINS = "Before"; 121: 122: 123: /** 124: * The constant indicating the position after the last item of the 125: * layout. The exact position depends on the writing system: For a 126: * left-to-right orientation, it is the same as {@link #EAST}, for 127: * a right-to-left orientation, it is the same as {@link #WEST}. 128: * 129: * <p>This constant is an older name for {@link #LINE_END} which 130: * has exactly the same value. 131: * 132: * @since 1.2 133: */ 134: public static final String AFTER_LINE_ENDS = "After"; 135: 136: 137: /** 138: * The constant indicating the position before the first line of the 139: * layout. The exact position depends on the writing system: For a 140: * top-to-bottom orientation, it is the same as {@link #NORTH}, for 141: * a bottom-to-top orientation, it is the same as {@link #SOUTH}. 142: * 143: * @since 1.4 144: */ 145: public static final String PAGE_START = BEFORE_FIRST_LINE; 146: 147: 148: /** 149: * The constant indicating the position after the last line of the 150: * layout. The exact position depends on the writing system: For a 151: * top-to-bottom orientation, it is the same as {@link #SOUTH}, for 152: * a bottom-to-top orientation, it is the same as {@link #NORTH}. 153: * 154: * @since 1.4 155: */ 156: public static final String PAGE_END = AFTER_LAST_LINE; 157: 158: 159: /** 160: * The constant indicating the position before the first item of the 161: * layout. The exact position depends on the writing system: For a 162: * left-to-right orientation, it is the same as {@link #WEST}, for 163: * a right-to-left orientation, it is the same as {@link #EAST}. 164: * 165: * @since 1.4 166: */ 167: public static final String LINE_START = BEFORE_LINE_BEGINS; 168: 169: 170: /** 171: * The constant indicating the position after the last item of the 172: * layout. The exact position depends on the writing system: For a 173: * left-to-right orientation, it is the same as {@link #EAST}, for 174: * a right-to-left orientation, it is the same as {@link #WEST}. 175: * 176: * @since 1.4 177: */ 178: public static final String LINE_END = AFTER_LINE_ENDS; 179: 180: 181: 182: // Serialization constant 183: private static final long serialVersionUID = -8658291919501921765L; 184: 185: /*************************************************************************/ 186: 187: /* 188: * Instance Variables 189: */ 190: 191: /** 192: * @serial 193: */ 194: private Component north; 195: 196: /** 197: * @serial 198: */ 199: private Component south; 200: 201: /** 202: * @serial 203: */ 204: private Component east; 205: 206: /** 207: * @serial 208: */ 209: private Component west; 210: 211: /** 212: * @serial 213: */ 214: private Component center; 215: 216: /** 217: * @serial 218: */ 219: private Component firstLine; 220: 221: /** 222: * @serial 223: */ 224: private Component lastLine; 225: 226: /** 227: * @serial 228: */ 229: private Component firstItem; 230: 231: /** 232: * @serial 233: */ 234: private Component lastItem; 235: 236: /** 237: * @serial The horizontal gap between components 238: */ 239: private int hgap; 240: 241: /** 242: * @serial The vertical gap between components 243: */ 244: private int vgap; 245: 246: /*************************************************************************/ 247: 248: /* 249: * Constructors 250: */ 251: 252: /** 253: * Initializes a new instance of <code>BorderLayout</code> with no 254: * horiztonal or vertical gaps between components. 255: */ 256: public 257: BorderLayout() 258: { 259: this(0,0); 260: } 261: 262: /*************************************************************************/ 263: 264: /** 265: * Initializes a new instance of <code>BorderLayout</code> with the 266: * specified horiztonal and vertical gaps between components. 267: * 268: * @param hgap The horizontal gap between components. 269: * @param vgap The vertical gap between components. 270: */ 271: public 272: BorderLayout(int hgap, int vgap) 273: { 274: this.hgap = hgap; 275: this.vgap = vgap; 276: } 277: 278: /*************************************************************************/ 279: 280: /* 281: * Instance Variables 282: */ 283: 284: /** 285: * Returns the horitzontal gap value. 286: * 287: * @return The horitzontal gap value. 288: */ 289: public int 290: getHgap() 291: { 292: return(hgap); 293: } 294: 295: /*************************************************************************/ 296: 297: /** 298: * Sets the horizontal gap to the specified value. 299: * 300: * @param hgap The new horizontal gap. 301: */ 302: public void 303: setHgap(int hgap) 304: { 305: this.hgap = hgap; 306: } 307: 308: /*************************************************************************/ 309: 310: /** 311: * Returns the vertical gap value. 312: * 313: * @return The vertical gap value. 314: */ 315: public int 316: getVgap() 317: { 318: return(vgap); 319: } 320: 321: /*************************************************************************/ 322: 323: /** 324: * Sets the vertical gap to the specified value. 325: * 326: * @param vgap The new vertical gap value. 327: */ 328: public void 329: setVgap(int vgap) 330: { 331: this.vgap = vgap; 332: } 333: 334: /*************************************************************************/ 335: 336: /** 337: * Adds a component to the layout in the specified constraint position, 338: * which must be one of the string constants defined in this class. 339: * 340: * @param component The component to add. 341: * @param constraints The constraint string. 342: * 343: * @exception IllegalArgumentException If the constraint object is not 344: * a string, or is not one of the specified constants in this class. 345: */ 346: public void 347: addLayoutComponent(Component component, Object constraints) 348: { 349: if (constraints != null && ! (constraints instanceof String)) 350: throw new IllegalArgumentException("Constraint must be a string"); 351: 352: addLayoutComponent((String) constraints, component); 353: } 354: 355: /*************************************************************************/ 356: 357: /** 358: * Adds a component to the layout in the specified constraint position, 359: * which must be one of the string constants defined in this class. 360: * 361: * @param constraints The constraint string. 362: * @param component The component to add. 363: * 364: * @exception IllegalArgumentException If the constraint object is not 365: * one of the specified constants in this class. 366: * 367: * @deprecated This method is deprecated in favor of 368: * <code>addLayoutComponent(Component, Object)</code>. 369: */ 370: public void 371: addLayoutComponent(String constraints, Component component) 372: { 373: String str = constraints; 374: 375: if (str == null || str.equals(CENTER)) 376: center = component; 377: else if (str.equals(NORTH)) 378: north = component; 379: else if (str.equals(SOUTH)) 380: south = component; 381: else if (str.equals(EAST)) 382: east = component; 383: else if (str.equals(WEST)) 384: west = component; 385: else if (str.equals(BEFORE_FIRST_LINE)) 386: firstLine = component; 387: else if (str.equals(AFTER_LAST_LINE)) 388: lastLine = component; 389: else if (str.equals(BEFORE_LINE_BEGINS)) 390: firstItem = component; 391: else if (str.equals(AFTER_LINE_ENDS)) 392: lastItem = component; 393: else 394: throw new IllegalArgumentException("Constraint value not valid: " + str); 395: } 396: 397: /*************************************************************************/ 398: 399: /** 400: * Removes the specified component from the layout. 401: * 402: * @param component The component to remove from the layout. 403: */ 404: public void 405: removeLayoutComponent(Component component) 406: { 407: if (north == component) 408: north = null; 409: if (south == component) 410: south = null; 411: if (east == component) 412: east = null; 413: if (west == component) 414: west = null; 415: if (center == component) 416: center = null; 417: if (firstItem == component) 418: firstItem = null; 419: if (lastItem == component) 420: lastItem = null; 421: if (firstLine == component) 422: firstLine = null; 423: if (lastLine == component) 424: lastLine = null; 425: } 426: 427: /*************************************************************************/ 428: 429: /** 430: * Returns the minimum size of the specified container using this layout. 431: * 432: * @param target The container to calculate the minimum size for. 433: * 434: * @return The minimum size of the container 435: */ 436: public Dimension 437: minimumLayoutSize(Container target) 438: { 439: return calcSize(target, MIN); 440: } 441: 442: /*************************************************************************/ 443: 444: /** 445: * Returns the preferred size of the specified container using this layout. 446: * 447: * @param target The container to calculate the preferred size for. 448: * 449: * @return The preferred size of the container 450: */ 451: public Dimension 452: preferredLayoutSize(Container target) 453: { 454: return calcSize(target, PREF); 455: } 456: 457: /*************************************************************************/ 458: 459: /** 460: * Returns the maximum size of the specified container using this layout. 461: * 462: * @param target The container to calculate the maximum size for. 463: * 464: * @return The maximum size of the container 465: */ 466: public Dimension 467: maximumLayoutSize(Container target) 468: { 469: return calcSize(target, MAX); 470: } 471: 472: /*************************************************************************/ 473: 474: /** 475: * Returns the X axis alignment, which is a <code>float</code> indicating 476: * where along the X axis this container wishs to position its layout. 477: * 0 indicates align to the left, 1 indicates align to the right, and 0.5 478: * indicates align to the center. 479: * 480: * @param parent The parent container. 481: * 482: * @return The X alignment value. 483: */ 484: public float 485: getLayoutAlignmentX(Container parent) 486: { 487: return(parent.getAlignmentX()); 488: } 489: 490: /*************************************************************************/ 491: 492: /** 493: * Returns the Y axis alignment, which is a <code>float</code> indicating 494: * where along the Y axis this container wishs to position its layout. 495: * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5 496: * indicates align to the center. 497: * 498: * @param parent The parent container. 499: * 500: * @return The Y alignment value. 501: */ 502: public float 503: getLayoutAlignmentY(Container parent) 504: { 505: return(parent.getAlignmentY()); 506: } 507: 508: /*************************************************************************/ 509: 510: /** 511: * Instructs this object to discard any layout information it might 512: * have cached. 513: * 514: * @param parent The parent container. 515: */ 516: public void 517: invalidateLayout(Container parent) 518: { 519: } 520: 521: /*************************************************************************/ 522: 523: /** 524: * Lays out the specified container according to the constraints 525: * in this object. 526: * 527: * @param target The container to lay out. 528: */ 529: public void 530: layoutContainer(Container target) 531: { 532: synchronized (target.getTreeLock ()) 533: { 534: Insets i = target.getInsets(); 535: 536: ComponentOrientation orient = target.getComponentOrientation (); 537: boolean left_to_right = orient.isLeftToRight (); 538: 539: Component my_north = north; 540: Component my_east = east; 541: Component my_south = south; 542: Component my_west = west; 543: 544: // Note that we currently don't handle vertical layouts. Neither 545: // does JDK 1.3. 546: if (firstLine != null) 547: my_north = firstLine; 548: if (lastLine != null) 549: my_south = lastLine; 550: if (firstItem != null) 551: { 552: if (left_to_right) 553: my_west = firstItem; 554: else 555: my_east = firstItem; 556: } 557: if (lastItem != null) 558: { 559: if (left_to_right) 560: my_east = lastItem; 561: else 562: my_west = lastItem; 563: } 564: 565: Dimension c = calcCompSize(center, PREF); 566: Dimension n = calcCompSize(my_north, PREF); 567: Dimension s = calcCompSize(my_south, PREF); 568: Dimension e = calcCompSize(my_east, PREF); 569: Dimension w = calcCompSize(my_west, PREF); 570: Dimension t = target.getSize(); 571: 572: /* 573: <-> hgap <-> hgap 574: +----------------------------+ } 575: |t | } i.top 576: | +----------------------+ | --- y1 } 577: | |n | | 578: | +----------------------+ | } vgap 579: | +---+ +----------+ +---+ | --- y2 } } 580: | |w | |c | |e | | } hh 581: | +---+ +----------+ +---+ | } vgap } 582: | +----------------------+ | --- y3 } 583: | |s | | 584: | +----------------------+ | } 585: | | } i.bottom 586: +----------------------------+ } 587: |x1 |x2 |x3 588: <----------------------> 589: <--> ww <--> 590: i.left i.right 591: */ 592: 593: int x1 = i.left; 594: int x2 = x1 + w.width + hgap; 595: int x3; 596: if (t.width <= i.right + e.width) 597: x3 = x2 + w.width + hgap; 598: else 599: x3 = t.width - i.right - e.width; 600: int ww = t.width - i.right - i.left; 601: 602: int y1 = i.top; 603: int y2 = y1 + n.height + vgap; 604: int midh = Math.max(e.height, Math.max(w.height, c.height)); 605: int y3; 606: if (t.height <= i.bottom + s.height) 607: y3 = y2 + midh + vgap; 608: else 609: y3 = t.height - i.bottom - s.height; 610: int hh = y3-y2-vgap; 611: 612: setBounds(center, x2, y2, x3-x2-hgap, hh); 613: setBounds(my_north, x1, y1, ww, n.height); 614: setBounds(my_south, x1, y3, ww, s.height); 615: setBounds(my_west, x1, y2, w.width, hh); 616: setBounds(my_east, x3, y2, e.width, hh); 617: } 618: } 619: 620: /*************************************************************************/ 621: 622: /** 623: * Returns a string representation of this layout manager. 624: * 625: * @return A string representation of this object. 626: */ 627: public String 628: toString() 629: { 630: return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; 631: } 632: 633: private void 634: setBounds(Component comp, int x, int y, int w, int h) 635: { 636: if (comp == null) 637: return; 638: comp.setBounds(x, y, w, h); 639: } 640: 641: // Some constants for use with calcSize(). 642: private static final int MIN = 0; 643: private static final int MAX = 1; 644: private static final int PREF = 2; 645: 646: private Dimension 647: calcCompSize(Component comp, int what) 648: { 649: if (comp == null || !comp.isVisible()) 650: return new Dimension(0, 0); 651: if (what == MIN) 652: return comp.getMinimumSize(); 653: else if (what == MAX) 654: return comp.getMaximumSize(); 655: return comp.getPreferredSize(); 656: } 657: 658: // This is a helper function used to compute the various sizes for 659: // this layout. 660: private Dimension 661: calcSize(Container target, int what) 662: { 663: synchronized (target.getTreeLock ()) 664: { 665: Insets ins = target.getInsets(); 666: 667: ComponentOrientation orient = target.getComponentOrientation (); 668: boolean left_to_right = orient.isLeftToRight (); 669: 670: Component my_north = north; 671: Component my_east = east; 672: Component my_south = south; 673: Component my_west = west; 674: 675: // Note that we currently don't handle vertical layouts. Neither 676: // does JDK 1.3. 677: if (firstLine != null) 678: my_north = firstLine; 679: if (lastLine != null) 680: my_south = lastLine; 681: if (firstItem != null) 682: { 683: if (left_to_right) 684: my_west = firstItem; 685: else 686: my_east = firstItem; 687: } 688: if (lastItem != null) 689: { 690: if (left_to_right) 691: my_east = lastItem; 692: else 693: my_west = lastItem; 694: } 695: 696: Dimension ndim = calcCompSize(my_north, what); 697: Dimension sdim = calcCompSize(my_south, what); 698: Dimension edim = calcCompSize(my_east, what); 699: Dimension wdim = calcCompSize(my_west, what); 700: Dimension cdim = calcCompSize(center, what); 701: 702: int width = edim.width + cdim.width + wdim.width + (hgap * 2); 703: // check for overflow 704: if (width < edim.width || width < cdim.width || width < cdim.width) 705: width = Integer.MAX_VALUE; 706: 707: if (ndim.width > width) 708: width = ndim.width; 709: if (sdim.width > width) 710: width = sdim.width; 711: 712: width += (ins.left + ins.right); 713: 714: int height = edim.height; 715: if (cdim.height > height) 716: height = cdim.height; 717: if (wdim.height > height) 718: height = wdim.height; 719: 720: int addedHeight = height + (ndim.height + sdim.height + (vgap * 2) 721: + ins.top + ins.bottom); 722: // check for overflow 723: if (addedHeight < height) 724: height = Integer.MAX_VALUE; 725: else 726: height = addedHeight; 727: 728: return(new Dimension(width, height)); 729: } 730: } 731: } // class BorderLayout
GNU Classpath (0.17) |