OSDN Git Service

d33059bf25268981a29a977c367330126671c3f4
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / FlowLayout.java
1 // FlowLayout.java - Grid-based layout engine
2
3 /* Copyright (C) 2000, 2001  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 package java.awt;
12
13 import java.io.Serializable;
14
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
19  * between components.
20  */
21 public class FlowLayout implements LayoutManager, Serializable
22 {
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;
29
30   /** Constant that specifies alignment to leading edge of container's
31    * orientation.  */
32   public static final int LEADING = 3;
33   /** Constant that specifies alignment to trailing edge of container's
34    * orientation.  */
35   public static final int TRAILING = 4;
36
37   /** Add a new component to the layout.  This particular implementation
38    * does nothing.
39    */
40   public void addLayoutComponent (String name, Component comp)
41   {
42     // Nothing.
43   }
44
45   /** Return the alignment.  */
46   public int getAlignment ()
47   {
48     return align;
49   }
50
51   /** Return the horizontal gap.  */
52   public int getHgap ()
53   {
54     return hgap;
55   }
56
57   /** Return the vertical gap.  */
58   public int getVgap ()
59   {
60     return vgap;
61   }
62
63   /** Create a new FlowLayout with center alignment.
64    * Both gaps are set to 5.
65    */
66   public FlowLayout ()
67   {
68     this (CENTER, 5, 5);
69   }
70
71   /** Create a new FlowLayout with the alignment.
72    * columns.  Both gaps are set to 5.
73    * @param align Alignment
74    */
75   public FlowLayout (int align)
76   {
77     this (align, 5, 5);
78   }
79
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
85    */
86   public FlowLayout (int align, int hgap, int vgap)
87   {
88     // Use methods to set fields so that we can have all the checking
89     // in one place.
90     setVgap (vgap);
91     setHgap (hgap);
92     setAlignment (align);
93   }
94
95   /** Lay out the container's components based on current settings.
96    * @param parent The parent container
97    */
98   public void layoutContainer (Container parent)
99   {
100     int num = parent.getComponentCount ();
101     // This is more efficient than calling getComponents().
102     Component[] comps = parent.component;
103
104     Dimension d = parent.getSize ();
105     Insets ins = parent.getInsets ();
106
107     ComponentOrientation orient = parent.getComponentOrientation ();
108     boolean left_to_right = orient.isLeftToRight ();
109
110     int y = ins.top + vgap;
111     int i = 0;
112     while (i < num)
113       {
114         // Find the components which go in the current row.
115         int new_w = ins.left + hgap + ins.right;
116         int new_h = 0;
117         int j;
118         boolean found_one = false;
119         for (j = i; j < num && ! found_one; ++j)
120           {
121             // FIXME: this is very inefficient.
122             Dimension c = comps[i].getPreferredSize ();
123
124             // Skip invisible items.
125             if (! comps[i].visible)
126               continue;
127
128             int next_w = new_w + hgap + c.width;
129             if (next_w <= d.width || ! found_one)
130               {
131                 new_w = next_w;
132                 new_h = Math.max (new_h, c.height);
133                 found_one = true;
134               }
135             else
136               {
137                 // Must start a new row, and we already found an item
138                 break;
139               }
140           }
141
142         // Set the location of each component for this row.
143         int x;
144
145         int myalign = align;
146         if (align == LEADING)
147           myalign = left_to_right ? LEFT : RIGHT;
148         else if (align == TRAILING)
149           myalign = left_to_right ? RIGHT : LEFT;
150
151         if (myalign == LEFT)
152           x = ins.left + hgap;
153         else if (myalign == CENTER)
154           x = (d.width - new_w) / 2;
155         else
156           x = d.width - new_w;
157
158         for (int k = i; i < j; ++k)
159           {
160             // FIXME: this is very inefficient.
161             Dimension c = comps[i].getPreferredSize ();
162             if (comps[i].visible)
163               {
164                 comps[i].setLocation (x, y);
165                 x += c.width + vgap;
166               }
167           }
168
169         // Advance to next row.
170         i = j;
171         y += new_h + vgap;
172       }
173   }
174
175   /** Get the minimum layout size of the container.
176    * @param cont The parent container
177    */
178   public Dimension minimumLayoutSize (Container cont)
179   {
180     return getSize (cont, true);
181   }
182
183   /** Get the preferred layout size of the container.
184    * @param cont The parent container
185    */
186   public Dimension preferredLayoutSize (Container cont)
187   {
188     return getSize (cont, false);
189   }
190
191   /** Remove the indicated component from this layout manager.
192    * This particular implementation does nothing.
193    * @param comp The component to remove
194    */
195   public void removeLayoutComponent (Component comp)
196   {
197     // Nothing.
198   }
199
200   /** Set the alignment.
201    * @param align The alignment
202    */
203   public void setAlignment (int align)
204   {
205     if (align != LEFT && align != RIGHT && align != CENTER
206         && align != LEADING && align != TRAILING)
207       throw new IllegalArgumentException ("invalid align: " + align);
208     this.align = align;
209   }
210
211   /** Set the horizontal gap
212    * @param hgap The horizontal gap
213    */
214   public void setHgap (int hgap)
215   {
216     if (hgap < 0)
217       throw new IllegalArgumentException ("horizontal gap must be nonnegative");
218     this.hgap = hgap;
219   }
220
221   /** Set the vertical gap.
222    * @param vgap The vertical gap
223    */
224   public void setVgap (int vgap)
225   {
226     if (vgap < 0)
227       throw new IllegalArgumentException ("vertical gap must be nonnegative");
228     this.vgap = vgap;
229   }
230
231   /** Return String description of this object.  */
232   public String toString ()
233   {
234     return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap
235             + ",align=" + align + "]");
236   }
237
238   // This method is used to compute the various sizes.
239   private Dimension getSize (Container parent, boolean is_min)
240   {
241     int w, h, num = parent.getComponentCount ();
242     // This is more efficient than calling getComponents().
243     Component[] comps = parent.component;
244
245     w = 0;
246     h = 0;
247     for (int i = 0; i < num; ++i)
248       {
249         if (! comps[i].visible)
250           continue;
251
252         // FIXME: can we just directly read the fields in Component?
253         // Or will that not work with subclassing?
254         Dimension d;
255
256         if (is_min)
257           d = comps[i].getMinimumSize ();
258         else
259           d = comps[i].getPreferredSize ();
260
261         w += d.width;
262         h = Math.max (d.height, h);
263       }
264
265     Insets ins = parent.getInsets ();
266
267     w += (num + 1) * hgap + ins.left + ins.right;
268     h += 2 * vgap + ins.top + ins.bottom;
269
270     return new Dimension (w, h);
271   }
272
273   // Alignment.
274   private int align;
275   // The gaps.
276   private int hgap;
277   private int vgap;
278 }