001 /* Window.java --
002 Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.awt;
040
041 import java.awt.event.ComponentEvent;
042 import java.awt.event.WindowEvent;
043 import java.awt.event.WindowFocusListener;
044 import java.awt.event.WindowListener;
045 import java.awt.event.WindowStateListener;
046 import java.awt.image.BufferStrategy;
047 import java.awt.peer.WindowPeer;
048 import java.lang.ref.Reference;
049 import java.lang.ref.WeakReference;
050 import java.util.EventListener;
051 import java.util.Iterator;
052 import java.util.Locale;
053 import java.util.ResourceBundle;
054 import java.util.Vector;
055
056 import javax.accessibility.Accessible;
057 import javax.accessibility.AccessibleContext;
058 import javax.accessibility.AccessibleRole;
059 import javax.accessibility.AccessibleState;
060 import javax.accessibility.AccessibleStateSet;
061
062 /**
063 * This class represents a top-level window with no decorations.
064 *
065 * @author Aaron M. Renn (arenn@urbanophile.com)
066 * @author Warren Levy (warrenl@cygnus.com)
067 */
068 public class Window extends Container implements Accessible
069 {
070 private static final long serialVersionUID = 4497834738069338734L;
071
072 // Serialized fields, from Sun's serialization spec.
073 private String warningString = null;
074 private int windowSerializedDataVersion = 0; // FIXME
075 /** @since 1.2 */
076 // private FocusManager focusMgr; // FIXME: what is this?
077 /** @since 1.2 */
078 private int state = 0;
079 /** @since 1.4 */
080 private boolean focusableWindowState = true;
081 /** @since 1.5 */
082 private boolean alwaysOnTop = false;
083
084 // A list of other top-level windows owned by this window.
085 private transient Vector ownedWindows = new Vector();
086
087 private transient WindowListener windowListener;
088 private transient WindowFocusListener windowFocusListener;
089 private transient WindowStateListener windowStateListener;
090
091 private transient boolean shown;
092
093 // This is package-private to avoid an accessor method.
094 transient Component windowFocusOwner;
095
096 /*
097 * The number used to generate the name returned by getName.
098 */
099 private static transient long next_window_number;
100
101 protected class AccessibleAWTWindow extends AccessibleAWTContainer
102 {
103 private static final long serialVersionUID = 4215068635060671780L;
104
105 public AccessibleRole getAccessibleRole()
106 {
107 return AccessibleRole.WINDOW;
108 }
109
110 public AccessibleStateSet getAccessibleStateSet()
111 {
112 AccessibleStateSet states = super.getAccessibleStateSet();
113 if (isActive())
114 states.add(AccessibleState.ACTIVE);
115 return states;
116 }
117 }
118
119 /**
120 * This (package access) constructor is used by subclasses that want
121 * to build windows that do not have parents. Eg. toplevel
122 * application frames. Subclasses cannot call super(null), since
123 * null is an illegal argument.
124 */
125 Window()
126 {
127 visible = false;
128 // Windows are the only Containers that default to being focus
129 // cycle roots.
130 focusCycleRoot = true;
131 setLayout(new BorderLayout());
132
133 GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
134 graphicsConfig = g.getDefaultScreenDevice().getDefaultConfiguration();
135 }
136
137 Window(GraphicsConfiguration gc)
138 {
139 this();
140 graphicsConfig = gc;
141 }
142
143 /**
144 * Initializes a new instance of <code>Window</code> with the specified
145 * parent. The window will initially be invisible.
146 *
147 * @param owner The owning <code>Frame</code> of this window.
148 *
149 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
150 * is not from a screen device, or if owner is null; this exception is always
151 * thrown when GraphicsEnvironment.isHeadless returns true.
152 */
153 public Window(Frame owner)
154 {
155 this (owner, owner.getGraphicsConfiguration ());
156 }
157
158 /**
159 * Initializes a new instance of <code>Window</code> with the specified
160 * parent. The window will initially be invisible.
161 *
162 * @exception IllegalArgumentException If the owner's GraphicsConfiguration
163 * is not from a screen device, or if owner is null; this exception is always
164 * thrown when GraphicsEnvironment.isHeadless returns true.
165 *
166 * @since 1.2
167 */
168 public Window(Window owner)
169 {
170 this (owner, owner.getGraphicsConfiguration ());
171 }
172
173 /**
174 * Initializes a new instance of <code>Window</code> with the specified
175 * parent. The window will initially be invisible.
176 *
177 * @exception IllegalArgumentException If owner is null or if gc is not from a
178 * screen device; this exception is always thrown when
179 * GraphicsEnvironment.isHeadless returns true.
180 *
181 * @since 1.3
182 */
183 public Window(Window owner, GraphicsConfiguration gc)
184 {
185 this ();
186
187 synchronized (getTreeLock())
188 {
189 if (owner == null)
190 throw new IllegalArgumentException ("owner must not be null");
191
192 parent = owner;
193 owner.ownedWindows.add(new WeakReference(this));
194 }
195
196 // FIXME: make this text visible in the window.
197 SecurityManager s = System.getSecurityManager();
198 if (s != null && ! s.checkTopLevelWindow(this))
199 warningString = System.getProperty("awt.appletWarning");
200
201 if (gc != null
202 && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
203 throw new IllegalArgumentException ("gc must be from a screen device");
204
205 if (gc == null)
206 graphicsConfig = GraphicsEnvironment.getLocalGraphicsEnvironment()
207 .getDefaultScreenDevice()
208 .getDefaultConfiguration();
209 else
210 graphicsConfig = gc;
211 }
212
213 /**
214 * Creates the native peer for this window.
215 */
216 public void addNotify()
217 {
218 if (peer == null)
219 peer = getToolkit().createWindow(this);
220 super.addNotify();
221 }
222
223 /**
224 * Relays out this window's child components at their preferred size.
225 *
226 * @specnote pack() doesn't appear to be called internally by show(), so
227 * we duplicate some of the functionality.
228 */
229 public void pack()
230 {
231 if (parent != null && !parent.isDisplayable())
232 parent.addNotify();
233 if (peer == null)
234 addNotify();
235
236 setSize(getPreferredSize());
237
238 validate();
239 }
240
241 /**
242 * Shows on-screen this window and any of its owned windows for whom
243 * isVisible returns true.
244 * @specnote: Deprecated starting in 1.5.
245 */
246 @Deprecated
247 public void show()
248 {
249 synchronized (getTreeLock())
250 {
251 if (peer == null)
252 addNotify();
253
254 validate();
255 if (visible)
256 toFront();
257 else
258 {
259 super.show();
260 // Show visible owned windows.
261 Iterator e = ownedWindows.iterator();
262 while (e.hasNext())
263 {
264 Window w = (Window) (((Reference) e.next()).get());
265 if (w != null)
266 {
267 if (w.isVisible())
268 w.getPeer().setVisible(true);
269 }
270 else
271 // Remove null weak reference from ownedWindows.
272 // Unfortunately this can't be done in the Window's
273 // finalize method because there is no way to guarantee
274 // synchronous access to ownedWindows there.
275 e.remove();
276 }
277 }
278 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
279 manager.setGlobalFocusedWindow(this);
280
281 if (! shown)
282 {
283 FocusTraversalPolicy policy = getFocusTraversalPolicy();
284 Component initialFocusOwner = null;
285
286 if (policy != null)
287 initialFocusOwner = policy.getInitialComponent(this);
288
289 if (initialFocusOwner != null)
290 initialFocusOwner.requestFocusInWindow();
291
292 // Post WINDOW_OPENED from here.
293 if (windowListener != null
294 || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
295 {
296 WindowEvent ev = new WindowEvent(this,
297 WindowEvent.WINDOW_OPENED);
298 Toolkit tk = Toolkit.getDefaultToolkit();
299 tk.getSystemEventQueue().postEvent(ev);
300 }
301 shown = true;
302 }
303 }
304 }
305
306 /**
307 * @specnote: Deprecated starting in 1.5.
308 */
309 @Deprecated
310 public void hide()
311 {
312 // Hide visible owned windows.
313 synchronized (getTreeLock ())
314 {
315 Iterator e = ownedWindows.iterator();
316 while(e.hasNext())
317 {
318 Window w = (Window)(((Reference) e.next()).get());
319 if (w != null)
320 {
321 if (w.isVisible() && w.getPeer() != null)
322 w.getPeer().setVisible(false);
323 }
324 else
325 e.remove();
326 }
327 }
328 super.hide();
329 }
330
331 /**
332 * Destroys any resources associated with this window. This includes
333 * all components in the window and all owned top-level windows.
334 */
335 public void dispose()
336 {
337 hide();
338
339 synchronized (getTreeLock ())
340 {
341 Iterator e = ownedWindows.iterator();
342 while(e.hasNext())
343 {
344 Window w = (Window)(((Reference) e.next()).get());
345 if (w != null)
346 w.dispose();
347 else
348 // Remove null weak reference from ownedWindows.
349 e.remove();
350 }
351
352 for (int i = 0; i < ncomponents; ++i)
353 component[i].removeNotify();
354 this.removeNotify();
355
356 // Post WINDOW_CLOSED from here.
357 if (windowListener != null
358 || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
359 {
360 WindowEvent ev = new WindowEvent(this,
361 WindowEvent.WINDOW_CLOSED);
362 Toolkit tk = Toolkit.getDefaultToolkit();
363 tk.getSystemEventQueue().postEvent(ev);
364 }
365 }
366 }
367
368 /**
369 * Sends this window to the back so that all other windows display in
370 * front of it.
371 *
372 * If the window is set to be always-on-top, this will remove its
373 * always-on-top status.
374 */
375 public void toBack()
376 {
377 if (peer != null)
378 {
379 if( alwaysOnTop )
380 setAlwaysOnTop( false );
381 ( (WindowPeer) peer ).toBack();
382 }
383 }
384
385 /**
386 * Brings this window to the front so that it displays in front of
387 * any other windows.
388 */
389 public void toFront()
390 {
391 if (peer != null)
392 ( (WindowPeer) peer ).toFront();
393 }
394
395 /**
396 * Returns the toolkit used to create this window.
397 *
398 * @return The toolkit used to create this window.
399 *
400 * @specnote Unlike Component.getToolkit, this implementation always
401 * returns the value of Toolkit.getDefaultToolkit().
402 */
403 public Toolkit getToolkit()
404 {
405 return Toolkit.getDefaultToolkit();
406 }
407
408 /**
409 * Returns the warning string that will be displayed if this window is
410 * popped up by an unsecure applet or application.
411 *
412 * @return The unsecure window warning message.
413 */
414 public final String getWarningString()
415 {
416 return warningString;
417 }
418
419 /**
420 * Returns the locale that this window is configured for.
421 *
422 * @return The locale this window is configured for.
423 */
424 public Locale getLocale()
425 {
426 return locale == null ? Locale.getDefault() : locale;
427 }
428
429 /*
430 /** @since 1.2
431 public InputContext getInputContext()
432 {
433 // FIXME
434 }
435 */
436
437 /**
438 * Sets the cursor for this window to the specifiec cursor.
439 *
440 * @param cursor The new cursor for this window.
441 */
442 public void setCursor(Cursor cursor)
443 {
444 super.setCursor(cursor);
445 }
446
447 public Window getOwner()
448 {
449 return (Window) parent;
450 }
451
452 /** @since 1.2 */
453 public Window[] getOwnedWindows()
454 {
455 Window [] trimmedList;
456 synchronized (getTreeLock ())
457 {
458 // Windows with non-null weak references in ownedWindows.
459 Window [] validList = new Window [ownedWindows.size()];
460
461 Iterator e = ownedWindows.iterator();
462 int numValid = 0;
463 while (e.hasNext())
464 {
465 Window w = (Window)(((Reference) e.next()).get());
466 if (w != null)
467 validList[numValid++] = w;
468 else
469 // Remove null weak reference from ownedWindows.
470 e.remove();
471 }
472
473 if (numValid != validList.length)
474 {
475 trimmedList = new Window [numValid];
476 System.arraycopy (validList, 0, trimmedList, 0, numValid);
477 }
478 else
479 trimmedList = validList;
480 }
481 return trimmedList;
482 }
483
484 /**
485 * Adds the specified listener to the list of <code>WindowListeners</code>
486 * that will receive events for this window.
487 *
488 * @param listener The <code>WindowListener</code> to add.
489 */
490 public synchronized void addWindowListener(WindowListener listener)
491 {
492 if (listener != null)
493 {
494 newEventsOnly = true;
495 windowListener = AWTEventMulticaster.add(windowListener, listener);
496 }
497 }
498
499 /**
500 * Removes the specified listener from the list of
501 * <code>WindowListeners</code> that will receive events for this window.
502 *
503 * @param listener The <code>WindowListener</code> to remove.
504 */
505 public synchronized void removeWindowListener(WindowListener listener)
506 {
507 windowListener = AWTEventMulticaster.remove(windowListener, listener);
508 }
509
510 /**
511 * Returns an array of all the window listeners registered on this window.
512 *
513 * @since 1.4
514 */
515 public synchronized WindowListener[] getWindowListeners()
516 {
517 return (WindowListener[])
518 AWTEventMulticaster.getListeners(windowListener,
519 WindowListener.class);
520 }
521
522 /**
523 * Returns an array of all the window focus listeners registered on this
524 * window.
525 *
526 * @since 1.4
527 */
528 public synchronized WindowFocusListener[] getWindowFocusListeners()
529 {
530 return (WindowFocusListener[])
531 AWTEventMulticaster.getListeners(windowFocusListener,
532 WindowFocusListener.class);
533 }
534
535 /**
536 * Returns an array of all the window state listeners registered on this
537 * window.
538 *
539 * @since 1.4
540 */
541 public synchronized WindowStateListener[] getWindowStateListeners()
542 {
543 return (WindowStateListener[])
544 AWTEventMulticaster.getListeners(windowStateListener,
545 WindowStateListener.class);
546 }
547
548 /**
549 * Adds the specified listener to this window.
550 */
551 public void addWindowFocusListener (WindowFocusListener wfl)
552 {
553 if (wfl != null)
554 {
555 newEventsOnly = true;
556 windowFocusListener = AWTEventMulticaster.add (windowFocusListener,
557 wfl);
558 }
559 }
560
561 /**
562 * Adds the specified listener to this window.
563 *
564 * @since 1.4
565 */
566 public void addWindowStateListener (WindowStateListener wsl)
567 {
568 if (wsl != null)
569 {
570 newEventsOnly = true;
571 windowStateListener = AWTEventMulticaster.add (windowStateListener,
572 wsl);
573 }
574 }
575
576 /**
577 * Removes the specified listener from this window.
578 */
579 public void removeWindowFocusListener (WindowFocusListener wfl)
580 {
581 windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
582 }
583
584 /**
585 * Removes the specified listener from this window.
586 *
587 * @since 1.4
588 */
589 public void removeWindowStateListener (WindowStateListener wsl)
590 {
591 windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
592 }
593
594 /**
595 * Returns an array of all the objects currently registered as FooListeners
596 * upon this Window. FooListeners are registered using the addFooListener
597 * method.
598 *
599 * @exception ClassCastException If listenerType doesn't specify a class or
600 * interface that implements java.util.EventListener.
601 *
602 * @since 1.3
603 */
604 public <T extends EventListener> T[] getListeners(Class<T> listenerType)
605 {
606 if (listenerType == WindowListener.class)
607 return (T[]) getWindowListeners();
608 return super.getListeners(listenerType);
609 }
610
611 void dispatchEventImpl(AWTEvent e)
612 {
613 if (e.getID() == ComponentEvent.COMPONENT_RESIZED)
614 {
615 invalidate();
616 validate();
617 }
618 super.dispatchEventImpl(e);
619 }
620
621 /**
622 * Processes the specified event for this window. If the event is an
623 * instance of <code>WindowEvent</code>, then
624 * <code>processWindowEvent()</code> is called to process the event,
625 * otherwise the superclass version of this method is invoked.
626 *
627 * @param evt The event to process.
628 */
629 protected void processEvent(AWTEvent evt)
630 {
631 if (evt instanceof WindowEvent)
632 {
633 WindowEvent we = (WindowEvent) evt;
634 switch (evt.getID())
635 {
636 case WindowEvent.WINDOW_OPENED:
637 case WindowEvent.WINDOW_CLOSED:
638 case WindowEvent.WINDOW_CLOSING:
639 case WindowEvent.WINDOW_ICONIFIED:
640 case WindowEvent.WINDOW_DEICONIFIED:
641 case WindowEvent.WINDOW_ACTIVATED:
642 case WindowEvent.WINDOW_DEACTIVATED:
643 processWindowEvent(we);
644 break;
645 case WindowEvent.WINDOW_GAINED_FOCUS:
646 case WindowEvent.WINDOW_LOST_FOCUS:
647 processWindowFocusEvent(we);
648 break;
649 case WindowEvent.WINDOW_STATE_CHANGED:
650 processWindowStateEvent(we);
651 break;
652 }
653 }
654 else
655 super.processEvent(evt);
656 }
657
658 /**
659 * Dispatches this event to any listeners that are listening for
660 * <code>WindowEvents</code> on this window. This method only gets
661 * invoked if it is enabled via <code>enableEvents()</code> or if
662 * a listener has been added.
663 *
664 * @param evt The event to process.
665 */
666 protected void processWindowEvent(WindowEvent evt)
667 {
668 if (windowListener != null)
669 {
670 switch (evt.getID())
671 {
672 case WindowEvent.WINDOW_ACTIVATED:
673 windowListener.windowActivated(evt);
674 break;
675 case WindowEvent.WINDOW_CLOSED:
676 windowListener.windowClosed(evt);
677 break;
678 case WindowEvent.WINDOW_CLOSING:
679 windowListener.windowClosing(evt);
680 break;
681 case WindowEvent.WINDOW_DEACTIVATED:
682 windowListener.windowDeactivated(evt);
683 break;
684 case WindowEvent.WINDOW_DEICONIFIED:
685 windowListener.windowDeiconified(evt);
686 break;
687 case WindowEvent.WINDOW_ICONIFIED:
688 windowListener.windowIconified(evt);
689 break;
690 case WindowEvent.WINDOW_OPENED:
691 windowListener.windowOpened(evt);
692 break;
693 }
694 }
695 }
696
697 /**
698 * Identifies if this window is active. The active window is a Frame or
699 * Dialog that has focus or owns the active window.
700 *
701 * @return true if active, else false.
702 * @since 1.4
703 */
704 public boolean isActive()
705 {
706 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
707 return manager.getActiveWindow() == this;
708 }
709
710 /**
711 * Identifies if this window is focused. A window is focused if it is the
712 * focus owner or it contains the focus owner.
713 *
714 * @return true if focused, else false.
715 * @since 1.4
716 */
717 public boolean isFocused()
718 {
719 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
720 return manager.getFocusedWindow() == this;
721 }
722
723 /**
724 * Returns the child window that has focus if this window is active.
725 * This method returns <code>null</code> if this window is not active
726 * or no children have focus.
727 *
728 * @return The component that has focus, or <code>null</code> if no
729 * component has focus.
730 */
731 public Component getFocusOwner ()
732 {
733 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
734
735 Window activeWindow = manager.getActiveWindow ();
736
737 // The currently-focused Component belongs to the active Window.
738 if (activeWindow == this)
739 return manager.getFocusOwner ();
740 else
741 return null;
742 }
743
744 /**
745 * Returns the child component of this window that would receive
746 * focus if this window were to become focused. If the window
747 * already has the top-level focus, then this method returns the
748 * same component as getFocusOwner. If no child component has
749 * requested focus within the window, then the initial focus owner
750 * is returned. If this is a non-focusable window, this method
751 * returns null.
752 *
753 * @return the child component of this window that most recently had
754 * the focus, or <code>null</code>
755 * @since 1.4
756 */
757 public Component getMostRecentFocusOwner ()
758 {
759 return windowFocusOwner;
760 }
761
762 /**
763 * Set the focus owner for this window. This method is used to
764 * remember which component was focused when this window lost
765 * top-level focus, so that when it regains top-level focus the same
766 * child component can be refocused.
767 *
768 * @param windowFocusOwner the component in this window that owns
769 * the focus.
770 */
771 void setFocusOwner (Component windowFocusOwner)
772 {
773 this.windowFocusOwner = windowFocusOwner;
774 }
775
776 /**
777 * Post a Java 1.0 event to the event queue.
778 *
779 * @param e The event to post.
780 *
781 * @deprecated
782 */
783 public boolean postEvent(Event e)
784 {
785 return handleEvent (e);
786 }
787
788 /**
789 * Tests whether or not this window is visible on the screen.
790 *
791 * In contrast to the normal behaviour of Container, which is that
792 * a container is showing if its parent is visible and showing, a Window
793 * is even showing, if its parent (i.e. an invisible Frame) is not showing.
794 *
795 * @return <code>true</code> if this window is visible, <code>false</code>
796 * otherwise.
797 */
798 public boolean isShowing()
799 {
800 return isVisible();
801 }
802
803 public void setLocationRelativeTo(Component c)
804 {
805 int x = 0;
806 int y = 0;
807
808 if (c == null || !c.isShowing())
809 {
810 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
811 Point center = ge.getCenterPoint();
812 x = center.x - (width / 2);
813 y = center.y - (height / 2);
814 }
815 else
816 {
817 int cWidth = c.getWidth();
818 int cHeight = c.getHeight();
819 Dimension screenSize = getToolkit().getScreenSize();
820
821 x = c.getLocationOnScreen().x;
822 y = c.getLocationOnScreen().y;
823
824 // If bottom of component is cut off, window placed
825 // on the left or the right side of component
826 if ((y + cHeight) > screenSize.height)
827 {
828 // If the right side of the component is closer to the center
829 if ((screenSize.width / 2 - x) <= 0)
830 {
831 if ((x - width) >= 0)
832 x -= width;
833 else
834 x = 0;
835 }
836 else
837 {
838 if ((x + cWidth + width) <= screenSize.width)
839 x += cWidth;
840 else
841 x = screenSize.width - width;
842 }
843
844 y = screenSize.height - height;
845 }
846 else if (cWidth > width || cHeight > height)
847 {
848 // If right side of component is cut off
849 if ((x + width) > screenSize.width)
850 x = screenSize.width - width;
851 // If left side of component is cut off
852 else if (x < 0)
853 x = 0;
854 else
855 x += (cWidth - width) / 2;
856
857 y += (cHeight - height) / 2;
858 }
859 else
860 {
861 // If right side of component is cut off
862 if ((x + width) > screenSize.width)
863 x = screenSize.width - width;
864 // If left side of component is cut off
865 else if (x < 0 || (x - (width - cWidth) / 2) < 0)
866 x = 0;
867 else
868 x -= (width - cWidth) / 2;
869
870 if ((y - (height - cHeight) / 2) > 0)
871 y -= (height - cHeight) / 2;
872 else
873 y = 0;
874 }
875 }
876
877 setLocation(x, y);
878 }
879
880 /**
881 * A BltBufferStrategy for windows.
882 */
883 private class WindowBltBufferStrategy extends BltBufferStrategy
884 {
885 /**
886 * Creates a block transfer strategy for this window.
887 *
888 * @param numBuffers the number of buffers in this strategy
889 * @param accelerated true if the buffer should be accelerated,
890 * false otherwise
891 */
892 WindowBltBufferStrategy(int numBuffers, boolean accelerated)
893 {
894 super(numBuffers,
895 new BufferCapabilities(new ImageCapabilities(accelerated),
896 new ImageCapabilities(accelerated),
897 BufferCapabilities.FlipContents.COPIED));
898 }
899 }
900
901 /**
902 * A FlipBufferStrategy for windows.
903 */
904 private class WindowFlipBufferStrategy extends FlipBufferStrategy
905 {
906 /**
907 * Creates a flip buffer strategy for this window.
908 *
909 * @param numBuffers the number of buffers in this strategy
910 *
911 * @throws AWTException if the requested number of buffers is not
912 * supported
913 */
914 WindowFlipBufferStrategy(int numBuffers)
915 throws AWTException
916 {
917 super(numBuffers,
918 new BufferCapabilities(new ImageCapabilities(true),
919 new ImageCapabilities(true),
920 BufferCapabilities.FlipContents.COPIED));
921 }
922 }
923
924 /**
925 * Creates a buffering strategy that manages how this window is
926 * repainted. This method attempts to create the optimum strategy
927 * based on the desired number of buffers. Hardware or software
928 * acceleration may be used.
929 *
930 * createBufferStrategy attempts different levels of optimization,
931 * but guarantees that some strategy with the requested number of
932 * buffers will be created even if it is not optimal. First it
933 * attempts to create a page flipping strategy, then an accelerated
934 * blitting strategy, then an unaccelerated blitting strategy.
935 *
936 * Calling this method causes any existing buffer strategy to be
937 * destroyed.
938 *
939 * @param numBuffers the number of buffers in this strategy
940 *
941 * @throws IllegalArgumentException if requested number of buffers
942 * is less than one
943 * @throws IllegalStateException if this window is not displayable
944 *
945 * @since 1.4
946 */
947 public void createBufferStrategy(int numBuffers)
948 {
949 if (numBuffers < 1)
950 throw new IllegalArgumentException("Window.createBufferStrategy: number"
951 + " of buffers is less than one");
952
953 if (!isDisplayable())
954 throw new IllegalStateException("Window.createBufferStrategy: window is"
955 + " not displayable");
956
957 BufferStrategy newStrategy = null;
958
959 // try a flipping strategy
960 try
961 {
962 newStrategy = new WindowFlipBufferStrategy(numBuffers);
963 }
964 catch (AWTException e)
965 {
966 }
967
968 // fall back to an accelerated blitting strategy
969 if (newStrategy == null)
970 newStrategy = new WindowBltBufferStrategy(numBuffers, true);
971
972 bufferStrategy = newStrategy;
973 }
974
975 /**
976 * Creates a buffering strategy that manages how this window is
977 * repainted. This method attempts to create a strategy based on
978 * the specified capabilities and throws an exception if the
979 * requested strategy is not supported.
980 *
981 * Calling this method causes any existing buffer strategy to be
982 * destroyed.
983 *
984 * @param numBuffers the number of buffers in this strategy
985 * @param caps the requested buffering capabilities
986 *
987 * @throws AWTException if the requested capabilities are not
988 * supported
989 * @throws IllegalArgumentException if requested number of buffers
990 * is less than one or if caps is null
991 *
992 * @since 1.4
993 */
994 public void createBufferStrategy(int numBuffers, BufferCapabilities caps)
995 throws AWTException
996 {
997 if (numBuffers < 1)
998 throw new IllegalArgumentException("Window.createBufferStrategy: number"
999 + " of buffers is less than one");
1000
1001 if (caps == null)
1002 throw new IllegalArgumentException("Window.createBufferStrategy:"
1003 + " capabilities object is null");
1004
1005 // a flipping strategy was requested
1006 if (caps.isPageFlipping())
1007 bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
1008 else
1009 bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
1010 }
1011
1012 /**
1013 * Returns the buffer strategy used by the window.
1014 *
1015 * @return the buffer strategy.
1016 * @since 1.4
1017 */
1018 public BufferStrategy getBufferStrategy()
1019 {
1020 return bufferStrategy;
1021 }
1022
1023 /**
1024 * @since 1.2
1025 *
1026 * @deprecated replaced by Component.applyComponentOrientation.
1027 */
1028 public void applyResourceBundle(ResourceBundle rb)
1029 {
1030 applyComponentOrientation(ComponentOrientation.getOrientation(rb));
1031 }
1032
1033 /**
1034 * @since 1.2
1035 *
1036 * @deprecated
1037 */
1038 public void applyResourceBundle(String rbName)
1039 {
1040 ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
1041 ClassLoader.getSystemClassLoader());
1042 if (rb != null)
1043 applyResourceBundle(rb);
1044 }
1045
1046 /**
1047 * Gets the AccessibleContext associated with this <code>Window</code>.
1048 * The context is created, if necessary.
1049 *
1050 * @return the associated context
1051 */
1052 public AccessibleContext getAccessibleContext()
1053 {
1054 /* Create the context if this is the first request */
1055 if (accessibleContext == null)
1056 accessibleContext = new AccessibleAWTWindow();
1057 return accessibleContext;
1058 }
1059
1060 /**
1061 * Get graphics configuration. The implementation for Window will
1062 * not ask any parent containers, since Window is a toplevel
1063 * window and not actually embedded in the parent component.
1064 */
1065 public GraphicsConfiguration getGraphicsConfiguration()
1066 {
1067 GraphicsConfiguration conf = graphicsConfig;
1068 if (conf == null)
1069 {
1070 conf = GraphicsEnvironment.getLocalGraphicsEnvironment()
1071 .getDefaultScreenDevice().getDefaultConfiguration();
1072 graphicsConfig = conf;
1073 }
1074 return conf;
1075 }
1076
1077 protected void processWindowFocusEvent(WindowEvent event)
1078 {
1079 if (windowFocusListener != null)
1080 {
1081 switch (event.getID ())
1082 {
1083 case WindowEvent.WINDOW_GAINED_FOCUS:
1084 windowFocusListener.windowGainedFocus (event);
1085 break;
1086
1087 case WindowEvent.WINDOW_LOST_FOCUS:
1088 windowFocusListener.windowLostFocus (event);
1089 break;
1090
1091 default:
1092 break;
1093 }
1094 }
1095 }
1096
1097 /**
1098 * @since 1.4
1099 */
1100 protected void processWindowStateEvent(WindowEvent event)
1101 {
1102 if (windowStateListener != null
1103 && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
1104 windowStateListener.windowStateChanged (event);
1105 }
1106
1107 /**
1108 * Returns whether this <code>Window</code> can get the focus or not.
1109 *
1110 * @since 1.4
1111 */
1112 public final boolean isFocusableWindow ()
1113 {
1114 if (getFocusableWindowState () == false)
1115 return false;
1116
1117 if (this instanceof Dialog
1118 || this instanceof Frame)
1119 return true;
1120
1121 // FIXME: Implement more possible cases for returning true.
1122
1123 return false;
1124 }
1125
1126 /**
1127 * Returns the value of the focusableWindowState property.
1128 *
1129 * @since 1.4
1130 */
1131 public boolean getFocusableWindowState ()
1132 {
1133 return focusableWindowState;
1134 }
1135
1136 /**
1137 * Sets the value of the focusableWindowState property.
1138 *
1139 * @since 1.4
1140 */
1141 public void setFocusableWindowState (boolean focusableWindowState)
1142 {
1143 this.focusableWindowState = focusableWindowState;
1144 }
1145
1146 /**
1147 * Check whether this Container is a focus cycle root.
1148 * Returns always <code>true</code> as Windows are the
1149 * root of the focus cycle.
1150 *
1151 * @return Always <code>true</code>.
1152 *
1153 * @since 1.4
1154 */
1155 public final boolean isFocusCycleRoot()
1156 {
1157 return true;
1158 }
1159
1160 /**
1161 * Set whether or not this Container is the root of a focus
1162 * traversal cycle. Windows are the root of the focus cycle
1163 * and therefore this method does nothing.
1164 *
1165 * @param focusCycleRoot ignored.
1166 *
1167 * @since 1.4
1168 */
1169 public final void setFocusCycleRoot(boolean focusCycleRoot)
1170 {
1171 // calls to the method are ignored
1172 }
1173
1174 /**
1175 * Returns the root container that owns the focus cycle where this
1176 * component resides. Windows have no ancestors and this method
1177 * returns always <code>null</code>.
1178 *
1179 * @return Always <code>null</code>.
1180 * @since 1.4
1181 */
1182 public final Container getFocusCycleRootAncestor()
1183 {
1184 return null;
1185 }
1186
1187 /**
1188 * Returns whether the Windows is an always-on-top window,
1189 * meaning whether the window can be obscured by other windows or not.
1190 *
1191 * @return <code>true</code> if the windows is always-on-top,
1192 * <code>false</code> otherwise.
1193 * @since 1.5
1194 */
1195 public final boolean isAlwaysOnTop()
1196 {
1197 return alwaysOnTop;
1198 }
1199
1200 /**
1201 * Sets the always-on-top state of this window (if supported).
1202 *
1203 * Setting a window to always-on-top means it will not be obscured
1204 * by any other windows (with the exception of other always-on-top
1205 * windows). Not all platforms may support this.
1206 *
1207 * If an window's always-on-top status is changed to false, the window
1208 * will remain at the front but not be anchored there.
1209 *
1210 * Calling toBack() on an always-on-top window will change its
1211 * always-on-top status to false.
1212 *
1213 * @since 1.5
1214 */
1215 public final void setAlwaysOnTop(boolean alwaysOnTop)
1216 {
1217 SecurityManager sm = System.getSecurityManager();
1218 if (sm != null)
1219 sm.checkPermission( new AWTPermission("setWindowAlwaysOnTop") );
1220
1221 if( this.alwaysOnTop == alwaysOnTop )
1222 return;
1223
1224 if( alwaysOnTop )
1225 toFront();
1226
1227 firePropertyChange("alwaysOnTop", this.alwaysOnTop, alwaysOnTop );
1228 this.alwaysOnTop = alwaysOnTop;
1229
1230 if (peer != null)
1231 ( (WindowPeer) peer).updateAlwaysOnTop();
1232 else
1233 System.out.println("Null peer?!");
1234 }
1235
1236 /**
1237 * Generate a unique name for this window.
1238 *
1239 * @return A unique name for this window.
1240 */
1241 String generateName()
1242 {
1243 return "win" + getUniqueLong();
1244 }
1245
1246 /**
1247 * Overridden to handle WindowEvents.
1248 *
1249 * @return <code>true</code> when the specified event type is enabled,
1250 * <code>false</code> otherwise
1251 */
1252 boolean eventTypeEnabled(int type)
1253 {
1254 boolean enabled = false;
1255 switch (type)
1256 {
1257 case WindowEvent.WINDOW_OPENED:
1258 case WindowEvent.WINDOW_CLOSED:
1259 case WindowEvent.WINDOW_CLOSING:
1260 case WindowEvent.WINDOW_ICONIFIED:
1261 case WindowEvent.WINDOW_DEICONIFIED:
1262 case WindowEvent.WINDOW_ACTIVATED:
1263 case WindowEvent.WINDOW_DEACTIVATED:
1264 enabled = ((eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
1265 || windowListener != null;
1266 break;
1267 case WindowEvent.WINDOW_GAINED_FOCUS:
1268 case WindowEvent.WINDOW_LOST_FOCUS:
1269 enabled = ((eventMask & AWTEvent.WINDOW_FOCUS_EVENT_MASK) != 0)
1270 || windowFocusListener != null;
1271 break;
1272 case WindowEvent.WINDOW_STATE_CHANGED:
1273 enabled = ((eventMask & AWTEvent.WINDOW_STATE_EVENT_MASK) != 0)
1274 || windowStateListener != null;
1275 break;
1276 default:
1277 enabled = super.eventTypeEnabled(type);
1278 }
1279 return enabled;
1280 }
1281
1282 private static synchronized long getUniqueLong()
1283 {
1284 return next_window_number++;
1285 }
1286 }