GNU Classpath (0.18) | ||
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: * Constant indicating the top of the container 53: */ 54: public static final String NORTH = "North"; 55: 56: /** 57: * Constant indicating the bottom of the container 58: */ 59: public static final String SOUTH = "South"; 60: 61: /** 62: * Constant indicating the right side of the container 63: */ 64: public static final String EAST = "East"; 65: 66: /** 67: * Constant indicating the left side of the container 68: */ 69: public static final String WEST = "West"; 70: 71: /** 72: * Constant indicating the center of the container 73: */ 74: public static final String CENTER = "Center"; 75: 76: 77: /** 78: * The constant indicating the position before the first line of the 79: * layout. The exact position depends on the writing system: For a 80: * top-to-bottom orientation, it is the same as {@link #NORTH}, for 81: * a bottom-to-top orientation, it is the same as {@link #SOUTH}. 82: * 83: * <p>This constant is an older name for {@link #PAGE_START} which 84: * has exactly the same value. 85: * 86: * @since 1.2 87: */ 88: public static final String BEFORE_FIRST_LINE = "First"; 89: 90: /** 91: * The constant indicating the position after the last line of the 92: * layout. The exact position depends on the writing system: For a 93: * top-to-bottom orientation, it is the same as {@link #SOUTH}, for 94: * a bottom-to-top orientation, it is the same as {@link #NORTH}. 95: * 96: * <p>This constant is an older name for {@link #PAGE_END} which 97: * has exactly the same value. 98: * 99: * @since 1.2 100: */ 101: public static final String AFTER_LAST_LINE = "Last"; 102: 103: /** 104: * The constant indicating the position before the first item of the 105: * layout. The exact position depends on the writing system: For a 106: * left-to-right orientation, it is the same as {@link #WEST}, for 107: * a right-to-left orientation, it is the same as {@link #EAST}. 108: * 109: * <p>This constant is an older name for {@link #LINE_START} which 110: * has exactly the same value. 111: * 112: * @since 1.2 113: */ 114: public static final String BEFORE_LINE_BEGINS = "Before"; 115: 116: /** 117: * The constant indicating the position after the last item of the 118: * layout. The exact position depends on the writing system: For a 119: * left-to-right orientation, it is the same as {@link #EAST}, for 120: * a right-to-left orientation, it is the same as {@link #WEST}. 121: * 122: * <p>This constant is an older name for {@link #LINE_END} which 123: * has exactly the same value. 124: * 125: * @since 1.2 126: */ 127: public static final String AFTER_LINE_ENDS = "After"; 128: 129: /** 130: * The constant indicating the position before the first line of the 131: * layout. The exact position depends on the writing system: For a 132: * top-to-bottom orientation, it is the same as {@link #NORTH}, for 133: * a bottom-to-top orientation, it is the same as {@link #SOUTH}. 134: * 135: * @since 1.4 136: */ 137: public static final String PAGE_START = BEFORE_FIRST_LINE; 138: 139: /** 140: * The constant indicating the position after the last line of the 141: * layout. The exact position depends on the writing system: For a 142: * top-to-bottom orientation, it is the same as {@link #SOUTH}, for 143: * a bottom-to-top orientation, it is the same as {@link #NORTH}. 144: * 145: * @since 1.4 146: */ 147: public static final String PAGE_END = AFTER_LAST_LINE; 148: 149: /** 150: * The constant indicating the position before the first item of the 151: * layout. The exact position depends on the writing system: For a 152: * left-to-right orientation, it is the same as {@link #WEST}, for 153: * a right-to-left orientation, it is the same as {@link #EAST}. 154: * 155: * @since 1.4 156: */ 157: public static final String LINE_START = BEFORE_LINE_BEGINS; 158: 159: /** 160: * The constant indicating the position after the last 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 #EAST}, for 163: * a right-to-left orientation, it is the same as {@link #WEST}. 164: * 165: * @since 1.4 166: */ 167: public static final String LINE_END = AFTER_LINE_ENDS; 168: 169: 170: /** 171: * Serialization constant. 172: */ 173: private static final long serialVersionUID = -8658291919501921765L; 174: 175: 176: /** 177: * @serial 178: */ 179: private Component north; 180: 181: /** 182: * @serial 183: */ 184: private Component south; 185: 186: /** 187: * @serial 188: */ 189: private Component east; 190: 191: /** 192: * @serial 193: */ 194: private Component west; 195: 196: /** 197: * @serial 198: */ 199: private Component center; 200: 201: /** 202: * @serial 203: */ 204: private Component firstLine; 205: 206: /** 207: * @serial 208: */ 209: private Component lastLine; 210: 211: /** 212: * @serial 213: */ 214: private Component firstItem; 215: 216: /** 217: * @serial 218: */ 219: private Component lastItem; 220: 221: /** 222: * @serial The horizontal gap between components 223: */ 224: private int hgap; 225: 226: /** 227: * @serial The vertical gap between components 228: */ 229: private int vgap; 230: 231: 232: /** 233: * Initializes a new instance of <code>BorderLayout</code> with no 234: * horiztonal or vertical gaps between components. 235: */ 236: public BorderLayout() 237: { 238: this(0,0); 239: } 240: 241: /** 242: * Initializes a new instance of <code>BorderLayout</code> with the 243: * specified horiztonal and vertical gaps between components. 244: * 245: * @param hgap The horizontal gap between components. 246: * @param vgap The vertical gap between components. 247: */ 248: public BorderLayout(int hgap, int vgap) 249: { 250: this.hgap = hgap; 251: this.vgap = vgap; 252: } 253: 254: /** 255: * Returns the horitzontal gap value. 256: * 257: * @return The horitzontal gap value. 258: */ 259: public int getHgap() 260: { 261: return(hgap); 262: } 263: 264: /** 265: * Sets the horizontal gap to the specified value. 266: * 267: * @param hgap The new horizontal gap. 268: */ 269: public void setHgap(int hgap) 270: { 271: this.hgap = hgap; 272: } 273: 274: /** 275: * Returns the vertical gap value. 276: * 277: * @return The vertical gap value. 278: */ 279: public int getVgap() 280: { 281: return(vgap); 282: } 283: 284: /** 285: * Sets the vertical gap to the specified value. 286: * 287: * @param vgap The new vertical gap value. 288: */ 289: public void setVgap(int vgap) 290: { 291: this.vgap = vgap; 292: } 293: 294: /** 295: * Adds a component to the layout in the specified constraint position, 296: * which must be one of the string constants defined in this class. 297: * 298: * @param component The component to add. 299: * @param constraints The constraint string. 300: * 301: * @exception IllegalArgumentException If the constraint object is not 302: * a string, or is not one of the specified constants in this class. 303: */ 304: public void addLayoutComponent(Component component, Object constraints) 305: { 306: if (constraints != null && ! (constraints instanceof String)) 307: throw new IllegalArgumentException("Constraint must be a string"); 308: 309: addLayoutComponent((String) constraints, component); 310: } 311: 312: /** 313: * Adds a component to the layout in the specified constraint position, 314: * which must be one of the string constants defined in this class. 315: * 316: * @param constraints The constraint string. 317: * @param component The component to add. 318: * 319: * @exception IllegalArgumentException If the constraint object is not 320: * one of the specified constants in this class. 321: * 322: * @deprecated This method is deprecated in favor of 323: * <code>addLayoutComponent(Component, Object)</code>. 324: */ 325: public void addLayoutComponent(String constraints, Component component) 326: { 327: String str = constraints; 328: 329: if (str == null || str.equals(CENTER)) 330: center = component; 331: else if (str.equals(NORTH)) 332: north = component; 333: else if (str.equals(SOUTH)) 334: south = component; 335: else if (str.equals(EAST)) 336: east = component; 337: else if (str.equals(WEST)) 338: west = component; 339: else if (str.equals(BEFORE_FIRST_LINE)) 340: firstLine = component; 341: else if (str.equals(AFTER_LAST_LINE)) 342: lastLine = component; 343: else if (str.equals(BEFORE_LINE_BEGINS)) 344: firstItem = component; 345: else if (str.equals(AFTER_LINE_ENDS)) 346: lastItem = component; 347: else 348: throw new IllegalArgumentException("Constraint value not valid: " + str); 349: } 350: 351: /** 352: * Removes the specified component from the layout. 353: * 354: * @param component The component to remove from the layout. 355: */ 356: public void removeLayoutComponent(Component component) 357: { 358: if (north == component) 359: north = null; 360: if (south == component) 361: south = null; 362: if (east == component) 363: east = null; 364: if (west == component) 365: west = null; 366: if (center == component) 367: center = null; 368: if (firstItem == component) 369: firstItem = null; 370: if (lastItem == component) 371: lastItem = null; 372: if (firstLine == component) 373: firstLine = null; 374: if (lastLine == component) 375: lastLine = null; 376: } 377: 378: /** 379: * Returns the minimum size of the specified container using this layout. 380: * 381: * @param target The container to calculate the minimum size for. 382: * 383: * @return The minimum size of the container 384: */ 385: public Dimension minimumLayoutSize(Container target) 386: { 387: return calcSize(target, MIN); 388: } 389: 390: /** 391: * Returns the preferred size of the specified container using this layout. 392: * 393: * @param target The container to calculate the preferred size for. 394: * 395: * @return The preferred size of the container 396: */ 397: public Dimension preferredLayoutSize(Container target) 398: { 399: return calcSize(target, PREF); 400: } 401: 402: /** 403: * Returns the maximum size of the specified container using this layout. 404: * 405: * @param target The container to calculate the maximum size for. 406: * 407: * @return The maximum size of the container 408: */ 409: public Dimension maximumLayoutSize(Container target) 410: { 411: return calcSize(target, MAX); 412: } 413: 414: /** 415: * Returns the X axis alignment, which is a <code>float</code> indicating 416: * where along the X axis this container wishs to position its layout. 417: * 0 indicates align to the left, 1 indicates align to the right, and 0.5 418: * indicates align to the center. 419: * 420: * @param parent The parent container. 421: * 422: * @return The X alignment value. 423: */ 424: public float getLayoutAlignmentX(Container parent) 425: { 426: return(parent.getAlignmentX()); 427: } 428: 429: /** 430: * Returns the Y axis alignment, which is a <code>float</code> indicating 431: * where along the Y axis this container wishs to position its layout. 432: * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5 433: * indicates align to the center. 434: * 435: * @param parent The parent container. 436: * 437: * @return The Y alignment value. 438: */ 439: public float getLayoutAlignmentY(Container parent) 440: { 441: return(parent.getAlignmentY()); 442: } 443: 444: /** 445: * Instructs this object to discard any layout information it might 446: * have cached. 447: * 448: * @param parent The parent container. 449: */ 450: public void invalidateLayout(Container parent) 451: { 452: // FIXME: Implement this properly! 453: } 454: 455: /** 456: * Lays out the specified container according to the constraints 457: * in this object. 458: * 459: * @param target The container to lay out. 460: */ 461: public void layoutContainer(Container target) 462: { 463: synchronized (target.getTreeLock ()) 464: { 465: Insets i = target.getInsets(); 466: 467: ComponentOrientation orient = target.getComponentOrientation (); 468: boolean left_to_right = orient.isLeftToRight (); 469: 470: Component my_north = north; 471: Component my_east = east; 472: Component my_south = south; 473: Component my_west = west; 474: 475: // Note that we currently don't handle vertical layouts. Neither 476: // does JDK 1.3. 477: if (firstLine != null) 478: my_north = firstLine; 479: if (lastLine != null) 480: my_south = lastLine; 481: if (firstItem != null) 482: { 483: if (left_to_right) 484: my_west = firstItem; 485: else 486: my_east = firstItem; 487: } 488: if (lastItem != null) 489: { 490: if (left_to_right) 491: my_east = lastItem; 492: else 493: my_west = lastItem; 494: } 495: 496: Dimension c = calcCompSize(center, PREF); 497: Dimension n = calcCompSize(my_north, PREF); 498: Dimension s = calcCompSize(my_south, PREF); 499: Dimension e = calcCompSize(my_east, PREF); 500: Dimension w = calcCompSize(my_west, PREF); 501: int targetWidth = target.getWidth(); 502: int targetHeight = target.getHeight(); 503: 504: /* 505: <-> hgap <-> hgap 506: +----------------------------+ } 507: |t | } i.top 508: | +----------------------+ | --- y1 } 509: | |n | | 510: | +----------------------+ | } vgap 511: | +---+ +----------+ +---+ | --- y2 } } 512: | |w | |c | |e | | } hh 513: | +---+ +----------+ +---+ | } vgap } 514: | +----------------------+ | --- y3 } 515: | |s | | 516: | +----------------------+ | } 517: | | } i.bottom 518: +----------------------------+ } 519: |x1 |x2 |x3 520: <----------------------> 521: <--> ww <--> 522: i.left i.right 523: */ 524: 525: int x1 = i.left; 526: int x2 = x1 + w.width + (w.width == 0 ? 0 : hgap); 527: int x3; 528: if (targetWidth <= i.right + e.width) 529: x3 = x2 + w.width + (w.width == 0 ? 0 : hgap); 530: else 531: x3 = targetWidth - i.right - e.width; 532: int ww = targetWidth - i.right - i.left; 533: 534: int y1 = i.top; 535: int y2 = y1 + n.height + (n.height == 0 ? 0 : vgap); 536: int midh = Math.max(e.height, Math.max(w.height, c.height)); 537: int y3; 538: if (targetHeight <= i.bottom + s.height) 539: y3 = y2 + midh + vgap; 540: else 541: y3 = targetHeight - i.bottom - s.height; 542: int hh = y3-y2-(s.height == 0 ? 0 : vgap); 543: 544: setBounds(center, x2, y2, x3-x2-(w.width == 0 ? 0 : hgap), hh); 545: setBounds(my_north, x1, y1, ww, n.height); 546: setBounds(my_south, x1, y3, ww, s.height); 547: setBounds(my_west, x1, y2, w.width, hh); 548: setBounds(my_east, x3, y2, e.width, hh); 549: } 550: } 551: 552: /** 553: * Returns a string representation of this layout manager. 554: * 555: * @return A string representation of this object. 556: */ 557: public String toString() 558: { 559: return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; 560: } 561: 562: /** 563: * FIXME: Document me! 564: */ 565: private void setBounds(Component comp, int x, int y, int w, int h) 566: { 567: if (comp == null) 568: return; 569: comp.setBounds(x, y, w, h); 570: } 571: 572: // FIXME: Maybe move to top of file. 573: // Some constants for use with calcSize(). 574: private static final int MIN = 0; 575: private static final int MAX = 1; 576: private static final int PREF = 2; 577: 578: private Dimension calcCompSize(Component comp, int what) 579: { 580: if (comp == null || !comp.isVisible()) 581: return new Dimension(0, 0); 582: if (what == MIN) 583: return comp.getMinimumSize(); 584: else if (what == MAX) 585: return comp.getMaximumSize(); 586: return comp.getPreferredSize(); 587: } 588: 589: /** 590: * This is a helper function used to compute the various sizes for 591: * this layout. 592: */ 593: private Dimension calcSize(Container target, int what) 594: { 595: synchronized (target.getTreeLock ()) 596: { 597: Insets ins = target.getInsets(); 598: 599: ComponentOrientation orient = target.getComponentOrientation (); 600: boolean left_to_right = orient.isLeftToRight (); 601: 602: Component my_north = north; 603: Component my_east = east; 604: Component my_south = south; 605: Component my_west = west; 606: 607: // Note that we currently don't handle vertical layouts. Neither 608: // does JDK 1.3. 609: if (firstLine != null) 610: my_north = firstLine; 611: if (lastLine != null) 612: my_south = lastLine; 613: if (firstItem != null) 614: { 615: if (left_to_right) 616: my_west = firstItem; 617: else 618: my_east = firstItem; 619: } 620: if (lastItem != null) 621: { 622: if (left_to_right) 623: my_east = lastItem; 624: else 625: my_west = lastItem; 626: } 627: 628: Dimension ndim = calcCompSize(my_north, what); 629: Dimension sdim = calcCompSize(my_south, what); 630: Dimension edim = calcCompSize(my_east, what); 631: Dimension wdim = calcCompSize(my_west, what); 632: Dimension cdim = calcCompSize(center, what); 633: 634: int width = edim.width + cdim.width + wdim.width + (hgap * 2); 635: // Check for overflow. 636: if (width < edim.width || width < cdim.width || width < cdim.width) 637: width = Integer.MAX_VALUE; 638: 639: if (ndim.width > width) 640: width = ndim.width; 641: if (sdim.width > width) 642: width = sdim.width; 643: 644: width += (ins.left + ins.right); 645: 646: int height = edim.height; 647: if (cdim.height > height) 648: height = cdim.height; 649: if (wdim.height > height) 650: height = wdim.height; 651: 652: int addedHeight = height + (ndim.height + sdim.height + (vgap * 2) 653: + ins.top + ins.bottom); 654: // Check for overflow. 655: if (addedHeight < height) 656: height = Integer.MAX_VALUE; 657: else 658: height = addedHeight; 659: 660: return(new Dimension(width, height)); 661: } 662: } 663: }
GNU Classpath (0.18) |