1 // FlowLayout.java - Grid-based layout engine
3 /* Copyright (C) 2000, 2001 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 import java.io.Serializable;
15 /** This class implements a flow-based layout. Components are laid
16 * out in order from left to right. When a component cannot be placed
17 * without horizontal clipping, a new row is started. This class
18 * supports horizontal and vertical gaps. These are used for spacing
21 public class FlowLayout implements LayoutManager, Serializable
23 /** Constant that specifies left alignment. */
24 public static final int LEFT = 0;
25 /** Constant that specifies center alignment. */
26 public static final int CENTER = 1;
27 /** Constant that specifies right alignment. */
28 public static final int RIGHT = 2;
30 /** Constant that specifies alignment to leading edge of container's
32 public static final int LEADING = 3;
33 /** Constant that specifies alignment to trailing edge of container's
35 public static final int TRAILING = 4;
37 /** Add a new component to the layout. This particular implementation
40 public void addLayoutComponent (String name, Component comp)
45 /** Return the alignment. */
46 public int getAlignment ()
51 /** Return the horizontal gap. */
57 /** Return the vertical gap. */
63 /** Create a new FlowLayout with center alignment.
64 * Both gaps are set to 5.
71 /** Create a new FlowLayout with the alignment.
72 * columns. Both gaps are set to 5.
73 * @param align Alignment
75 public FlowLayout (int align)
80 /** Create a new FlowLayout with the specified alignment and gaps.
81 * @param align Alignment
82 * @param hgap The horizontal gap
83 * @param vgap The vertical gap
84 * @exception IllegalArgumentException If either gap is negative
86 public FlowLayout (int align, int hgap, int vgap)
88 // Use methods to set fields so that we can have all the checking
95 /** Lay out the container's components based on current settings.
96 * @param parent The parent container
98 public void layoutContainer (Container parent)
100 int num = parent.getComponentCount ();
101 // This is more efficient than calling getComponents().
102 Component[] comps = parent.component;
104 Dimension d = parent.getSize ();
105 Insets ins = parent.getInsets ();
107 ComponentOrientation orient = parent.getComponentOrientation ();
108 boolean left_to_right = orient.isLeftToRight ();
110 int y = ins.top + vgap;
114 // Find the components which go in the current row.
115 int new_w = ins.left + hgap + ins.right;
118 boolean found_one = false;
119 for (j = i; j < num && ! found_one; ++j)
121 // FIXME: this is very inefficient.
122 Dimension c = comps[i].getPreferredSize ();
124 // Skip invisible items.
125 if (! comps[i].visible)
128 int next_w = new_w + hgap + c.width;
129 if (next_w <= d.width || ! found_one)
132 new_h = Math.max (new_h, c.height);
137 // Must start a new row, and we already found an item
142 // Set the location of each component for this row.
146 if (align == LEADING)
147 myalign = left_to_right ? LEFT : RIGHT;
148 else if (align == TRAILING)
149 myalign = left_to_right ? RIGHT : LEFT;
153 else if (myalign == CENTER)
154 x = (d.width - new_w) / 2;
158 for (int k = i; i < j; ++k)
160 // FIXME: this is very inefficient.
161 Dimension c = comps[i].getPreferredSize ();
162 if (comps[i].visible)
164 comps[i].setLocation (x, y);
169 // Advance to next row.
175 /** Get the minimum layout size of the container.
176 * @param cont The parent container
178 public Dimension minimumLayoutSize (Container cont)
180 return getSize (cont, true);
183 /** Get the preferred layout size of the container.
184 * @param cont The parent container
186 public Dimension preferredLayoutSize (Container cont)
188 return getSize (cont, false);
191 /** Remove the indicated component from this layout manager.
192 * This particular implementation does nothing.
193 * @param comp The component to remove
195 public void removeLayoutComponent (Component comp)
200 /** Set the alignment.
201 * @param align The alignment
203 public void setAlignment (int align)
205 if (align != LEFT && align != RIGHT && align != CENTER
206 && align != LEADING && align != TRAILING)
207 throw new IllegalArgumentException ("invalid align: " + align);
211 /** Set the horizontal gap
212 * @param hgap The horizontal gap
214 public void setHgap (int hgap)
217 throw new IllegalArgumentException ("horizontal gap must be nonnegative");
221 /** Set the vertical gap.
222 * @param vgap The vertical gap
224 public void setVgap (int vgap)
227 throw new IllegalArgumentException ("vertical gap must be nonnegative");
231 /** Return String description of this object. */
232 public String toString ()
234 return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap
235 + ",align=" + align + "]");
238 // This method is used to compute the various sizes.
239 private Dimension getSize (Container parent, boolean is_min)
241 int w, h, num = parent.getComponentCount ();
242 // This is more efficient than calling getComponents().
243 Component[] comps = parent.component;
247 for (int i = 0; i < num; ++i)
249 if (! comps[i].visible)
252 // FIXME: can we just directly read the fields in Component?
253 // Or will that not work with subclassing?
257 d = comps[i].getMinimumSize ();
259 d = comps[i].getPreferredSize ();
262 h = Math.max (d.height, h);
265 Insets ins = parent.getInsets ();
267 w += (num + 1) * hgap + ins.left + ins.right;
268 h += 2 * vgap + ins.top + ins.bottom;
270 return new Dimension (w, h);