GNU Classpath (0.20) | |
Frames | No Frames |
1: /* FlowLayout.java -- Grid-based layout engine 2: Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation 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: import java.io.Serializable; 42: 43: /** This class implements a flow-based layout. Components are laid 44: * out in order from left to right. When a component cannot be placed 45: * without horizontal clipping, a new row is started. This class 46: * supports horizontal and vertical gaps. These are used for spacing 47: * between components. 48: * 49: * @author Tom Tromey (tromey@redhat.com) 50: * @author Aaron M. Renn (arenn@urbanophile.com) 51: */ 52: public class FlowLayout implements LayoutManager, Serializable 53: { 54: /** Constant that specifies left alignment. */ 55: public static final int LEFT = 0; 56: /** Constant that specifies center alignment. */ 57: public static final int CENTER = 1; 58: /** Constant that specifies right alignment. */ 59: public static final int RIGHT = 2; 60: 61: /** Constant that specifies alignment to leading edge of container's 62: * orientation. */ 63: public static final int LEADING = 3; 64: /** Constant that specifies alignment to trailing edge of container's 65: * orientation. */ 66: public static final int TRAILING = 4; 67: 68: // Serialization constant 69: private static final long serialVersionUID = -7262534875583282631L; 70: 71: /** 72: * Add a new component to the layout. This particular implementation 73: * does nothing. 74: * 75: * @param name the name 76: * @param comp the component 77: */ 78: public void addLayoutComponent (String name, Component comp) 79: { 80: // Nothing. 81: } 82: 83: /** 84: * Returns the current justification value for this object. 85: * 86: * @return The current justification value for this object. 87: */ 88: public int getAlignment () 89: { 90: return align; 91: } 92: 93: /** 94: * Returns the horizontal gap between components. 95: * 96: * @return The horizontal gap between components. 97: */ 98: public int getHgap () 99: { 100: return hgap; 101: } 102: 103: /** 104: * Returns the vertical gap between lines of components. 105: * 106: * @return The vertical gap between lines of components. 107: */ 108: public int getVgap () 109: { 110: return vgap; 111: } 112: 113: /** 114: * Initializes a new instance of <code>FlowLayout</code> with a center 115: * justification and a default horizontal and vertical gap of 5. 116: */ 117: public FlowLayout () 118: { 119: this (CENTER, 5, 5); 120: } 121: 122: /** 123: * Initializes a new instance of <code>FlowLayout</code> with the specified 124: * justification and a default horizontal and vertical gap of 5. 125: * 126: * @param align The justification setting, which should be one of the 127: * contants in this class. 128: */ 129: public FlowLayout (int align) 130: { 131: this (align, 5, 5); 132: } 133: 134: /** 135: * Initializes a new instance of <code>FlowLayout</code> with the specified 136: * justification and gap values 137: * @param align Alignment 138: * @param hgap The horizontal gap 139: * @param vgap The vertical gap 140: * @exception IllegalArgumentException If either gap is negative 141: */ 142: public FlowLayout (int align, int hgap, int vgap) 143: { 144: // Use methods to set fields so that we can have all the checking 145: // in one place. 146: setVgap (vgap); 147: setHgap (hgap); 148: setAlignment (align); 149: } 150: 151: /** Lay out the container's components based on current settings. 152: * @param parent The parent container 153: */ 154: public void layoutContainer (Container parent) 155: { 156: synchronized (parent.getTreeLock ()) 157: { 158: int num = parent.getComponentCount (); 159: // This is more efficient than calling getComponents(). 160: Component[] comps = parent.component; 161: 162: Dimension d = parent.getSize (); 163: Insets ins = parent.getInsets (); 164: 165: ComponentOrientation orient = parent.getComponentOrientation (); 166: boolean left_to_right = orient.isLeftToRight (); 167: 168: int y = ins.top + vgap; 169: int i = 0; 170: while (i < num) 171: { 172: // Find the components which go in the current row. 173: int new_w = ins.left + hgap + ins.right; 174: int new_h = 0; 175: int j; 176: boolean found_one = false; 177: for (j = i; j < num; ++j) 178: { 179: // Skip invisible items. 180: if (! comps[j].visible) 181: continue; 182: 183: Dimension c = comps[j].getPreferredSize (); 184: 185: int next_w = new_w + hgap + c.width; 186: if (next_w <= d.width || ! found_one) 187: { 188: new_w = next_w; 189: new_h = Math.max (new_h, c.height); 190: found_one = true; 191: } 192: else 193: { 194: // Must start a new row, and we already found an item 195: break; 196: } 197: } 198: 199: // Set the location of each component for this row. 200: int x; 201: 202: int myalign = align; 203: if (align == LEADING) 204: myalign = left_to_right ? LEFT : RIGHT; 205: else if (align == TRAILING) 206: myalign = left_to_right ? RIGHT : LEFT; 207: 208: if (myalign == RIGHT) 209: x = ins.left + (d.width - new_w) + hgap; 210: else if (myalign == CENTER) 211: x = ins.left + (d.width - new_w) / 2 + hgap; 212: else // LEFT and all other values of align. 213: x = ins.left + hgap; 214: 215: for (int k = i; k < j; ++k) 216: { 217: if (comps[k].visible) 218: { 219: Dimension c = comps[k].getPreferredSize (); 220: comps[k].setBounds (x, y + (new_h - c.height) / 2, 221: c.width, c.height); 222: x += c.width + hgap; 223: } 224: } 225: 226: // Advance to next row. 227: i = j; 228: y += new_h + vgap; 229: } 230: } 231: } 232: 233: /** 234: * Returns the minimum layout size for the specified container using 235: * this layout. 236: * @param cont The parent container 237: * @return The minimum layout size. 238: */ 239: public Dimension minimumLayoutSize (Container cont) 240: { 241: return getSize (cont, true); 242: } 243: 244: /** 245: * Returns the preferred layout size for the specified container using 246: * this layout. 247: * @param cont The parent container 248: * @return The preferred layout size. 249: */ 250: public Dimension preferredLayoutSize (Container cont) 251: { 252: return getSize (cont, false); 253: } 254: 255: /** Remove the indicated component from this layout manager. 256: * This particular implementation does nothing. 257: * @param comp The component to remove 258: */ 259: public void removeLayoutComponent (Component comp) 260: { 261: // Nothing. 262: } 263: 264: /** 265: * Sets the justification value for this object to the specified value. 266: * 267: * @param align The new justification value for this object, which must 268: * be one of the constants in this class. 269: */ 270: public void setAlignment (int align) 271: { 272: // The JDK accepts invalid values and treats them as 273: // LEFT during layout, so do we. The invalid value is even stored, 274: // getAlignment() returns the same invalid value. 275: this.align = align; 276: } 277: 278: /** 279: * Sets the horizontal gap between components to the specified value. 280: * 281: * @param hgap The new horizontal gap between components. 282: */ 283: public void setHgap (int hgap) 284: { 285: if (hgap < 0) 286: throw new IllegalArgumentException ("horizontal gap must be nonnegative"); 287: this.hgap = hgap; 288: } 289: 290: /** 291: * Sets the vertical gap between lines of components to the specified value. 292: * 293: * @param vgap The new vertical gap. 294: */ 295: public void setVgap (int vgap) 296: { 297: if (vgap < 0) 298: throw new IllegalArgumentException ("vertical gap must be nonnegative"); 299: this.vgap = vgap; 300: } 301: 302: /** Return String description of this object. 303: * @return A string representation of this object. 304: */ 305: public String toString () 306: { 307: return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap 308: + ",align=" + align + "]"); 309: } 310: 311: // This method is used to compute the various sizes. 312: private Dimension getSize (Container parent, boolean is_min) 313: { 314: synchronized (parent.getTreeLock ()) 315: { 316: int w, h, num = parent.getComponentCount (); 317: // This is more efficient than calling getComponents(). 318: Component[] comps = parent.component; 319: 320: w = 0; 321: h = 0; 322: for (int i = 0; i < num; ++i) 323: { 324: if (! comps[i].visible) 325: continue; 326: 327: // FIXME: can we just directly read the fields in Component? 328: // Or will that not work with subclassing? 329: Dimension d; 330: 331: if (is_min) 332: d = comps[i].getMinimumSize (); 333: else 334: d = comps[i].getPreferredSize (); 335: 336: w += d.width; 337: h = Math.max (d.height, h); 338: } 339: 340: Insets ins = parent.getInsets (); 341: 342: w += (num + 1) * hgap + ins.left + ins.right; 343: h += 2 * vgap + ins.top + ins.bottom; 344: 345: return new Dimension (w, h); 346: } 347: } 348: 349: /** 350: * @serial The justification alignment of the lines of components, which 351: * will be one of the constants defined in this class. 352: */ 353: private int align; 354: 355: /** 356: * @serial The horizontal gap between components. 357: */ 358: private int hgap; 359: 360: /** 361: * @serial The vertical gap between lines of components. 362: */ 363: private int vgap; 364: }
GNU Classpath (0.20) |