Frames | No Frames |
1: /* OverlayLayout.java -- A layout manager 2: Copyright (C) 2002, 2004, 2005, 2006, 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: package javax.swing; 39: 40: import java.awt.AWTError; 41: import java.awt.Component; 42: import java.awt.Container; 43: import java.awt.Dimension; 44: import java.awt.Insets; 45: import java.awt.LayoutManager2; 46: import java.io.Serializable; 47: 48: /** 49: * A layout manager that lays out the components of a container one over 50: * another. 51: * 52: * The components take as much space as is available in the container, but not 53: * more than specified by their maximum size. 54: * 55: * The overall layout is mainly affected by the components 56: * <code>alignmentX</code> and <code>alignmentY</code> properties. All 57: * components are aligned, so that their alignment points (for either 58: * direction) are placed in one line (the baseline for this direction). 59: * 60: * For example: An X alignment of 0.0 means that the component's alignment 61: * point is at it's left edge, an X alignment of 0.5 means that the alignment 62: * point is in the middle, an X alignment of 1.0 means, the aligment point is 63: * at the right edge. So if you have three components, the first with 0.0, the 64: * second with 0.5 and the third with 1.0, then they are laid out like this: 65: * 66: * <pre> 67: * +-------+ 68: * | 1 | 69: * +-------+ 70: * +-------+ 71: * | 2 | 72: * +-------+ 73: * +---------+ 74: * | 3 + 75: * +---------+ 76: * </pre> 77: * The above picture shows the X alignment between the components. An Y 78: * alignment like shown above cannot be achieved with this layout manager. The 79: * components are place on top of each other, with the X alignment shown above. 80: * 81: * @author Roman Kennke (kennke@aicas.com) 82: * @author Andrew Selkirk 83: */ 84: public class OverlayLayout implements LayoutManager2, Serializable 85: { 86: private static final long serialVersionUID = 18082829169631543L; 87: 88: /** 89: * The container to be laid out. 90: */ 91: private Container target; 92: 93: /** 94: * The size requirements of the containers children for the X direction. 95: */ 96: private SizeRequirements[] xChildren; 97: 98: /** 99: * The size requirements of the containers children for the Y direction. 100: */ 101: private SizeRequirements[] yChildren; 102: 103: /** 104: * The size requirements of the container to be laid out for the X direction. 105: */ 106: private SizeRequirements xTotal; 107: 108: /** 109: * The size requirements of the container to be laid out for the Y direction. 110: */ 111: private SizeRequirements yTotal; 112: 113: /** 114: * The offsets of the child components in the X direction. 115: */ 116: private int[] offsetsX; 117: 118: /** 119: * The offsets of the child components in the Y direction. 120: */ 121: private int[] offsetsY; 122: 123: /** 124: * The spans of the child components in the X direction. 125: */ 126: private int[] spansX; 127: 128: /** 129: * The spans of the child components in the Y direction. 130: */ 131: private int[] spansY; 132: 133: /** 134: * Creates a new OverlayLayout for the specified container. 135: * 136: * @param target the container to be laid out 137: */ 138: public OverlayLayout(Container target) 139: { 140: this.target = target; 141: } 142: 143: /** 144: * Notifies the layout manager that the layout has become invalid. It throws 145: * away cached layout information and recomputes it the next time it is 146: * requested. 147: * 148: * @param target not used here 149: */ 150: public void invalidateLayout(Container target) 151: { 152: xChildren = null; 153: yChildren = null; 154: xTotal = null; 155: yTotal = null; 156: offsetsX = null; 157: offsetsY = null; 158: spansX = null; 159: spansY = null; 160: } 161: 162: /** 163: * This method is not used in this layout manager. 164: * 165: * @param string not used here 166: * @param component not used here 167: */ 168: public void addLayoutComponent(String string, Component component) 169: { 170: // Nothing to do here. 171: } 172: 173: /** 174: * This method is not used in this layout manager. 175: * 176: * @param component not used here 177: * @param constraints not used here 178: */ 179: public void addLayoutComponent(Component component, Object constraints) 180: { 181: // Nothing to do here. 182: } 183: 184: /** 185: * This method is not used in this layout manager. 186: * 187: * @param component not used here 188: */ 189: public void removeLayoutComponent(Component component) 190: { 191: // Nothing to do here. 192: } 193: 194: /** 195: * Returns the preferred size of the container that is laid out. This is 196: * computed by the children's preferred sizes, taking their alignments into 197: * account. 198: * 199: * @param target not used here 200: * 201: * @return the preferred size of the container that is laid out 202: */ 203: public Dimension preferredLayoutSize(Container target) 204: { 205: if (target != this.target) 206: throw new AWTError("OverlayLayout can't be shared"); 207: 208: checkTotalRequirements(); 209: return new Dimension(xTotal.preferred, yTotal.preferred); 210: } 211: 212: /** 213: * Returns the minimum size of the container that is laid out. This is 214: * computed by the children's minimum sizes, taking their alignments into 215: * account. 216: * 217: * @param target not used here 218: * 219: * @return the minimum size of the container that is laid out 220: */ 221: public Dimension minimumLayoutSize(Container target) 222: { 223: if (target != this.target) 224: throw new AWTError("OverlayLayout can't be shared"); 225: 226: checkTotalRequirements(); 227: return new Dimension(xTotal.minimum, yTotal.minimum); 228: } 229: 230: /** 231: * Returns the maximum size of the container that is laid out. This is 232: * computed by the children's maximum sizes, taking their alignments into 233: * account. 234: * 235: * @param target not used here 236: * 237: * @return the maximum size of the container that is laid out 238: */ 239: public Dimension maximumLayoutSize(Container target) 240: { 241: if (target != this.target) 242: throw new AWTError("OverlayLayout can't be shared"); 243: 244: checkTotalRequirements(); 245: return new Dimension(xTotal.maximum, yTotal.maximum); 246: } 247: 248: /** 249: * Returns the X alignment of the container that is laid out. This is 250: * computed by the children's preferred sizes, taking their alignments into 251: * account. 252: * 253: * @param target not used here 254: * 255: * @return the X alignment of the container that is laid out 256: */ 257: public float getLayoutAlignmentX(Container target) 258: { 259: if (target != this.target) 260: throw new AWTError("OverlayLayout can't be shared"); 261: 262: checkTotalRequirements(); 263: return xTotal.alignment; 264: } 265: 266: /** 267: * Returns the Y alignment of the container that is laid out. This is 268: * computed by the children's preferred sizes, taking their alignments into 269: * account. 270: * 271: * @param target not used here 272: * 273: * @return the X alignment of the container that is laid out 274: */ 275: public float getLayoutAlignmentY(Container target) 276: { 277: if (target != this.target) 278: throw new AWTError("OverlayLayout can't be shared"); 279: 280: checkTotalRequirements(); 281: return yTotal.alignment; 282: } 283: 284: /** 285: * Lays out the container and it's children. 286: * 287: * The children are laid out one over another. 288: * 289: * The components take as much space as is available in the container, but 290: * not more than specified by their maximum size. 291: * 292: * The overall layout is mainly affected by the components 293: * <code>alignmentX</code> and <code>alignmentY</code> properties. All 294: * components are aligned, so that their alignment points (for either 295: * direction) are placed in one line (the baseline for this direction). 296: * 297: * For example: An X alignment of 0.0 means that the component's alignment 298: * point is at it's left edge, an X alignment of 0.5 means that the alignment 299: * point is in the middle, an X alignment of 1.0 means, the aligment point is 300: * at the right edge. So if you have three components, the first with 0.0, 301: * the second with 0.5 and the third with 1.0, then they are laid out like 302: * this: 303: * 304: * <pre> 305: * +-------+ 306: * | 1 | 307: * +-------+ 308: * +-------+ 309: * | 2 | 310: * +-------+ 311: * +---------+ 312: * | 3 + 313: * +---------+ 314: * </pre> 315: * The above picture shows the X alignment between the components. An Y 316: * alignment like shown above cannot be achieved with this layout manager. 317: * The components are place on top of each other, with the X alignment shown 318: * above. 319: * 320: * @param target not used here 321: */ 322: public void layoutContainer(Container target) 323: { 324: if (target != this.target) 325: throw new AWTError("OverlayLayout can't be shared"); 326: 327: checkLayout(); 328: Component[] children = target.getComponents(); 329: for (int i = 0; i < children.length; i++) 330: children[i].setBounds(offsetsX[i], offsetsY[i], spansX[i], spansY[i]); 331: } 332: 333: /** 334: * Makes sure that the xChildren and yChildren fields are correctly set up. 335: * A call to {@link #invalidateLayout(Container)} sets these fields to null, 336: * so they have to be set up again. 337: */ 338: private void checkRequirements() 339: { 340: if (xChildren == null || yChildren == null) 341: { 342: Component[] children = target.getComponents(); 343: xChildren = new SizeRequirements[children.length]; 344: yChildren = new SizeRequirements[children.length]; 345: for (int i = 0; i < children.length; i++) 346: { 347: if (! children[i].isVisible()) 348: { 349: xChildren[i] = new SizeRequirements(); 350: yChildren[i] = new SizeRequirements(); 351: } 352: else 353: { 354: xChildren[i] = 355: new SizeRequirements(children[i].getMinimumSize().width, 356: children[i].getPreferredSize().width, 357: children[i].getMaximumSize().width, 358: children[i].getAlignmentX()); 359: yChildren[i] = 360: new SizeRequirements(children[i].getMinimumSize().height, 361: children[i].getPreferredSize().height, 362: children[i].getMaximumSize().height, 363: children[i].getAlignmentY()); 364: } 365: } 366: } 367: } 368: 369: /** 370: * Makes sure that the xTotal and yTotal fields are set up correctly. A call 371: * to {@link #invalidateLayout} sets these fields to null and they have to be 372: * recomputed. 373: */ 374: private void checkTotalRequirements() 375: { 376: if (xTotal == null || yTotal == null) 377: { 378: checkRequirements(); 379: xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren); 380: yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren); 381: } 382: } 383: 384: /** 385: * Makes sure that the offsetsX, offsetsY, spansX and spansY fields are set 386: * up correctly. A call to {@link #invalidateLayout} sets these fields 387: * to null and they have to be recomputed. 388: */ 389: private void checkLayout() 390: { 391: if (offsetsX == null || offsetsY == null || spansX == null 392: || spansY == null) 393: { 394: checkRequirements(); 395: checkTotalRequirements(); 396: int len = target.getComponents().length; 397: offsetsX = new int[len]; 398: offsetsY = new int[len]; 399: spansX = new int[len]; 400: spansY = new int[len]; 401: 402: Insets in = target.getInsets(); 403: int width = target.getWidth() - in.left - in.right; 404: int height = target.getHeight() - in.top - in.bottom; 405: 406: SizeRequirements.calculateAlignedPositions(width, xTotal, 407: xChildren, offsetsX, spansX); 408: SizeRequirements.calculateAlignedPositions(height, yTotal, 409: yChildren, offsetsY, spansY); 410: } 411: } 412: }