OSDN Git Service

* Makefile.in: Rebuilt.
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / CardLayout.java
1 // CardLayout.java - Card-based layout engine
2
3 /* Copyright (C) 2000  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.util.Enumeration;
14 import java.util.Hashtable;
15 import java.io.Serializable;
16
17 /** This class implements a card-based layout scheme.  Each included
18  * component is treated as a card.  Only one card can be shown at a
19  * time.  This class includes methods for changing which card is
20  * shown.
21  *
22  * @verson 0.0
23  * @author Tom Tromey <tromey@redhat.com>
24  * @date December 2, 2000
25  */
26 public class CardLayout implements LayoutManager2, Serializable
27 {
28   /** Create a new CardLayout object with both gaps zero.  */
29   public CardLayout ()
30   {
31     this (0, 0);
32   }
33
34   /** Create a new CardLayout object with the specified horizontal and
35    * vertical gaps.
36    * @param hgap The horizontal gap
37    * @param vgap The vertical gap
38    */
39   public CardLayout (int hgap, int vgap)
40   {
41     this.hgap = hgap;
42     this.vgap = vgap;
43     this.map = new Hashtable ();
44   }
45
46   /** Add a new component to the layout.  The constraint must be a
47    * string which is used to name the component.  This string can
48    * later be used to refer to the particular component.
49    * @param comp The component to add
50    * @param constraints The name by which the component can later be called
51    * @exception IllegalArgumentException If `constraints' is not a string
52    */
53   public void addLayoutComponent (Component comp, Object constraints)
54   {
55     if (! (constraints instanceof String))
56       throw new IllegalArgumentException ("Object " + constraints
57                                           + " is not a string");
58     map.put (constraints, comp);
59   }
60
61   /** Add a new component to the layout.  The name can be used later
62    * to refer to the component.
63    * @param name The name by which the component can later be called
64    * @param comp The component to add
65    * @deprecated
66    */
67   public void addLayoutComponent (String name, Component comp)
68   {
69     addLayoutComponent (comp, name);
70   }
71
72   /** Cause the first component in the container to be displayed.
73    * @param parent The parent container
74    */
75   public void first (Container parent)
76   {
77     gotoComponent (parent, FIRST, null);
78   }
79
80   /** Return this layout manager's horizontal gap.  */
81   public int getHgap ()
82   {
83     return hgap;
84   }
85
86   /** Return this layout manager's x alignment.  This method always
87    * returns Component.CENTER_ALIGNMENT.
88    * @param parent Container using this layout manager instance
89    */
90   public float getLayoutAlignmentX (Container parent)
91   {
92     return Component.CENTER_ALIGNMENT;
93   }
94
95   /** Returns this layout manager's y alignment.  This method always
96    * returns Component.CENTER_ALIGNMENT.
97    * @param parent Container using this layout manager instance
98    */
99   public float getLayoutAlignmentY (Container parent)
100   {
101     return Component.CENTER_ALIGNMENT;
102   }
103
104   /** Return this layout manager's vertical gap.  */
105   public int getVgap ()
106   {
107     return vgap;
108   }
109
110   /** Invalidate this layout manager's state.  */
111   public void invalidateLayout (Container target)
112   {
113     // Do nothing.
114   }
115
116   /** Cause the last component in the container to be displayed.
117    * @param parent The parent container
118    */
119   public void last (Container parent)
120   {
121     gotoComponent (parent, LAST, null);
122   }
123
124   /** Lay out the container's components based on the current
125    * settings.
126    * @param parent The parent container
127    */
128   public void layoutContainer (Container parent)
129   {
130     // FIXME: can we just use the width and height fields of parent?
131     // Or will that break with subclassing?
132     Dimension d = parent.getSize ();
133
134     Insets ins = parent.getInsets ();
135
136     int num = parent.getComponentCount ();
137     // This is more efficient than calling getComponents().
138     Component[] comps = parent.component;
139     
140     for (int i = 0; i < num; ++i)
141       {
142         if (comps[i].isVisible ())
143           {
144             // Only resize the one we care about.
145             comps[i].setBounds (hgap + ins.left, vgap + ins.top,
146                                 d.width - 2 * hgap - ins.left - ins.right,
147                                 d.height - 2 * vgap - ins.top - ins.bottom);
148             break;
149           }
150       }
151   }
152
153   /** Get the maximum layout size of the container.
154    * @param target The parent container
155    */
156   public Dimension maximumLayoutSize (Container target)
157   {
158     // The JCL says that this returns Integer.MAX_VALUE for both
159     // dimensions.  But that just seems wrong to me.
160     return getSize (target, MAX);
161   }
162
163   /** Get the minimum layout size of the container.
164    * @param target The parent container
165    */
166   public Dimension minimumLayoutSize (Container target)
167   {
168     return getSize (target, MIN);
169   }
170
171   /** Cause the next component in the container to be displayed.
172    * @param parent The parent container
173    */
174   public void next (Container parent)
175   {
176     gotoComponent (parent, NEXT, null);
177   }
178
179   /** Get the preferred layout size of the container.
180    * @param target The parent container
181    */
182   public Dimension preferredLayoutSize (Container parent)
183   {
184     return getSize (parent, PREF);
185   }
186
187   /** Cause the previous component in the container to be displayed.
188    * @param parent The parent container
189    */
190   public void previous (Container parent)
191   {
192     gotoComponent (parent, PREV, null);
193   }
194
195   /** Remove the indicated component from this layout manager.
196    * @param comp The component to remove
197    */
198   public void removeLayoutComponent (Component comp)
199   {
200     Enumeration e = map.keys ();
201     while (e.hasMoreElements ())
202       {
203         Object key = e.nextElement ();
204         if (map.get (key) == comp)
205           {
206             map.remove (key);
207             break;
208           }
209       }
210   }
211
212   /** Set this layout manager's horizontal gap.
213    * @param hgap The new gap
214    */
215   public void setHgap (int hgap)
216   {
217     this.hgap = hgap;
218   }
219
220   /** Set this layout manager's vertical gap.
221    * @param vgap The new gap
222    */
223   public void setVgap (int vgap)
224   {
225     this.vgap = vgap;
226   }
227
228   /** Cause the named component to be shown.  If the component name is
229    * unknown, this method does nothing.
230    * @param parent The parent container
231    * @param name The name of the component to show
232    */
233   public void show (Container parent, String name)
234   {
235     Object target = map.get (name);
236     if (target != null)
237       gotoComponent (parent, NONE, (Component) target);
238   }
239
240   public String toString ()
241   {
242     return getClass ().getName () + "[" + hgap + "," + vgap + "]";
243   }
244
245   // This implements first(), last(), next(), and previous().
246   private void gotoComponent (Container parent, int what,
247                               Component target)
248   {
249     int num = parent.getComponentCount ();
250     // This is more efficient than calling getComponents().
251     Component[] comps = parent.component;
252     int choice = -1;
253
254     if (what == FIRST)
255       choice = 0;
256     else if (what == LAST)
257       choice = num;
258     else if (what >= 0)
259       choice = what;
260
261     for (int i = 0; i < num; ++i)
262       {
263         // If TARGET is set then we are looking for a specific
264         // component.
265         if (target != null)
266           {
267             if (target == comps[i])
268               choice = i;
269           }
270
271         if (comps[i].isVisible ())
272           {
273             if (what == NEXT)
274               {
275                 choice = i + 1;
276                 if (choice == num)
277                   choice = num - 1;
278               }
279             else if (what == PREV)
280               {
281                 choice = i - 1;
282                 if (choice < 0)
283                   choice = 0;
284               }
285             else
286               {
287                 // Do nothing if we're already looking at the right
288                 // component.
289                 if (choice == i)
290                   return;
291               }
292             comps[i].setVisible (false);
293
294             if (choice >= 0)
295               break;
296           }
297       }
298
299     comps[choice].setVisible (true);
300   }
301
302   // Compute the size according to WHAT.
303   private Dimension getSize (Container parent, int what)
304   {
305     int w = 0, h = 0, num = parent.getComponentCount ();
306     // This is more efficient than calling getComponents().
307     Component[] comps = parent.component;
308
309     for (int i = 0; i < num; ++i)
310       {
311         // FIXME: can we just directly read the fields in Component?
312         // Or will that not work with subclassing?
313         Dimension d;
314
315         if (what == MIN)
316           d = comps[i].getMinimumSize ();
317         else if (what == MAX)
318           d = comps[i].getMaximumSize ();
319         else
320           d = comps[i].getPreferredSize ();
321
322         w = Math.max (d.width, w);
323         h = Math.max (d.height, h);
324       }
325
326     Insets i = parent.getInsets ();
327     w += 2 * hgap + i.right + i.left;
328     h += 2 * vgap + i.bottom + i.top;
329
330     // Handle overflow.
331     if (w < 0)
332       w = Integer.MAX_VALUE;
333     if (h < 0)
334       h = Integer.MAX_VALUE;
335
336     return new Dimension (w, h);
337   }
338
339   // The gaps.
340   private int hgap;
341   private int vgap;
342
343   // This hashtable maps a name to a component.
344   private Hashtable map;
345
346   // These constants are used by the private gotoComponent method.
347   private int FIRST = 0;
348   private int LAST = 1;
349   private int NEXT = 2;
350   private int PREV = 3;
351   private int NONE = 4;
352
353   // These constants are used by the private getSize method.
354   private int MIN = 0;
355   private int MAX = 1;
356   private int PREF = 2;
357 }