// GridLayout.java - Grid-based layout engine /* Copyright (C) 2000 Free Software Foundation This file is part of libgcj. This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ 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. */ 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; /** Add a new component to the layout. This particular implementation * does nothing. */ public void addLayoutComponent (String name, Component comp) { // Nothing. } /** Return the alignment. */ public int getAlignment () { return align; } /** Return the horizontal gap. */ public int getHgap () { return hgap; } /** Return the vertical gap. */ public int getVgap () { return vgap; } /** Create a new FlowLayout with center alignment. * Both gaps are set to 0. */ public FlowLayout () { this (CENTER, 0, 0); } /** Create a new FlowLayout with the alignment. * columns. Both gaps are set to 0. * @param align Alignment */ public FlowLayout (int align) { this (align, 0, 0); } /** Create a new FlowLayout with the specified alignment and gaps. * @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) { if (hgap < 0) throw new IllegalArgumentException ("horizontal gap must be nonnegative"); if (vgap < 0) throw new IllegalArgumentException ("vertical gap must be nonnegative"); if (align != LEFT && align != RIGHT && align != CENTER && align != LEADING && align != TRAILING) throw new IllegalArgumentException ("invalid align: " + align); this.align = align; this.hgap = hgap; this.vgap = vgap; } /** Lay out the container's components based on current settings. * @param parent The parent container */ public void layoutContainer (Container parent) { 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; for (j = i; j < num; ++j) { // FIXME: this is very inefficient. Dimension c = comps[i].getPreferredSize (); int next_w = new_w + hgap + c.width; if (next_w > d.width) { // We must start a new row. break; } new_w = next_w; new_h = Math.max (new_h, c.height); } // We always need at least one item. if (j == i) ++j; // 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 = (d.width - new_w) / 2; else x = d.width - new_w; for (int k = i; i < j; ++k) { // FIXME: this is very inefficient. Dimension c = comps[i].getPreferredSize (); comps[i].setLocation (x, y); x += c.width + vgap; } // Advance to next row. i = j; y += new_h + vgap; } } /** Get the minimum layout size of the container. * @param cont The parent container */ public Dimension minimumLayoutSize (Container cont) { return getSize (cont, true); } /** Get the preferred layout size of the container. * @param cont The parent container */ 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. } /** Set the alignment. * @param align The alignment */ public void setAlignment (int align) { if (align != LEFT && align != RIGHT && align != CENTER && align != LEADING && align != TRAILING) throw new IllegalArgumentException ("invalid align: " + align); this.align = align; } /** Set the horizontal gap * @param hgap The horizontal gap */ public void setHgap (int hgap) { if (hgap < 0) throw new IllegalArgumentException ("horizontal gap must be nonnegative"); this.hgap = hgap; } /** Set the vertical gap. * @param vgap The 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. */ 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) { 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) { // 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); } // Alignment. private int align; // The gaps. private int hgap; private int vgap; }