OSDN Git Service

libjava/classpath/ChangeLog.gcj:
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / awt / Frame.java
1 /* Frame.java -- AWT toplevel window
2    Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006
3    Free Software Foundation, Inc.
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38
39
40 package java.awt;
41
42 import java.awt.peer.FramePeer;
43 import java.lang.ref.Reference;
44 import java.lang.ref.ReferenceQueue;
45 import java.lang.ref.WeakReference;
46 import java.util.ArrayList;
47 import java.util.Vector;
48
49 import javax.accessibility.AccessibleContext;
50 import javax.accessibility.AccessibleRole;
51 import javax.accessibility.AccessibleState;
52 import javax.accessibility.AccessibleStateSet;
53
54 /**
55   * This class is a top-level window with a title bar and window
56   * decorations.
57   *
58   * @author Aaron M. Renn (arenn@urbanophile.com)
59   */
60 public class Frame extends Window implements MenuContainer
61 {
62
63   /**
64    * Constant for the default cursor.
65    *
66    * @deprecated Replaced by <code>Cursor.DEFAULT_CURSOR</code> instead.
67    */
68   public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR;
69
70   /**
71    * Constant for a cross-hair cursor.
72    *
73    * @deprecated Use <code>Cursor.CROSSHAIR_CURSOR</code> instead.
74    */
75   public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR;
76
77   /**
78    * Constant for a cursor over a text field.
79    *
80    * @deprecated Use <code>Cursor.TEXT_CURSOR</code> instead.
81    */
82   public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR;
83
84   /**
85    * Constant for a cursor to display while waiting for an action to complete.
86    *
87    * @deprecated Use <code>Cursor.WAIT_CURSOR</code>.
88    */
89   public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR;
90
91   /**
92    * Cursor used over SW corner of window decorations.
93    *
94    * @deprecated Use <code>Cursor.SW_RESIZE_CURSOR</code> instead.
95    */
96   public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR;
97
98   /**
99    * Cursor used over SE corner of window decorations.
100    * @deprecated Use <code>Cursor.SE_RESIZE_CURSOR</code> instead.
101    */
102   public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR;
103
104   /**
105    * Cursor used over NW corner of window decorations.
106    *
107    * @deprecated Use <code>Cursor.NW_RESIZE_CURSOR</code> instead.
108    */
109   public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR;
110
111   /**
112    * Cursor used over NE corner of window decorations.
113    *
114    * @deprecated Use <code>Cursor.NE_RESIZE_CURSOR</code> instead.
115    */
116   public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR;
117
118   /**
119    * Cursor used over N edge of window decorations.
120    *
121    * @deprecated Use <code>Cursor.N_RESIZE_CURSOR</code> instead.
122    */
123   public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR;
124
125   /**
126    * Cursor used over S edge of window decorations.
127    *
128    * @deprecated Use <code>Cursor.S_RESIZE_CURSOR</code> instead.
129    */
130   public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR;
131
132   /**
133    * Cursor used over E edge of window decorations.
134    *
135    * @deprecated Use <code>Cursor.E_RESIZE_CURSOR</code> instead.
136    */
137   public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR;
138
139   /**
140    * Cursor used over W edge of window decorations.
141    *
142    * @deprecated Use <code>Cursor.W_RESIZE_CURSOR</code> instead.
143    */
144   public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR;
145
146   /**
147    * Constant for a hand cursor.
148    *
149    * @deprecated Use <code>Cursor.HAND_CURSOR</code> instead.
150    */
151   public static final int HAND_CURSOR = Cursor.HAND_CURSOR;
152
153   /**
154    * Constant for a cursor used during window move operations.
155    *
156    * @deprecated Use <code>Cursor.MOVE_CURSOR</code> instead.
157    */
158   public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR;
159
160   public static final int ICONIFIED = 1;
161   public static final int MAXIMIZED_BOTH = 6;
162   public static final int MAXIMIZED_HORIZ = 2;
163   public static final int MAXIMIZED_VERT = 4;
164   public static final int NORMAL = 0;
165
166 //Serialization version constant
167   private static final long serialVersionUID = 2673458971256075116L;
168
169   /**
170    * @serial The version of the class data being serialized
171    * FIXME: what is this value?
172    */
173   private int frameSerializedDataVersion;
174
175   /**
176    * @serial Image used as the icon when this frame is minimized.
177    */
178   private Image icon;
179
180   /**
181    * @serial Constant used by the JDK Motif peer set.  Not used in
182    * this implementation.
183    */
184   private boolean mbManagement;
185
186   /**
187    * @serial The menu bar for this frame.
188    */
189   private MenuBar menuBar;
190
191   /**
192    * @serial A list of other top-level windows owned by this window.
193    */
194   Vector ownedWindows = new Vector();
195
196   /**
197    * @serial Indicates whether or not this frame is resizable.
198    */
199   private boolean resizable = true;
200
201   /**
202    * @serial The state of this frame.
203    * // FIXME: What are the values here?
204    * This is package-private to avoid an accessor method.
205    */
206   int state;
207
208   /**
209    * @serial The title of the frame.
210    */
211   private String title = "";
212
213   /**
214    * Maximized bounds for this frame.
215    */
216   private Rectangle maximizedBounds;
217
218   /**
219    * This field indicates whether the frame is undecorated or not.
220    */
221   private boolean undecorated = false;
222
223   /*
224    * The number used to generate the name returned by getName.
225    */
226   private static transient long next_frame_number;
227
228   /**
229    * Initializes a new instance of <code>Frame</code> that is not visible
230    * and has no title.
231    */
232   public Frame()
233   {
234     this("");
235     noteFrame(this);
236   }
237
238   /**
239    * Initializes a new instance of <code>Frame</code> that is not visible
240    * and has the specified title.
241    *
242    * @param title the title of this frame
243    */
244   public Frame(String title)
245   {
246     super();
247     this.title = title;
248     // Top-level frames are initially invisible.
249     visible = false;
250     noteFrame(this);
251   }
252
253   public Frame(GraphicsConfiguration gc)
254   {
255     super(gc);
256     visible = false;
257     noteFrame(this);
258   }
259
260   public Frame(String title, GraphicsConfiguration gc)
261   {
262     super(gc);
263     setTitle(title);
264     visible = false;
265     noteFrame(this);
266   }
267
268   /**
269    * Returns this frame's title string.
270    *
271    * @return this frame's title string
272    */
273   public String getTitle()
274   {
275     return title;
276   }
277
278   /**
279    * Sets this frame's title to the specified value.
280    *
281    * @param title the new frame title
282    */
283   public synchronized void setTitle(String title)
284   {
285     this.title = title;
286     if (peer != null)
287       ((FramePeer) peer).setTitle(title);
288   }
289
290   /**
291    * Returns this frame's icon.
292    *
293    * @return this frame's icon, or <code>null</code> if this frame does not
294    *         have an icon
295    */
296   public Image getIconImage()
297   {
298     return icon;
299   }
300
301   /**
302    * Sets this frame's icon to the specified value.
303    *
304    * @icon the new icon for this frame
305    */
306   public synchronized void setIconImage(Image icon)
307   {
308     this.icon = icon;
309     if (peer != null)
310       ((FramePeer) peer).setIconImage(icon);
311   }
312
313   /**
314    * Returns this frame's menu bar.
315    *
316    * @return this frame's menu bar, or <code>null</code> if this frame
317    *         does not have a menu bar
318    */
319   public MenuBar getMenuBar()
320   {
321     return menuBar;
322   }
323
324   /**
325    * Sets this frame's menu bar. Removes any existing menu bar. If the
326    * given menu bar is part of another frame it will be removed from
327    * that frame.
328    *
329    * @param menuBar the new menu bar for this frame
330    */
331   public synchronized void setMenuBar(MenuBar menuBar)
332   {
333     if (this.menuBar != null)
334       remove(this.menuBar);
335
336     this.menuBar = menuBar;
337     if (menuBar != null)
338       {
339         MenuContainer parent = menuBar.getParent();
340         if (parent != null)
341           parent.remove(menuBar);
342         menuBar.setParent(this);
343
344         // Create local copy for thread safety.
345         FramePeer p = (FramePeer) peer;
346         if (p != null)
347           {
348             if (menuBar != null)
349               menuBar.addNotify();
350             if (valid)
351               invalidate();
352             p.setMenuBar(menuBar);
353           }
354       }
355   }
356
357   /**
358    * Tests whether or not this frame is resizable.  This will be 
359    * <code>true</code> by default.
360    *
361    * @return <code>true</code> if this frame is resizable, <code>false</code>
362    *         otherwise
363    */
364   public boolean isResizable()
365   {
366     return resizable;
367   }
368
369   /**
370    * Sets the resizability of this frame to the specified value.
371    *
372    * @param resizable <code>true</code> to make the frame resizable,
373    * <code>false</code> to make it non-resizable
374    */
375   public synchronized void setResizable(boolean resizable)
376   {
377     this.resizable = resizable;
378     if (peer != null)
379       ((FramePeer) peer).setResizable(resizable);
380   }
381
382   /**
383    * Returns the cursor type of the cursor for this window.  This will
384    * be one of the constants in this class.
385    *
386    * @return the cursor type for this frame
387    *
388    * @deprecated Use <code>Component.getCursor()</code> instead.
389    */
390   public int getCursorType()
391   {
392     return getCursor().getType();
393   }
394
395   /**
396    * Sets the cursor for this window to the specified type.  The specified
397    * type should be one of the constants in this class.
398    *
399    * @param type the cursor type
400    *
401    * @deprecated Use <code>Component.setCursor(Cursor)</code> instead.
402    */
403   public void setCursor(int type)
404   {
405     setCursor(new Cursor(type));
406   }
407
408   /**
409    * Removes the specified menu component from this frame. If it is
410    * the current MenuBar it is removed from the frame. If it is a
411    * Popup it is removed from this component. If it is any other menu
412    * component it is ignored.
413    *
414    * @param menu the menu component to remove
415    */
416   public void remove(MenuComponent menu)
417   {
418     if (menu == menuBar)
419       {
420         if (menuBar != null)
421           {
422             if (peer != null)
423               {
424                 ((FramePeer) peer).setMenuBar(null);
425                 menuBar.removeNotify();
426               }
427             menuBar.setParent(null);
428           }
429         menuBar = null;
430       }
431     else
432       super.remove(menu);
433   }
434
435   public void addNotify()
436   {
437     if (menuBar != null)
438       menuBar.addNotify();
439     if (peer == null)
440       peer = getToolkit ().createFrame (this);
441
442     super.addNotify();
443   }
444
445   public void removeNotify()
446   {
447     if (menuBar != null)
448       menuBar.removeNotify();
449     super.removeNotify();
450   }
451
452   /**
453    * Returns a debugging string describing this window.
454    *
455    * @return a debugging string describing this window
456    */
457   protected String paramString()
458   {
459     String title = getTitle();
460
461     String resizable = "";
462     if (isResizable ())
463       resizable = ",resizable";
464
465     String state = "";
466     switch (getState ())
467       {
468       case NORMAL:
469         state = ",normal";
470         break;
471       case ICONIFIED:
472         state = ",iconified";
473         break;
474       case MAXIMIZED_BOTH:
475         state = ",maximized-both";
476         break;
477       case MAXIMIZED_HORIZ:
478         state = ",maximized-horiz";
479         break;
480       case MAXIMIZED_VERT:
481         state = ",maximized-vert";
482         break;
483       }
484
485     return super.paramString () + ",title=" + title + resizable + state;
486   }
487
488   /**
489    * The list of active frames. GC'ed frames get removed in noteFrame().
490    */
491   private static ArrayList<WeakReference<Frame>> weakFrames =
492     new ArrayList<WeakReference<Frame>>();
493
494   /**
495    * The death queue for all frames.
496    */ 
497   private static ReferenceQueue weakFramesQueue =
498     new ReferenceQueue<Frame>();
499
500   private static void noteFrame(Frame f)
501   {
502     synchronized (weakFrames)
503       {
504         // Remove GCed frames from the list.
505         Reference ref = weakFramesQueue.poll();
506         while (ref != null)
507           {
508             weakFrames.remove(ref);
509             ref = weakFramesQueue.poll();
510           }
511         // Add new frame.
512         weakFrames.add(new WeakReference<Frame>(f));
513       }
514   }
515
516   /**
517    * Returns <code>true</code> when there are any displayable frames,
518    * <code>false</code> otherwise.
519    *
520    * @return <code>true</code> when there are any displayable frames,
521    *         <code>false</code> otherwise
522    */
523   static boolean hasDisplayableFrames()
524   {
525     synchronized (weakFrames)
526       {
527         for (WeakReference<Frame> r : Frame.weakFrames)
528           {
529             Frame f = (Frame) r.get();
530             if (f != null && f.isDisplayable())
531               return true;
532           }
533       }
534     return false;
535   }
536
537   public static Frame[] getFrames()
538   {
539     synchronized (weakFrames)
540       {
541         ArrayList<Frame> existingFrames = new ArrayList<Frame>();
542         for (WeakReference<Frame> ref : weakFrames)
543           {
544             Frame f = ref.get();
545             if (f != null)
546               {
547                 existingFrames.add(f);
548               }
549           }
550         Frame[] frames = new Frame[existingFrames.size()];
551         frames = existingFrames.toArray(frames);
552         return frames;
553       }
554   }
555
556   public void setState(int state)
557   {
558     int current_state = getExtendedState ();
559
560     if (state == NORMAL
561         && (current_state & ICONIFIED) != 0)
562       setExtendedState(current_state | ICONIFIED);
563     
564     if (state == ICONIFIED
565         && (current_state & ~ICONIFIED) == 0)
566       setExtendedState(current_state & ~ICONIFIED);
567   }
568
569   public int getState()
570   {
571     return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
572   }
573
574   /**
575    * @since 1.4
576    */
577   public void setExtendedState(int state)
578   {
579     if (getToolkit().isFrameStateSupported(state))
580       {
581         this.state = state;
582         FramePeer p = (FramePeer) peer;
583         if (p != null)
584           p.setState(state);
585       }
586   }
587
588   /**
589    * @since 1.4
590    */
591   public int getExtendedState()
592   {
593     FramePeer p = (FramePeer) peer;
594     if (p != null)
595       state = p.getState();
596     return state;
597   }
598
599   /**
600    * @since 1.4
601    */
602   public void setMaximizedBounds(Rectangle maximizedBounds)
603   {
604     this.maximizedBounds = maximizedBounds;
605   }
606
607   /**
608    * Returns the maximized bounds of this frame.
609    *
610    * @return the maximized rectangle, may be null
611    *
612    * @since 1.4
613    */
614   public Rectangle getMaximizedBounds()
615   {
616     return maximizedBounds;
617   }
618
619   /**
620    * Returns whether this frame is undecorated or not.
621    * 
622    * @since 1.4
623    */
624   public boolean isUndecorated()
625   {
626     return undecorated;
627   }
628
629   /**
630    * Disables or enables decorations for this frame. This method can only be
631    * called while the frame is not displayable.
632    * 
633    * @throws IllegalComponentStateException if this frame is displayable
634    * 
635    * @since 1.4
636    */
637   public void setUndecorated(boolean undecorated)
638   {
639     if (isDisplayable())
640       throw new IllegalComponentStateException();
641
642     this.undecorated = undecorated;
643   }
644
645   /**
646    * Generate a unique name for this frame.
647    *
648    * @return a unique name for this frame
649    */
650   String generateName()
651   {
652     return "frame" + getUniqueLong();
653   }
654
655   private static synchronized long getUniqueLong()
656   {
657     return next_frame_number++;
658   }
659   
660   /**
661    * Accessibility support for <code>Frame</code>.
662    */
663   protected class AccessibleAWTFrame extends AccessibleAWTWindow
664   {
665     private static final long serialVersionUID = -6172960752956030250L;
666
667     /**
668      * Gets the role of this object.
669      * @return AccessibleRole.FRAME
670      */
671     public AccessibleRole getAccessibleRole()
672     {
673       return AccessibleRole.FRAME;
674     }
675     
676     /**
677      * Gets the state set of this object.
678      * @return The current state of this frame.
679      */
680     public AccessibleStateSet getAccessibleStateSet()
681     {
682       AccessibleStateSet states = super.getAccessibleStateSet();
683       if (isResizable())
684         states.add(AccessibleState.RESIZABLE);
685       if ((state & ICONIFIED) != 0)
686         states.add(AccessibleState.ICONIFIED);
687       return states;
688     }
689   }
690   
691   /**
692    * Gets the AccessibleContext associated with this <code>Frame</code>.
693    * The context is created, if necessary.
694    *
695    * @return the associated context
696    */
697   public AccessibleContext getAccessibleContext()
698   {
699     // Create the context if this is the first request.
700     if (accessibleContext == null)
701       accessibleContext = new AccessibleAWTFrame();
702     return accessibleContext;
703   }
704 }