001: /*
002: * @(#)Window.java 1.12 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program 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 version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: /*
029: * Warning :
030: * Two versions of this file exist in this workspace.
031: * One for Personal Basis, and one for Personal Profile.
032: * Don't edit the wrong one !!!
033: */
034:
035: package java.awt;
036:
037: import java.awt.event.*;
038: import java.util.Vector;
039: import java.util.Locale;
040: import java.util.Timer;
041: import java.util.TimerTask;
042: import java.io.Serializable;
043: import java.io.ObjectOutputStream;
044: import java.io.ObjectInputStream;
045: import java.io.IOException;
046: import java.lang.reflect.Constructor;
047: import sun.awt.FocusManagement;
048: import sun.awt.im.InputContext;
049: import java.security.AccessController;
050: import sun.security.action.GetPropertyAction;
051:
052: /**
053: * A <code>Window</code> object is a top-level window with no borders and no
054: * menubar. It could be used to implement a pop-up menu.
055: * The default layout for a window is <code>BorderLayout</code>.
056: * A <code>Window</code> object blocks input to other application
057: * windows when it is shown.
058: * <p>
059: * Windows are capable of generating the following window events:
060: * WindowOpened, WindowClosed.
061: * <h3>Compatibility</h3>
062: * The direct creation of Window objects is an optional feature
063: * in PersonalJava and Personal Profile implementations. If the
064: * implementation prohibits the direct creation of Window objects,
065: * the constructor throws and <code>UnsupportedOperationException</code>.
066: * <h3>System Properties</h3>
067: * <code>java.awt.SupportsWindow</code> is set to <code>"true"</code>
068: * or <code>"false"</code> indicating if the platform supports direct creation
069: * of window objects.
070: *
071: * @version 1.7, 08/19/02
072: * @author Nicholas Allen
073: * @see WindowEvent
074: * @see #addWindowListener
075: * @see java.awt.BorderLayout
076: * @since JDK1.0
077: */
078: public class Window extends Container {
079: String warningString;
080: static final int OPENED = 0x01;
081: int state;
082: transient WindowListener windowListener;
083: private transient boolean active;
084: transient InputContext inputContext;
085: //private FocusManager focusMgr; // For serialization. SUPERCEDED by:
086: transient private FocusManagement focusMgmt;
087: private static final String base = "win";
088: private static int nameCounter = 0;
089: /* Personal Java allows only one top-level window */
090: private static boolean madeOneAlready = false;
091: /*
092: * JDK 1.1 serialVersionUID
093: */
094: private static final long serialVersionUID = 4497834738069338734L;
095:
096: Window() {
097: setWarningString();
098: this .cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
099: checkSecurity();
100: // Compatibility for serialization
101: //this.focusMgr = new FocusManager(this);
102:
103: // Instantiate a pluggable focus manager instead
104: try {
105: Class paramTypes[] = new Class[1];
106: paramTypes[0] = Class.forName("java.awt.Container");
107: Object initArgs[] = new Object[1];
108: initArgs[0] = this ;
109: String s = (String) AccessController
110: .doPrivileged(new GetPropertyAction(
111: "awt.focusManger"));
112: if (s != null) {
113: Class c = Class.forName(s);
114: Constructor cons = c.getConstructor(paramTypes);
115: this .focusMgmt = (FocusManagement) cons
116: .newInstance(initArgs);
117: }
118: } catch (Throwable t) {
119: System.err.println("Problem instantiating focus manager:"
120: + t);
121: t.printStackTrace();
122: }
123: if (this .focusMgmt == null) {
124: this .focusMgmt = new sun.awt.TabFocusManager(this );
125: }
126: this .visible = false;
127: this .foreground = Color.black;
128: this .background = Color.lightGray;
129: this .font = new Font("Dialog", Font.PLAIN, 12);
130: }
131:
132: /**
133: * Construct a name for this component. Called by getName() when the
134: * name is null.
135: */
136: String constructComponentName() {
137: return base + nameCounter++;
138: }
139:
140: boolean isLightweightWhenDisplayable() {
141: return false;
142: }
143:
144: /**
145: * Constructs a new invisible window.
146: * <p>
147: * The window is not initially visible. Call the <code>show</code>
148: * method to cause the window to become visible.
149: * @param parent the main application frame.
150: * @exception UnsupportedOperationException if the implementation does
151: * not allow the direct creation of window objects.
152: * @see java.awt.Window#show
153: * @see java.awt.Component#setSize
154: * @since JDK1.0
155: */
156: public Window(Frame parent) {
157: this ();
158: if (parent == null) {
159: throw new IllegalArgumentException("null parent frame");
160: }
161: this .parent = parent;
162: parent.addOwnedWindow(this );
163: setLayout(new BorderLayout());
164: }
165:
166: private void checkSecurity() {/*if (this instanceof FileDialog) {
167: // FileDialog not allowed if minawt
168: throw new UnsupportedOperationException();
169: } else if (this instanceof Dialog) {
170: // Other Dialog is always OK
171: } else if (this instanceof sun.awt.EmbeddedFrame) {
172: // EmbeddedFrame is always OK
173: } else if (this instanceof Frame) {
174: if (madeOneAlready) {
175: // if minawt, only one regular Frame is allowed
176: throw new UnsupportedOperationException();
177: } else {
178: madeOneAlready = true;
179: }
180: } else {
181: // We've checked everything else, so this must be a plain Window.
182: // Not allowed if minawt
183: throw new UnsupportedOperationException();
184: }*/
185: }
186:
187: ComponentXWindow createXWindow() {
188: return new WindowXWindow(this );
189: }
190:
191: /**
192: * Causes subcomponents of this window to be laid out at their
193: * preferred size.
194: * @since JDK1.0
195: */
196: public void pack() {
197: Container parent = this .parent;
198: if (parent != null && parent.xwindow == null) {
199: parent.addNotify();
200: }
201: if (xwindow == null) {
202: addNotify();
203: }
204: setSize(getPreferredSize());
205: validate();
206: }
207:
208: /**
209: * Creates a graphics context for this component. This method will
210: * return <code>null</code> if this component is currently not on
211: * the screen.
212: * @return A graphics context for this component, or <code>null</code>
213: * if it has none.
214: * @see java.awt.Component#paint
215: * @since JDK1.0
216: */
217: public Graphics getGraphics() {
218: WindowXWindow xwindow = (WindowXWindow) this .xwindow;
219: if (xwindow != null)
220: return new X11Graphics(xwindow);
221: return null;
222: }
223:
224: public void validate() {
225: if (!valid) {
226: super .validate();
227: WindowXWindow xwindow = (WindowXWindow) this .xwindow;
228: if (xwindow != null) {
229: xwindow
230: .setSizeHints(getMinimumSize(),
231: getMaximumSize());
232: }
233: }
234: }
235:
236: public void update(Graphics g) {
237: g.clearRect(0, 0, width, height);
238: paint(g);
239: }
240:
241: /**
242: * Shows this window, and brings it to the front.
243: * <p>
244: * If this window is not yet visible, <code>show</code>
245: * makes it visible. If this window is already visible,
246: * then this method brings it to the front.
247: * @see java.awt.Window#toFront
248: * @see java.awt.Component#setVisible
249: * @since JDK1.0
250: */
251: public void show() {
252: Container parent = this .parent;
253: if (parent != null && parent.xwindow == null) {
254: parent.addNotify();
255: }
256: if (xwindow == null) {
257: addNotify();
258: }
259: validate();
260: if (visible) {
261: toFront();
262: } else {
263: super .show();
264: }
265: // If first time shown, generate WindowOpened event
266: if ((state & OPENED) == 0) {
267: postWindowEvent(WindowEvent.WINDOW_OPENED);
268: state |= OPENED;
269: }
270: }
271:
272: synchronized void postWindowEvent(int id) {
273: if (windowListener != null
274: || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0) {
275: WindowEvent e = new WindowEvent(this , id);
276: Toolkit.getEventQueue().postEvent(e);
277: }
278: }
279:
280: /**
281: * Disposes of this window. This method must
282: * be called to release the resources that
283: * are used for the window.
284: * @since JDK1.0
285: */
286: public void dispose() {
287: synchronized (getTreeLock()) {
288: if (inputContext != null) {
289: InputContext toDispose = inputContext;
290: inputContext = null;
291: toDispose.dispose();
292: }
293: hide();
294: removeNotify();
295: if (parent != null) {
296: Frame parent = (Frame) this .parent;
297: parent.removeOwnedWindow(this );
298: }
299: postWindowEvent(WindowEvent.WINDOW_CLOSED);
300: }
301: // allows next instance of Frame to be created
302: // as per PJAE spec 1.2.
303: if (this instanceof Frame) {
304: madeOneAlready = false;
305: }
306: }
307:
308: /**
309: * Brings this window to the front.
310: * Places this window at the top of the stacking order and
311: * shows it in front of any other windows.
312: * @see java.awt.Window#toBack
313: * @since JDK1.0
314: */
315: public void toFront() {
316: WindowXWindow xwindow = (WindowXWindow) this .xwindow;
317: if (xwindow != null) {
318: xwindow.toFront();
319: }
320: }
321:
322: /**
323: * Sends this window to the back.
324: * Places this window at the bottom of the stacking order and
325: * makes the corresponding adjustment to other visible windows.
326: * @see java.awt.Window#toFront
327: * @since JDK1.0
328: */
329: public void toBack() {
330: WindowXWindow xwindow = (WindowXWindow) this .xwindow;
331: if (xwindow != null) {
332: xwindow.toBack();
333: }
334: }
335:
336: /**
337: * Returns the toolkit of this frame.
338: * @return the toolkit of this window.
339: * @see java.awt.Toolkit
340: * @see java.awt.Toolkit#getDefaultToolkit()
341: * @see java.awt.Component#getToolkit()
342: * @since JDK1.0
343: */
344: public Toolkit getToolkit() {
345: return Toolkit.getDefaultToolkit();
346: }
347:
348: /**
349: * Gets the warning string that is displayed with this window.
350: * If this window is insecure, the warning string is displayed
351: * somewhere in the visible area of the window. A window is
352: * insecure if there is a security manager, and the security
353: * manager's <code>checkTopLevelWindow</code> method returns
354: * <code>false</code> when this window is passed to it as an
355: * argument.
356: * <p>
357: * If the window is secure, then <code>getWarningString</code>
358: * returns <code>null</code>. If the window is insecure, this
359: * method checks for the system property
360: * <code>awt.appletWarning</code>
361: * and returns the string value of that property.
362: * @return the warning string for this window.
363: * @see java.lang.SecurityManager#checkTopLevelWindow(java.lang.Object)
364: * @since JDK1.0
365: */
366: public final String getWarningString() {
367: return warningString;
368: }
369:
370: private void setWarningString() {
371: warningString = null;
372: SecurityManager sm = System.getSecurityManager();
373: if (sm != null) {
374: if (!sm.checkTopLevelWindow(this )) {
375: // make sure the privileged action is only
376: // for getting the property! We don't want the
377: // above checkTopLevelWindow call to always succeed!
378: warningString = (String) AccessController
379: .doPrivileged(new GetPropertyAction(
380: "awt.appletWarning",
381: "Warning: Applet Window"));
382: }
383: }
384: }
385:
386: /**
387: * Gets the <code>Locale</code> object that is associated
388: * with this window, if the locale has been set.
389: * If no locale has been set, then the default locale
390: * is returned.
391: * @return the locale that is set for this window.
392: * @see java.util.Locale
393: * @since JDK1.1
394: */
395:
396: public Locale getLocale() {
397: if (this .locale == null) {
398: return Locale.getDefault();
399: }
400: return this .locale;
401: }
402:
403: public Insets getInsets() {
404: WindowXWindow xwindow = (WindowXWindow) this .xwindow;
405: if (xwindow != null)
406: return new Insets(xwindow.topBorder, xwindow.leftBorder,
407: xwindow.bottomBorder, xwindow.rightBorder);
408: return super .getInsets();
409: }
410:
411: /**
412: * Gets the input context for this window. A window always has an input context,
413: * which is shared by subcomponents unless they create and set their own.
414: * @see Component#getInputContext
415: */
416:
417: synchronized InputContext getInputContext() {
418: if (inputContext == null) {
419: inputContext = InputContext.getInstance();
420: }
421: return inputContext;
422: }
423:
424: public void setBackground(Color c) {
425: super .setBackground(c);
426: WindowXWindow xwindow = (WindowXWindow) this .xwindow;
427: if (xwindow != null)
428: xwindow.setBackground(c);
429: }
430:
431: /**
432: * Set the cursor image to a predefined cursor.
433: * @param <code>cursor</code> One of the constants defined
434: * by the <code>Cursor</code> class. If this parameter is null
435: * then the cursor for this window will be set to the type
436: * Cursor.DEFAULT_CURSOR .
437: * @see java.awt.Component#getCursor
438: * @see java.awt.Cursor
439: * @since JDK1.1
440: */
441: public synchronized void setCursor(Cursor cursor) {
442: if (cursor == null) {
443: cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
444: }
445: super .setCursor(cursor);
446: }
447:
448: /**
449: * Adds the specified window listener to receive window events from
450: * this window.
451: * @param l the window listener
452: */
453: public synchronized void addWindowListener(WindowListener l) {
454: windowListener = AWTEventMulticaster.add(windowListener, l);
455: checkEnableNewEventsOnly(l);
456: }
457:
458: /**
459: * Removes the specified window listener so that it no longer
460: * receives window events from this window.
461: * @param l the window listener
462: */
463: public synchronized void removeWindowListener(WindowListener l) {
464: windowListener = AWTEventMulticaster.remove(windowListener, l);
465: }
466:
467: // NOTE: remove when filtering is handled at lower level
468: boolean eventEnabled(AWTEvent e) {
469: switch (e.id) {
470: case WindowEvent.WINDOW_OPENED:
471: case WindowEvent.WINDOW_CLOSING:
472: case WindowEvent.WINDOW_CLOSED:
473: case WindowEvent.WINDOW_ICONIFIED:
474: case WindowEvent.WINDOW_DEICONIFIED:
475: case WindowEvent.WINDOW_ACTIVATED:
476: case WindowEvent.WINDOW_DEACTIVATED:
477: if ((eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0
478: || windowListener != null) {
479: return true;
480: }
481: return false;
482:
483: default:
484: break;
485: }
486: return super .eventEnabled(e);
487: }
488:
489: /**
490: * Processes events on this window. If the event is an WindowEvent,
491: * it invokes the processWindowEvent method, else it invokes its
492: * superclass's processEvent.
493: * @param e the event
494: */
495: protected void processEvent(AWTEvent e) {
496: if (e instanceof WindowEvent) {
497: processWindowEvent((WindowEvent) e);
498: return;
499: }
500: super .processEvent(e);
501: }
502:
503: /**
504: * Processes window events occurring on this window by
505: * dispatching them to any registered WindowListener objects.
506: * NOTE: This method will not be called unless window events
507: * are enabled for this component; this happens when one of the
508: * following occurs:
509: * a) A WindowListener object is registered via addWindowListener()
510: * b) Window events are enabled via enableEvents()
511: * @see Component#enableEvents
512: * @param e the window event
513: */
514: protected void processWindowEvent(WindowEvent e) {
515: if (windowListener != null) {
516: switch (e.getID()) {
517: case WindowEvent.WINDOW_OPENED:
518: windowListener.windowOpened(e);
519: break;
520:
521: case WindowEvent.WINDOW_CLOSING:
522: windowListener.windowClosing(e);
523: break;
524:
525: case WindowEvent.WINDOW_CLOSED:
526: windowListener.windowClosed(e);
527: break;
528:
529: case WindowEvent.WINDOW_ICONIFIED:
530: windowListener.windowIconified(e);
531: break;
532:
533: case WindowEvent.WINDOW_DEICONIFIED:
534: windowListener.windowDeiconified(e);
535: break;
536:
537: case WindowEvent.WINDOW_ACTIVATED:
538: windowListener.windowActivated(e);
539: break;
540:
541: case WindowEvent.WINDOW_DEACTIVATED:
542: windowListener.windowDeactivated(e);
543: break;
544:
545: default:
546: break;
547: }
548: }
549: }
550:
551: void preProcessKeyEvent(KeyEvent e) {
552: // Dump the list of child windows to System.out.
553: if (e.isActionKey() && e.getKeyCode() == KeyEvent.VK_F1
554: && e.isControlDown() && e.isShiftDown()) {
555: list(System.out, 0);
556: }
557: }
558:
559: void postProcessKeyEvent(KeyEvent e) {
560: if (focusMgmt.handleKeyEvent(e)) {
561: e.consume();
562: return;
563: }
564: }
565:
566: boolean isActive() {
567: return active;
568: }
569:
570: public void repaint(long tm, int x, int y, final int width,
571: final int height) {
572: if (tm == 0)
573: Toolkit.getEventQueue().postEvent(
574: new PaintEvent(this , PaintEvent.UPDATE,
575: new Rectangle(x, y, width, height)));
576: else {
577: final int x1 = x;
578: final int y1 = y;
579: updateTimer.schedule(new TimerTask() {
580: public void run() {
581: Toolkit.getEventQueue().postEvent(
582: new PaintEvent(Window.this ,
583: PaintEvent.UPDATE, new Rectangle(
584: x1, y1, width, height)));
585: }
586: }, tm);
587: }
588: }
589:
590: void setFocusOwner(Component c) {
591: Component oldFocusOwner = focusMgmt.getFocusOwner();
592: if (oldFocusOwner != c) {
593: focusMgmt.setFocusOwner(c);
594: if (oldFocusOwner != null)
595: Toolkit.getEventQueue().postEvent(
596: new FocusEvent(oldFocusOwner,
597: FocusEvent.FOCUS_LOST, false));
598: Toolkit.getEventQueue()
599: .postEvent(
600: new FocusEvent(c, FocusEvent.FOCUS_GAINED,
601: !active));
602: }
603: }
604:
605: void transferFocus(Component base) {
606: nextFocus(base);
607: }
608:
609: /**
610: * Returns the child component of this Window which has focus if and
611: * only if this Window is active.
612: * @return the component with focus, or null if no children have focus
613: * assigned to them.
614: */
615: public Component getFocusOwner() {
616: //System.out.println("Window.getFocusOwner(), active:"+active+", owner:"+focusMgmt.getFocusOwner());
617: if (active)
618: return focusMgmt.getFocusOwner();
619: else
620: return null;
621: }
622:
623: /**
624: * @deprecated As of JDK version 1.1,
625: * replaced by <code>transferFocus(Component)</code>.
626: */
627: void nextFocus(Component base) {
628: focusMgmt.focusNext(base);
629: }
630:
631: /*
632: * Dispatches an event to this window or one of its sub components.
633: * @param e the event
634: */
635: void dispatchEventImpl(AWTEvent e) {
636: Thread.yield();
637: Component focusOwner;
638: switch (e.id) {
639: case ComponentEvent.COMPONENT_RESIZED:
640: int width = this .width;
641: int height = this .height;
642: if (width != lastResizeWidth || height != lastResizeHeight) {
643: invalidate();
644: validate();
645: repaint();
646: lastResizeWidth = width;
647: lastResizeHeight = height;
648: }
649: break;
650:
651: case WindowEvent.WINDOW_ACTIVATED:
652: active = true;
653: focusOwner = focusMgmt.getFocusOwner();
654: if (focusOwner == null)
655: setFocusOwner(this );
656: else
657: Toolkit.getEventQueue().postEvent(
658: new FocusEvent(focusOwner,
659: FocusEvent.FOCUS_GAINED, false));
660: break;
661:
662: case WindowEvent.WINDOW_DEACTIVATED:
663: active = false;
664: focusOwner = focusMgmt.getFocusOwner();
665: if (focusOwner != null)
666: Toolkit.getEventQueue().postEvent(
667: new FocusEvent(focusOwner,
668: FocusEvent.FOCUS_LOST, true));
669: break;
670:
671: case KeyEvent.KEY_PRESSED:
672: case KeyEvent.KEY_RELEASED:
673: case KeyEvent.KEY_TYPED:
674: focusOwner = focusMgmt.getFocusOwner();
675: KeyEvent keyEvent = (KeyEvent) e;
676: if (focusOwner != null && focusOwner != this )
677: focusOwner.dispatchEvent(new KeyEvent(focusOwner,
678: keyEvent.id, keyEvent.getWhen(), keyEvent
679: .getModifiers(), keyEvent.getKeyCode(),
680: keyEvent.getKeyChar()));
681: break;
682:
683: default:
684: break;
685: }
686: super .dispatchEventImpl(e);
687: }
688:
689: /**
690: * @deprecated As of JDK version 1.1
691: * replaced by <code>dispatchEvent(AWTEvent)</code>.
692: */
693: public boolean postEvent(Event e) {
694: if (handleEvent(e)) {
695: e.consume();
696: return true;
697: }
698: return false;
699: }
700:
701: /**
702: * Checks if this Window is showing on screen.
703: * @see java.awt.Component#setVisible(boolean)
704: */
705: public boolean isShowing() {
706: return visible;
707: }
708:
709: /* Serialization support.
710: */
711:
712: private int windowSerializedDataVersion = 1;
713:
714: private void writeObject(ObjectOutputStream s) throws IOException {
715: s.defaultWriteObject();
716: AWTEventMulticaster.save(s, windowListenerK, windowListener);
717: s.writeObject(null);
718: }
719:
720: private void readObject(ObjectInputStream s)
721: throws ClassNotFoundException, IOException {
722: s.defaultReadObject();
723: checkSecurity();
724: Object keyOrNull;
725: while (null != (keyOrNull = s.readObject())) {
726: String key = ((String) keyOrNull).intern();
727: if (windowListenerK == key)
728: addWindowListener((WindowListener) (s.readObject()));
729: else
730: // skip value for unrecognized key
731: s.readObject();
732: }
733: setWarningString();
734: }
735:
736: private int lastResizeWidth = -1;
737: private int lastResizeHeight = -1;
738: } // class Window
|