]> gcc.gnu.org Git - gcc.git/blob - libjava/java/awt/Window.java
51b00dc175d194e6f9119da9fbe90b4618483105
[gcc.git] / libjava / java / awt / Window.java
1 /* Window.java --
2 Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.awt;
40
41 import java.awt.event.ComponentEvent;
42 import java.awt.event.WindowEvent;
43 import java.awt.event.WindowFocusListener;
44 import java.awt.event.WindowListener;
45 import java.awt.event.WindowStateListener;
46 import java.awt.peer.WindowPeer;
47 import java.lang.ref.Reference;
48 import java.lang.ref.WeakReference;
49 import java.util.Iterator;
50 import java.util.EventListener;
51 import java.util.Locale;
52 import java.util.ResourceBundle;
53 import java.util.Vector;
54 import javax.accessibility.Accessible;
55 import javax.accessibility.AccessibleContext;
56
57 /**
58 * This class represents a top-level window with no decorations.
59 *
60 * @author Aaron M. Renn <arenn@urbanophile.com>
61 * @author Warren Levy <warrenl@cygnus.com>
62 */
63 public class Window extends Container implements Accessible
64 {
65 private static final long serialVersionUID = 4497834738069338734L;
66
67 // Serialized fields, from Sun's serialization spec.
68 private String warningString = null;
69 private int windowSerializedDataVersion = 0; // FIXME
70 /** @since 1.2 */
71 // private FocusManager focusMgr; // FIXME: what is this?
72 /** @since 1.2 */
73 private int state = 0;
74 /** @since 1.4 */
75 private boolean focusableWindowState = true;
76
77 // A list of other top-level windows owned by this window.
78 private transient Vector ownedWindows = new Vector();
79
80 private transient WindowListener windowListener;
81 private transient WindowFocusListener windowFocusListener;
82 private transient WindowStateListener windowStateListener;
83 private transient GraphicsConfiguration graphicsConfiguration;
84 private transient AccessibleContext accessibleContext;
85
86 private transient boolean shown;
87
88 /**
89 * This (package access) constructor is used by subclasses that want
90 * to build windows that do not have parents. Eg. toplevel
91 * application frames. Subclasses cannot call super(null), since
92 * null is an illegal argument.
93 */
94 Window()
95 {
96 visible = false;
97 // Windows are the only Containers that default to being focus
98 // cycle roots.
99 focusCycleRoot = true;
100 setLayout(new BorderLayout());
101 }
102
103 Window(GraphicsConfiguration gc)
104 {
105 this();
106 graphicsConfiguration = gc;
107 }
108
109 /**
110 * Initializes a new instance of <code>Window</code> with the specified
111 * parent. The window will initially be invisible.
112 *
113 * @param parent The owning <code>Frame</code> of this window.
114 *
115 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
116 * is not from a screen device, or if owner is null; this exception is always
117 * thrown when GraphicsEnvironment.isHeadless returns true.
118 */
119 public Window(Frame owner)
120 {
121 this (owner, owner.getGraphicsConfiguration ());
122 }
123
124 /**
125 * Initializes a new instance of <code>Window</code> with the specified
126 * parent. The window will initially be invisible.
127 *
128 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
129 * is not from a screen device, or if owner is null; this exception is always
130 * thrown when GraphicsEnvironment.isHeadless returns true.
131 *
132 * @since 1.2
133 */
134 public Window(Window owner)
135 {
136 this (owner, owner.getGraphicsConfiguration ());
137 }
138
139 /**
140 * Initializes a new instance of <code>Window</code> with the specified
141 * parent. The window will initially be invisible.
142 *
143 * @exception IllegalArgumentException If owner is null or if gc is not from a
144 * screen device; this exception is always thrown when
145 * GraphicsEnvironment.isHeadless returns true.
146 *
147 * @since 1.3
148 */
149 public Window(Window owner, GraphicsConfiguration gc)
150 {
151 this ();
152
153 synchronized (getTreeLock())
154 {
155 if (owner == null)
156 throw new IllegalArgumentException ("owner must not be null");
157
158 parent = owner;
159 owner.ownedWindows.add(new WeakReference(this));
160 }
161
162 // FIXME: make this text visible in the window.
163 SecurityManager s = System.getSecurityManager();
164 if (s != null && ! s.checkTopLevelWindow(this))
165 warningString = System.getProperty("awt.appletWarning");
166
167 if (gc != null
168 && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
169 throw new IllegalArgumentException ("gc must be from a screen device");
170
171 // FIXME: until we implement this, it just causes AWT to crash.
172 // if (gc == null)
173 // graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
174 // .getDefaultScreenDevice()
175 // .getDefaultConfiguration();
176 // else
177 graphicsConfiguration = gc;
178 }
179
180 GraphicsConfiguration getGraphicsConfigurationImpl()
181 {
182 if (graphicsConfiguration != null)
183 return graphicsConfiguration;
184
185 return super.getGraphicsConfigurationImpl();
186 }
187
188 /**
189 * Creates the native peer for this window.
190 */
191 public void addNotify()
192 {
193 if (peer == null)
194 peer = getToolkit().createWindow(this);
195 super.addNotify();
196 }
197
198 /**
199 * Relays out this window's child components at their preferred size.
200 *
201 * @specnote pack() doesn't appear to be called internally by show(), so
202 * we duplicate some of the functionality.
203 */
204 public void pack()
205 {
206 if (parent != null && !parent.isDisplayable())
207 parent.addNotify();
208 if (peer == null)
209 addNotify();
210
211 setSize(getPreferredSize());
212
213 validate();
214 }
215
216 /**
217 * Shows on-screen this window and any of its owned windows for whom
218 * isVisible returns true.
219 */
220 public void show()
221 {
222 if (parent != null && !parent.isDisplayable())
223 parent.addNotify();
224 if (peer == null)
225 addNotify();
226
227 // Show visible owned windows.
228 synchronized (getTreeLock())
229 {
230 Iterator e = ownedWindows.iterator();
231 while(e.hasNext())
232 {
233 Window w = (Window)(((Reference) e.next()).get());
234 if (w != null)
235 {
236 if (w.isVisible())
237 w.getPeer().setVisible(true);
238 }
239 else
240 // Remove null weak reference from ownedWindows.
241 // Unfortunately this can't be done in the Window's
242 // finalize method because there is no way to guarantee
243 // synchronous access to ownedWindows there.
244 e.remove();
245 }
246 }
247 validate();
248 super.show();
249 toFront();
250
251 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
252 manager.setGlobalFocusedWindow (this);
253
254 if (!shown)
255 {
256 FocusTraversalPolicy policy = getFocusTraversalPolicy ();
257 Component initialFocusOwner = null;
258
259 if (policy != null)
260 initialFocusOwner = policy.getInitialComponent (this);
261
262 if (initialFocusOwner != null)
263 initialFocusOwner.requestFocusInWindow (false);
264
265 shown = true;
266 }
267 }
268
269 public void hide()
270 {
271 // Hide visible owned windows.
272 synchronized (getTreeLock ())
273 {
274 Iterator e = ownedWindows.iterator();
275 while(e.hasNext())
276 {
277 Window w = (Window)(((Reference) e.next()).get());
278 if (w != null)
279 {
280 if (w.isVisible() && w.getPeer() != null)
281 w.getPeer().setVisible(false);
282 }
283 else
284 e.remove();
285 }
286 }
287 super.hide();
288 }
289
290 public boolean isDisplayable()
291 {
292 if (super.isDisplayable())
293 return true;
294 return peer != null;
295 }
296
297 /**
298 * Destroys any resources associated with this window. This includes
299 * all components in the window and all owned top-level windows.
300 */
301 public void dispose()
302 {
303 hide();
304
305 synchronized (getTreeLock ())
306 {
307 Iterator e = ownedWindows.iterator();
308 while(e.hasNext())
309 {
310 Window w = (Window)(((Reference) e.next()).get());
311 if (w != null)
312 w.dispose();
313 else
314 // Remove null weak reference from ownedWindows.
315 e.remove();
316 }
317
318 for (int i = 0; i < ncomponents; ++i)
319 component[i].removeNotify();
320 this.removeNotify();
321
322 // Post a WINDOW_CLOSED event.
323 WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
324 getToolkit().getSystemEventQueue().postEvent(we);
325 }
326 }
327
328 /**
329 * Sends this window to the back so that all other windows display in
330 * front of it.
331 */
332 public void toBack()
333 {
334 if (peer != null)
335 {
336 WindowPeer wp = (WindowPeer) peer;
337 wp.toBack();
338 }
339 }
340
341 /**
342 * Brings this window to the front so that it displays in front of
343 * any other windows.
344 */
345 public void toFront()
346 {
347 if (peer != null)
348 {
349 WindowPeer wp = (WindowPeer) peer;
350 wp.toFront();
351 }
352 }
353
354 /**
355 * Returns the toolkit used to create this window.
356 *
357 * @return The toolkit used to create this window.
358 *
359 * @specnote Unlike Component.getToolkit, this implementation always
360 * returns the value of Toolkit.getDefaultToolkit().
361 */
362 public Toolkit getToolkit()
363 {
364 return Toolkit.getDefaultToolkit();
365 }
366
367 /**
368 * Returns the warning string that will be displayed if this window is
369 * popped up by an unsecure applet or application.
370 *
371 * @return The unsecure window warning message.
372 */
373 public final String getWarningString()
374 {
375 return warningString;
376 }
377
378 /**
379 * Returns the locale that this window is configured for.
380 *
381 * @return The locale this window is configured for.
382 */
383 public Locale getLocale()
384 {
385 return locale == null ? Locale.getDefault() : locale;
386 }
387
388 /*
389 /** @since 1.2
390 public InputContext getInputContext()
391 {
392 // FIXME
393 }
394 */
395
396 /**
397 * Sets the cursor for this window to the specifiec cursor.
398 *
399 * @param cursor The new cursor for this window.
400 */
401 public void setCursor(Cursor cursor)
402 {
403 super.setCursor(cursor);
404 }
405
406 public Window getOwner()
407 {
408 return (Window) parent;
409 }
410
411 /** @since 1.2 */
412 public Window[] getOwnedWindows()
413 {
414 Window [] trimmedList;
415 synchronized (getTreeLock ())
416 {
417 // Windows with non-null weak references in ownedWindows.
418 Window [] validList = new Window [ownedWindows.size()];
419
420 Iterator e = ownedWindows.iterator();
421 int numValid = 0;
422 while (e.hasNext())
423 {
424 Window w = (Window)(((Reference) e.next()).get());
425 if (w != null)
426 validList[numValid++] = w;
427 else
428 // Remove null weak reference from ownedWindows.
429 e.remove();
430 }
431
432 if (numValid != validList.length)
433 {
434 trimmedList = new Window [numValid];
435 System.arraycopy (validList, 0, trimmedList, 0, numValid);
436 }
437 else
438 trimmedList = validList;
439 }
440 return trimmedList;
441 }
442
443 /**
444 * Adds the specified listener to the list of <code>WindowListeners</code>
445 * that will receive events for this window.
446 *
447 * @param listener The <code>WindowListener</code> to add.
448 */
449 public synchronized void addWindowListener(WindowListener listener)
450 {
451 windowListener = AWTEventMulticaster.add(windowListener, listener);
452 }
453
454 /**
455 * Removes the specified listener from the list of
456 * <code>WindowListeners</code> that will receive events for this window.
457 *
458 * @param listener The <code>WindowListener</code> to remove.
459 */
460 public synchronized void removeWindowListener(WindowListener listener)
461 {
462 windowListener = AWTEventMulticaster.remove(windowListener, listener);
463 }
464
465 /**
466 * Returns an array of all the window listeners registered on this window.
467 *
468 * @since 1.4
469 */
470 public synchronized WindowListener[] getWindowListeners()
471 {
472 return (WindowListener[])
473 AWTEventMulticaster.getListeners(windowListener,
474 WindowListener.class);
475 }
476
477 /**
478 * Returns an array of all the window focus listeners registered on this
479 * window.
480 *
481 * @since 1.4
482 */
483 public synchronized WindowFocusListener[] getWindowFocusListeners()
484 {
485 return (WindowFocusListener[])
486 AWTEventMulticaster.getListeners(windowFocusListener,
487 WindowFocusListener.class);
488 }
489
490 /**
491 * Returns an array of all the window state listeners registered on this
492 * window.
493 *
494 * @since 1.4
495 */
496 public synchronized WindowStateListener[] getWindowStateListeners()
497 {
498 return (WindowStateListener[])
499 AWTEventMulticaster.getListeners(windowStateListener,
500 WindowStateListener.class);
501 }
502
503 /**
504 * Adds the specified listener to this window.
505 */
506 public void addWindowFocusListener (WindowFocusListener wfl)
507 {
508 windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
509 }
510
511 /**
512 * Adds the specified listener to this window.
513 *
514 * @since 1.4
515 */
516 public void addWindowStateListener (WindowStateListener wsl)
517 {
518 windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);
519 }
520
521 /**
522 * Removes the specified listener from this window.
523 */
524 public void removeWindowFocusListener (WindowFocusListener wfl)
525 {
526 windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
527 }
528
529 /**
530 * Removes the specified listener from this window.
531 *
532 * @since 1.4
533 */
534 public void removeWindowStateListener (WindowStateListener wsl)
535 {
536 windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
537 }
538
539 /**
540 * Returns an array of all the objects currently registered as FooListeners
541 * upon this Window. FooListeners are registered using the addFooListener
542 * method.
543 *
544 * @exception ClassCastException If listenerType doesn't specify a class or
545 * interface that implements java.util.EventListener.
546 *
547 * @since 1.3
548 */
549 public EventListener[] getListeners(Class listenerType)
550 {
551 if (listenerType == WindowListener.class)
552 return getWindowListeners();
553 return super.getListeners(listenerType);
554 }
555
556 void dispatchEventImpl(AWTEvent e)
557 {
558 // Make use of event id's in order to avoid multiple instanceof tests.
559 if (e.id <= WindowEvent.WINDOW_LAST
560 && e.id >= WindowEvent.WINDOW_FIRST
561 && (windowListener != null
562 || windowFocusListener != null
563 || windowStateListener != null
564 || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
565 processEvent(e);
566 else
567 super.dispatchEventImpl(e);
568 }
569
570 /**
571 * Processes the specified event for this window. If the event is an
572 * instance of <code>WindowEvent</code>, then
573 * <code>processWindowEvent()</code> is called to process the event,
574 * otherwise the superclass version of this method is invoked.
575 *
576 * @param event The event to process.
577 */
578 protected void processEvent(AWTEvent evt)
579 {
580 if (evt instanceof WindowEvent)
581 processWindowEvent((WindowEvent) evt);
582 else
583 super.processEvent(evt);
584 }
585
586 /**
587 * Dispatches this event to any listeners that are listening for
588 * <code>WindowEvents</code> on this window. This method only gets
589 * invoked if it is enabled via <code>enableEvents()</code> or if
590 * a listener has been added.
591 *
592 * @param event The event to process.
593 */
594 protected void processWindowEvent(WindowEvent evt)
595 {
596 int id = evt.getID();
597
598 if (id == WindowEvent.WINDOW_GAINED_FOCUS
599 || id == WindowEvent.WINDOW_LOST_FOCUS)
600 processWindowFocusEvent (evt);
601 else if (id == WindowEvent.WINDOW_STATE_CHANGED)
602 processWindowStateEvent (evt);
603 else
604 {
605 if (windowListener != null)
606 {
607 switch (evt.getID())
608 {
609 case WindowEvent.WINDOW_ACTIVATED:
610 windowListener.windowActivated(evt);
611 break;
612
613 case WindowEvent.WINDOW_CLOSED:
614 windowListener.windowClosed(evt);
615 break;
616
617 case WindowEvent.WINDOW_CLOSING:
618 windowListener.windowClosing(evt);
619 break;
620
621 case WindowEvent.WINDOW_DEACTIVATED:
622 windowListener.windowDeactivated(evt);
623 break;
624
625 case WindowEvent.WINDOW_DEICONIFIED:
626 windowListener.windowDeiconified(evt);
627 break;
628
629 case WindowEvent.WINDOW_ICONIFIED:
630 windowListener.windowIconified(evt);
631 break;
632
633 case WindowEvent.WINDOW_OPENED:
634 windowListener.windowOpened(evt);
635 break;
636
637 default:
638 break;
639 }
640 }
641 }
642 }
643
644 /**
645 * Returns the child window that has focus if this window is active.
646 * This method returns <code>null</code> if this window is not active
647 * or no children have focus.
648 *
649 * @return The component that has focus, or <code>null</code> if no
650 * component has focus.
651 */
652 public Component getFocusOwner ()
653 {
654 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
655
656 Window activeWindow = manager.getActiveWindow ();
657
658 // The currently-focused Component belongs to the active Window.
659 if (activeWindow == this)
660 return manager.getFocusOwner ();
661
662 return null;
663 }
664
665 /**
666 * Post a Java 1.0 event to the event queue.
667 *
668 * @param event The event to post.
669 *
670 * @deprecated
671 */
672 public boolean postEvent(Event e)
673 {
674 // FIXME
675 return false;
676 }
677
678 /**
679 * Tests whether or not this window is visible on the screen.
680 *
681 * @return <code>true</code> if this window is visible, <code>false</code>
682 * otherwise.
683 */
684 public boolean isShowing()
685 {
686 return super.isShowing();
687 }
688
689 /**
690 * @since 1.2
691 *
692 * @deprecated
693 */
694 public void applyResourceBundle(ResourceBundle rb)
695 {
696 throw new Error ("Not implemented");
697 }
698
699 /**
700 * @since 1.2
701 *
702 * @deprecated
703 */
704 public void applyResourceBundle(String rbName)
705 {
706 ResourceBundle rb = ResourceBundle.getBundle(rbName);
707 if (rb != null)
708 applyResourceBundle(rb);
709 }
710
711 public AccessibleContext getAccessibleContext()
712 {
713 // FIXME
714 //return null;
715 throw new Error ("Not implemented");
716 }
717
718 /**
719 * Get graphics configuration. The implementation for Window will
720 * not ask any parent containers, since Window is a toplevel
721 * window and not actually embedded in the parent component.
722 */
723 public GraphicsConfiguration getGraphicsConfiguration()
724 {
725 if (graphicsConfiguration != null) return graphicsConfiguration;
726 if (peer != null) return peer.getGraphicsConfiguration();
727 return null;
728 }
729
730 protected void processWindowFocusEvent(WindowEvent event)
731 {
732 if (windowFocusListener != null)
733 {
734 switch (event.getID ())
735 {
736 case WindowEvent.WINDOW_GAINED_FOCUS:
737 windowFocusListener.windowGainedFocus (event);
738 break;
739
740 case WindowEvent.WINDOW_LOST_FOCUS:
741 windowFocusListener.windowLostFocus (event);
742 break;
743
744 default:
745 break;
746 }
747 }
748 }
749
750 /**
751 * @since 1.4
752 */
753 protected void processWindowStateEvent(WindowEvent event)
754 {
755 if (windowStateListener != null
756 && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
757 windowStateListener.windowStateChanged (event);
758 }
759
760 /**
761 * Returns whether this <code>Window</code> can get the focus or not.
762 *
763 * @since 1.4
764 */
765 public final boolean isFocusableWindow ()
766 {
767 if (getFocusableWindowState () == false)
768 return false;
769
770 if (this instanceof Dialog
771 || this instanceof Frame)
772 return true;
773
774 // FIXME: Implement more possible cases for returning true.
775
776 return false;
777 }
778
779 /**
780 * Returns the value of the focusableWindowState property.
781 *
782 * @since 1.4
783 */
784 public boolean getFocusableWindowState ()
785 {
786 return focusableWindowState;
787 }
788
789 /**
790 * Sets the value of the focusableWindowState property.
791 *
792 * @since 1.4
793 */
794 public void setFocusableWindowState (boolean focusableWindowState)
795 {
796 this.focusableWindowState = focusableWindowState;
797 }
798
799 // setBoundsCallback is needed so that when a user moves a window,
800 // the Window's location can be updated without calling the peer's
801 // setBounds method. When a user moves a window the peer window's
802 // location is updated automatically and the windowing system sends
803 // a message back to the application informing it of its updated
804 // dimensions. We must update the AWT Window class with these new
805 // dimensions. But we don't want to call the peer's setBounds
806 // method, because the peer's dimensions have already been updated.
807 // (Under X, having this method prevents Configure event loops when
808 // moving windows: Component.setBounds -> peer.setBounds ->
809 // postConfigureEvent -> Component.setBounds -> ... In some cases
810 // Configure event loops cause windows to jitter back and forth
811 // continuously).
812 void setBoundsCallback (int x, int y, int w, int h)
813 {
814 if (this.x == x && this.y == y && width == w && height == h)
815 return;
816 invalidate();
817 boolean resized = width != w || height != h;
818 boolean moved = this.x != x || this.y != y;
819 this.x = x;
820 this.y = y;
821 width = w;
822 height = h;
823 if (resized)
824 {
825 ComponentEvent ce =
826 new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED);
827 getToolkit().getSystemEventQueue().postEvent(ce);
828 }
829 if (moved)
830 {
831 ComponentEvent ce =
832 new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED);
833 getToolkit().getSystemEventQueue().postEvent(ce);
834 }
835 }
836 }
This page took 0.071057 seconds and 5 git commands to generate.