| /* FlowLayout.java -- Grid-based layout engine |
| Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package java.awt; |
| |
| import java.io.Serializable; |
| |
| /** This class implements a flow-based layout. Components are laid |
| * out in order from left to right. When a component cannot be placed |
| * without horizontal clipping, a new row is started. This class |
| * supports horizontal and vertical gaps. These are used for spacing |
| * between components. |
| * |
| * @author Tom Tromey (tromey@redhat.com) |
| * @author Aaron M. Renn (arenn@urbanophile.com) |
| */ |
| public class FlowLayout implements LayoutManager, Serializable |
| { |
| /** Constant that specifies left alignment. */ |
| public static final int LEFT = 0; |
| /** Constant that specifies center alignment. */ |
| public static final int CENTER = 1; |
| /** Constant that specifies right alignment. */ |
| public static final int RIGHT = 2; |
| |
| /** Constant that specifies alignment to leading edge of container's |
| * orientation. */ |
| public static final int LEADING = 3; |
| /** Constant that specifies alignment to trailing edge of container's |
| * orientation. */ |
| public static final int TRAILING = 4; |
| |
| // Serialization constant |
| private static final long serialVersionUID = -7262534875583282631L; |
| |
| /** |
| * Add a new component to the layout. This particular implementation |
| * does nothing. |
| * |
| * @param name the name |
| * @param comp the component |
| */ |
| public void addLayoutComponent (String name, Component comp) |
| { |
| // Nothing. |
| } |
| |
| /** |
| * Returns the current justification value for this object. |
| * |
| * @return The current justification value for this object. |
| */ |
| public int getAlignment () |
| { |
| return align; |
| } |
| |
| /** |
| * Returns the horizontal gap between components. |
| * |
| * @return The horizontal gap between components. |
| */ |
| public int getHgap () |
| { |
| return hgap; |
| } |
| |
| /** |
| * Returns the vertical gap between lines of components. |
| * |
| * @return The vertical gap between lines of components. |
| */ |
| public int getVgap () |
| { |
| return vgap; |
| } |
| |
| /** |
| * Initializes a new instance of <code>FlowLayout</code> with a center |
| * justification and a default horizontal and vertical gap of 5. |
| */ |
| public FlowLayout () |
| { |
| this (CENTER, 5, 5); |
| } |
| |
| /** |
| * Initializes a new instance of <code>FlowLayout</code> with the specified |
| * justification and a default horizontal and vertical gap of 5. |
| * |
| * @param align The justification setting, which should be one of the |
| * contants in this class. |
| */ |
| public FlowLayout (int align) |
| { |
| this (align, 5, 5); |
| } |
| |
| /** |
| * Initializes a new instance of <code>FlowLayout</code> with the specified |
| * justification and gap values |
| * @param align Alignment |
| * @param hgap The horizontal gap |
| * @param vgap The vertical gap |
| * @exception IllegalArgumentException If either gap is negative |
| */ |
| public FlowLayout (int align, int hgap, int vgap) |
| { |
| // Use methods to set fields so that we can have all the checking |
| // in one place. |
| setVgap (vgap); |
| setHgap (hgap); |
| setAlignment (align); |
| } |
| |
| /** Lay out the container's components based on current settings. |
| * @param parent The parent container |
| */ |
| public void layoutContainer (Container parent) |
| { |
| synchronized (parent.getTreeLock ()) |
| { |
| int num = parent.getComponentCount (); |
| // This is more efficient than calling getComponents(). |
| Component[] comps = parent.component; |
| |
| Dimension d = parent.getSize (); |
| Insets ins = parent.getInsets (); |
| |
| ComponentOrientation orient = parent.getComponentOrientation (); |
| boolean left_to_right = orient.isLeftToRight (); |
| |
| int y = ins.top + vgap; |
| int i = 0; |
| while (i < num) |
| { |
| // Find the components which go in the current row. |
| int new_w = ins.left + hgap + ins.right; |
| int new_h = 0; |
| int j; |
| boolean found_one = false; |
| for (j = i; j < num; ++j) |
| { |
| // Skip invisible items. |
| if (! comps[j].visible) |
| continue; |
| |
| Dimension c = comps[j].getPreferredSize (); |
| |
| int next_w = new_w + hgap + c.width; |
| if (next_w <= d.width || ! found_one) |
| { |
| new_w = next_w; |
| new_h = Math.max (new_h, c.height); |
| found_one = true; |
| } |
| else |
| { |
| // Must start a new row, and we already found an item |
| break; |
| } |
| } |
| |
| // Set the location of each component for this row. |
| int x; |
| |
| int myalign = align; |
| if (align == LEADING) |
| myalign = left_to_right ? LEFT : RIGHT; |
| else if (align == TRAILING) |
| myalign = left_to_right ? RIGHT : LEFT; |
| |
| if (myalign == LEFT) |
| x = ins.left + hgap; |
| else if (myalign == CENTER) |
| x = ins.left + (d.width - new_w) / 2 + hgap; |
| else |
| x = ins.left + (d.width - new_w) + hgap; |
| |
| for (int k = i; k < j; ++k) |
| { |
| if (comps[k].visible) |
| { |
| Dimension c = comps[k].getPreferredSize (); |
| comps[k].setBounds (x, y + (new_h - c.height) / 2, |
| c.width, c.height); |
| x += c.width + hgap; |
| } |
| } |
| |
| // Advance to next row. |
| i = j; |
| y += new_h + vgap; |
| } |
| } |
| } |
| |
| /** |
| * Returns the minimum layout size for the specified container using |
| * this layout. |
| * @param cont The parent container |
| * @return The minimum layout size. |
| */ |
| public Dimension minimumLayoutSize (Container cont) |
| { |
| return getSize (cont, true); |
| } |
| |
| /** |
| * Returns the preferred layout size for the specified container using |
| * this layout. |
| * @param cont The parent container |
| * @return The preferred layout size. |
| */ |
| public Dimension preferredLayoutSize (Container cont) |
| { |
| return getSize (cont, false); |
| } |
| |
| /** Remove the indicated component from this layout manager. |
| * This particular implementation does nothing. |
| * @param comp The component to remove |
| */ |
| public void removeLayoutComponent (Component comp) |
| { |
| // Nothing. |
| } |
| |
| /** |
| * Sets the justification value for this object to the specified value. |
| * |
| * @param align The new justification value for this object, which must |
| * be one of the constants in this class. |
| */ |
| public void setAlignment (int align) |
| { |
| if (align != LEFT && align != RIGHT && align != CENTER |
| && align != LEADING && align != TRAILING) |
| throw new IllegalArgumentException ("invalid alignment: " + align); |
| this.align = align; |
| } |
| |
| /** |
| * Sets the horizontal gap between components to the specified value. |
| * |
| * @param hgap The new horizontal gap between components. |
| */ |
| public void setHgap (int hgap) |
| { |
| if (hgap < 0) |
| throw new IllegalArgumentException ("horizontal gap must be nonnegative"); |
| this.hgap = hgap; |
| } |
| |
| /** |
| * Sets the vertical gap between lines of components to the specified value. |
| * |
| * @param vgap The new vertical gap. |
| */ |
| public void setVgap (int vgap) |
| { |
| if (vgap < 0) |
| throw new IllegalArgumentException ("vertical gap must be nonnegative"); |
| this.vgap = vgap; |
| } |
| |
| /** Return String description of this object. |
| * @return A string representation of this object. |
| */ |
| public String toString () |
| { |
| return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap |
| + ",align=" + align + "]"); |
| } |
| |
| // This method is used to compute the various sizes. |
| private Dimension getSize (Container parent, boolean is_min) |
| { |
| synchronized (parent.getTreeLock ()) |
| { |
| int w, h, num = parent.getComponentCount (); |
| // This is more efficient than calling getComponents(). |
| Component[] comps = parent.component; |
| |
| w = 0; |
| h = 0; |
| for (int i = 0; i < num; ++i) |
| { |
| if (! comps[i].visible) |
| continue; |
| |
| // FIXME: can we just directly read the fields in Component? |
| // Or will that not work with subclassing? |
| Dimension d; |
| |
| if (is_min) |
| d = comps[i].getMinimumSize (); |
| else |
| d = comps[i].getPreferredSize (); |
| |
| w += d.width; |
| h = Math.max (d.height, h); |
| } |
| |
| Insets ins = parent.getInsets (); |
| |
| w += (num + 1) * hgap + ins.left + ins.right; |
| h += 2 * vgap + ins.top + ins.bottom; |
| |
| return new Dimension (w, h); |
| } |
| } |
| |
| /** |
| * @serial The justification alignment of the lines of components, which |
| * will be one of the constants defined in this class. |
| */ |
| private int align; |
| |
| /** |
| * @serial The horizontal gap between components. |
| */ |
| private int hgap; |
| |
| /** |
| * @serial The vertical gap between lines of components. |
| */ |
| private int vgap; |
| } |