blob: 38d50d5d09fec933cfcbdb8dc94b5e7c13801cad [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package java.awt;
26
27import java.io.PrintStream;
28import java.io.PrintWriter;
29import java.util.Vector;
30import java.util.Locale;
31import java.util.EventListener;
32import java.util.Iterator;
33import java.util.HashSet;
34import java.util.Map;
35import java.util.Set;
36import java.util.Collections;
37import java.awt.peer.ComponentPeer;
38import java.awt.peer.ContainerPeer;
39import java.awt.peer.LightweightPeer;
40import java.awt.image.BufferStrategy;
41import java.awt.image.ImageObserver;
42import java.awt.image.ImageProducer;
43import java.awt.image.ColorModel;
44import java.awt.image.VolatileImage;
45import java.awt.event.*;
46import java.io.Serializable;
47import java.io.ObjectOutputStream;
48import java.io.ObjectInputStream;
49import java.io.IOException;
50import java.beans.PropertyChangeListener;
51import java.beans.PropertyChangeSupport;
52import java.awt.event.InputMethodListener;
53import java.awt.event.InputMethodEvent;
54import java.awt.im.InputContext;
55import java.awt.im.InputMethodRequests;
56import java.awt.dnd.DropTarget;
57import java.lang.reflect.InvocationTargetException;
58import java.lang.reflect.Method;
59import java.security.AccessController;
60import java.security.PrivilegedAction;
61import javax.accessibility.*;
62import java.util.logging.*;
63import java.applet.Applet;
64
65import sun.security.action.GetPropertyAction;
66import sun.awt.AppContext;
67import sun.awt.ConstrainableGraphics;
68import sun.awt.SubRegionShowable;
69import sun.awt.WindowClosingListener;
70import sun.awt.CausedFocusEvent;
71import sun.awt.EmbeddedFrame;
72import sun.awt.dnd.SunDropTargetEvent;
73import sun.awt.im.CompositionArea;
74import sun.java2d.SunGraphics2D;
75import sun.java2d.pipe.Region;
76import sun.awt.RequestFocusController;
77
78/**
79 * A <em>component</em> is an object having a graphical representation
80 * that can be displayed on the screen and that can interact with the
81 * user. Examples of components are the buttons, checkboxes, and scrollbars
82 * of a typical graphical user interface. <p>
83 * The <code>Component</code> class is the abstract superclass of
84 * the nonmenu-related Abstract Window Toolkit components. Class
85 * <code>Component</code> can also be extended directly to create a
86 * lightweight component. A lightweight component is a component that is
87 * not associated with a native opaque window.
88 * <p>
89 * <h3>Serialization</h3>
90 * It is important to note that only AWT listeners which conform
91 * to the <code>Serializable</code> protocol will be saved when
92 * the object is stored. If an AWT object has listeners that
93 * aren't marked serializable, they will be dropped at
94 * <code>writeObject</code> time. Developers will need, as always,
95 * to consider the implications of making an object serializable.
96 * One situation to watch out for is this:
97 * <pre>
98 * import java.awt.*;
99 * import java.awt.event.*;
100 * import java.io.Serializable;
101 *
102 * class MyApp implements ActionListener, Serializable
103 * {
104 * BigObjectThatShouldNotBeSerializedWithAButton bigOne;
105 * Button aButton = new Button();
106 *
107 * MyApp()
108 * {
109 * // Oops, now aButton has a listener with a reference
110 * // to bigOne!
111 * aButton.addActionListener(this);
112 * }
113 *
114 * public void actionPerformed(ActionEvent e)
115 * {
116 * System.out.println("Hello There");
117 * }
118 * }
119 * </pre>
120 * In this example, serializing <code>aButton</code> by itself
121 * will cause <code>MyApp</code> and everything it refers to
122 * to be serialized as well. The problem is that the listener
123 * is serializable by coincidence, not by design. To separate
124 * the decisions about <code>MyApp</code> and the
125 * <code>ActionListener</code> being serializable one can use a
126 * nested class, as in the following example:
127 * <pre>
128 * import java.awt.*;
129 * import java.awt.event.*;
130 * import java.io.Serializable;
131 *
132 * class MyApp java.io.Serializable
133 * {
134 * BigObjectThatShouldNotBeSerializedWithAButton bigOne;
135 * Button aButton = new Button();
136 *
137 * static class MyActionListener implements ActionListener
138 * {
139 * public void actionPerformed(ActionEvent e)
140 * {
141 * System.out.println("Hello There");
142 * }
143 * }
144 *
145 * MyApp()
146 * {
147 * aButton.addActionListener(new MyActionListener());
148 * }
149 * }
150 * </pre>
151 * <p>
152 * <b>Note</b>: For more information on the paint mechanisms utilitized
153 * by AWT and Swing, including information on how to write the most
154 * efficient painting code, see
155 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
156 * <p>
157 * For details on the focus subsystem, see
158 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
159 * How to Use the Focus Subsystem</a>,
160 * a section in <em>The Java Tutorial</em>, and the
161 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
162 * for more information.
163 *
164 * @author Arthur van Hoff
165 * @author Sami Shaio
166 */
167public abstract class Component implements ImageObserver, MenuContainer,
168 Serializable
169{
170
171 private static final Logger log = Logger.getLogger("java.awt.Component");
172 private static final Logger eventLog = Logger.getLogger("java.awt.event.Component");
173 private static final Logger focusLog = Logger.getLogger("java.awt.focus.Component");
174 private static final Logger mixingLog = Logger.getLogger("java.awt.mixing.Component");
175
176 /**
177 * The peer of the component. The peer implements the component's
178 * behavior. The peer is set when the <code>Component</code> is
179 * added to a container that also is a peer.
180 * @see #addNotify
181 * @see #removeNotify
182 */
183 transient ComponentPeer peer;
184
185 /**
186 * The parent of the object. It may be <code>null</code>
187 * for top-level components.
188 * @see #getParent
189 */
190 transient Container parent;
191
192 /**
193 * The <code>AppContext</code> of the component. Applets/Plugin may
194 * change the AppContext.
195 */
196 transient AppContext appContext;
197
198 /**
199 * The x position of the component in the parent's coordinate system.
200 *
201 * @serial
202 * @see #getLocation
203 */
204 int x;
205
206 /**
207 * The y position of the component in the parent's coordinate system.
208 *
209 * @serial
210 * @see #getLocation
211 */
212 int y;
213
214 /**
215 * The width of the component.
216 *
217 * @serial
218 * @see #getSize
219 */
220 int width;
221
222 /**
223 * The height of the component.
224 *
225 * @serial
226 * @see #getSize
227 */
228 int height;
229
230 /**
231 * The foreground color for this component.
232 * <code>foreground</code> can be <code>null</code>.
233 *
234 * @serial
235 * @see #getForeground
236 * @see #setForeground
237 */
238 Color foreground;
239
240 /**
241 * The background color for this component.
242 * <code>background</code> can be <code>null</code>.
243 *
244 * @serial
245 * @see #getBackground
246 * @see #setBackground
247 */
248 Color background;
249
250 /**
251 * The font used by this component.
252 * The <code>font</code> can be <code>null</code>.
253 *
254 * @serial
255 * @see #getFont
256 * @see #setFont
257 */
258 Font font;
259
260 /**
261 * The font which the peer is currently using.
262 * (<code>null</code> if no peer exists.)
263 */
264 Font peerFont;
265
266 /**
267 * The cursor displayed when pointer is over this component.
268 * This value can be <code>null</code>.
269 *
270 * @serial
271 * @see #getCursor
272 * @see #setCursor
273 */
274 Cursor cursor;
275
276 /**
277 * The locale for the component.
278 *
279 * @serial
280 * @see #getLocale
281 * @see #setLocale
282 */
283 Locale locale;
284
285 /**
286 * A reference to a <code>GraphicsConfiguration</code> object
287 * used to describe the characteristics of a graphics
288 * destination.
289 * This value can be <code>null</code>.
290 *
291 * @since 1.3
292 * @serial
293 * @see GraphicsConfiguration
294 * @see #getGraphicsConfiguration
295 */
296 transient GraphicsConfiguration graphicsConfig = null;
297
298 /**
299 * A reference to a <code>BufferStrategy</code> object
300 * used to manipulate the buffers on this component.
301 *
302 * @since 1.4
303 * @see java.awt.image.BufferStrategy
304 * @see #getBufferStrategy()
305 */
306 transient BufferStrategy bufferStrategy = null;
307
308 /**
309 * True when the object should ignore all repaint events.
310 *
311 * @since 1.4
312 * @serial
313 * @see #setIgnoreRepaint
314 * @see #getIgnoreRepaint
315 */
316 boolean ignoreRepaint = false;
317
318 /**
319 * True when the object is visible. An object that is not
320 * visible is not drawn on the screen.
321 *
322 * @serial
323 * @see #isVisible
324 * @see #setVisible
325 */
326 boolean visible = true;
327
328 /**
329 * True when the object is enabled. An object that is not
330 * enabled does not interact with the user.
331 *
332 * @serial
333 * @see #isEnabled
334 * @see #setEnabled
335 */
336 boolean enabled = true;
337
338 /**
339 * True when the object is valid. An invalid object needs to
340 * be layed out. This flag is set to false when the object
341 * size is changed.
342 *
343 * @serial
344 * @see #isValid
345 * @see #validate
346 * @see #invalidate
347 */
348 volatile boolean valid = false;
349
350 /**
351 * The <code>DropTarget</code> associated with this component.
352 *
353 * @since 1.2
354 * @serial
355 * @see #setDropTarget
356 * @see #getDropTarget
357 */
358 DropTarget dropTarget;
359
360 /**
361 * @serial
362 * @see #add
363 */
364 Vector popups;
365
366 /**
367 * A component's name.
368 * This field can be <code>null</code>.
369 *
370 * @serial
371 * @see #getName
372 * @see #setName(String)
373 */
374 private String name;
375
376 /**
377 * A bool to determine whether the name has
378 * been set explicitly. <code>nameExplicitlySet</code> will
379 * be false if the name has not been set and
380 * true if it has.
381 *
382 * @serial
383 * @see #getName
384 * @see #setName(String)
385 */
386 private boolean nameExplicitlySet = false;
387
388 /**
389 * Indicates whether this Component can be focused.
390 *
391 * @serial
392 * @see #setFocusable
393 * @see #isFocusable
394 * @since 1.4
395 */
396 private boolean focusable = true;
397
398 private static final int FOCUS_TRAVERSABLE_UNKNOWN = 0;
399 private static final int FOCUS_TRAVERSABLE_DEFAULT = 1;
400 private static final int FOCUS_TRAVERSABLE_SET = 2;
401
402 /**
403 * Tracks whether this Component is relying on default focus travesability.
404 *
405 * @serial
406 * @since 1.4
407 */
408 private int isFocusTraversableOverridden = FOCUS_TRAVERSABLE_UNKNOWN;
409
410 /**
411 * The focus traversal keys. These keys will generate focus traversal
412 * behavior for Components for which focus traversal keys are enabled. If a
413 * value of null is specified for a traversal key, this Component inherits
414 * that traversal key from its parent. If all ancestors of this Component
415 * have null specified for that traversal key, then the current
416 * KeyboardFocusManager's default traversal key is used.
417 *
418 * @serial
419 * @see #setFocusTraversalKeys
420 * @see #getFocusTraversalKeys
421 * @since 1.4
422 */
423 Set[] focusTraversalKeys;
424
425 private static final String[] focusTraversalKeyPropertyNames = {
426 "forwardFocusTraversalKeys",
427 "backwardFocusTraversalKeys",
428 "upCycleFocusTraversalKeys",
429 "downCycleFocusTraversalKeys"
430 };
431
432 /**
433 * Indicates whether focus traversal keys are enabled for this Component.
434 * Components for which focus traversal keys are disabled receive key
435 * events for focus traversal keys. Components for which focus traversal
436 * keys are enabled do not see these events; instead, the events are
437 * automatically converted to traversal operations.
438 *
439 * @serial
440 * @see #setFocusTraversalKeysEnabled
441 * @see #getFocusTraversalKeysEnabled
442 * @since 1.4
443 */
444 private boolean focusTraversalKeysEnabled = true;
445
446 /**
447 * The locking object for AWT component-tree and layout operations.
448 *
449 * @see #getTreeLock
450 */
451 static final Object LOCK = new AWTTreeLock();
452 static class AWTTreeLock {}
453
454 /**
455 * Minimum size.
456 * (This field perhaps should have been transient).
457 *
458 * @serial
459 */
460 Dimension minSize;
461
462 /**
463 * Whether or not setMinimumSize has been invoked with a non-null value.
464 */
465 boolean minSizeSet;
466
467 /**
468 * Preferred size.
469 * (This field perhaps should have been transient).
470 *
471 * @serial
472 */
473 Dimension prefSize;
474
475 /**
476 * Whether or not setPreferredSize has been invoked with a non-null value.
477 */
478 boolean prefSizeSet;
479
480 /**
481 * Maximum size
482 *
483 * @serial
484 */
485 Dimension maxSize;
486
487 /**
488 * Whether or not setMaximumSize has been invoked with a non-null value.
489 */
490 boolean maxSizeSet;
491
492 /**
493 * The orientation for this component.
494 * @see #getComponentOrientation
495 * @see #setComponentOrientation
496 */
497 transient ComponentOrientation componentOrientation
498 = ComponentOrientation.UNKNOWN;
499
500 /**
501 * <code>newEventsOnly</code> will be true if the event is
502 * one of the event types enabled for the component.
503 * It will then allow for normal processing to
504 * continue. If it is false the event is passed
505 * to the component's parent and up the ancestor
506 * tree until the event has been consumed.
507 *
508 * @serial
509 * @see #dispatchEvent
510 */
511 boolean newEventsOnly = false;
512 transient ComponentListener componentListener;
513 transient FocusListener focusListener;
514 transient HierarchyListener hierarchyListener;
515 transient HierarchyBoundsListener hierarchyBoundsListener;
516 transient KeyListener keyListener;
517 transient MouseListener mouseListener;
518 transient MouseMotionListener mouseMotionListener;
519 transient MouseWheelListener mouseWheelListener;
520 transient InputMethodListener inputMethodListener;
521
522 transient RuntimeException windowClosingException = null;
523
524 /** Internal, constants for serialization */
525 final static String actionListenerK = "actionL";
526 final static String adjustmentListenerK = "adjustmentL";
527 final static String componentListenerK = "componentL";
528 final static String containerListenerK = "containerL";
529 final static String focusListenerK = "focusL";
530 final static String itemListenerK = "itemL";
531 final static String keyListenerK = "keyL";
532 final static String mouseListenerK = "mouseL";
533 final static String mouseMotionListenerK = "mouseMotionL";
534 final static String mouseWheelListenerK = "mouseWheelL";
535 final static String textListenerK = "textL";
536 final static String ownedWindowK = "ownedL";
537 final static String windowListenerK = "windowL";
538 final static String inputMethodListenerK = "inputMethodL";
539 final static String hierarchyListenerK = "hierarchyL";
540 final static String hierarchyBoundsListenerK = "hierarchyBoundsL";
541 final static String windowStateListenerK = "windowStateL";
542 final static String windowFocusListenerK = "windowFocusL";
543
544 /**
545 * The <code>eventMask</code> is ONLY set by subclasses via
546 * <code>enableEvents</code>.
547 * The mask should NOT be set when listeners are registered
548 * so that we can distinguish the difference between when
549 * listeners request events and subclasses request them.
550 * One bit is used to indicate whether input methods are
551 * enabled; this bit is set by <code>enableInputMethods</code> and is
552 * on by default.
553 *
554 * @serial
555 * @see #enableInputMethods
556 * @see AWTEvent
557 */
558 long eventMask = AWTEvent.INPUT_METHODS_ENABLED_MASK;
559
560 /**
561 * Static properties for incremental drawing.
562 * @see #imageUpdate
563 */
564 static boolean isInc;
565 static int incRate;
566 static {
567 /* ensure that the necessary native libraries are loaded */
568 Toolkit.loadLibraries();
569 /* initialize JNI field and method ids */
570 if (!GraphicsEnvironment.isHeadless()) {
571 initIDs();
572 }
573
574 String s = (String) java.security.AccessController.doPrivileged(
575 new GetPropertyAction("awt.image.incrementaldraw"));
576 isInc = (s == null || s.equals("true"));
577
578 s = (String) java.security.AccessController.doPrivileged(
579 new GetPropertyAction("awt.image.redrawrate"));
580 incRate = (s != null) ? Integer.parseInt(s) : 100;
581 }
582
583 /**
584 * Ease-of-use constant for <code>getAlignmentY()</code>.
585 * Specifies an alignment to the top of the component.
586 * @see #getAlignmentY
587 */
588 public static final float TOP_ALIGNMENT = 0.0f;
589
590 /**
591 * Ease-of-use constant for <code>getAlignmentY</code> and
592 * <code>getAlignmentX</code>. Specifies an alignment to
593 * the center of the component
594 * @see #getAlignmentX
595 * @see #getAlignmentY
596 */
597 public static final float CENTER_ALIGNMENT = 0.5f;
598
599 /**
600 * Ease-of-use constant for <code>getAlignmentY</code>.
601 * Specifies an alignment to the bottom of the component.
602 * @see #getAlignmentY
603 */
604 public static final float BOTTOM_ALIGNMENT = 1.0f;
605
606 /**
607 * Ease-of-use constant for <code>getAlignmentX</code>.
608 * Specifies an alignment to the left side of the component.
609 * @see #getAlignmentX
610 */
611 public static final float LEFT_ALIGNMENT = 0.0f;
612
613 /**
614 * Ease-of-use constant for <code>getAlignmentX</code>.
615 * Specifies an alignment to the right side of the component.
616 * @see #getAlignmentX
617 */
618 public static final float RIGHT_ALIGNMENT = 1.0f;
619
620 /*
621 * JDK 1.1 serialVersionUID
622 */
623 private static final long serialVersionUID = -7644114512714619750L;
624
625 /**
626 * If any <code>PropertyChangeListeners</code> have been registered,
627 * the <code>changeSupport</code> field describes them.
628 *
629 * @serial
630 * @since 1.2
631 * @see #addPropertyChangeListener
632 * @see #removePropertyChangeListener
633 * @see #firePropertyChange
634 */
635 private PropertyChangeSupport changeSupport;
636
637 boolean isPacked = false;
638
639 /**
640 * Pseudoparameter for direct Geometry API (setLocation, setBounds setSize
641 * to signal setBounds what's changing. Should be used under TreeLock.
642 * This is only needed due to the inability to change the cross-calling
643 * order of public and deprecated methods.
644 */
645 private int boundsOp = ComponentPeer.DEFAULT_OPERATION;
646
647 /**
648 * Enumeration of the common ways the baseline of a component can
649 * change as the size changes. The baseline resize behavior is
650 * primarily for layout managers that need to know how the
651 * position of the baseline changes as the component size changes.
652 * In general the baseline resize behavior will be valid for sizes
653 * greater than or equal to the minimum size (the actual minimum
654 * size; not a developer specified minimum size). For sizes
655 * smaller than the minimum size the baseline may change in a way
656 * other than the baseline resize behavior indicates. Similarly,
657 * as the size approaches <code>Integer.MAX_VALUE</code> and/or
658 * <code>Short.MAX_VALUE</code> the baseline may change in a way
659 * other than the baseline resize behavior indicates.
660 *
661 * @see #getBaselineResizeBehavior
662 * @see #getBaseline(int,int)
663 * @since 1.6
664 */
665 public enum BaselineResizeBehavior {
666 /**
667 * Indicates the baseline remains fixed relative to the
668 * y-origin. That is, <code>getBaseline</code> returns
669 * the same value regardless of the height or width. For example, a
670 * <code>JLabel</code> containing non-empty text with a
671 * vertical alignment of <code>TOP</code> should have a
672 * baseline type of <code>CONSTANT_ASCENT</code>.
673 */
674 CONSTANT_ASCENT,
675
676 /**
677 * Indicates the baseline remains fixed relative to the height
678 * and does not change as the width is varied. That is, for
679 * any height H the difference between H and
680 * <code>getBaseline(w, H)</code> is the same. For example, a
681 * <code>JLabel</code> containing non-empty text with a
682 * vertical alignment of <code>BOTTOM</code> should have a
683 * baseline type of <code>CONSTANT_DESCENT</code>.
684 */
685 CONSTANT_DESCENT,
686
687 /**
688 * Indicates the baseline remains a fixed distance from
689 * the center of the component. That is, for any height H the
690 * difference between <code>getBaseline(w, H)</code> and
691 * <code>H / 2</code> is the same (plus or minus one depending upon
692 * rounding error).
693 * <p>
694 * Because of possible rounding errors it is recommended
695 * you ask for the baseline with two consecutive heights and use
696 * the return value to determine if you need to pad calculations
697 * by 1. The following shows how to calculate the baseline for
698 * any height:
699 * <pre>
700 * Dimension preferredSize = component.getPreferredSize();
701 * int baseline = getBaseline(preferredSize.width,
702 * preferredSize.height);
703 * int nextBaseline = getBaseline(preferredSize.width,
704 * preferredSize.height + 1);
705 * // Amount to add to height when calculating where baseline
706 * // lands for a particular height:
707 * int padding = 0;
708 * // Where the baseline is relative to the mid point
709 * int baselineOffset = baseline - height / 2;
710 * if (preferredSize.height % 2 == 0 &amp;&amp;
711 * baseline != nextBaseline) {
712 * padding = 1;
713 * }
714 * else if (preferredSize.height % 2 == 1 &amp;&amp;
715 * baseline == nextBaseline) {
716 * baselineOffset--;
717 * padding = 1;
718 * }
719 * // The following calculates where the baseline lands for
720 * // the height z:
721 * int calculatedBaseline = (z + padding) / 2 + baselineOffset;
722 * </pre>
723 */
724 CENTER_OFFSET,
725
726 /**
727 * Indicates the baseline resize behavior can not be expressed using
728 * any of the other constants. This may also indicate the baseline
729 * varies with the width of the component. This is also returned
730 * by components that do not have a baseline.
731 */
732 OTHER
733 }
734
735 /*
736 * The shape set with the applyCompoundShape() method. It uncludes the result
737 * of the HW/LW mixing related shape computation. It may also include
738 * the user-specified shape of the component.
739 */
740 private transient Region compoundShape = null;
741
742 /*
743 * Indicates whether addNotify() is complete
744 * (i.e. the peer is created).
745 */
746 private transient boolean isAddNotifyComplete = false;
747
748 private static final PropertyChangeListener opaquePropertyChangeListener =
749 new PropertyChangeListener() {
750 public void propertyChange(java.beans.PropertyChangeEvent evt) {
751 ((Component)evt.getSource()).mixOnOpaqueChanging();
752 }
753 };
754
755 /**
756 * Should only be used in subclass getBounds to check that part of bounds
757 * is actualy changing
758 */
759 int getBoundsOp() {
760 assert Thread.holdsLock(getTreeLock());
761 return boundsOp;
762 }
763
764 void setBoundsOp(int op) {
765 assert Thread.holdsLock(getTreeLock());
766 if (op == ComponentPeer.RESET_OPERATION) {
767 boundsOp = ComponentPeer.DEFAULT_OPERATION;
768 } else
769 if (boundsOp == ComponentPeer.DEFAULT_OPERATION) {
770 boundsOp = op;
771 }
772 }
773
774 /**
775 * Constructs a new component. Class <code>Component</code> can be
776 * extended directly to create a lightweight component that does not
777 * utilize an opaque native window. A lightweight component must be
778 * hosted by a native container somewhere higher up in the component
779 * tree (for example, by a <code>Frame</code> object).
780 */
781 protected Component() {
782 appContext = AppContext.getAppContext();
783 }
784
785 void initializeFocusTraversalKeys() {
786 focusTraversalKeys = new Set[3];
787 }
788
789 /**
790 * Constructs a name for this component. Called by <code>getName</code>
791 * when the name is <code>null</code>.
792 */
793 String constructComponentName() {
794 return null; // For strict compliance with prior platform versions, a Component
795 // that doesn't set its name should return null from
796 // getName()
797 }
798
799 /**
800 * Gets the name of the component.
801 * @return this component's name
802 * @see #setName
803 * @since JDK1.1
804 */
805 public String getName() {
806 if (name == null && !nameExplicitlySet) {
807 synchronized(this) {
808 if (name == null && !nameExplicitlySet)
809 name = constructComponentName();
810 }
811 }
812 return name;
813 }
814
815 /**
816 * Sets the name of the component to the specified string.
817 * @param name the string that is to be this
818 * component's name
819 * @see #getName
820 * @since JDK1.1
821 */
822 public void setName(String name) {
823 String oldName;
824 synchronized(this) {
825 oldName = this.name;
826 this.name = name;
827 nameExplicitlySet = true;
828 }
829 firePropertyChange("name", oldName, name);
830 }
831
832 /**
833 * Gets the parent of this component.
834 * @return the parent container of this component
835 * @since JDK1.0
836 */
837 public Container getParent() {
838 return getParent_NoClientCode();
839 }
840
841 // NOTE: This method may be called by privileged threads.
842 // This functionality is implemented in a package-private method
843 // to insure that it cannot be overridden by client subclasses.
844 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
845 final Container getParent_NoClientCode() {
846 return parent;
847 }
848
849 // This method is overriden in the Window class to return null,
850 // because the parent field of the Window object contains
851 // the owner of the window, not its parent.
852 Container getContainer() {
853 return getParent();
854 }
855
856 /**
857 * @deprecated As of JDK version 1.1,
858 * programs should not directly manipulate peers;
859 * replaced by <code>boolean isDisplayable()</code>.
860 */
861 @Deprecated
862 public ComponentPeer getPeer() {
863 return peer;
864 }
865
866 /**
867 * Associate a <code>DropTarget</code> with this component.
868 * The <code>Component</code> will receive drops only if it
869 * is enabled.
870 *
871 * @see #isEnabled
872 * @param dt The DropTarget
873 */
874
875 public synchronized void setDropTarget(DropTarget dt) {
876 if (dt == dropTarget || (dropTarget != null && dropTarget.equals(dt)))
877 return;
878
879 DropTarget old;
880
881 if ((old = dropTarget) != null) {
882 if (peer != null) dropTarget.removeNotify(peer);
883
884 DropTarget t = dropTarget;
885
886 dropTarget = null;
887
888 try {
889 t.setComponent(null);
890 } catch (IllegalArgumentException iae) {
891 // ignore it.
892 }
893 }
894
895 // if we have a new one, and we have a peer, add it!
896
897 if ((dropTarget = dt) != null) {
898 try {
899 dropTarget.setComponent(this);
900 if (peer != null) dropTarget.addNotify(peer);
901 } catch (IllegalArgumentException iae) {
902 if (old != null) {
903 try {
904 old.setComponent(this);
905 if (peer != null) dropTarget.addNotify(peer);
906 } catch (IllegalArgumentException iae1) {
907 // ignore it!
908 }
909 }
910 }
911 }
912 }
913
914 /**
915 * Gets the <code>DropTarget</code> associated with this
916 * <code>Component</code>.
917 */
918
919 public synchronized DropTarget getDropTarget() { return dropTarget; }
920
921 /**
922 * Gets the <code>GraphicsConfiguration</code> associated with this
923 * <code>Component</code>.
924 * If the <code>Component</code> has not been assigned a specific
925 * <code>GraphicsConfiguration</code>,
926 * the <code>GraphicsConfiguration</code> of the
927 * <code>Component</code> object's top-level container is
928 * returned.
929 * If the <code>Component</code> has been created, but not yet added
930 * to a <code>Container</code>, this method returns <code>null</code>.
931 *
932 * @return the <code>GraphicsConfiguration</code> used by this
933 * <code>Component</code> or <code>null</code>
934 * @since 1.3
935 */
936 public GraphicsConfiguration getGraphicsConfiguration() {
937 synchronized(getTreeLock()) {
938 GraphicsConfiguration gc = graphicsConfig;
939 Component parent = getParent();
940 while ((gc == null) && (parent != null)) {
941 gc = parent.getGraphicsConfiguration();
942 parent = parent.getParent();
943 }
944 return gc;
945 }
946 }
947
948 final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() {
949 GraphicsConfiguration gc = this.graphicsConfig;
950 Component par = this.parent;
951 while ((gc == null) && (par != null)) {
952 gc = par.getGraphicsConfiguration_NoClientCode();
953 par = par.parent;
954 }
955 return gc;
956 }
957
958 /**
959 * Resets this <code>Component</code>'s
960 * <code>GraphicsConfiguration</code> back to a default
961 * value. For most componenets, this is <code>null</code>.
962 * Called from the Toolkit thread, so NO CLIENT CODE.
963 */
964 void resetGC() {
965 synchronized(getTreeLock()) {
966 graphicsConfig = null;
967 }
968 }
969
970 /*
971 * Not called on Component, but needed for Canvas and Window
972 */
973 void setGCFromPeer() {
974 synchronized(getTreeLock()) {
975 if (peer != null) { // can't imagine how this will be false,
976 // but just in case
977 graphicsConfig = peer.getGraphicsConfiguration();
978 } else {
979 graphicsConfig = null;
980 }
981 }
982 }
983
984 /**
985 * Checks that this component's <code>GraphicsDevice</code>
986 * <code>idString</code> matches the string argument.
987 */
988 void checkGD(String stringID) {
989 if (graphicsConfig != null) {
990 if (!graphicsConfig.getDevice().getIDstring().equals(stringID)) {
991 throw new IllegalArgumentException(
992 "adding a container to a container on a different GraphicsDevice");
993 }
994 }
995 }
996
997 /**
998 * Gets this component's locking object (the object that owns the thread
999 * sychronization monitor) for AWT component-tree and layout
1000 * operations.
1001 * @return this component's locking object
1002 */
1003 public final Object getTreeLock() {
1004 return LOCK;
1005 }
1006
1007 final void checkTreeLock() {
1008 if (!Thread.holdsLock(getTreeLock())) {
1009 throw new IllegalStateException("This function should be called while holding treeLock");
1010 }
1011 }
1012
1013 /**
1014 * Gets the toolkit of this component. Note that
1015 * the frame that contains a component controls which
1016 * toolkit is used by that component. Therefore if the component
1017 * is moved from one frame to another, the toolkit it uses may change.
1018 * @return the toolkit of this component
1019 * @since JDK1.0
1020 */
1021 public Toolkit getToolkit() {
1022 return getToolkitImpl();
1023 }
1024
1025 /*
1026 * This is called by the native code, so client code can't
1027 * be called on the toolkit thread.
1028 */
1029 final Toolkit getToolkitImpl() {
1030 ComponentPeer peer = this.peer;
1031 if ((peer != null) && ! (peer instanceof LightweightPeer)){
1032 return peer.getToolkit();
1033 }
1034 Container parent = this.parent;
1035 if (parent != null) {
1036 return parent.getToolkitImpl();
1037 }
1038 return Toolkit.getDefaultToolkit();
1039 }
1040
1041 /**
1042 * Determines whether this component is valid. A component is valid
1043 * when it is correctly sized and positioned within its parent
1044 * container and all its children are also valid.
1045 * In order to account for peers' size requirements, components are invalidated
1046 * before they are first shown on the screen. By the time the parent container
1047 * is fully realized, all its components will be valid.
1048 * @return <code>true</code> if the component is valid, <code>false</code>
1049 * otherwise
1050 * @see #validate
1051 * @see #invalidate
1052 * @since JDK1.0
1053 */
1054 public boolean isValid() {
1055 return (peer != null) && valid;
1056 }
1057
1058 /**
1059 * Determines whether this component is displayable. A component is
1060 * displayable when it is connected to a native screen resource.
1061 * <p>
1062 * A component is made displayable either when it is added to
1063 * a displayable containment hierarchy or when its containment
1064 * hierarchy is made displayable.
1065 * A containment hierarchy is made displayable when its ancestor
1066 * window is either packed or made visible.
1067 * <p>
1068 * A component is made undisplayable either when it is removed from
1069 * a displayable containment hierarchy or when its containment hierarchy
1070 * is made undisplayable. A containment hierarchy is made
1071 * undisplayable when its ancestor window is disposed.
1072 *
1073 * @return <code>true</code> if the component is displayable,
1074 * <code>false</code> otherwise
1075 * @see Container#add(Component)
1076 * @see Window#pack
1077 * @see Window#show
1078 * @see Container#remove(Component)
1079 * @see Window#dispose
1080 * @since 1.2
1081 */
1082 public boolean isDisplayable() {
1083 return getPeer() != null;
1084 }
1085
1086 /**
1087 * Determines whether this component should be visible when its
1088 * parent is visible. Components are
1089 * initially visible, with the exception of top level components such
1090 * as <code>Frame</code> objects.
1091 * @return <code>true</code> if the component is visible,
1092 * <code>false</code> otherwise
1093 * @see #setVisible
1094 * @since JDK1.0
1095 */
1096 public boolean isVisible() {
1097 return isVisible_NoClientCode();
1098 }
1099 final boolean isVisible_NoClientCode() {
1100 return visible;
1101 }
1102
1103 /**
1104 * Determines whether this component will be displayed on the screen.
1105 * @return <code>true</code> if the component and all of its ancestors
1106 * until a toplevel window or null parent are visible,
1107 * <code>false</code> otherwise
1108 */
1109 boolean isRecursivelyVisible() {
1110 return visible && (parent == null || parent.isRecursivelyVisible());
1111 }
1112
1113 /**
1114 * Translates absolute coordinates into coordinates in the coordinate
1115 * space of this component.
1116 */
1117 Point pointRelativeToComponent(Point absolute) {
1118 Point compCoords = getLocationOnScreen();
1119 return new Point(absolute.x - compCoords.x,
1120 absolute.y - compCoords.y);
1121 }
1122
1123 /**
1124 * Assuming that mouse location is stored in PointerInfo passed
1125 * to this method, it finds a Component that is in the same
1126 * Window as this Component and is located under the mouse pointer.
1127 * If no such Component exists, null is returned.
1128 * NOTE: this method should be called under the protection of
1129 * tree lock, as it is done in Component.getMousePosition() and
1130 * Container.getMousePosition(boolean).
1131 */
1132 Component findUnderMouseInWindow(PointerInfo pi) {
1133 if (!isShowing()) {
1134 return null;
1135 }
1136 Window win = getContainingWindow();
1137 if (!Toolkit.getDefaultToolkit().getMouseInfoPeer().isWindowUnderMouse(win)) {
1138 return null;
1139 }
1140 final boolean INCLUDE_DISABLED = true;
1141 Point relativeToWindow = win.pointRelativeToComponent(pi.getLocation());
1142 Component inTheSameWindow = win.findComponentAt(relativeToWindow.x,
1143 relativeToWindow.y,
1144 INCLUDE_DISABLED);
1145 return inTheSameWindow;
1146 }
1147
1148 /**
1149 * Returns the position of the mouse pointer in this <code>Component</code>'s
1150 * coordinate space if the <code>Component</code> is directly under the mouse
1151 * pointer, otherwise returns <code>null</code>.
1152 * If the <code>Component</code> is not showing on the screen, this method
1153 * returns <code>null</code> even if the mouse pointer is above the area
1154 * where the <code>Component</code> would be displayed.
1155 * If the <code>Component</code> is partially or fully obscured by other
1156 * <code>Component</code>s or native windows, this method returns a non-null
1157 * value only if the mouse pointer is located above the unobscured part of the
1158 * <code>Component</code>.
1159 * <p>
1160 * For <code>Container</code>s it returns a non-null value if the mouse is
1161 * above the <code>Container</code> itself or above any of its descendants.
1162 * Use {@link Container#getMousePosition(boolean)} if you need to exclude children.
1163 * <p>
1164 * Sometimes the exact mouse coordinates are not important, and the only thing
1165 * that matters is whether a specific <code>Component</code> is under the mouse
1166 * pointer. If the return value of this method is <code>null</code>, mouse
1167 * pointer is not directly above the <code>Component</code>.
1168 *
1169 * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
1170 * @see #isShowing
1171 * @see Container#getMousePosition
1172 * @return mouse coordinates relative to this <code>Component</code>, or null
1173 * @since 1.5
1174 */
1175 public Point getMousePosition() throws HeadlessException {
1176 if (GraphicsEnvironment.isHeadless()) {
1177 throw new HeadlessException();
1178 }
1179
1180 PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged(
1181 new java.security.PrivilegedAction() {
1182 public Object run() {
1183 return MouseInfo.getPointerInfo();
1184 }
1185 }
1186 );
1187
1188 synchronized (getTreeLock()) {
1189 Component inTheSameWindow = findUnderMouseInWindow(pi);
1190 if (!isSameOrAncestorOf(inTheSameWindow, true)) {
1191 return null;
1192 }
1193 return pointRelativeToComponent(pi.getLocation());
1194 }
1195 }
1196
1197 /**
1198 * Overridden in Container. Must be called under TreeLock.
1199 */
1200 boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
1201 return comp == this;
1202 }
1203
1204 /**
1205 * Determines whether this component is showing on screen. This means
1206 * that the component must be visible, and it must be in a container
1207 * that is visible and showing.
1208 * <p>
1209 * <strong>Note:</strong> sometimes there is no way to detect whether the
1210 * {@code Component} is actually visible to the user. This can happen when:
1211 * <ul>
1212 * <li>the component has been added to a visible {@code ScrollPane} but
1213 * the {@code Component} is not currently in the scroll pane's view port.
1214 * <li>the {@code Component} is obscured by another {@code Component} or
1215 * {@code Container}.
1216 * </ul>
1217 * @return <code>true</code> if the component is showing,
1218 * <code>false</code> otherwise
1219 * @see #setVisible
1220 * @since JDK1.0
1221 */
1222 public boolean isShowing() {
1223 if (visible && (peer != null)) {
1224 Container parent = this.parent;
1225 return (parent == null) || parent.isShowing();
1226 }
1227 return false;
1228 }
1229
1230 /**
1231 * Determines whether this component is enabled. An enabled component
1232 * can respond to user input and generate events. Components are
1233 * enabled initially by default. A component may be enabled or disabled by
1234 * calling its <code>setEnabled</code> method.
1235 * @return <code>true</code> if the component is enabled,
1236 * <code>false</code> otherwise
1237 * @see #setEnabled
1238 * @since JDK1.0
1239 */
1240 public boolean isEnabled() {
1241 return isEnabledImpl();
1242 }
1243
1244 /*
1245 * This is called by the native code, so client code can't
1246 * be called on the toolkit thread.
1247 */
1248 final boolean isEnabledImpl() {
1249 return enabled;
1250 }
1251
1252 /**
1253 * Enables or disables this component, depending on the value of the
1254 * parameter <code>b</code>. An enabled component can respond to user
1255 * input and generate events. Components are enabled initially by default.
1256 *
1257 * <p>Note: Disabling a lightweight component does not prevent it from
1258 * receiving MouseEvents.
1259 * <p>Note: Disabling a heavyweight container prevents all components
1260 * in this container from receiving any input events. But disabling a
1261 * lightweight container affects only this container.
1262 *
1263 * @param b If <code>true</code>, this component is
1264 * enabled; otherwise this component is disabled
1265 * @see #isEnabled
1266 * @see #isLightweight
1267 * @since JDK1.1
1268 */
1269 public void setEnabled(boolean b) {
1270 enable(b);
1271 }
1272
1273 /**
1274 * @deprecated As of JDK version 1.1,
1275 * replaced by <code>setEnabled(boolean)</code>.
1276 */
1277 @Deprecated
1278 public void enable() {
1279 if (!enabled) {
1280 synchronized (getTreeLock()) {
1281 enabled = true;
1282 ComponentPeer peer = this.peer;
1283 if (peer != null) {
1284 peer.enable();
1285 if (visible) {
1286 updateCursorImmediately();
1287 }
1288 }
1289 }
1290 if (accessibleContext != null) {
1291 accessibleContext.firePropertyChange(
1292 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1293 null, AccessibleState.ENABLED);
1294 }
1295 }
1296 }
1297
1298 /**
1299 * @deprecated As of JDK version 1.1,
1300 * replaced by <code>setEnabled(boolean)</code>.
1301 */
1302 @Deprecated
1303 public void enable(boolean b) {
1304 if (b) {
1305 enable();
1306 } else {
1307 disable();
1308 }
1309 }
1310
1311 /**
1312 * @deprecated As of JDK version 1.1,
1313 * replaced by <code>setEnabled(boolean)</code>.
1314 */
1315 @Deprecated
1316 public void disable() {
1317 if (enabled) {
1318 KeyboardFocusManager.clearMostRecentFocusOwner(this);
1319 synchronized (getTreeLock()) {
1320 enabled = false;
1321 if (isFocusOwner()) {
1322 // Don't clear the global focus owner. If transferFocus
1323 // fails, we want the focus to stay on the disabled
1324 // Component so that keyboard traversal, et. al. still
1325 // makes sense to the user.
1326 autoTransferFocus(false);
1327 }
1328 ComponentPeer peer = this.peer;
1329 if (peer != null) {
1330 peer.disable();
1331 if (visible) {
1332 updateCursorImmediately();
1333 }
1334 }
1335 }
1336 if (accessibleContext != null) {
1337 accessibleContext.firePropertyChange(
1338 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1339 null, AccessibleState.ENABLED);
1340 }
1341 }
1342 }
1343
1344 /**
1345 * Returns true if this component is painted to an offscreen image
1346 * ("buffer") that's copied to the screen later. Component
1347 * subclasses that support double buffering should override this
1348 * method to return true if double buffering is enabled.
1349 *
1350 * @return false by default
1351 */
1352 public boolean isDoubleBuffered() {
1353 return false;
1354 }
1355
1356 /**
1357 * Enables or disables input method support for this component. If input
1358 * method support is enabled and the component also processes key events,
1359 * incoming events are offered to
1360 * the current input method and will only be processed by the component or
1361 * dispatched to its listeners if the input method does not consume them.
1362 * By default, input method support is enabled.
1363 *
1364 * @param enable true to enable, false to disable
1365 * @see #processKeyEvent
1366 * @since 1.2
1367 */
1368 public void enableInputMethods(boolean enable) {
1369 if (enable) {
1370 if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0)
1371 return;
1372
1373 // If this component already has focus, then activate the
1374 // input method by dispatching a synthesized focus gained
1375 // event.
1376 if (isFocusOwner()) {
1377 InputContext inputContext = getInputContext();
1378 if (inputContext != null) {
1379 FocusEvent focusGainedEvent =
1380 new FocusEvent(this, FocusEvent.FOCUS_GAINED);
1381 inputContext.dispatchEvent(focusGainedEvent);
1382 }
1383 }
1384
1385 eventMask |= AWTEvent.INPUT_METHODS_ENABLED_MASK;
1386 } else {
1387 if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) {
1388 InputContext inputContext = getInputContext();
1389 if (inputContext != null) {
1390 inputContext.endComposition();
1391 inputContext.removeNotify(this);
1392 }
1393 }
1394 eventMask &= ~AWTEvent.INPUT_METHODS_ENABLED_MASK;
1395 }
1396 }
1397
1398 /**
1399 * Shows or hides this component depending on the value of parameter
1400 * <code>b</code>.
1401 * @param b if <code>true</code>, shows this component;
1402 * otherwise, hides this component
1403 * @see #isVisible
1404 * @since JDK1.1
1405 */
1406 public void setVisible(boolean b) {
1407 show(b);
1408 }
1409
1410 /**
1411 * @deprecated As of JDK version 1.1,
1412 * replaced by <code>setVisible(boolean)</code>.
1413 */
1414 @Deprecated
1415 public void show() {
1416 if (!visible) {
1417 synchronized (getTreeLock()) {
1418 visible = true;
1419 mixOnShowing();
1420 ComponentPeer peer = this.peer;
1421 if (peer != null) {
1422 peer.show();
1423 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
1424 this, parent,
1425 HierarchyEvent.SHOWING_CHANGED,
1426 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1427 if (peer instanceof LightweightPeer) {
1428 repaint();
1429 }
1430 updateCursorImmediately();
1431 }
1432
1433 if (componentListener != null ||
1434 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 ||
1435 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) {
1436 ComponentEvent e = new ComponentEvent(this,
1437 ComponentEvent.COMPONENT_SHOWN);
1438 Toolkit.getEventQueue().postEvent(e);
1439 }
1440 }
1441 Container parent = this.parent;
1442 if (parent != null) {
1443 parent.invalidate();
1444 }
1445 }
1446 }
1447
1448 /**
1449 * @deprecated As of JDK version 1.1,
1450 * replaced by <code>setVisible(boolean)</code>.
1451 */
1452 @Deprecated
1453 public void show(boolean b) {
1454 if (b) {
1455 show();
1456 } else {
1457 hide();
1458 }
1459 }
1460
1461 boolean containsFocus() {
1462 return isFocusOwner();
1463 }
1464
1465 void clearMostRecentFocusOwnerOnHide() {
1466 KeyboardFocusManager.clearMostRecentFocusOwner(this);
1467 }
1468
1469 void clearCurrentFocusCycleRootOnHide() {
1470 /* do nothing */
1471 }
1472
1473 /**
1474 * @deprecated As of JDK version 1.1,
1475 * replaced by <code>setVisible(boolean)</code>.
1476 */
1477 @Deprecated
1478 public void hide() {
1479 isPacked = false;
1480
1481 if (visible) {
1482 clearCurrentFocusCycleRootOnHide();
1483 clearMostRecentFocusOwnerOnHide();
1484 synchronized (getTreeLock()) {
1485 visible = false;
1486 mixOnHiding(isLightweight());
1487 if (containsFocus()) {
1488 autoTransferFocus(true);
1489 }
1490 ComponentPeer peer = this.peer;
1491 if (peer != null) {
1492 peer.hide();
1493 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
1494 this, parent,
1495 HierarchyEvent.SHOWING_CHANGED,
1496 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1497 if (peer instanceof LightweightPeer) {
1498 repaint();
1499 }
1500 updateCursorImmediately();
1501 }
1502 if (componentListener != null ||
1503 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 ||
1504 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) {
1505 ComponentEvent e = new ComponentEvent(this,
1506 ComponentEvent.COMPONENT_HIDDEN);
1507 Toolkit.getEventQueue().postEvent(e);
1508 }
1509 }
1510 Container parent = this.parent;
1511 if (parent != null) {
1512 parent.invalidate();
1513 }
1514 }
1515 }
1516
1517 /**
1518 * Gets the foreground color of this component.
1519 * @return this component's foreground color; if this component does
1520 * not have a foreground color, the foreground color of its parent
1521 * is returned
1522 * @see #setForeground
1523 * @since JDK1.0
1524 * @beaninfo
1525 * bound: true
1526 */
1527 public Color getForeground() {
1528 Color foreground = this.foreground;
1529 if (foreground != null) {
1530 return foreground;
1531 }
1532 Container parent = this.parent;
1533 return (parent != null) ? parent.getForeground() : null;
1534 }
1535
1536 /**
1537 * Sets the foreground color of this component.
1538 * @param c the color to become this component's
1539 * foreground color; if this parameter is <code>null</code>
1540 * then this component will inherit
1541 * the foreground color of its parent
1542 * @see #getForeground
1543 * @since JDK1.0
1544 */
1545 public void setForeground(Color c) {
1546 Color oldColor = foreground;
1547 ComponentPeer peer = this.peer;
1548 foreground = c;
1549 if (peer != null) {
1550 c = getForeground();
1551 if (c != null) {
1552 peer.setForeground(c);
1553 }
1554 }
1555 // This is a bound property, so report the change to
1556 // any registered listeners. (Cheap if there are none.)
1557 firePropertyChange("foreground", oldColor, c);
1558 }
1559
1560 /**
1561 * Returns whether the foreground color has been explicitly set for this
1562 * Component. If this method returns <code>false</code>, this Component is
1563 * inheriting its foreground color from an ancestor.
1564 *
1565 * @return <code>true</code> if the foreground color has been explicitly
1566 * set for this Component; <code>false</code> otherwise.
1567 * @since 1.4
1568 */
1569 public boolean isForegroundSet() {
1570 return (foreground != null);
1571 }
1572
1573 /**
1574 * Gets the background color of this component.
1575 * @return this component's background color; if this component does
1576 * not have a background color,
1577 * the background color of its parent is returned
1578 * @see #setBackground
1579 * @since JDK1.0
1580 */
1581 public Color getBackground() {
1582 Color background = this.background;
1583 if (background != null) {
1584 return background;
1585 }
1586 Container parent = this.parent;
1587 return (parent != null) ? parent.getBackground() : null;
1588 }
1589
1590 /**
1591 * Sets the background color of this component.
1592 * <p>
1593 * The background color affects each component differently and the
1594 * parts of the component that are affected by the background color
1595 * may differ between operating systems.
1596 *
1597 * @param c the color to become this component's color;
1598 * if this parameter is <code>null</code>, then this
1599 * component will inherit the background color of its parent
1600 * @see #getBackground
1601 * @since JDK1.0
1602 * @beaninfo
1603 * bound: true
1604 */
1605 public void setBackground(Color c) {
1606 Color oldColor = background;
1607 ComponentPeer peer = this.peer;
1608 background = c;
1609 if (peer != null) {
1610 c = getBackground();
1611 if (c != null) {
1612 peer.setBackground(c);
1613 }
1614 }
1615 // This is a bound property, so report the change to
1616 // any registered listeners. (Cheap if there are none.)
1617 firePropertyChange("background", oldColor, c);
1618 }
1619
1620 /**
1621 * Returns whether the background color has been explicitly set for this
1622 * Component. If this method returns <code>false</code>, this Component is
1623 * inheriting its background color from an ancestor.
1624 *
1625 * @return <code>true</code> if the background color has been explicitly
1626 * set for this Component; <code>false</code> otherwise.
1627 * @since 1.4
1628 */
1629 public boolean isBackgroundSet() {
1630 return (background != null);
1631 }
1632
1633 /**
1634 * Gets the font of this component.
1635 * @return this component's font; if a font has not been set
1636 * for this component, the font of its parent is returned
1637 * @see #setFont
1638 * @since JDK1.0
1639 */
1640 public Font getFont() {
1641 return getFont_NoClientCode();
1642 }
1643
1644 // NOTE: This method may be called by privileged threads.
1645 // This functionality is implemented in a package-private method
1646 // to insure that it cannot be overridden by client subclasses.
1647 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
1648 final Font getFont_NoClientCode() {
1649 Font font = this.font;
1650 if (font != null) {
1651 return font;
1652 }
1653 Container parent = this.parent;
1654 return (parent != null) ? parent.getFont_NoClientCode() : null;
1655 }
1656
1657 /**
1658 * Sets the font of this component.
1659 * @param f the font to become this component's font;
1660 * if this parameter is <code>null</code> then this
1661 * component will inherit the font of its parent
1662 * @see #getFont
1663 * @since JDK1.0
1664 * @beaninfo
1665 * bound: true
1666 */
1667 public void setFont(Font f) {
1668 Font oldFont, newFont;
1669 synchronized(getTreeLock()) {
1670 synchronized (this) {
1671 oldFont = font;
1672 newFont = font = f;
1673 }
1674 ComponentPeer peer = this.peer;
1675 if (peer != null) {
1676 f = getFont();
1677 if (f != null) {
1678 peer.setFont(f);
1679 peerFont = f;
1680 }
1681 }
1682 }
1683 // This is a bound property, so report the change to
1684 // any registered listeners. (Cheap if there are none.)
1685 firePropertyChange("font", oldFont, newFont);
1686
1687 // This could change the preferred size of the Component.
1688 // Fix for 6213660. Should compare old and new fonts and do not
1689 // call invalidate() if they are equal.
1690 if (valid && f != oldFont && (oldFont == null ||
1691 !oldFont.equals(f))) {
1692 invalidate();
1693 }
1694 }
1695
1696 /**
1697 * Returns whether the font has been explicitly set for this Component. If
1698 * this method returns <code>false</code>, this Component is inheriting its
1699 * font from an ancestor.
1700 *
1701 * @return <code>true</code> if the font has been explicitly set for this
1702 * Component; <code>false</code> otherwise.
1703 * @since 1.4
1704 */
1705 public boolean isFontSet() {
1706 return (font != null);
1707 }
1708
1709 /**
1710 * Gets the locale of this component.
1711 * @return this component's locale; if this component does not
1712 * have a locale, the locale of its parent is returned
1713 * @see #setLocale
1714 * @exception IllegalComponentStateException if the <code>Component</code>
1715 * does not have its own locale and has not yet been added to
1716 * a containment hierarchy such that the locale can be determined
1717 * from the containing parent
1718 * @since JDK1.1
1719 */
1720 public Locale getLocale() {
1721 Locale locale = this.locale;
1722 if (locale != null) {
1723 return locale;
1724 }
1725 Container parent = this.parent;
1726
1727 if (parent == null) {
1728 throw new IllegalComponentStateException("This component must have a parent in order to determine its locale");
1729 } else {
1730 return parent.getLocale();
1731 }
1732 }
1733
1734 /**
1735 * Sets the locale of this component. This is a bound property.
1736 * @param l the locale to become this component's locale
1737 * @see #getLocale
1738 * @since JDK1.1
1739 */
1740 public void setLocale(Locale l) {
1741 Locale oldValue = locale;
1742 locale = l;
1743
1744 // This is a bound property, so report the change to
1745 // any registered listeners. (Cheap if there are none.)
1746 firePropertyChange("locale", oldValue, l);
1747
1748 // This could change the preferred size of the Component.
1749 if (valid) {
1750 invalidate();
1751 }
1752 }
1753
1754 /**
1755 * Gets the instance of <code>ColorModel</code> used to display
1756 * the component on the output device.
1757 * @return the color model used by this component
1758 * @see java.awt.image.ColorModel
1759 * @see java.awt.peer.ComponentPeer#getColorModel()
1760 * @see Toolkit#getColorModel()
1761 * @since JDK1.0
1762 */
1763 public ColorModel getColorModel() {
1764 ComponentPeer peer = this.peer;
1765 if ((peer != null) && ! (peer instanceof LightweightPeer)) {
1766 return peer.getColorModel();
1767 } else if (GraphicsEnvironment.isHeadless()) {
1768 return ColorModel.getRGBdefault();
1769 } // else
1770 return getToolkit().getColorModel();
1771 }
1772
1773 /**
1774 * Gets the location of this component in the form of a
1775 * point specifying the component's top-left corner.
1776 * The location will be relative to the parent's coordinate space.
1777 * <p>
1778 * Due to the asynchronous nature of native event handling, this
1779 * method can return outdated values (for instance, after several calls
1780 * of <code>setLocation()</code> in rapid succession). For this
1781 * reason, the recommended method of obtaining a component's position is
1782 * within <code>java.awt.event.ComponentListener.componentMoved()</code>,
1783 * which is called after the operating system has finished moving the
1784 * component.
1785 * </p>
1786 * @return an instance of <code>Point</code> representing
1787 * the top-left corner of the component's bounds in
1788 * the coordinate space of the component's parent
1789 * @see #setLocation
1790 * @see #getLocationOnScreen
1791 * @since JDK1.1
1792 */
1793 public Point getLocation() {
1794 return location();
1795 }
1796
1797 /**
1798 * Gets the location of this component in the form of a point
1799 * specifying the component's top-left corner in the screen's
1800 * coordinate space.
1801 * @return an instance of <code>Point</code> representing
1802 * the top-left corner of the component's bounds in the
1803 * coordinate space of the screen
1804 * @throws <code>IllegalComponentStateException</code> if the
1805 * component is not showing on the screen
1806 * @see #setLocation
1807 * @see #getLocation
1808 */
1809 public Point getLocationOnScreen() {
1810 synchronized (getTreeLock()) {
1811 return getLocationOnScreen_NoTreeLock();
1812 }
1813 }
1814
1815 /*
1816 * a package private version of getLocationOnScreen
1817 * used by GlobalCursormanager to update cursor
1818 */
1819 final Point getLocationOnScreen_NoTreeLock() {
1820
1821 if (peer != null && isShowing()) {
1822 if (peer instanceof LightweightPeer) {
1823 // lightweight component location needs to be translated
1824 // relative to a native component.
1825 Container host = getNativeContainer();
1826 Point pt = host.peer.getLocationOnScreen();
1827 for(Component c = this; c != host; c = c.getParent()) {
1828 pt.x += c.x;
1829 pt.y += c.y;
1830 }
1831 return pt;
1832 } else {
1833 Point pt = peer.getLocationOnScreen();
1834 return pt;
1835 }
1836 } else {
1837 throw new IllegalComponentStateException("component must be showing on the screen to determine its location");
1838 }
1839 }
1840
1841
1842 /**
1843 * @deprecated As of JDK version 1.1,
1844 * replaced by <code>getLocation()</code>.
1845 */
1846 @Deprecated
1847 public Point location() {
1848 return location_NoClientCode();
1849 }
1850
1851 private Point location_NoClientCode() {
1852 return new Point(x, y);
1853 }
1854
1855 /**
1856 * Moves this component to a new location. The top-left corner of
1857 * the new location is specified by the <code>x</code> and <code>y</code>
1858 * parameters in the coordinate space of this component's parent.
1859 * @param x the <i>x</i>-coordinate of the new location's
1860 * top-left corner in the parent's coordinate space
1861 * @param y the <i>y</i>-coordinate of the new location's
1862 * top-left corner in the parent's coordinate space
1863 * @see #getLocation
1864 * @see #setBounds
1865 * @since JDK1.1
1866 */
1867 public void setLocation(int x, int y) {
1868 move(x, y);
1869 }
1870
1871 /**
1872 * @deprecated As of JDK version 1.1,
1873 * replaced by <code>setLocation(int, int)</code>.
1874 */
1875 @Deprecated
1876 public void move(int x, int y) {
1877 synchronized(getTreeLock()) {
1878 setBoundsOp(ComponentPeer.SET_LOCATION);
1879 setBounds(x, y, width, height);
1880 }
1881 }
1882
1883 /**
1884 * Moves this component to a new location. The top-left corner of
1885 * the new location is specified by point <code>p</code>. Point
1886 * <code>p</code> is given in the parent's coordinate space.
1887 * @param p the point defining the top-left corner
1888 * of the new location, given in the coordinate space of this
1889 * component's parent
1890 * @see #getLocation
1891 * @see #setBounds
1892 * @since JDK1.1
1893 */
1894 public void setLocation(Point p) {
1895 setLocation(p.x, p.y);
1896 }
1897
1898 /**
1899 * Returns the size of this component in the form of a
1900 * <code>Dimension</code> object. The <code>height</code>
1901 * field of the <code>Dimension</code> object contains
1902 * this component's height, and the <code>width</code>
1903 * field of the <code>Dimension</code> object contains
1904 * this component's width.
1905 * @return a <code>Dimension</code> object that indicates the
1906 * size of this component
1907 * @see #setSize
1908 * @since JDK1.1
1909 */
1910 public Dimension getSize() {
1911 return size();
1912 }
1913
1914 /**
1915 * @deprecated As of JDK version 1.1,
1916 * replaced by <code>getSize()</code>.
1917 */
1918 @Deprecated
1919 public Dimension size() {
1920 return new Dimension(width, height);
1921 }
1922
1923 /**
1924 * Resizes this component so that it has width <code>width</code>
1925 * and height <code>height</code>.
1926 * @param width the new width of this component in pixels
1927 * @param height the new height of this component in pixels
1928 * @see #getSize
1929 * @see #setBounds
1930 * @since JDK1.1
1931 */
1932 public void setSize(int width, int height) {
1933 resize(width, height);
1934 }
1935
1936 /**
1937 * @deprecated As of JDK version 1.1,
1938 * replaced by <code>setSize(int, int)</code>.
1939 */
1940 @Deprecated
1941 public void resize(int width, int height) {
1942 synchronized(getTreeLock()) {
1943 setBoundsOp(ComponentPeer.SET_SIZE);
1944 setBounds(x, y, width, height);
1945 }
1946 }
1947
1948 /**
1949 * Resizes this component so that it has width <code>d.width</code>
1950 * and height <code>d.height</code>.
1951 * @param d the dimension specifying the new size
1952 * of this component
1953 * @see #setSize
1954 * @see #setBounds
1955 * @since JDK1.1
1956 */
1957 public void setSize(Dimension d) {
1958 resize(d);
1959 }
1960
1961 /**
1962 * @deprecated As of JDK version 1.1,
1963 * replaced by <code>setSize(Dimension)</code>.
1964 */
1965 @Deprecated
1966 public void resize(Dimension d) {
1967 setSize(d.width, d.height);
1968 }
1969
1970 /**
1971 * Gets the bounds of this component in the form of a
1972 * <code>Rectangle</code> object. The bounds specify this
1973 * component's width, height, and location relative to
1974 * its parent.
1975 * @return a rectangle indicating this component's bounds
1976 * @see #setBounds
1977 * @see #getLocation
1978 * @see #getSize
1979 */
1980 public Rectangle getBounds() {
1981 return bounds();
1982 }
1983
1984 /**
1985 * @deprecated As of JDK version 1.1,
1986 * replaced by <code>getBounds()</code>.
1987 */
1988 @Deprecated
1989 public Rectangle bounds() {
1990 return new Rectangle(x, y, width, height);
1991 }
1992
1993 /**
1994 * Moves and resizes this component. The new location of the top-left
1995 * corner is specified by <code>x</code> and <code>y</code>, and the
1996 * new size is specified by <code>width</code> and <code>height</code>.
1997 * @param x the new <i>x</i>-coordinate of this component
1998 * @param y the new <i>y</i>-coordinate of this component
1999 * @param width the new <code>width</code> of this component
2000 * @param height the new <code>height</code> of this
2001 * component
2002 * @see #getBounds
2003 * @see #setLocation(int, int)
2004 * @see #setLocation(Point)
2005 * @see #setSize(int, int)
2006 * @see #setSize(Dimension)
2007 * @since JDK1.1
2008 */
2009 public void setBounds(int x, int y, int width, int height) {
2010 reshape(x, y, width, height);
2011 }
2012
2013 /**
2014 * @deprecated As of JDK version 1.1,
2015 * replaced by <code>setBounds(int, int, int, int)</code>.
2016 */
2017 @Deprecated
2018 public void reshape(int x, int y, int width, int height) {
2019 synchronized (getTreeLock()) {
2020 try {
2021 setBoundsOp(ComponentPeer.SET_BOUNDS);
2022 boolean resized = (this.width != width) || (this.height != height);
2023 boolean moved = (this.x != x) || (this.y != y);
2024 if (!resized && !moved) {
2025 return;
2026 }
2027 int oldX = this.x;
2028 int oldY = this.y;
2029 int oldWidth = this.width;
2030 int oldHeight = this.height;
2031 this.x = x;
2032 this.y = y;
2033 this.width = width;
2034 this.height = height;
2035
2036 if (resized) {
2037 isPacked = false;
2038 }
2039
2040 boolean needNotify = true;
2041 mixOnReshaping();
2042 if (peer != null) {
2043 // LightwightPeer is an empty stub so can skip peer.reshape
2044 if (!(peer instanceof LightweightPeer)) {
2045 reshapeNativePeer(x, y, width, height, getBoundsOp());
2046 // Check peer actualy changed coordinates
2047 resized = (oldWidth != this.width) || (oldHeight != this.height);
2048 moved = (oldX != this.x) || (oldY != this.y);
2049 // fix for 5025858: do not send ComponentEvents for toplevel
2050 // windows here as it is done from peer or native code when
2051 // the window is really resized or moved, otherwise some
2052 // events may be sent twice
2053 if (this instanceof Window) {
2054 needNotify = false;
2055 }
2056 }
2057 if (resized) {
2058 invalidate();
2059 }
2060 if (parent != null && parent.valid) {
2061 parent.invalidate();
2062 }
2063 }
2064 if (needNotify) {
2065 notifyNewBounds(resized, moved);
2066 }
2067 repaintParentIfNeeded(oldX, oldY, oldWidth, oldHeight);
2068 } finally {
2069 setBoundsOp(ComponentPeer.RESET_OPERATION);
2070 }
2071 }
2072 }
2073
2074 private void repaintParentIfNeeded(int oldX, int oldY, int oldWidth,
2075 int oldHeight)
2076 {
2077 if (parent != null && peer instanceof LightweightPeer && isShowing()) {
2078 // Have the parent redraw the area this component occupied.
2079 parent.repaint(oldX, oldY, oldWidth, oldHeight);
2080 // Have the parent redraw the area this component *now* occupies.
2081 repaint();
2082 }
2083 }
2084
2085 private void reshapeNativePeer(int x, int y, int width, int height, int op) {
2086 // native peer might be offset by more than direct
2087 // parent since parent might be lightweight.
2088 int nativeX = x;
2089 int nativeY = y;
2090 for (Component c = parent;
2091 (c != null) && (c.peer instanceof LightweightPeer);
2092 c = c.parent)
2093 {
2094 nativeX += c.x;
2095 nativeY += c.y;
2096 }
2097 peer.setBounds(nativeX, nativeY, width, height, op);
2098 }
2099
2100
2101 private void notifyNewBounds(boolean resized, boolean moved) {
2102 if (componentListener != null
2103 || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0
2104 || Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK))
2105 {
2106 if (resized) {
2107 ComponentEvent e = new ComponentEvent(this,
2108 ComponentEvent.COMPONENT_RESIZED);
2109 Toolkit.getEventQueue().postEvent(e);
2110 }
2111 if (moved) {
2112 ComponentEvent e = new ComponentEvent(this,
2113 ComponentEvent.COMPONENT_MOVED);
2114 Toolkit.getEventQueue().postEvent(e);
2115 }
2116 } else {
2117 if (this instanceof Container && ((Container)this).ncomponents > 0) {
2118 boolean enabledOnToolkit =
2119 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
2120 if (resized) {
2121
2122 ((Container)this).createChildHierarchyEvents(
2123 HierarchyEvent.ANCESTOR_RESIZED, 0, enabledOnToolkit);
2124 }
2125 if (moved) {
2126 ((Container)this).createChildHierarchyEvents(
2127 HierarchyEvent.ANCESTOR_MOVED, 0, enabledOnToolkit);
2128 }
2129 }
2130 }
2131 }
2132
2133 /**
2134 * Moves and resizes this component to conform to the new
2135 * bounding rectangle <code>r</code>. This component's new
2136 * position is specified by <code>r.x</code> and <code>r.y</code>,
2137 * and its new size is specified by <code>r.width</code> and
2138 * <code>r.height</code>
2139 * @param r the new bounding rectangle for this component
2140 * @see #getBounds
2141 * @see #setLocation(int, int)
2142 * @see #setLocation(Point)
2143 * @see #setSize(int, int)
2144 * @see #setSize(Dimension)
2145 * @since JDK1.1
2146 */
2147 public void setBounds(Rectangle r) {
2148 setBounds(r.x, r.y, r.width, r.height);
2149 }
2150
2151
2152 /**
2153 * Returns the current x coordinate of the components origin.
2154 * This method is preferable to writing
2155 * <code>component.getBounds().x</code>,
2156 * or <code>component.getLocation().x</code> because it doesn't
2157 * cause any heap allocations.
2158 *
2159 * @return the current x coordinate of the components origin
2160 * @since 1.2
2161 */
2162 public int getX() {
2163 return x;
2164 }
2165
2166
2167 /**
2168 * Returns the current y coordinate of the components origin.
2169 * This method is preferable to writing
2170 * <code>component.getBounds().y</code>,
2171 * or <code>component.getLocation().y</code> because it
2172 * doesn't cause any heap allocations.
2173 *
2174 * @return the current y coordinate of the components origin
2175 * @since 1.2
2176 */
2177 public int getY() {
2178 return y;
2179 }
2180
2181
2182 /**
2183 * Returns the current width of this component.
2184 * This method is preferable to writing
2185 * <code>component.getBounds().width</code>,
2186 * or <code>component.getSize().width</code> because it
2187 * doesn't cause any heap allocations.
2188 *
2189 * @return the current width of this component
2190 * @since 1.2
2191 */
2192 public int getWidth() {
2193 return width;
2194 }
2195
2196
2197 /**
2198 * Returns the current height of this component.
2199 * This method is preferable to writing
2200 * <code>component.getBounds().height</code>,
2201 * or <code>component.getSize().height</code> because it
2202 * doesn't cause any heap allocations.
2203 *
2204 * @return the current height of this component
2205 * @since 1.2
2206 */
2207 public int getHeight() {
2208 return height;
2209 }
2210
2211 /**
2212 * Stores the bounds of this component into "return value" <b>rv</b> and
2213 * return <b>rv</b>. If rv is <code>null</code> a new
2214 * <code>Rectangle</code> is allocated.
2215 * This version of <code>getBounds</code> is useful if the caller
2216 * wants to avoid allocating a new <code>Rectangle</code> object
2217 * on the heap.
2218 *
2219 * @param rv the return value, modified to the components bounds
2220 * @return rv
2221 */
2222 public Rectangle getBounds(Rectangle rv) {
2223 if (rv == null) {
2224 return new Rectangle(getX(), getY(), getWidth(), getHeight());
2225 }
2226 else {
2227 rv.setBounds(getX(), getY(), getWidth(), getHeight());
2228 return rv;
2229 }
2230 }
2231
2232 /**
2233 * Stores the width/height of this component into "return value" <b>rv</b>
2234 * and return <b>rv</b>. If rv is <code>null</code> a new
2235 * <code>Dimension</code> object is allocated. This version of
2236 * <code>getSize</code> is useful if the caller wants to avoid
2237 * allocating a new <code>Dimension</code> object on the heap.
2238 *
2239 * @param rv the return value, modified to the components size
2240 * @return rv
2241 */
2242 public Dimension getSize(Dimension rv) {
2243 if (rv == null) {
2244 return new Dimension(getWidth(), getHeight());
2245 }
2246 else {
2247 rv.setSize(getWidth(), getHeight());
2248 return rv;
2249 }
2250 }
2251
2252 /**
2253 * Stores the x,y origin of this component into "return value" <b>rv</b>
2254 * and return <b>rv</b>. If rv is <code>null</code> a new
2255 * <code>Point</code> is allocated.
2256 * This version of <code>getLocation</code> is useful if the
2257 * caller wants to avoid allocating a new <code>Point</code>
2258 * object on the heap.
2259 *
2260 * @param rv the return value, modified to the components location
2261 * @return rv
2262 */
2263 public Point getLocation(Point rv) {
2264 if (rv == null) {
2265 return new Point(getX(), getY());
2266 }
2267 else {
2268 rv.setLocation(getX(), getY());
2269 return rv;
2270 }
2271 }
2272
2273 /**
2274 * Returns true if this component is completely opaque, returns
2275 * false by default.
2276 * <p>
2277 * An opaque component paints every pixel within its
2278 * rectangular region. A non-opaque component paints only some of
2279 * its pixels, allowing the pixels underneath it to "show through".
2280 * A component that does not fully paint its pixels therefore
2281 * provides a degree of transparency. Only lightweight
2282 * components can be transparent.
2283 * <p>
2284 * Subclasses that guarantee to always completely paint their
2285 * contents should override this method and return true. All
2286 * of the "heavyweight" AWT components are opaque.
2287 *
2288 * @return true if this component is completely opaque
2289 * @see #isLightweight
2290 * @since 1.2
2291 */
2292 public boolean isOpaque() {
2293 if (getPeer() == null) {
2294 return false;
2295 }
2296 else {
2297 return !isLightweight();
2298 }
2299 }
2300
2301
2302 /**
2303 * A lightweight component doesn't have a native toolkit peer.
2304 * Subclasses of <code>Component</code> and <code>Container</code>,
2305 * other than the ones defined in this package like <code>Button</code>
2306 * or <code>Scrollbar</code>, are lightweight.
2307 * All of the Swing components are lightweights.
2308 * <p>
2309 * This method will always return <code>false</code> if this component
2310 * is not displayable because it is impossible to determine the
2311 * weight of an undisplayable component.
2312 *
2313 * @return true if this component has a lightweight peer; false if
2314 * it has a native peer or no peer
2315 * @see #isDisplayable
2316 * @since 1.2
2317 */
2318 public boolean isLightweight() {
2319 return getPeer() instanceof LightweightPeer;
2320 }
2321
2322
2323 /**
2324 * Sets the preferred size of this component to a constant
2325 * value. Subsequent calls to <code>getPreferredSize</code> will always
2326 * return this value. Setting the preferred size to <code>null</code>
2327 * restores the default behavior.
2328 *
2329 * @param preferredSize The new preferred size, or null
2330 * @see #getPreferredSize
2331 * @see #isPreferredSizeSet
2332 * @since 1.5
2333 */
2334 public void setPreferredSize(Dimension preferredSize) {
2335 Dimension old;
2336 // If the preferred size was set, use it as the old value, otherwise
2337 // use null to indicate we didn't previously have a set preferred
2338 // size.
2339 if (prefSizeSet) {
2340 old = this.prefSize;
2341 }
2342 else {
2343 old = null;
2344 }
2345 this.prefSize = preferredSize;
2346 prefSizeSet = (preferredSize != null);
2347 firePropertyChange("preferredSize", old, preferredSize);
2348 }
2349
2350
2351 /**
2352 * Returns true if the preferred size has been set to a
2353 * non-<code>null</code> value otherwise returns false.
2354 *
2355 * @return true if <code>setPreferredSize</code> has been invoked
2356 * with a non-null value.
2357 * @since 1.5
2358 */
2359 public boolean isPreferredSizeSet() {
2360 return prefSizeSet;
2361 }
2362
2363
2364 /**
2365 * Gets the preferred size of this component.
2366 * @return a dimension object indicating this component's preferred size
2367 * @see #getMinimumSize
2368 * @see LayoutManager
2369 */
2370 public Dimension getPreferredSize() {
2371 return preferredSize();
2372 }
2373
2374
2375 /**
2376 * @deprecated As of JDK version 1.1,
2377 * replaced by <code>getPreferredSize()</code>.
2378 */
2379 @Deprecated
2380 public Dimension preferredSize() {
2381 /* Avoid grabbing the lock if a reasonable cached size value
2382 * is available.
2383 */
2384 Dimension dim = prefSize;
2385 if (dim == null || !(isPreferredSizeSet() || isValid())) {
2386 synchronized (getTreeLock()) {
2387 prefSize = (peer != null) ?
2388 peer.preferredSize() :
2389 getMinimumSize();
2390 dim = prefSize;
2391 }
2392 }
2393 return new Dimension(dim);
2394 }
2395
2396 /**
2397 * Sets the minimum size of this component to a constant
2398 * value. Subsequent calls to <code>getMinimumSize</code> will always
2399 * return this value. Setting the minimum size to <code>null</code>
2400 * restores the default behavior.
2401 *
2402 * @param minimumSize the new minimum size of this component
2403 * @see #getMinimumSize
2404 * @see #isMinimumSizeSet
2405 * @since 1.5
2406 */
2407 public void setMinimumSize(Dimension minimumSize) {
2408 Dimension old;
2409 // If the minimum size was set, use it as the old value, otherwise
2410 // use null to indicate we didn't previously have a set minimum
2411 // size.
2412 if (minSizeSet) {
2413 old = this.minSize;
2414 }
2415 else {
2416 old = null;
2417 }
2418 this.minSize = minimumSize;
2419 minSizeSet = (minimumSize != null);
2420 firePropertyChange("minimumSize", old, minimumSize);
2421 }
2422
2423 /**
2424 * Returns whether or not <code>setMinimumSize</code> has been
2425 * invoked with a non-null value.
2426 *
2427 * @return true if <code>setMinimumSize</code> has been invoked with a
2428 * non-null value.
2429 * @since 1.5
2430 */
2431 public boolean isMinimumSizeSet() {
2432 return minSizeSet;
2433 }
2434
2435 /**
2436 * Gets the mininimum size of this component.
2437 * @return a dimension object indicating this component's minimum size
2438 * @see #getPreferredSize
2439 * @see LayoutManager
2440 */
2441 public Dimension getMinimumSize() {
2442 return minimumSize();
2443 }
2444
2445 /**
2446 * @deprecated As of JDK version 1.1,
2447 * replaced by <code>getMinimumSize()</code>.
2448 */
2449 @Deprecated
2450 public Dimension minimumSize() {
2451 /* Avoid grabbing the lock if a reasonable cached size value
2452 * is available.
2453 */
2454 Dimension dim = minSize;
2455 if (dim == null || !(isMinimumSizeSet() || isValid())) {
2456 synchronized (getTreeLock()) {
2457 minSize = (peer != null) ?
2458 peer.minimumSize() :
2459 size();
2460 dim = minSize;
2461 }
2462 }
2463 return new Dimension(dim);
2464 }
2465
2466 /**
2467 * Sets the maximum size of this component to a constant
2468 * value. Subsequent calls to <code>getMaximumSize</code> will always
2469 * return this value. Setting the maximum size to <code>null</code>
2470 * restores the default behavior.
2471 *
2472 * @param maximumSize a <code>Dimension</code> containing the
2473 * desired maximum allowable size
2474 * @see #getMaximumSize
2475 * @see #isMaximumSizeSet
2476 * @since 1.5
2477 */
2478 public void setMaximumSize(Dimension maximumSize) {
2479 // If the maximum size was set, use it as the old value, otherwise
2480 // use null to indicate we didn't previously have a set maximum
2481 // size.
2482 Dimension old;
2483 if (maxSizeSet) {
2484 old = this.maxSize;
2485 }
2486 else {
2487 old = null;
2488 }
2489 this.maxSize = maximumSize;
2490 maxSizeSet = (maximumSize != null);
2491 firePropertyChange("maximumSize", old, maximumSize);
2492 }
2493
2494 /**
2495 * Returns true if the maximum size has been set to a non-<code>null</code>
2496 * value otherwise returns false.
2497 *
2498 * @return true if <code>maximumSize</code> is non-<code>null</code>,
2499 * false otherwise
2500 * @since 1.5
2501 */
2502 public boolean isMaximumSizeSet() {
2503 return maxSizeSet;
2504 }
2505
2506 /**
2507 * Gets the maximum size of this component.
2508 * @return a dimension object indicating this component's maximum size
2509 * @see #getMinimumSize
2510 * @see #getPreferredSize
2511 * @see LayoutManager
2512 */
2513 public Dimension getMaximumSize() {
2514 if (isMaximumSizeSet()) {
2515 return new Dimension(maxSize);
2516 }
2517 return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
2518 }
2519
2520 /**
2521 * Returns the alignment along the x axis. This specifies how
2522 * the component would like to be aligned relative to other
2523 * components. The value should be a number between 0 and 1
2524 * where 0 represents alignment along the origin, 1 is aligned
2525 * the furthest away from the origin, 0.5 is centered, etc.
2526 */
2527 public float getAlignmentX() {
2528 return CENTER_ALIGNMENT;
2529 }
2530
2531 /**
2532 * Returns the alignment along the y axis. This specifies how
2533 * the component would like to be aligned relative to other
2534 * components. The value should be a number between 0 and 1
2535 * where 0 represents alignment along the origin, 1 is aligned
2536 * the furthest away from the origin, 0.5 is centered, etc.
2537 */
2538 public float getAlignmentY() {
2539 return CENTER_ALIGNMENT;
2540 }
2541
2542 /**
2543 * Returns the baseline. The baseline is measured from the top of
2544 * the component. This method is primarily meant for
2545 * <code>LayoutManager</code>s to align components along their
2546 * baseline. A return value less than 0 indicates this component
2547 * does not have a reasonable baseline and that
2548 * <code>LayoutManager</code>s should not align this component on
2549 * its baseline.
2550 * <p>
2551 * The default implementation returns -1. Subclasses that support
2552 * baseline should override appropriately. If a value &gt;= 0 is
2553 * returned, then the component has a valid baseline for any
2554 * size &gt;= the minimum size and <code>getBaselineResizeBehavior</code>
2555 * can be used to determine how the baseline changes with size.
2556 *
2557 * @param width the width to get the baseline for
2558 * @param height the height to get the baseline for
2559 * @return the baseline or &lt; 0 indicating there is no reasonable
2560 * baseline
2561 * @throws IllegalArgumentException if width or height is &lt; 0
2562 * @see #getBaselineResizeBehavior
2563 * @see java.awt.FontMetrics
2564 * @since 1.6
2565 */
2566 public int getBaseline(int width, int height) {
2567 if (width < 0 || height < 0) {
2568 throw new IllegalArgumentException(
2569 "Width and height must be >= 0");
2570 }
2571 return -1;
2572 }
2573
2574 /**
2575 * Returns an enum indicating how the baseline of the component
2576 * changes as the size changes. This method is primarily meant for
2577 * layout managers and GUI builders.
2578 * <p>
2579 * The default implementation returns
2580 * <code>BaselineResizeBehavior.OTHER</code>. Subclasses that have a
2581 * baseline should override appropriately. Subclasses should
2582 * never return <code>null</code>; if the baseline can not be
2583 * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers
2584 * should first ask for the baseline using
2585 * <code>getBaseline</code> and if a value &gt;= 0 is returned use
2586 * this method. It is acceptable for this method to return a
2587 * value other than <code>BaselineResizeBehavior.OTHER</code> even if
2588 * <code>getBaseline</code> returns a value less than 0.
2589 *
2590 * @return an enum indicating how the baseline changes as the component
2591 * size changes
2592 * @see #getBaseline(int, int)
2593 * @since 1.6
2594 */
2595 public BaselineResizeBehavior getBaselineResizeBehavior() {
2596 return BaselineResizeBehavior.OTHER;
2597 }
2598
2599 /**
2600 * Prompts the layout manager to lay out this component. This is
2601 * usually called when the component (more specifically, container)
2602 * is validated.
2603 * @see #validate
2604 * @see LayoutManager
2605 */
2606 public void doLayout() {
2607 layout();
2608 }
2609
2610 /**
2611 * @deprecated As of JDK version 1.1,
2612 * replaced by <code>doLayout()</code>.
2613 */
2614 @Deprecated
2615 public void layout() {
2616 }
2617
2618 /**
2619 * Ensures that this component has a valid layout. This method is
2620 * primarily intended to operate on instances of <code>Container</code>.
2621 * @see #invalidate
2622 * @see #doLayout()
2623 * @see LayoutManager
2624 * @see Container#validate
2625 * @since JDK1.0
2626 */
2627 public void validate() {
2628 synchronized (getTreeLock()) {
2629 ComponentPeer peer = this.peer;
2630 if (!valid && peer != null) {
2631 Font newfont = getFont();
2632 Font oldfont = peerFont;
2633 if (newfont != oldfont && (oldfont == null
2634 || !oldfont.equals(newfont))) {
2635 peer.setFont(newfont);
2636 peerFont = newfont;
2637 }
2638 peer.layout();
2639 }
2640 valid = true;
2641 }
2642 }
2643
2644 /**
2645 * Invalidates this component. This component and all parents
2646 * above it are marked as needing to be laid out. This method can
2647 * be called often, so it needs to execute quickly.
2648 * @see #validate
2649 * @see #doLayout
2650 * @see LayoutManager
2651 * @since JDK1.0
2652 */
2653 public void invalidate() {
2654 synchronized (getTreeLock()) {
2655 /* Nullify cached layout and size information.
2656 * For efficiency, propagate invalidate() upwards only if
2657 * some other component hasn't already done so first.
2658 */
2659 valid = false;
2660 if (!isPreferredSizeSet()) {
2661 prefSize = null;
2662 }
2663 if (!isMinimumSizeSet()) {
2664 minSize = null;
2665 }
2666 if (!isMaximumSizeSet()) {
2667 maxSize = null;
2668 }
2669 if (parent != null && parent.valid) {
2670 parent.invalidate();
2671 }
2672 }
2673 }
2674
2675 /**
2676 * Creates a graphics context for this component. This method will
2677 * return <code>null</code> if this component is currently not
2678 * displayable.
2679 * @return a graphics context for this component, or <code>null</code>
2680 * if it has none
2681 * @see #paint
2682 * @since JDK1.0
2683 */
2684 public Graphics getGraphics() {
2685 if (peer instanceof LightweightPeer) {
2686 // This is for a lightweight component, need to
2687 // translate coordinate spaces and clip relative
2688 // to the parent.
2689 if (parent == null) return null;
2690 Graphics g = parent.getGraphics();
2691 if (g == null) return null;
2692 if (g instanceof ConstrainableGraphics) {
2693 ((ConstrainableGraphics) g).constrain(x, y, width, height);
2694 } else {
2695 g.translate(x,y);
2696 g.setClip(0, 0, width, height);
2697 }
2698 g.setFont(getFont());
2699 return g;
2700 } else {
2701 ComponentPeer peer = this.peer;
2702 return (peer != null) ? peer.getGraphics() : null;
2703 }
2704 }
2705
2706 final Graphics getGraphics_NoClientCode() {
2707 ComponentPeer peer = this.peer;
2708 if (peer instanceof LightweightPeer) {
2709 // This is for a lightweight component, need to
2710 // translate coordinate spaces and clip relative
2711 // to the parent.
2712 Container parent = this.parent;
2713 if (parent == null) return null;
2714 Graphics g = parent.getGraphics_NoClientCode();
2715 if (g == null) return null;
2716 if (g instanceof ConstrainableGraphics) {
2717 ((ConstrainableGraphics) g).constrain(x, y, width, height);
2718 } else {
2719 g.translate(x,y);
2720 g.setClip(0, 0, width, height);
2721 }
2722 g.setFont(getFont_NoClientCode());
2723 return g;
2724 } else {
2725 return (peer != null) ? peer.getGraphics() : null;
2726 }
2727 }
2728
2729 /**
2730 * Gets the font metrics for the specified font.
2731 * Warning: Since Font metrics are affected by the
2732 * {@link java.awt.font.FontRenderContext FontRenderContext} and
2733 * this method does not provide one, it can return only metrics for
2734 * the default render context which may not match that used when
2735 * rendering on the Component if {@link Graphics2D} functionality is being
2736 * used. Instead metrics can be obtained at rendering time by calling
2737 * {@link Graphics#getFontMetrics()} or text measurement APIs on the
2738 * {@link Font Font} class.
2739 * @param font the font for which font metrics is to be
2740 * obtained
2741 * @return the font metrics for <code>font</code>
2742 * @see #getFont
2743 * @see #getPeer
2744 * @see java.awt.peer.ComponentPeer#getFontMetrics(Font)
2745 * @see Toolkit#getFontMetrics(Font)
2746 * @since JDK1.0
2747 */
2748 public FontMetrics getFontMetrics(Font font) {
2749 // REMIND: PlatformFont flag should be obsolete soon...
2750 if (sun.font.FontManager.usePlatformFontMetrics()) {
2751 if (peer != null &&
2752 !(peer instanceof LightweightPeer)) {
2753 return peer.getFontMetrics(font);
2754 }
2755 }
2756 return sun.font.FontDesignMetrics.getMetrics(font);
2757 }
2758
2759 /**
2760 * Sets the cursor image to the specified cursor. This cursor
2761 * image is displayed when the <code>contains</code> method for
2762 * this component returns true for the current cursor location, and
2763 * this Component is visible, displayable, and enabled. Setting the
2764 * cursor of a <code>Container</code> causes that cursor to be displayed
2765 * within all of the container's subcomponents, except for those
2766 * that have a non-<code>null</code> cursor.
2767 * <p>
2768 * The method may have no visual effect if the Java platform
2769 * implementation and/or the native system do not support
2770 * changing the mouse cursor shape.
2771 * @param cursor One of the constants defined
2772 * by the <code>Cursor</code> class;
2773 * if this parameter is <code>null</code>
2774 * then this component will inherit
2775 * the cursor of its parent
2776 * @see #isEnabled
2777 * @see #isShowing
2778 * @see #getCursor
2779 * @see #contains
2780 * @see Toolkit#createCustomCursor
2781 * @see Cursor
2782 * @since JDK1.1
2783 */
2784 public void setCursor(Cursor cursor) {
2785 this.cursor = cursor;
2786 updateCursorImmediately();
2787 }
2788
2789 /**
2790 * Updates the cursor. May not be invoked from the native
2791 * message pump.
2792 */
2793 final void updateCursorImmediately() {
2794 if (peer instanceof LightweightPeer) {
2795 Container nativeContainer = getNativeContainer();
2796
2797 if (nativeContainer == null) return;
2798
2799 ComponentPeer cPeer = nativeContainer.getPeer();
2800
2801 if (cPeer != null) {
2802 cPeer.updateCursorImmediately();
2803 }
2804 } else if (peer != null) {
2805 peer.updateCursorImmediately();
2806 }
2807 }
2808
2809 /**
2810 * Gets the cursor set in the component. If the component does
2811 * not have a cursor set, the cursor of its parent is returned.
2812 * If no cursor is set in the entire hierarchy,
2813 * <code>Cursor.DEFAULT_CURSOR</code> is returned.
2814 * @see #setCursor
2815 * @since JDK1.1
2816 */
2817 public Cursor getCursor() {
2818 return getCursor_NoClientCode();
2819 }
2820
2821 final Cursor getCursor_NoClientCode() {
2822 Cursor cursor = this.cursor;
2823 if (cursor != null) {
2824 return cursor;
2825 }
2826 Container parent = this.parent;
2827 if (parent != null) {
2828 return parent.getCursor_NoClientCode();
2829 } else {
2830 return Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
2831 }
2832 }
2833
2834 /**
2835 * Returns whether the cursor has been explicitly set for this Component.
2836 * If this method returns <code>false</code>, this Component is inheriting
2837 * its cursor from an ancestor.
2838 *
2839 * @return <code>true</code> if the cursor has been explicitly set for this
2840 * Component; <code>false</code> otherwise.
2841 * @since 1.4
2842 */
2843 public boolean isCursorSet() {
2844 return (cursor != null);
2845 }
2846
2847 /**
2848 * Paints this component.
2849 * <p>
2850 * This method is called when the contents of the component should
2851 * be painted; such as when the component is first being shown or
2852 * is damaged and in need of repair. The clip rectangle in the
2853 * <code>Graphics</code> parameter is set to the area
2854 * which needs to be painted.
2855 * Subclasses of <code>Component</code> that override this
2856 * method need not call <code>super.paint(g)</code>.
2857 * <p>
2858 * For performance reasons, <code>Component</code>s with zero width
2859 * or height aren't considered to need painting when they are first shown,
2860 * and also aren't considered to need repair.
2861 * <p>
2862 * <b>Note</b>: For more information on the paint mechanisms utilitized
2863 * by AWT and Swing, including information on how to write the most
2864 * efficient painting code, see
2865 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
2866 *
2867 * @param g the graphics context to use for painting
2868 * @see #update
2869 * @since JDK1.0
2870 */
2871 public void paint(Graphics g) {
2872 }
2873
2874 /**
2875 * Updates this component.
2876 * <p>
2877 * If this component is not a lightweight component, the
2878 * AWT calls the <code>update</code> method in response to
2879 * a call to <code>repaint</code>. You can assume that
2880 * the background is not cleared.
2881 * <p>
2882 * The <code>update</code> method of <code>Component</code>
2883 * calls this component's <code>paint</code> method to redraw
2884 * this component. This method is commonly overridden by subclasses
2885 * which need to do additional work in response to a call to
2886 * <code>repaint</code>.
2887 * Subclasses of Component that override this method should either
2888 * call <code>super.update(g)</code>, or call <code>paint(g)</code>
2889 * directly from their <code>update</code> method.
2890 * <p>
2891 * The origin of the graphics context, its
2892 * (<code>0</code>,&nbsp;<code>0</code>) coordinate point, is the
2893 * top-left corner of this component. The clipping region of the
2894 * graphics context is the bounding rectangle of this component.
2895 *
2896 * <p>
2897 * <b>Note</b>: For more information on the paint mechanisms utilitized
2898 * by AWT and Swing, including information on how to write the most
2899 * efficient painting code, see
2900 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
2901 *
2902 * @param g the specified context to use for updating
2903 * @see #paint
2904 * @see #repaint()
2905 * @since JDK1.0
2906 */
2907 public void update(Graphics g) {
2908 paint(g);
2909 }
2910
2911 /**
2912 * Paints this component and all of its subcomponents.
2913 * <p>
2914 * The origin of the graphics context, its
2915 * (<code>0</code>,&nbsp;<code>0</code>) coordinate point, is the
2916 * top-left corner of this component. The clipping region of the
2917 * graphics context is the bounding rectangle of this component.
2918 *
2919 * @param g the graphics context to use for painting
2920 * @see #paint
2921 * @since JDK1.0
2922 */
2923 public void paintAll(Graphics g) {
2924 if (isShowing()) {
2925 GraphicsCallback.PeerPaintCallback.getInstance().
2926 runOneComponent(this, new Rectangle(0, 0, width, height),
2927 g, g.getClip(),
2928 GraphicsCallback.LIGHTWEIGHTS |
2929 GraphicsCallback.HEAVYWEIGHTS);
2930 }
2931 }
2932
2933 /**
2934 * Simulates the peer callbacks into java.awt for painting of
2935 * lightweight Components.
2936 * @param g the graphics context to use for painting
2937 * @see #paintAll
2938 */
2939 void lightweightPaint(Graphics g) {
2940 paint(g);
2941 }
2942
2943 /**
2944 * Paints all the heavyweight subcomponents.
2945 */
2946 void paintHeavyweightComponents(Graphics g) {
2947 }
2948
2949 /**
2950 * Repaints this component.
2951 * <p>
2952 * If this component is a lightweight component, this method
2953 * causes a call to this component's <code>paint</code>
2954 * method as soon as possible. Otherwise, this method causes
2955 * a call to this component's <code>update</code> method as soon
2956 * as possible.
2957 * <p>
2958 * <b>Note</b>: For more information on the paint mechanisms utilitized
2959 * by AWT and Swing, including information on how to write the most
2960 * efficient painting code, see
2961 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
2962
2963 *
2964 * @see #update(Graphics)
2965 * @since JDK1.0
2966 */
2967 public void repaint() {
2968 repaint(0, 0, 0, width, height);
2969 }
2970
2971 /**
2972 * Repaints the component. If this component is a lightweight
2973 * component, this results in a call to <code>paint</code>
2974 * within <code>tm</code> milliseconds.
2975 * <p>
2976 * <b>Note</b>: For more information on the paint mechanisms utilitized
2977 * by AWT and Swing, including information on how to write the most
2978 * efficient painting code, see
2979 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
2980 *
2981 * @param tm maximum time in milliseconds before update
2982 * @see #paint
2983 * @see #update(Graphics)
2984 * @since JDK1.0
2985 */
2986 public void repaint(long tm) {
2987 repaint(tm, 0, 0, width, height);
2988 }
2989
2990 /**
2991 * Repaints the specified rectangle of this component.
2992 * <p>
2993 * If this component is a lightweight component, this method
2994 * causes a call to this component's <code>paint</code> method
2995 * as soon as possible. Otherwise, this method causes a call to
2996 * this component's <code>update</code> method as soon as possible.
2997 * <p>
2998 * <b>Note</b>: For more information on the paint mechanisms utilitized
2999 * by AWT and Swing, including information on how to write the most
3000 * efficient painting code, see
3001 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
3002 *
3003 * @param x the <i>x</i> coordinate
3004 * @param y the <i>y</i> coordinate
3005 * @param width the width
3006 * @param height the height
3007 * @see #update(Graphics)
3008 * @since JDK1.0
3009 */
3010 public void repaint(int x, int y, int width, int height) {
3011 repaint(0, x, y, width, height);
3012 }
3013
3014 /**
3015 * Repaints the specified rectangle of this component within
3016 * <code>tm</code> milliseconds.
3017 * <p>
3018 * If this component is a lightweight component, this method causes
3019 * a call to this component's <code>paint</code> method.
3020 * Otherwise, this method causes a call to this component's
3021 * <code>update</code> method.
3022 * <p>
3023 * <b>Note</b>: For more information on the paint mechanisms utilitized
3024 * by AWT and Swing, including information on how to write the most
3025 * efficient painting code, see
3026 * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>.
3027 *
3028 * @param tm maximum time in milliseconds before update
3029 * @param x the <i>x</i> coordinate
3030 * @param y the <i>y</i> coordinate
3031 * @param width the width
3032 * @param height the height
3033 * @see #update(Graphics)
3034 * @since JDK1.0
3035 */
3036 public void repaint(long tm, int x, int y, int width, int height) {
3037 if (this.peer instanceof LightweightPeer) {
3038 // Needs to be translated to parent coordinates since
3039 // a parent native container provides the actual repaint
3040 // services. Additionally, the request is restricted to
3041 // the bounds of the component.
3042 if (parent != null) {
3043 int px = this.x + ((x < 0) ? 0 : x);
3044 int py = this.y + ((y < 0) ? 0 : y);
3045 int pwidth = (width > this.width) ? this.width : width;
3046 int pheight = (height > this.height) ? this.height : height;
3047 parent.repaint(tm, px, py, pwidth, pheight);
3048 }
3049 } else {
3050 if (isVisible() && (this.peer != null) &&
3051 (width > 0) && (height > 0)) {
3052 PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
3053 new Rectangle(x, y, width, height));
3054 Toolkit.getEventQueue().postEvent(e);
3055 }
3056 }
3057 }
3058
3059 /**
3060 * Prints this component. Applications should override this method
3061 * for components that must do special processing before being
3062 * printed or should be printed differently than they are painted.
3063 * <p>
3064 * The default implementation of this method calls the
3065 * <code>paint</code> method.
3066 * <p>
3067 * The origin of the graphics context, its
3068 * (<code>0</code>,&nbsp;<code>0</code>) coordinate point, is the
3069 * top-left corner of this component. The clipping region of the
3070 * graphics context is the bounding rectangle of this component.
3071 * @param g the graphics context to use for printing
3072 * @see #paint(Graphics)
3073 * @since JDK1.0
3074 */
3075 public void print(Graphics g) {
3076 paint(g);
3077 }
3078
3079 /**
3080 * Prints this component and all of its subcomponents.
3081 * <p>
3082 * The origin of the graphics context, its
3083 * (<code>0</code>,&nbsp;<code>0</code>) coordinate point, is the
3084 * top-left corner of this component. The clipping region of the
3085 * graphics context is the bounding rectangle of this component.
3086 * @param g the graphics context to use for printing
3087 * @see #print(Graphics)
3088 * @since JDK1.0
3089 */
3090 public void printAll(Graphics g) {
3091 if (isShowing()) {
3092 GraphicsCallback.PeerPrintCallback.getInstance().
3093 runOneComponent(this, new Rectangle(0, 0, width, height),
3094 g, g.getClip(),
3095 GraphicsCallback.LIGHTWEIGHTS |
3096 GraphicsCallback.HEAVYWEIGHTS);
3097 }
3098 }
3099
3100 /**
3101 * Simulates the peer callbacks into java.awt for printing of
3102 * lightweight Components.
3103 * @param g the graphics context to use for printing
3104 * @see #printAll
3105 */
3106 void lightweightPrint(Graphics g) {
3107 print(g);
3108 }
3109
3110 /**
3111 * Prints all the heavyweight subcomponents.
3112 */
3113 void printHeavyweightComponents(Graphics g) {
3114 }
3115
3116 private Insets getInsets_NoClientCode() {
3117 ComponentPeer peer = this.peer;
3118 if (peer instanceof ContainerPeer) {
3119 return (Insets)((ContainerPeer)peer).insets().clone();
3120 }
3121 return new Insets(0, 0, 0, 0);
3122 }
3123
3124 /**
3125 * Repaints the component when the image has changed.
3126 * This <code>imageUpdate</code> method of an <code>ImageObserver</code>
3127 * is called when more information about an
3128 * image which had been previously requested using an asynchronous
3129 * routine such as the <code>drawImage</code> method of
3130 * <code>Graphics</code> becomes available.
3131 * See the definition of <code>imageUpdate</code> for
3132 * more information on this method and its arguments.
3133 * <p>
3134 * The <code>imageUpdate</code> method of <code>Component</code>
3135 * incrementally draws an image on the component as more of the bits
3136 * of the image are available.
3137 * <p>
3138 * If the system property <code>awt.image.incrementaldraw</code>
3139 * is missing or has the value <code>true</code>, the image is
3140 * incrementally drawn. If the system property has any other value,
3141 * then the image is not drawn until it has been completely loaded.
3142 * <p>
3143 * Also, if incremental drawing is in effect, the value of the
3144 * system property <code>awt.image.redrawrate</code> is interpreted
3145 * as an integer to give the maximum redraw rate, in milliseconds. If
3146 * the system property is missing or cannot be interpreted as an
3147 * integer, the redraw rate is once every 100ms.
3148 * <p>
3149 * The interpretation of the <code>x</code>, <code>y</code>,
3150 * <code>width</code>, and <code>height</code> arguments depends on
3151 * the value of the <code>infoflags</code> argument.
3152 *
3153 * @param img the image being observed
3154 * @param infoflags see <code>imageUpdate</code> for more information
3155 * @param x the <i>x</i> coordinate
3156 * @param y the <i>y</i> coordinate
3157 * @param w the width
3158 * @param h the height
3159 * @return <code>false</code> if the infoflags indicate that the
3160 * image is completely loaded; <code>true</code> otherwise.
3161 *
3162 * @see java.awt.image.ImageObserver
3163 * @see Graphics#drawImage(Image, int, int, Color, java.awt.image.ImageObserver)
3164 * @see Graphics#drawImage(Image, int, int, java.awt.image.ImageObserver)
3165 * @see Graphics#drawImage(Image, int, int, int, int, Color, java.awt.image.ImageObserver)
3166 * @see Graphics#drawImage(Image, int, int, int, int, java.awt.image.ImageObserver)
3167 * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
3168 * @since JDK1.0
3169 */
3170 public boolean imageUpdate(Image img, int infoflags,
3171 int x, int y, int w, int h) {
3172 int rate = -1;
3173 if ((infoflags & (FRAMEBITS|ALLBITS)) != 0) {
3174 rate = 0;
3175 } else if ((infoflags & SOMEBITS) != 0) {
3176 if (isInc) {
3177 rate = incRate;
3178 if (rate < 0) {
3179 rate = 0;
3180 }
3181 }
3182 }
3183 if (rate >= 0) {
3184 repaint(rate, 0, 0, width, height);
3185 }
3186 return (infoflags & (ALLBITS|ABORT)) == 0;
3187 }
3188
3189 /**
3190 * Creates an image from the specified image producer.
3191 * @param producer the image producer
3192 * @return the image produced
3193 * @since JDK1.0
3194 */
3195 public Image createImage(ImageProducer producer) {
3196 ComponentPeer peer = this.peer;
3197 if ((peer != null) && ! (peer instanceof LightweightPeer)) {
3198 return peer.createImage(producer);
3199 }
3200 return getToolkit().createImage(producer);
3201 }
3202
3203 /**
3204 * Creates an off-screen drawable image
3205 * to be used for double buffering.
3206 * @param width the specified width
3207 * @param height the specified height
3208 * @return an off-screen drawable image, which can be used for double
3209 * buffering. The return value may be <code>null</code> if the
3210 * component is not displayable. This will always happen if
3211 * <code>GraphicsEnvironment.isHeadless()</code> returns
3212 * <code>true</code>.
3213 * @see #isDisplayable
3214 * @see GraphicsEnvironment#isHeadless
3215 * @since JDK1.0
3216 */
3217 public Image createImage(int width, int height) {
3218 ComponentPeer peer = this.peer;
3219 if (peer instanceof LightweightPeer) {
3220 if (parent != null) { return parent.createImage(width, height); }
3221 else { return null;}
3222 } else {
3223 return (peer != null) ? peer.createImage(width, height) : null;
3224 }
3225 }
3226
3227 /**
3228 * Creates a volatile off-screen drawable image
3229 * to be used for double buffering.
3230 * @param width the specified width.
3231 * @param height the specified height.
3232 * @return an off-screen drawable image, which can be used for double
3233 * buffering. The return value may be <code>null</code> if the
3234 * component is not displayable. This will always happen if
3235 * <code>GraphicsEnvironment.isHeadless()</code> returns
3236 * <code>true</code>.
3237 * @see java.awt.image.VolatileImage
3238 * @see #isDisplayable
3239 * @see GraphicsEnvironment#isHeadless
3240 * @since 1.4
3241 */
3242 public VolatileImage createVolatileImage(int width, int height) {
3243 ComponentPeer peer = this.peer;
3244 if (peer instanceof LightweightPeer) {
3245 if (parent != null) {
3246 return parent.createVolatileImage(width, height);
3247 }
3248 else { return null;}
3249 } else {
3250 return (peer != null) ?
3251 peer.createVolatileImage(width, height) : null;
3252 }
3253 }
3254
3255 /**
3256 * Creates a volatile off-screen drawable image, with the given capabilities.
3257 * The contents of this image may be lost at any time due
3258 * to operating system issues, so the image must be managed
3259 * via the <code>VolatileImage</code> interface.
3260 * @param width the specified width.
3261 * @param height the specified height.
3262 * @param caps the image capabilities
3263 * @exception AWTException if an image with the specified capabilities cannot
3264 * be created
3265 * @return a VolatileImage object, which can be used
3266 * to manage surface contents loss and capabilities.
3267 * @see java.awt.image.VolatileImage
3268 * @since 1.4
3269 */
3270 public VolatileImage createVolatileImage(int width, int height,
3271 ImageCapabilities caps) throws AWTException {
3272 // REMIND : check caps
3273 return createVolatileImage(width, height);
3274 }
3275
3276 /**
3277 * Prepares an image for rendering on this component. The image
3278 * data is downloaded asynchronously in another thread and the
3279 * appropriate screen representation of the image is generated.
3280 * @param image the <code>Image</code> for which to
3281 * prepare a screen representation
3282 * @param observer the <code>ImageObserver</code> object
3283 * to be notified as the image is being prepared
3284 * @return <code>true</code> if the image has already been fully
3285 * prepared; <code>false</code> otherwise
3286 * @since JDK1.0
3287 */
3288 public boolean prepareImage(Image image, ImageObserver observer) {
3289 return prepareImage(image, -1, -1, observer);
3290 }
3291
3292 /**
3293 * Prepares an image for rendering on this component at the
3294 * specified width and height.
3295 * <p>
3296 * The image data is downloaded asynchronously in another thread,
3297 * and an appropriately scaled screen representation of the image is
3298 * generated.
3299 * @param image the instance of <code>Image</code>
3300 * for which to prepare a screen representation
3301 * @param width the width of the desired screen representation
3302 * @param height the height of the desired screen representation
3303 * @param observer the <code>ImageObserver</code> object
3304 * to be notified as the image is being prepared
3305 * @return <code>true</code> if the image has already been fully
3306 * prepared; <code>false</code> otherwise
3307 * @see java.awt.image.ImageObserver
3308 * @since JDK1.0
3309 */
3310 public boolean prepareImage(Image image, int width, int height,
3311 ImageObserver observer) {
3312 ComponentPeer peer = this.peer;
3313 if (peer instanceof LightweightPeer) {
3314 return (parent != null)
3315 ? parent.prepareImage(image, width, height, observer)
3316 : getToolkit().prepareImage(image, width, height, observer);
3317 } else {
3318 return (peer != null)
3319 ? peer.prepareImage(image, width, height, observer)
3320 : getToolkit().prepareImage(image, width, height, observer);
3321 }
3322 }
3323
3324 /**
3325 * Returns the status of the construction of a screen representation
3326 * of the specified image.
3327 * <p>
3328 * This method does not cause the image to begin loading. An
3329 * application must use the <code>prepareImage</code> method
3330 * to force the loading of an image.
3331 * <p>
3332 * Information on the flags returned by this method can be found
3333 * with the discussion of the <code>ImageObserver</code> interface.
3334 * @param image the <code>Image</code> object whose status
3335 * is being checked
3336 * @param observer the <code>ImageObserver</code>
3337 * object to be notified as the image is being prepared
3338 * @return the bitwise inclusive <b>OR</b> of
3339 * <code>ImageObserver</code> flags indicating what
3340 * information about the image is currently available
3341 * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver)
3342 * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver)
3343 * @see java.awt.image.ImageObserver
3344 * @since JDK1.0
3345 */
3346 public int checkImage(Image image, ImageObserver observer) {
3347 return checkImage(image, -1, -1, observer);
3348 }
3349
3350 /**
3351 * Returns the status of the construction of a screen representation
3352 * of the specified image.
3353 * <p>
3354 * This method does not cause the image to begin loading. An
3355 * application must use the <code>prepareImage</code> method
3356 * to force the loading of an image.
3357 * <p>
3358 * The <code>checkImage</code> method of <code>Component</code>
3359 * calls its peer's <code>checkImage</code> method to calculate
3360 * the flags. If this component does not yet have a peer, the
3361 * component's toolkit's <code>checkImage</code> method is called
3362 * instead.
3363 * <p>
3364 * Information on the flags returned by this method can be found
3365 * with the discussion of the <code>ImageObserver</code> interface.
3366 * @param image the <code>Image</code> object whose status
3367 * is being checked
3368 * @param width the width of the scaled version
3369 * whose status is to be checked
3370 * @param height the height of the scaled version
3371 * whose status is to be checked
3372 * @param observer the <code>ImageObserver</code> object
3373 * to be notified as the image is being prepared
3374 * @return the bitwise inclusive <b>OR</b> of
3375 * <code>ImageObserver</code> flags indicating what
3376 * information about the image is currently available
3377 * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver)
3378 * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver)
3379 * @see java.awt.image.ImageObserver
3380 * @since JDK1.0
3381 */
3382 public int checkImage(Image image, int width, int height,
3383 ImageObserver observer) {
3384 ComponentPeer peer = this.peer;
3385 if (peer instanceof LightweightPeer) {
3386 return (parent != null)
3387 ? parent.checkImage(image, width, height, observer)
3388 : getToolkit().checkImage(image, width, height, observer);
3389 } else {
3390 return (peer != null)
3391 ? peer.checkImage(image, width, height, observer)
3392 : getToolkit().checkImage(image, width, height, observer);
3393 }
3394 }
3395
3396 /**
3397 * Creates a new strategy for multi-buffering on this component.
3398 * Multi-buffering is useful for rendering performance. This method
3399 * attempts to create the best strategy available with the number of
3400 * buffers supplied. It will always create a <code>BufferStrategy</code>
3401 * with that number of buffers.
3402 * A page-flipping strategy is attempted first, then a blitting strategy
3403 * using accelerated buffers. Finally, an unaccelerated blitting
3404 * strategy is used.
3405 * <p>
3406 * Each time this method is called,
3407 * the existing buffer strategy for this component is discarded.
3408 * @param numBuffers number of buffers to create, including the front buffer
3409 * @exception IllegalArgumentException if numBuffers is less than 1.
3410 * @exception IllegalStateException if the component is not displayable
3411 * @see #isDisplayable
3412 * @see Window#getBufferStrategy()
3413 * @see Canvas#getBufferStrategy()
3414 * @since 1.4
3415 */
3416 void createBufferStrategy(int numBuffers) {
3417 BufferCapabilities bufferCaps;
3418 if (numBuffers > 1) {
3419 // Try to create a page-flipping strategy
3420 bufferCaps = new BufferCapabilities(new ImageCapabilities(true),
3421 new ImageCapabilities(true),
3422 BufferCapabilities.FlipContents.UNDEFINED);
3423 try {
3424 createBufferStrategy(numBuffers, bufferCaps);
3425 return; // Success
3426 } catch (AWTException e) {
3427 // Failed
3428 }
3429 }
3430 // Try a blitting (but still accelerated) strategy
3431 bufferCaps = new BufferCapabilities(new ImageCapabilities(true),
3432 new ImageCapabilities(true),
3433 null);
3434 try {
3435 createBufferStrategy(numBuffers, bufferCaps);
3436 return; // Success
3437 } catch (AWTException e) {
3438 // Failed
3439 }
3440 // Try an unaccelerated blitting strategy
3441 bufferCaps = new BufferCapabilities(new ImageCapabilities(false),
3442 new ImageCapabilities(false),
3443 null);
3444 try {
3445 createBufferStrategy(numBuffers, bufferCaps);
3446 return; // Success
3447 } catch (AWTException e) {
3448 // Failed
3449 }
3450 // Code should never reach here (an unaccelerated blitting
3451 // strategy should always work)
3452 throw new InternalError("Could not create a buffer strategy");
3453 }
3454
3455 /**
3456 * Creates a new strategy for multi-buffering on this component with the
3457 * required buffer capabilities. This is useful, for example, if only
3458 * accelerated memory or page flipping is desired (as specified by the
3459 * buffer capabilities).
3460 * <p>
3461 * Each time this method
3462 * is called, <code>dispose</code> will be invoked on the existing
3463 * <code>BufferStrategy</code>.
3464 * @param numBuffers number of buffers to create
3465 * @param caps the required capabilities for creating the buffer strategy;
3466 * cannot be <code>null</code>
3467 * @exception AWTException if the capabilities supplied could not be
3468 * supported or met; this may happen, for example, if there is not enough
3469 * accelerated memory currently available, or if page flipping is specified
3470 * but not possible.
3471 * @exception IllegalArgumentException if numBuffers is less than 1, or if
3472 * caps is <code>null</code>
3473 * @see Window#getBufferStrategy()
3474 * @see Canvas#getBufferStrategy()
3475 * @since 1.4
3476 */
3477 void createBufferStrategy(int numBuffers,
3478 BufferCapabilities caps) throws AWTException {
3479 // Check arguments
3480 if (numBuffers < 1) {
3481 throw new IllegalArgumentException(
3482 "Number of buffers must be at least 1");
3483 }
3484 if (caps == null) {
3485 throw new IllegalArgumentException("No capabilities specified");
3486 }
3487 // Destroy old buffers
3488 if (bufferStrategy != null) {
3489 bufferStrategy.dispose();
3490 }
3491 if (numBuffers == 1) {
3492 bufferStrategy = new SingleBufferStrategy(caps);
3493 } else {
3494 // assert numBuffers > 1;
3495 if (caps.isPageFlipping()) {
3496 bufferStrategy = new FlipSubRegionBufferStrategy(numBuffers, caps);
3497 } else {
3498 bufferStrategy = new BltSubRegionBufferStrategy(numBuffers, caps);
3499 }
3500 }
3501 }
3502
3503 /**
3504 * @return the buffer strategy used by this component
3505 * @see Window#createBufferStrategy
3506 * @see Canvas#createBufferStrategy
3507 * @since 1.4
3508 */
3509 BufferStrategy getBufferStrategy() {
3510 return bufferStrategy;
3511 }
3512
3513 /**
3514 * @return the back buffer currently used by this component's
3515 * BufferStrategy. If there is no BufferStrategy or no
3516 * back buffer, this method returns null.
3517 */
3518 Image getBackBuffer() {
3519 if (bufferStrategy != null) {
3520 if (bufferStrategy instanceof BltBufferStrategy) {
3521 BltBufferStrategy bltBS = (BltBufferStrategy)bufferStrategy;
3522 return bltBS.getBackBuffer();
3523 } else if (bufferStrategy instanceof FlipBufferStrategy) {
3524 FlipBufferStrategy flipBS = (FlipBufferStrategy)bufferStrategy;
3525 return flipBS.getBackBuffer();
3526 }
3527 }
3528 return null;
3529 }
3530
3531 /**
3532 * Inner class for flipping buffers on a component. That component must
3533 * be a <code>Canvas</code> or <code>Window</code>.
3534 * @see Canvas
3535 * @see Window
3536 * @see java.awt.image.BufferStrategy
3537 * @author Michael Martak
3538 * @since 1.4
3539 */
3540 protected class FlipBufferStrategy extends BufferStrategy {
3541 /**
3542 * The number of buffers
3543 */
3544 protected int numBuffers; // = 0
3545 /**
3546 * The buffering capabilities
3547 */
3548 protected BufferCapabilities caps; // = null
3549 /**
3550 * The drawing buffer
3551 */
3552 protected Image drawBuffer; // = null
3553 /**
3554 * The drawing buffer as a volatile image
3555 */
3556 protected VolatileImage drawVBuffer; // = null
3557 /**
3558 * Whether or not the drawing buffer has been recently restored from
3559 * a lost state.
3560 */
3561 protected boolean validatedContents; // = false
3562 /**
3563 * Size of the back buffers. (Note: these fields were added in 6.0
3564 * but kept package-private to avoid exposing them in the spec.
3565 * None of these fields/methods really should have been marked
3566 * protected when they were introduced in 1.4, but now we just have
3567 * to live with that decision.)
3568 */
3569 int width;
3570 int height;
3571
3572 /**
3573 * Creates a new flipping buffer strategy for this component.
3574 * The component must be a <code>Canvas</code> or <code>Window</code>.
3575 * @see Canvas
3576 * @see Window
3577 * @param numBuffers the number of buffers
3578 * @param caps the capabilities of the buffers
3579 * @exception AWTException if the capabilities supplied could not be
3580 * supported or met
3581 * @exception ClassCastException if the component is not a canvas or
3582 * window.
3583 */
3584 protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
3585 throws AWTException
3586 {
3587 if (!(Component.this instanceof Window) &&
3588 !(Component.this instanceof Canvas))
3589 {
3590 throw new ClassCastException(
3591 "Component must be a Canvas or Window");
3592 }
3593 this.numBuffers = numBuffers;
3594 this.caps = caps;
3595 createBuffers(numBuffers, caps);
3596 }
3597
3598 /**
3599 * Creates one or more complex, flipping buffers with the given
3600 * capabilities.
3601 * @param numBuffers number of buffers to create; must be greater than
3602 * one
3603 * @param caps the capabilities of the buffers.
3604 * <code>BufferCapabilities.isPageFlipping</code> must be
3605 * <code>true</code>.
3606 * @exception AWTException if the capabilities supplied could not be
3607 * supported or met
3608 * @exception IllegalStateException if the component has no peer
3609 * @exception IllegalArgumentException if numBuffers is less than two,
3610 * or if <code>BufferCapabilities.isPageFlipping</code> is not
3611 * <code>true</code>.
3612 * @see java.awt.BufferCapabilities#isPageFlipping()
3613 */
3614 protected void createBuffers(int numBuffers, BufferCapabilities caps)
3615 throws AWTException
3616 {
3617 if (numBuffers < 2) {
3618 throw new IllegalArgumentException(
3619 "Number of buffers cannot be less than two");
3620 } else if (peer == null) {
3621 throw new IllegalStateException(
3622 "Component must have a valid peer");
3623 } else if (caps == null || !caps.isPageFlipping()) {
3624 throw new IllegalArgumentException(
3625 "Page flipping capabilities must be specified");
3626 }
3627
3628 // save the current bounds
3629 width = getWidth();
3630 height = getHeight();
3631
3632 if (drawBuffer == null) {
3633 peer.createBuffers(numBuffers, caps);
3634 } else {
3635 // dispose the existing backbuffers
3636 drawBuffer = null;
3637 drawVBuffer = null;
3638 destroyBuffers();
3639 // ... then recreate the backbuffers
3640 peer.createBuffers(numBuffers, caps);
3641 }
3642 updateInternalBuffers();
3643 }
3644
3645 /**
3646 * Updates internal buffers (both volatile and non-volatile)
3647 * by requesting the back-buffer from the peer.
3648 */
3649 private void updateInternalBuffers() {
3650 // get the images associated with the draw buffer
3651 drawBuffer = getBackBuffer();
3652 if (drawBuffer instanceof VolatileImage) {
3653 drawVBuffer = (VolatileImage)drawBuffer;
3654 } else {
3655 drawVBuffer = null;
3656 }
3657 }
3658
3659 /**
3660 * @return direct access to the back buffer, as an image.
3661 * @exception IllegalStateException if the buffers have not yet
3662 * been created
3663 */
3664 protected Image getBackBuffer() {
3665 if (peer != null) {
3666 return peer.getBackBuffer();
3667 } else {
3668 throw new IllegalStateException(
3669 "Component must have a valid peer");
3670 }
3671 }
3672
3673 /**
3674 * Flipping moves the contents of the back buffer to the front buffer,
3675 * either by copying or by moving the video pointer.
3676 * @param flipAction an integer value describing the flipping action
3677 * for the contents of the back buffer. This should be one of the
3678 * values of the <code>BufferCapabilities.FlipContents</code>
3679 * property.
3680 * @exception IllegalStateException if the buffers have not yet
3681 * been created
3682 * @see java.awt.BufferCapabilities#getFlipContents()
3683 */
3684 protected void flip(BufferCapabilities.FlipContents flipAction) {
3685 if (peer != null) {
3686 peer.flip(flipAction);
3687 } else {
3688 throw new IllegalStateException(
3689 "Component must have a valid peer");
3690 }
3691 }
3692
3693 /**
3694 * Destroys the buffers created through this object
3695 */
3696 protected void destroyBuffers() {
3697 if (peer != null) {
3698 peer.destroyBuffers();
3699 } else {
3700 throw new IllegalStateException(
3701 "Component must have a valid peer");
3702 }
3703 }
3704
3705 /**
3706 * @return the buffering capabilities of this strategy
3707 */
3708 public BufferCapabilities getCapabilities() {
3709 return caps;
3710 }
3711
3712 /**
3713 * @return the graphics on the drawing buffer. This method may not
3714 * be synchronized for performance reasons; use of this method by multiple
3715 * threads should be handled at the application level. Disposal of the
3716 * graphics object must be handled by the application.
3717 */
3718 public Graphics getDrawGraphics() {
3719 revalidate();
3720 return drawBuffer.getGraphics();
3721 }
3722
3723 /**
3724 * Restore the drawing buffer if it has been lost
3725 */
3726 protected void revalidate() {
3727 revalidate(true);
3728 }
3729
3730 void revalidate(boolean checkSize) {
3731 validatedContents = false;
3732
3733 if (checkSize && (getWidth() != width || getHeight() != height)) {
3734 // component has been resized; recreate the backbuffers
3735 try {
3736 createBuffers(numBuffers, caps);
3737 } catch (AWTException e) {
3738 // shouldn't be possible
3739 }
3740 validatedContents = true;
3741 }
3742
3743 // get the buffers from the peer every time since they
3744 // might have been replaced in response to a display change event
3745 updateInternalBuffers();
3746
3747 // now validate the backbuffer
3748 if (drawVBuffer != null) {
3749 GraphicsConfiguration gc =
3750 getGraphicsConfiguration_NoClientCode();
3751 int returnCode = drawVBuffer.validate(gc);
3752 if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
3753 try {
3754 createBuffers(numBuffers, caps);
3755 } catch (AWTException e) {
3756 // shouldn't be possible
3757 }
3758 if (drawVBuffer != null) {
3759 // backbuffers were recreated, so validate again
3760 drawVBuffer.validate(gc);
3761 }
3762 validatedContents = true;
3763 } else if (returnCode == VolatileImage.IMAGE_RESTORED) {
3764 validatedContents = true;
3765 }
3766 }
3767 }
3768
3769 /**
3770 * @return whether the drawing buffer was lost since the last call to
3771 * <code>getDrawGraphics</code>
3772 */
3773 public boolean contentsLost() {
3774 if (drawVBuffer == null) {
3775 return false;
3776 }
3777 return drawVBuffer.contentsLost();
3778 }
3779
3780 /**
3781 * @return whether the drawing buffer was recently restored from a lost
3782 * state and reinitialized to the default background color (white)
3783 */
3784 public boolean contentsRestored() {
3785 return validatedContents;
3786 }
3787
3788 /**
3789 * Makes the next available buffer visible by either blitting or
3790 * flipping.
3791 */
3792 public void show() {
3793 flip(caps.getFlipContents());
3794 }
3795
3796 /**
3797 * {@inheritDoc}
3798 * @since 1.6
3799 */
3800 public void dispose() {
3801 if (Component.this.bufferStrategy == this) {
3802 Component.this.bufferStrategy = null;
3803 if (peer != null) {
3804 destroyBuffers();
3805 }
3806 }
3807 }
3808
3809 } // Inner class FlipBufferStrategy
3810
3811 /**
3812 * Inner class for blitting offscreen surfaces to a component.
3813 *
3814 * @author Michael Martak
3815 * @since 1.4
3816 */
3817 protected class BltBufferStrategy extends BufferStrategy {
3818
3819 /**
3820 * The buffering capabilities
3821 */
3822 protected BufferCapabilities caps; // = null
3823 /**
3824 * The back buffers
3825 */
3826 protected VolatileImage[] backBuffers; // = null
3827 /**
3828 * Whether or not the drawing buffer has been recently restored from
3829 * a lost state.
3830 */
3831 protected boolean validatedContents; // = false
3832 /**
3833 * Size of the back buffers
3834 */
3835 protected int width;
3836 protected int height;
3837
3838 /**
3839 * Insets for the hosting Component. The size of the back buffer
3840 * is constrained by these.
3841 */
3842 private Insets insets;
3843
3844 /**
3845 * Creates a new blt buffer strategy around a component
3846 * @param numBuffers number of buffers to create, including the
3847 * front buffer
3848 * @param caps the capabilities of the buffers
3849 */
3850 protected BltBufferStrategy(int numBuffers, BufferCapabilities caps) {
3851 this.caps = caps;
3852 createBackBuffers(numBuffers - 1);
3853 }
3854
3855 /**
3856 * {@inheritDoc}
3857 * @since 1.6
3858 */
3859 public void dispose() {
3860 if (backBuffers != null) {
3861 for (int counter = backBuffers.length - 1; counter >= 0;
3862 counter--) {
3863 if (backBuffers[counter] != null) {
3864 backBuffers[counter].flush();
3865 backBuffers[counter] = null;
3866 }
3867 }
3868 }
3869 if (Component.this.bufferStrategy == this) {
3870 Component.this.bufferStrategy = null;
3871 }
3872 }
3873
3874 /**
3875 * Creates the back buffers
3876 */
3877 protected void createBackBuffers(int numBuffers) {
3878 if (numBuffers == 0) {
3879 backBuffers = null;
3880 } else {
3881 // save the current bounds
3882 width = getWidth();
3883 height = getHeight();
3884 insets = getInsets_NoClientCode();
3885 int iWidth = width - insets.left - insets.right;
3886 int iHeight = height - insets.top - insets.bottom;
3887
3888 // It is possible for the component's width and/or height
3889 // to be 0 here. Force the size of the backbuffers to
3890 // be > 0 so that creating the image won't fail.
3891 iWidth = Math.max(1, iWidth);
3892 iHeight = Math.max(1, iHeight);
3893 if (backBuffers == null) {
3894 backBuffers = new VolatileImage[numBuffers];
3895 } else {
3896 // flush any existing backbuffers
3897 for (int i = 0; i < numBuffers; i++) {
3898 if (backBuffers[i] != null) {
3899 backBuffers[i].flush();
3900 backBuffers[i] = null;
3901 }
3902 }
3903 }
3904
3905 // create the backbuffers
3906 for (int i = 0; i < numBuffers; i++) {
3907 backBuffers[i] = createVolatileImage(iWidth, iHeight);
3908 }
3909 }
3910 }
3911
3912 /**
3913 * @return the buffering capabilities of this strategy
3914 */
3915 public BufferCapabilities getCapabilities() {
3916 return caps;
3917 }
3918
3919 /**
3920 * @return the draw graphics
3921 */
3922 public Graphics getDrawGraphics() {
3923 revalidate();
3924 Image backBuffer = getBackBuffer();
3925 if (backBuffer == null) {
3926 return getGraphics();
3927 }
3928 SunGraphics2D g = (SunGraphics2D)backBuffer.getGraphics();
3929 g.constrain(-insets.left, -insets.top,
3930 backBuffer.getWidth(null) + insets.left,
3931 backBuffer.getHeight(null) + insets.top);
3932 return g;
3933 }
3934
3935 /**
3936 * @return direct access to the back buffer, as an image.
3937 * If there is no back buffer, returns null.
3938 */
3939 Image getBackBuffer() {
3940 if (backBuffers != null) {
3941 return backBuffers[backBuffers.length - 1];
3942 } else {
3943 return null;
3944 }
3945 }
3946
3947 /**
3948 * Makes the next available buffer visible.
3949 */
3950 public void show() {
3951 showSubRegion(insets.left, insets.top,
3952 width - insets.right,
3953 height - insets.bottom);
3954 }
3955
3956 /**
3957 * Package-private method to present a specific rectangular area
3958 * of this buffer. This class currently shows only the entire
3959 * buffer, by calling showSubRegion() with the full dimensions of
3960 * the buffer. Subclasses (e.g., BltSubRegionBufferStrategy
3961 * and FlipSubRegionBufferStrategy) may have region-specific show
3962 * methods that call this method with actual sub regions of the
3963 * buffer.
3964 */
3965 void showSubRegion(int x1, int y1, int x2, int y2) {
3966 if (backBuffers == null) {
3967 return;
3968 }
3969 // Adjust location to be relative to client area.
3970 x1 -= insets.left;
3971 x2 -= insets.left;
3972 y1 -= insets.top;
3973 y2 -= insets.top;
3974 Graphics g = getGraphics_NoClientCode();
3975 if (g == null) {
3976 // Not showing, bail
3977 return;
3978 }
3979 try {
3980 // First image copy is in terms of Frame's coordinates, need
3981 // to translate to client area.
3982 g.translate(insets.left, insets.top);
3983 for (int i = 0; i < backBuffers.length; i++) {
3984 g.drawImage(backBuffers[i],
3985 x1, y1, x2, y2,
3986 x1, y1, x2, y2,
3987 null);
3988 g.dispose();
3989 g = null;
3990 g = backBuffers[i].getGraphics();
3991 }
3992 } finally {
3993 if (g != null) {
3994 g.dispose();
3995 }
3996 }
3997 }
3998
3999 /**
4000 * Restore the drawing buffer if it has been lost
4001 */
4002 protected void revalidate() {
4003 revalidate(true);
4004 }
4005
4006 void revalidate(boolean checkSize) {
4007 validatedContents = false;
4008
4009 if (backBuffers == null) {
4010 return;
4011 }
4012
4013 if (checkSize) {
4014 Insets insets = getInsets_NoClientCode();
4015 if (getWidth() != width || getHeight() != height ||
4016 !insets.equals(this.insets)) {
4017 // component has been resized; recreate the backbuffers
4018 createBackBuffers(backBuffers.length);
4019 validatedContents = true;
4020 }
4021 }
4022
4023 // now validate the backbuffer
4024 GraphicsConfiguration gc = getGraphicsConfiguration_NoClientCode();
4025 int returnCode =
4026 backBuffers[backBuffers.length - 1].validate(gc);
4027 if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
4028 if (checkSize) {
4029 createBackBuffers(backBuffers.length);
4030 // backbuffers were recreated, so validate again
4031 backBuffers[backBuffers.length - 1].validate(gc);
4032 }
4033 // else case means we're called from Swing on the toolkit
4034 // thread, don't recreate buffers as that'll deadlock
4035 // (creating VolatileImages invokes getting GraphicsConfig
4036 // which grabs treelock).
4037 validatedContents = true;
4038 } else if (returnCode == VolatileImage.IMAGE_RESTORED) {
4039 validatedContents = true;
4040 }
4041 }
4042
4043 /**
4044 * @return whether the drawing buffer was lost since the last call to
4045 * <code>getDrawGraphics</code>
4046 */
4047 public boolean contentsLost() {
4048 if (backBuffers == null) {
4049 return false;
4050 } else {
4051 return backBuffers[backBuffers.length - 1].contentsLost();
4052 }
4053 }
4054
4055 /**
4056 * @return whether the drawing buffer was recently restored from a lost
4057 * state and reinitialized to the default background color (white)
4058 */
4059 public boolean contentsRestored() {
4060 return validatedContents;
4061 }
4062 } // Inner class BltBufferStrategy
4063
4064 /**
4065 * Private class to perform sub-region flipping.
4066 * REMIND: this subclass currently punts on subregions and
4067 * flips the entire buffer.
4068 */
4069 private class FlipSubRegionBufferStrategy extends FlipBufferStrategy
4070 implements SubRegionShowable
4071 {
4072
4073 protected FlipSubRegionBufferStrategy(int numBuffers,
4074 BufferCapabilities caps)
4075 throws AWTException
4076 {
4077 super(numBuffers, caps);
4078 }
4079
4080 public void show(int x1, int y1, int x2, int y2) {
4081 show();
4082 }
4083
4084 // This is invoked by Swing on the toolkit thread.
4085 public boolean validateAndShow(int x1, int y1, int x2, int y2) {
4086 revalidate(false);
4087 if (!contentsRestored() && !contentsLost()) {
4088 show();
4089 return !contentsLost();
4090 }
4091 return false;
4092 }
4093 }
4094
4095 /**
4096 * Private class to perform sub-region blitting. Swing will use
4097 * this subclass via the SubRegionShowable interface in order to
4098 * copy only the area changed during a repaint.
4099 * @see javax.swing.BufferStrategyPaintManager
4100 */
4101 private class BltSubRegionBufferStrategy extends BltBufferStrategy
4102 implements SubRegionShowable
4103 {
4104
4105 protected BltSubRegionBufferStrategy(int numBuffers,
4106 BufferCapabilities caps)
4107 {
4108 super(numBuffers, caps);
4109 }
4110
4111 public void show(int x1, int y1, int x2, int y2) {
4112 showSubRegion(x1, y1, x2, y2);
4113 }
4114
4115 // This method is called by Swing on the toolkit thread.
4116 public boolean validateAndShow(int x1, int y1, int x2, int y2) {
4117 revalidate(false);
4118 if (!contentsRestored() && !contentsLost()) {
4119 showSubRegion(x1, y1, x2, y2);
4120 return !contentsLost();
4121 }
4122 return false;
4123 }
4124 }
4125
4126 /**
4127 * Inner class for flipping buffers on a component. That component must
4128 * be a <code>Canvas</code> or <code>Window</code>.
4129 * @see Canvas
4130 * @see Window
4131 * @see java.awt.image.BufferStrategy
4132 * @author Michael Martak
4133 * @since 1.4
4134 */
4135 private class SingleBufferStrategy extends BufferStrategy {
4136
4137 private BufferCapabilities caps;
4138
4139 public SingleBufferStrategy(BufferCapabilities caps) {
4140 this.caps = caps;
4141 }
4142 public BufferCapabilities getCapabilities() {
4143 return caps;
4144 }
4145 public Graphics getDrawGraphics() {
4146 return getGraphics();
4147 }
4148 public boolean contentsLost() {
4149 return false;
4150 }
4151 public boolean contentsRestored() {
4152 return false;
4153 }
4154 public void show() {
4155 // Do nothing
4156 }
4157 } // Inner class SingleBufferStrategy
4158
4159 /**
4160 * Sets whether or not paint messages received from the operating system
4161 * should be ignored. This does not affect paint events generated in
4162 * software by the AWT, unless they are an immediate response to an
4163 * OS-level paint message.
4164 * <p>
4165 * This is useful, for example, if running under full-screen mode and
4166 * better performance is desired, or if page-flipping is used as the
4167 * buffer strategy.
4168 *
4169 * @since 1.4
4170 * @see #getIgnoreRepaint
4171 * @see Canvas#createBufferStrategy
4172 * @see Window#createBufferStrategy
4173 * @see java.awt.image.BufferStrategy
4174 * @see GraphicsDevice#setFullScreenWindow
4175 */
4176 public void setIgnoreRepaint(boolean ignoreRepaint) {
4177 this.ignoreRepaint = ignoreRepaint;
4178 }
4179
4180 /**
4181 * @return whether or not paint messages received from the operating system
4182 * should be ignored.
4183 *
4184 * @since 1.4
4185 * @see #setIgnoreRepaint
4186 */
4187 public boolean getIgnoreRepaint() {
4188 return ignoreRepaint;
4189 }
4190
4191 /**
4192 * Checks whether this component "contains" the specified point,
4193 * where <code>x</code> and <code>y</code> are defined to be
4194 * relative to the coordinate system of this component.
4195 * @param x the <i>x</i> coordinate of the point
4196 * @param y the <i>y</i> coordinate of the point
4197 * @see #getComponentAt(int, int)
4198 * @since JDK1.1
4199 */
4200 public boolean contains(int x, int y) {
4201 return inside(x, y);
4202 }
4203
4204 /**
4205 * @deprecated As of JDK version 1.1,
4206 * replaced by contains(int, int).
4207 */
4208 @Deprecated
4209 public boolean inside(int x, int y) {
4210 return (x >= 0) && (x < width) && (y >= 0) && (y < height);
4211 }
4212
4213 /**
4214 * Checks whether this component "contains" the specified point,
4215 * where the point's <i>x</i> and <i>y</i> coordinates are defined
4216 * to be relative to the coordinate system of this component.
4217 * @param p the point
4218 * @see #getComponentAt(Point)
4219 * @since JDK1.1
4220 */
4221 public boolean contains(Point p) {
4222 return contains(p.x, p.y);
4223 }
4224
4225 /**
4226 * Determines if this component or one of its immediate
4227 * subcomponents contains the (<i>x</i>,&nbsp;<i>y</i>) location,
4228 * and if so, returns the containing component. This method only
4229 * looks one level deep. If the point (<i>x</i>,&nbsp;<i>y</i>) is
4230 * inside a subcomponent that itself has subcomponents, it does not
4231 * go looking down the subcomponent tree.
4232 * <p>
4233 * The <code>locate</code> method of <code>Component</code> simply
4234 * returns the component itself if the (<i>x</i>,&nbsp;<i>y</i>)
4235 * coordinate location is inside its bounding box, and <code>null</code>
4236 * otherwise.
4237 * @param x the <i>x</i> coordinate
4238 * @param y the <i>y</i> coordinate
4239 * @return the component or subcomponent that contains the
4240 * (<i>x</i>,&nbsp;<i>y</i>) location;
4241 * <code>null</code> if the location
4242 * is outside this component
4243 * @see #contains(int, int)
4244 * @since JDK1.0
4245 */
4246 public Component getComponentAt(int x, int y) {
4247 return locate(x, y);
4248 }
4249
4250 /**
4251 * @deprecated As of JDK version 1.1,
4252 * replaced by getComponentAt(int, int).
4253 */
4254 @Deprecated
4255 public Component locate(int x, int y) {
4256 return contains(x, y) ? this : null;
4257 }
4258
4259 /**
4260 * Returns the component or subcomponent that contains the
4261 * specified point.
4262 * @param p the point
4263 * @see java.awt.Component#contains
4264 * @since JDK1.1
4265 */
4266 public Component getComponentAt(Point p) {
4267 return getComponentAt(p.x, p.y);
4268 }
4269
4270 /**
4271 * @deprecated As of JDK version 1.1,
4272 * replaced by <code>dispatchEvent(AWTEvent e)</code>.
4273 */
4274 @Deprecated
4275 public void deliverEvent(Event e) {
4276 postEvent(e);
4277 }
4278
4279 /**
4280 * Dispatches an event to this component or one of its sub components.
4281 * Calls <code>processEvent</code> before returning for 1.1-style
4282 * events which have been enabled for the <code>Component</code>.
4283 * @param e the event
4284 */
4285 public final void dispatchEvent(AWTEvent e) {
4286 dispatchEventImpl(e);
4287 }
4288
4289 void dispatchEventImpl(AWTEvent e) {
4290 int id = e.getID();
4291
4292 // Check that this component belongs to this app-context
4293 AppContext compContext = appContext;
4294 if (compContext != null && !compContext.equals(AppContext.getAppContext())) {
4295 if (eventLog.isLoggable(Level.FINE)) {
4296 eventLog.log(Level.FINE, "Event " + e + " is being dispatched on the wrong AppContext");
4297 }
4298 }
4299
4300 if (eventLog.isLoggable(Level.FINEST)) {
4301 eventLog.log(Level.FINEST, "{0}", e);
4302 }
4303
4304 /*
4305 * 0. Set timestamp and modifiers of current event.
4306 */
4307 EventQueue.setCurrentEventAndMostRecentTime(e);
4308
4309 /*
4310 * 1. Pre-dispatchers. Do any necessary retargeting/reordering here
4311 * before we notify AWTEventListeners.
4312 */
4313
4314 if (e instanceof SunDropTargetEvent) {
4315 ((SunDropTargetEvent)e).dispatch();
4316 return;
4317 }
4318
4319 if (!e.focusManagerIsDispatching) {
4320 // Invoke the private focus retargeting method which provides
4321 // lightweight Component support
4322 if (e.isPosted) {
4323 e = KeyboardFocusManager.retargetFocusEvent(e);
4324 e.isPosted = true;
4325 }
4326
4327 // Now, with the event properly targeted to a lightweight
4328 // descendant if necessary, invoke the public focus retargeting
4329 // and dispatching function
4330 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().
4331 dispatchEvent(e))
4332 {
4333 return;
4334 }
4335 }
4336 if ((e instanceof FocusEvent) && focusLog.isLoggable(Level.FINEST)) {
4337 focusLog.log(Level.FINEST, "" + e);
4338 }
4339 // MouseWheel may need to be retargeted here so that
4340 // AWTEventListener sees the event go to the correct
4341 // Component. If the MouseWheelEvent needs to go to an ancestor,
4342 // the event is dispatched to the ancestor, and dispatching here
4343 // stops.
4344 if (id == MouseEvent.MOUSE_WHEEL &&
4345 (!eventTypeEnabled(id)) &&
4346 (peer != null && !peer.handlesWheelScrolling()) &&
4347 (dispatchMouseWheelToAncestor((MouseWheelEvent)e)))
4348 {
4349 return;
4350 }
4351
4352 /*
4353 * 2. Allow the Toolkit to pass this to AWTEventListeners.
4354 */
4355 Toolkit toolkit = Toolkit.getDefaultToolkit();
4356 toolkit.notifyAWTEventListeners(e);
4357
4358
4359 /*
4360 * 3. If no one has consumed a key event, allow the
4361 * KeyboardFocusManager to process it.
4362 */
4363 if (!e.isConsumed()) {
4364 if (e instanceof java.awt.event.KeyEvent) {
4365 KeyboardFocusManager.getCurrentKeyboardFocusManager().
4366 processKeyEvent(this, (KeyEvent)e);
4367 if (e.isConsumed()) {
4368 return;
4369 }
4370 }
4371 }
4372
4373 /*
4374 * 4. Allow input methods to process the event
4375 */
4376 if (areInputMethodsEnabled()) {
4377 // We need to pass on InputMethodEvents since some host
4378 // input method adapters send them through the Java
4379 // event queue instead of directly to the component,
4380 // and the input context also handles the Java composition window
4381 if(((e instanceof InputMethodEvent) && !(this instanceof CompositionArea))
4382 ||
4383 // Otherwise, we only pass on input and focus events, because
4384 // a) input methods shouldn't know about semantic or component-level events
4385 // b) passing on the events takes time
4386 // c) isConsumed() is always true for semantic events.
4387 (e instanceof InputEvent) || (e instanceof FocusEvent)) {
4388 InputContext inputContext = getInputContext();
4389
4390
4391 if (inputContext != null) {
4392 inputContext.dispatchEvent(e);
4393 if (e.isConsumed()) {
4394 if ((e instanceof FocusEvent) && focusLog.isLoggable(Level.FINEST)) {
4395 focusLog.log(Level.FINEST, "3579: Skipping " + e);
4396 }
4397 return;
4398 }
4399 }
4400 }
4401 } else {
4402 // When non-clients get focus, we need to explicitly disable the native
4403 // input method. The native input method is actually not disabled when
4404 // the active/passive/peered clients loose focus.
4405 if (id == FocusEvent.FOCUS_GAINED) {
4406 InputContext inputContext = getInputContext();
4407 if (inputContext != null && inputContext instanceof sun.awt.im.InputContext) {
4408 ((sun.awt.im.InputContext)inputContext).disableNativeIM();
4409 }
4410 }
4411 }
4412
4413
4414 /*
4415 * 5. Pre-process any special events before delivery
4416 */
4417 switch(id) {
4418 // Handling of the PAINT and UPDATE events is now done in the
4419 // peer's handleEvent() method so the background can be cleared
4420 // selectively for non-native components on Windows only.
4421 // - Fred.Ecks@Eng.sun.com, 5-8-98
4422
4423 case KeyEvent.KEY_PRESSED:
4424 case KeyEvent.KEY_RELEASED:
4425 Container p = (Container)((this instanceof Container) ? this : parent);
4426 if (p != null) {
4427 p.preProcessKeyEvent((KeyEvent)e);
4428 if (e.isConsumed()) {
4429 if (focusLog.isLoggable(Level.FINEST)) {
4430 focusLog.log(Level.FINEST, "Pre-process consumed event");
4431 }
4432 return;
4433 }
4434 }
4435 break;
4436
4437 case WindowEvent.WINDOW_CLOSING:
4438 if (toolkit instanceof WindowClosingListener) {
4439 windowClosingException = ((WindowClosingListener)
4440 toolkit).windowClosingNotify((WindowEvent)e);
4441 if (checkWindowClosingException()) {
4442 return;
4443 }
4444 }
4445 break;
4446
4447 default:
4448 break;
4449 }
4450
4451 /*
4452 * 6. Deliver event for normal processing
4453 */
4454 if (newEventsOnly) {
4455 // Filtering needs to really be moved to happen at a lower
4456 // level in order to get maximum performance gain; it is
4457 // here temporarily to ensure the API spec is honored.
4458 //
4459 if (eventEnabled(e)) {
4460 processEvent(e);
4461 }
4462 } else if (id == MouseEvent.MOUSE_WHEEL) {
4463 // newEventsOnly will be false for a listenerless ScrollPane, but
4464 // MouseWheelEvents still need to be dispatched to it so scrolling
4465 // can be done.
4466 autoProcessMouseWheel((MouseWheelEvent)e);
4467 } else if (!(e instanceof MouseEvent && !postsOldMouseEvents())) {
4468 //
4469 // backward compatibility
4470 //
4471 Event olde = e.convertToOld();
4472 if (olde != null) {
4473 int key = olde.key;
4474 int modifiers = olde.modifiers;
4475
4476 postEvent(olde);
4477 if (olde.isConsumed()) {
4478 e.consume();
4479 }
4480 // if target changed key or modifier values, copy them
4481 // back to original event
4482 //
4483 switch(olde.id) {
4484 case Event.KEY_PRESS:
4485 case Event.KEY_RELEASE:
4486 case Event.KEY_ACTION:
4487 case Event.KEY_ACTION_RELEASE:
4488 if (olde.key != key) {
4489 ((KeyEvent)e).setKeyChar(olde.getKeyEventChar());
4490 }
4491 if (olde.modifiers != modifiers) {
4492 ((KeyEvent)e).setModifiers(olde.modifiers);
4493 }
4494 break;
4495 default:
4496 break;
4497 }
4498 }
4499 }
4500
4501 /*
4502 * 8. Special handling for 4061116 : Hook for browser to close modal
4503 * dialogs.
4504 */
4505 if (id == WindowEvent.WINDOW_CLOSING && !e.isConsumed()) {
4506 if (toolkit instanceof WindowClosingListener) {
4507 windowClosingException =
4508 ((WindowClosingListener)toolkit).
4509 windowClosingDelivered((WindowEvent)e);
4510 if (checkWindowClosingException()) {
4511 return;
4512 }
4513 }
4514 }
4515
4516 /*
4517 * 9. Allow the peer to process the event.
4518 * Except KeyEvents, they will be processed by peer after
4519 * all KeyEventPostProcessors
4520 * (see DefaultKeyboardFocusManager.dispatchKeyEvent())
4521 */
4522 if (!(e instanceof KeyEvent)) {
4523 ComponentPeer tpeer = peer;
4524 if (e instanceof FocusEvent && (tpeer == null || tpeer instanceof LightweightPeer)) {
4525 // if focus owner is lightweight then its native container
4526 // processes event
4527 Component source = (Component)e.getSource();
4528 if (source != null) {
4529 Container target = source.getNativeContainer();
4530 if (target != null) {
4531 tpeer = target.getPeer();
4532 }
4533 }
4534 }
4535 if (tpeer != null) {
4536 tpeer.handleEvent(e);
4537 }
4538 }
4539 } // dispatchEventImpl()
4540
4541 /*
4542 * If newEventsOnly is false, method is called so that ScrollPane can
4543 * override it and handle common-case mouse wheel scrolling. NOP
4544 * for Component.
4545 */
4546 void autoProcessMouseWheel(MouseWheelEvent e) {}
4547
4548 /*
4549 * Dispatch given MouseWheelEvent to the first ancestor for which
4550 * MouseWheelEvents are enabled.
4551 *
4552 * Returns whether or not event was dispatched to an ancestor
4553 */
4554 boolean dispatchMouseWheelToAncestor(MouseWheelEvent e) {
4555 int newX, newY;
4556 newX = e.getX() + getX(); // Coordinates take into account at least
4557 newY = e.getY() + getY(); // the cursor's position relative to this
4558 // Component (e.getX()), and this Component's
4559 // position relative to its parent.
4560 MouseWheelEvent newMWE;
4561
4562 if (eventLog.isLoggable(Level.FINEST)) {
4563 eventLog.log(Level.FINEST, "dispatchMouseWheelToAncestor");
4564 eventLog.log(Level.FINEST, "orig event src is of " + e.getSource().getClass());
4565 }
4566
4567 /* parent field for Window refers to the owning Window.
4568 * MouseWheelEvents should NOT be propagated into owning Windows
4569 */
4570 synchronized (getTreeLock()) {
4571 Container anc = getParent();
4572 while (anc != null && !anc.eventEnabled(e)) {
4573 // fix coordinates to be relative to new event source
4574 newX += anc.getX();
4575 newY += anc.getY();
4576
4577 if (!(anc instanceof Window)) {
4578 anc = anc.getParent();
4579 }
4580 else {
4581 break;
4582 }
4583 }
4584
4585 if (eventLog.isLoggable(Level.FINEST)) {
4586 eventLog.log(Level.FINEST, "new event src is " + anc.getClass());
4587 }
4588
4589 if (anc != null && anc.eventEnabled(e)) {
4590 // Change event to be from new source, with new x,y
4591 // For now, just create a new event - yucky
4592
4593 newMWE = new MouseWheelEvent(anc, // new source
4594 e.getID(),
4595 e.getWhen(),
4596 e.getModifiers(),
4597 newX, // x relative to new source
4598 newY, // y relative to new source
4599 e.getXOnScreen(),
4600 e.getYOnScreen(),
4601 e.getClickCount(),
4602 e.isPopupTrigger(),
4603 e.getScrollType(),
4604 e.getScrollAmount(),
4605 e.getWheelRotation());
4606 ((AWTEvent)e).copyPrivateDataInto(newMWE);
4607 // When dispatching a wheel event to
4608 // ancestor, there is no need trying to find descendant
4609 // lightweights to dispatch event to.
4610 // If we dispatch the event to toplevel ancestor,
4611 // this could encolse the loop: 6480024.
4612 anc.dispatchEventToSelf(newMWE);
4613 }
4614 }
4615 return true;
4616 }
4617
4618 boolean checkWindowClosingException() {
4619 if (windowClosingException != null) {
4620 if (this instanceof Dialog) {
4621 ((Dialog)this).interruptBlocking();
4622 } else {
4623 windowClosingException.fillInStackTrace();
4624 windowClosingException.printStackTrace();
4625 windowClosingException = null;
4626 }
4627 return true;
4628 }
4629 return false;
4630 }
4631
4632 boolean areInputMethodsEnabled() {
4633 // in 1.2, we assume input method support is required for all
4634 // components that handle key events, but components can turn off
4635 // input methods by calling enableInputMethods(false).
4636 return ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) &&
4637 ((eventMask & AWTEvent.KEY_EVENT_MASK) != 0 || keyListener != null);
4638 }
4639
4640 // REMIND: remove when filtering is handled at lower level
4641 boolean eventEnabled(AWTEvent e) {
4642 return eventTypeEnabled(e.id);
4643 }
4644
4645 boolean eventTypeEnabled(int type) {
4646 switch(type) {
4647 case ComponentEvent.COMPONENT_MOVED:
4648 case ComponentEvent.COMPONENT_RESIZED:
4649 case ComponentEvent.COMPONENT_SHOWN:
4650 case ComponentEvent.COMPONENT_HIDDEN:
4651 if ((eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 ||
4652 componentListener != null) {
4653 return true;
4654 }
4655 break;
4656 case FocusEvent.FOCUS_GAINED:
4657 case FocusEvent.FOCUS_LOST:
4658 if ((eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0 ||
4659 focusListener != null) {
4660 return true;
4661 }
4662 break;
4663 case KeyEvent.KEY_PRESSED:
4664 case KeyEvent.KEY_RELEASED:
4665 case KeyEvent.KEY_TYPED:
4666 if ((eventMask & AWTEvent.KEY_EVENT_MASK) != 0 ||
4667 keyListener != null) {
4668 return true;
4669 }
4670 break;
4671 case MouseEvent.MOUSE_PRESSED:
4672 case MouseEvent.MOUSE_RELEASED:
4673 case MouseEvent.MOUSE_ENTERED:
4674 case MouseEvent.MOUSE_EXITED:
4675 case MouseEvent.MOUSE_CLICKED:
4676 if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 ||
4677 mouseListener != null) {
4678 return true;
4679 }
4680 break;
4681 case MouseEvent.MOUSE_MOVED:
4682 case MouseEvent.MOUSE_DRAGGED:
4683 if ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 ||
4684 mouseMotionListener != null) {
4685 return true;
4686 }
4687 break;
4688 case MouseEvent.MOUSE_WHEEL:
4689 if ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 ||
4690 mouseWheelListener != null) {
4691 return true;
4692 }
4693 break;
4694 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
4695 case InputMethodEvent.CARET_POSITION_CHANGED:
4696 if ((eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0 ||
4697 inputMethodListener != null) {
4698 return true;
4699 }
4700 break;
4701 case HierarchyEvent.HIERARCHY_CHANGED:
4702 if ((eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 ||
4703 hierarchyListener != null) {
4704 return true;
4705 }
4706 break;
4707 case HierarchyEvent.ANCESTOR_MOVED:
4708 case HierarchyEvent.ANCESTOR_RESIZED:
4709 if ((eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 ||
4710 hierarchyBoundsListener != null) {
4711 return true;
4712 }
4713 break;
4714 case ActionEvent.ACTION_PERFORMED:
4715 if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0) {
4716 return true;
4717 }
4718 break;
4719 case TextEvent.TEXT_VALUE_CHANGED:
4720 if ((eventMask & AWTEvent.TEXT_EVENT_MASK) != 0) {
4721 return true;
4722 }
4723 break;
4724 case ItemEvent.ITEM_STATE_CHANGED:
4725 if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0) {
4726 return true;
4727 }
4728 break;
4729 case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
4730 if ((eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0) {
4731 return true;
4732 }
4733 break;
4734 default:
4735 break;
4736 }
4737 //
4738 // Always pass on events defined by external programs.
4739 //
4740 if (type > AWTEvent.RESERVED_ID_MAX) {
4741 return true;
4742 }
4743 return false;
4744 }
4745
4746 /**
4747 * @deprecated As of JDK version 1.1,
4748 * replaced by dispatchEvent(AWTEvent).
4749 */
4750 @Deprecated
4751 public boolean postEvent(Event e) {
4752 ComponentPeer peer = this.peer;
4753
4754 if (handleEvent(e)) {
4755 e.consume();
4756 return true;
4757 }
4758
4759 Component parent = this.parent;
4760 int eventx = e.x;
4761 int eventy = e.y;
4762 if (parent != null) {
4763 e.translate(x, y);
4764 if (parent.postEvent(e)) {
4765 e.consume();
4766 return true;
4767 }
4768 // restore coords
4769 e.x = eventx;
4770 e.y = eventy;
4771 }
4772 return false;
4773 }
4774
4775 // Event source interfaces
4776
4777 /**
4778 * Adds the specified component listener to receive component events from
4779 * this component.
4780 * If listener <code>l</code> is <code>null</code>,
4781 * no exception is thrown and no action is performed.
4782 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
4783 * >AWT Threading Issues</a> for details on AWT's threading model.
4784 *
4785 * @param l the component listener
4786 * @see java.awt.event.ComponentEvent
4787 * @see java.awt.event.ComponentListener
4788 * @see #removeComponentListener
4789 * @see #getComponentListeners
4790 * @since JDK1.1
4791 */
4792 public synchronized void addComponentListener(ComponentListener l) {
4793 if (l == null) {
4794 return;
4795 }
4796 componentListener = AWTEventMulticaster.add(componentListener, l);
4797 newEventsOnly = true;
4798 }
4799
4800 /**
4801 * Removes the specified component listener so that it no longer
4802 * receives component events from this component. This method performs
4803 * no function, nor does it throw an exception, if the listener
4804 * specified by the argument was not previously added to this component.
4805 * If listener <code>l</code> is <code>null</code>,
4806 * no exception is thrown and no action is performed.
4807 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
4808 * >AWT Threading Issues</a> for details on AWT's threading model.
4809 * @param l the component listener
4810 * @see java.awt.event.ComponentEvent
4811 * @see java.awt.event.ComponentListener
4812 * @see #addComponentListener
4813 * @see #getComponentListeners
4814 * @since JDK1.1
4815 */
4816 public synchronized void removeComponentListener(ComponentListener l) {
4817 if (l == null) {
4818 return;
4819 }
4820 componentListener = AWTEventMulticaster.remove(componentListener, l);
4821 }
4822
4823 /**
4824 * Returns an array of all the component listeners
4825 * registered on this component.
4826 *
4827 * @return all of this comonent's <code>ComponentListener</code>s
4828 * or an empty array if no component
4829 * listeners are currently registered
4830 *
4831 * @see #addComponentListener
4832 * @see #removeComponentListener
4833 * @since 1.4
4834 */
4835 public synchronized ComponentListener[] getComponentListeners() {
4836 return (ComponentListener[]) (getListeners(ComponentListener.class));
4837 }
4838
4839 /**
4840 * Adds the specified focus listener to receive focus events from
4841 * this component when this component gains input focus.
4842 * If listener <code>l</code> is <code>null</code>,
4843 * no exception is thrown and no action is performed.
4844 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
4845 * >AWT Threading Issues</a> for details on AWT's threading model.
4846 *
4847 * @param l the focus listener
4848 * @see java.awt.event.FocusEvent
4849 * @see java.awt.event.FocusListener
4850 * @see #removeFocusListener
4851 * @see #getFocusListeners
4852 * @since JDK1.1
4853 */
4854 public synchronized void addFocusListener(FocusListener l) {
4855 if (l == null) {
4856 return;
4857 }
4858 focusListener = AWTEventMulticaster.add(focusListener, l);
4859 newEventsOnly = true;
4860
4861 // if this is a lightweight component, enable focus events
4862 // in the native container.
4863 if (peer instanceof LightweightPeer) {
4864 parent.proxyEnableEvents(AWTEvent.FOCUS_EVENT_MASK);
4865 }
4866 }
4867
4868 /**
4869 * Removes the specified focus listener so that it no longer
4870 * receives focus events from this component. This method performs
4871 * no function, nor does it throw an exception, if the listener
4872 * specified by the argument was not previously added to this component.
4873 * If listener <code>l</code> is <code>null</code>,
4874 * no exception is thrown and no action is performed.
4875 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
4876 * >AWT Threading Issues</a> for details on AWT's threading model.
4877 *
4878 * @param l the focus listener
4879 * @see java.awt.event.FocusEvent
4880 * @see java.awt.event.FocusListener
4881 * @see #addFocusListener
4882 * @see #getFocusListeners
4883 * @since JDK1.1
4884 */
4885 public synchronized void removeFocusListener(FocusListener l) {
4886 if (l == null) {
4887 return;
4888 }
4889 focusListener = AWTEventMulticaster.remove(focusListener, l);
4890 }
4891
4892 /**
4893 * Returns an array of all the focus listeners
4894 * registered on this component.
4895 *
4896 * @return all of this component's <code>FocusListener</code>s
4897 * or an empty array if no component
4898 * listeners are currently registered
4899 *
4900 * @see #addFocusListener
4901 * @see #removeFocusListener
4902 * @since 1.4
4903 */
4904 public synchronized FocusListener[] getFocusListeners() {
4905 return (FocusListener[]) (getListeners(FocusListener.class));
4906 }
4907
4908 /**
4909 * Adds the specified hierarchy listener to receive hierarchy changed
4910 * events from this component when the hierarchy to which this container
4911 * belongs changes.
4912 * If listener <code>l</code> is <code>null</code>,
4913 * no exception is thrown and no action is performed.
4914 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
4915 * >AWT Threading Issues</a> for details on AWT's threading model.
4916 *
4917 * @param l the hierarchy listener
4918 * @see java.awt.event.HierarchyEvent
4919 * @see java.awt.event.HierarchyListener
4920 * @see #removeHierarchyListener
4921 * @see #getHierarchyListeners
4922 * @since 1.3
4923 */
4924 public void addHierarchyListener(HierarchyListener l) {
4925 if (l == null) {
4926 return;
4927 }
4928 boolean notifyAncestors;
4929 synchronized (this) {
4930 notifyAncestors =
4931 (hierarchyListener == null &&
4932 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0);
4933 hierarchyListener = AWTEventMulticaster.add(hierarchyListener, l);
4934 notifyAncestors = (notifyAncestors && hierarchyListener != null);
4935 newEventsOnly = true;
4936 }
4937 if (notifyAncestors) {
4938 synchronized (getTreeLock()) {
4939 adjustListeningChildrenOnParent(AWTEvent.HIERARCHY_EVENT_MASK,
4940 1);
4941 }
4942 }
4943 }
4944
4945 /**
4946 * Removes the specified hierarchy listener so that it no longer
4947 * receives hierarchy changed events from this component. This method
4948 * performs no function, nor does it throw an exception, if the listener
4949 * specified by the argument was not previously added to this component.
4950 * If listener <code>l</code> is <code>null</code>,
4951 * no exception is thrown and no action is performed.
4952 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
4953 * >AWT Threading Issues</a> for details on AWT's threading model.
4954 *
4955 * @param l the hierarchy listener
4956 * @see java.awt.event.HierarchyEvent
4957 * @see java.awt.event.HierarchyListener
4958 * @see #addHierarchyListener
4959 * @see #getHierarchyListeners
4960 * @since 1.3
4961 */
4962 public void removeHierarchyListener(HierarchyListener l) {
4963 if (l == null) {
4964 return;
4965 }
4966 boolean notifyAncestors;
4967 synchronized (this) {
4968 notifyAncestors =
4969 (hierarchyListener != null &&
4970 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0);
4971 hierarchyListener =
4972 AWTEventMulticaster.remove(hierarchyListener, l);
4973 notifyAncestors = (notifyAncestors && hierarchyListener == null);
4974 }
4975 if (notifyAncestors) {
4976 synchronized (getTreeLock()) {
4977 adjustListeningChildrenOnParent(AWTEvent.HIERARCHY_EVENT_MASK,
4978 -1);
4979 }
4980 }
4981 }
4982
4983 /**
4984 * Returns an array of all the hierarchy listeners
4985 * registered on this component.
4986 *
4987 * @return all of this component's <code>HierarchyListener</code>s
4988 * or an empty array if no hierarchy
4989 * listeners are currently registered
4990 *
4991 * @see #addHierarchyListener
4992 * @see #removeHierarchyListener
4993 * @since 1.4
4994 */
4995 public synchronized HierarchyListener[] getHierarchyListeners() {
4996 return (HierarchyListener[])(getListeners(HierarchyListener.class));
4997 }
4998
4999 /**
5000 * Adds the specified hierarchy bounds listener to receive hierarchy
5001 * bounds events from this component when the hierarchy to which this
5002 * container belongs changes.
5003 * If listener <code>l</code> is <code>null</code>,
5004 * no exception is thrown and no action is performed.
5005 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5006 * >AWT Threading Issues</a> for details on AWT's threading model.
5007 *
5008 * @param l the hierarchy bounds listener
5009 * @see java.awt.event.HierarchyEvent
5010 * @see java.awt.event.HierarchyBoundsListener
5011 * @see #removeHierarchyBoundsListener
5012 * @see #getHierarchyBoundsListeners
5013 * @since 1.3
5014 */
5015 public void addHierarchyBoundsListener(HierarchyBoundsListener l) {
5016 if (l == null) {
5017 return;
5018 }
5019 boolean notifyAncestors;
5020 synchronized (this) {
5021 notifyAncestors =
5022 (hierarchyBoundsListener == null &&
5023 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0);
5024 hierarchyBoundsListener =
5025 AWTEventMulticaster.add(hierarchyBoundsListener, l);
5026 notifyAncestors = (notifyAncestors &&
5027 hierarchyBoundsListener != null);
5028 newEventsOnly = true;
5029 }
5030 if (notifyAncestors) {
5031 synchronized (getTreeLock()) {
5032 adjustListeningChildrenOnParent(
5033 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
5034 }
5035 }
5036 }
5037
5038 /**
5039 * Removes the specified hierarchy bounds listener so that it no longer
5040 * receives hierarchy bounds events from this component. This method
5041 * performs no function, nor does it throw an exception, if the listener
5042 * specified by the argument was not previously added to this component.
5043 * If listener <code>l</code> is <code>null</code>,
5044 * no exception is thrown and no action is performed.
5045 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5046 * >AWT Threading Issues</a> for details on AWT's threading model.
5047 *
5048 * @param l the hierarchy bounds listener
5049 * @see java.awt.event.HierarchyEvent
5050 * @see java.awt.event.HierarchyBoundsListener
5051 * @see #addHierarchyBoundsListener
5052 * @see #getHierarchyBoundsListeners
5053 * @since 1.3
5054 */
5055 public void removeHierarchyBoundsListener(HierarchyBoundsListener l) {
5056 if (l == null) {
5057 return;
5058 }
5059 boolean notifyAncestors;
5060 synchronized (this) {
5061 notifyAncestors =
5062 (hierarchyBoundsListener != null &&
5063 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0);
5064 hierarchyBoundsListener =
5065 AWTEventMulticaster.remove(hierarchyBoundsListener, l);
5066 notifyAncestors = (notifyAncestors &&
5067 hierarchyBoundsListener == null);
5068 }
5069 if (notifyAncestors) {
5070 synchronized (getTreeLock()) {
5071 adjustListeningChildrenOnParent(
5072 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, -1);
5073 }
5074 }
5075 }
5076
5077 // Should only be called while holding the tree lock
5078 int numListening(long mask) {
5079 // One mask or the other, but not neither or both.
5080 if (eventLog.isLoggable(Level.FINE)) {
5081 if ((mask != AWTEvent.HIERARCHY_EVENT_MASK) &&
5082 (mask != AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK))
5083 {
5084 eventLog.log(Level.FINE, "Assertion failed");
5085 }
5086 }
5087 if ((mask == AWTEvent.HIERARCHY_EVENT_MASK &&
5088 (hierarchyListener != null ||
5089 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)) ||
5090 (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK &&
5091 (hierarchyBoundsListener != null ||
5092 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0))) {
5093 return 1;
5094 } else {
5095 return 0;
5096 }
5097 }
5098
5099 // Should only be called while holding tree lock
5100 int countHierarchyMembers() {
5101 return 1;
5102 }
5103 // Should only be called while holding the tree lock
5104 int createHierarchyEvents(int id, Component changed,
5105 Container changedParent, long changeFlags,
5106 boolean enabledOnToolkit) {
5107 switch (id) {
5108 case HierarchyEvent.HIERARCHY_CHANGED:
5109 if (hierarchyListener != null ||
5110 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 ||
5111 enabledOnToolkit) {
5112 HierarchyEvent e = new HierarchyEvent(this, id, changed,
5113 changedParent,
5114 changeFlags);
5115 dispatchEvent(e);
5116 return 1;
5117 }
5118 break;
5119 case HierarchyEvent.ANCESTOR_MOVED:
5120 case HierarchyEvent.ANCESTOR_RESIZED:
5121 if (eventLog.isLoggable(Level.FINE)) {
5122 if (changeFlags != 0) {
5123 eventLog.log(Level.FINE, "Assertion (changeFlags == 0) failed");
5124 }
5125 }
5126 if (hierarchyBoundsListener != null ||
5127 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 ||
5128 enabledOnToolkit) {
5129 HierarchyEvent e = new HierarchyEvent(this, id, changed,
5130 changedParent);
5131 dispatchEvent(e);
5132 return 1;
5133 }
5134 break;
5135 default:
5136 // assert false
5137 if (eventLog.isLoggable(Level.FINE)) {
5138 eventLog.log(Level.FINE, "This code must never be reached");
5139 }
5140 break;
5141 }
5142 return 0;
5143 }
5144
5145 /**
5146 * Returns an array of all the hierarchy bounds listeners
5147 * registered on this component.
5148 *
5149 * @return all of this component's <code>HierarchyBoundsListener</code>s
5150 * or an empty array if no hierarchy bounds
5151 * listeners are currently registered
5152 *
5153 * @see #addHierarchyBoundsListener
5154 * @see #removeHierarchyBoundsListener
5155 * @since 1.4
5156 */
5157 public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners() {
5158 return (HierarchyBoundsListener[])
5159 (getListeners(HierarchyBoundsListener.class));
5160 }
5161
5162 /*
5163 * Should only be called while holding the tree lock.
5164 * It's added only for overriding in java.awt.Window
5165 * because parent in Window is owner.
5166 */
5167 void adjustListeningChildrenOnParent(long mask, int num) {
5168 if (parent != null) {
5169 parent.adjustListeningChildren(mask, num);
5170 }
5171 }
5172
5173 /**
5174 * Adds the specified key listener to receive key events from
5175 * this component.
5176 * If l is null, no exception is thrown and no action is performed.
5177 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5178 * >AWT Threading Issues</a> for details on AWT's threading model.
5179 *
5180 * @param l the key listener.
5181 * @see java.awt.event.KeyEvent
5182 * @see java.awt.event.KeyListener
5183 * @see #removeKeyListener
5184 * @see #getKeyListeners
5185 * @since JDK1.1
5186 */
5187 public synchronized void addKeyListener(KeyListener l) {
5188 if (l == null) {
5189 return;
5190 }
5191 keyListener = AWTEventMulticaster.add(keyListener, l);
5192 newEventsOnly = true;
5193
5194 // if this is a lightweight component, enable key events
5195 // in the native container.
5196 if (peer instanceof LightweightPeer) {
5197 parent.proxyEnableEvents(AWTEvent.KEY_EVENT_MASK);
5198 }
5199 }
5200
5201 /**
5202 * Removes the specified key listener so that it no longer
5203 * receives key events from this component. This method performs
5204 * no function, nor does it throw an exception, if the listener
5205 * specified by the argument was not previously added to this component.
5206 * If listener <code>l</code> is <code>null</code>,
5207 * no exception is thrown and no action is performed.
5208 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5209 * >AWT Threading Issues</a> for details on AWT's threading model.
5210 *
5211 * @param l the key listener
5212 * @see java.awt.event.KeyEvent
5213 * @see java.awt.event.KeyListener
5214 * @see #addKeyListener
5215 * @see #getKeyListeners
5216 * @since JDK1.1
5217 */
5218 public synchronized void removeKeyListener(KeyListener l) {
5219 if (l == null) {
5220 return;
5221 }
5222 keyListener = AWTEventMulticaster.remove(keyListener, l);
5223 }
5224
5225 /**
5226 * Returns an array of all the key listeners
5227 * registered on this component.
5228 *
5229 * @return all of this component's <code>KeyListener</code>s
5230 * or an empty array if no key
5231 * listeners are currently registered
5232 *
5233 * @see #addKeyListener
5234 * @see #removeKeyListener
5235 * @since 1.4
5236 */
5237 public synchronized KeyListener[] getKeyListeners() {
5238 return (KeyListener[]) (getListeners(KeyListener.class));
5239 }
5240
5241 /**
5242 * Adds the specified mouse listener to receive mouse events from
5243 * this component.
5244 * If listener <code>l</code> is <code>null</code>,
5245 * no exception is thrown and no action is performed.
5246 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5247 * >AWT Threading Issues</a> for details on AWT's threading model.
5248 *
5249 * @param l the mouse listener
5250 * @see java.awt.event.MouseEvent
5251 * @see java.awt.event.MouseListener
5252 * @see #removeMouseListener
5253 * @see #getMouseListeners
5254 * @since JDK1.1
5255 */
5256 public synchronized void addMouseListener(MouseListener l) {
5257 if (l == null) {
5258 return;
5259 }
5260 mouseListener = AWTEventMulticaster.add(mouseListener,l);
5261 newEventsOnly = true;
5262
5263 // if this is a lightweight component, enable mouse events
5264 // in the native container.
5265 if (peer instanceof LightweightPeer) {
5266 parent.proxyEnableEvents(AWTEvent.MOUSE_EVENT_MASK);
5267 }
5268 }
5269
5270 /**
5271 * Removes the specified mouse listener so that it no longer
5272 * receives mouse events from this component. This method performs
5273 * no function, nor does it throw an exception, if the listener
5274 * specified by the argument was not previously added to this component.
5275 * If listener <code>l</code> is <code>null</code>,
5276 * no exception is thrown and no action is performed.
5277 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5278 * >AWT Threading Issues</a> for details on AWT's threading model.
5279 *
5280 * @param l the mouse listener
5281 * @see java.awt.event.MouseEvent
5282 * @see java.awt.event.MouseListener
5283 * @see #addMouseListener
5284 * @see #getMouseListeners
5285 * @since JDK1.1
5286 */
5287 public synchronized void removeMouseListener(MouseListener l) {
5288 if (l == null) {
5289 return;
5290 }
5291 mouseListener = AWTEventMulticaster.remove(mouseListener, l);
5292 }
5293
5294 /**
5295 * Returns an array of all the mouse listeners
5296 * registered on this component.
5297 *
5298 * @return all of this component's <code>MouseListener</code>s
5299 * or an empty array if no mouse
5300 * listeners are currently registered
5301 *
5302 * @see #addMouseListener
5303 * @see #removeMouseListener
5304 * @since 1.4
5305 */
5306 public synchronized MouseListener[] getMouseListeners() {
5307 return (MouseListener[]) (getListeners(MouseListener.class));
5308 }
5309
5310 /**
5311 * Adds the specified mouse motion listener to receive mouse motion
5312 * events from this component.
5313 * If listener <code>l</code> is <code>null</code>,
5314 * no exception is thrown and no action is performed.
5315 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5316 * >AWT Threading Issues</a> for details on AWT's threading model.
5317 *
5318 * @param l the mouse motion listener
5319 * @see java.awt.event.MouseEvent
5320 * @see java.awt.event.MouseMotionListener
5321 * @see #removeMouseMotionListener
5322 * @see #getMouseMotionListeners
5323 * @since JDK1.1
5324 */
5325 public synchronized void addMouseMotionListener(MouseMotionListener l) {
5326 if (l == null) {
5327 return;
5328 }
5329 mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,l);
5330 newEventsOnly = true;
5331
5332 // if this is a lightweight component, enable mouse events
5333 // in the native container.
5334 if (peer instanceof LightweightPeer) {
5335 parent.proxyEnableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
5336 }
5337 }
5338
5339 /**
5340 * Removes the specified mouse motion listener so that it no longer
5341 * receives mouse motion events from this component. This method performs
5342 * no function, nor does it throw an exception, if the listener
5343 * specified by the argument was not previously added to this component.
5344 * If listener <code>l</code> is <code>null</code>,
5345 * no exception is thrown and no action is performed.
5346 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5347 * >AWT Threading Issues</a> for details on AWT's threading model.
5348 *
5349 * @param l the mouse motion listener
5350 * @see java.awt.event.MouseEvent
5351 * @see java.awt.event.MouseMotionListener
5352 * @see #addMouseMotionListener
5353 * @see #getMouseMotionListeners
5354 * @since JDK1.1
5355 */
5356 public synchronized void removeMouseMotionListener(MouseMotionListener l) {
5357 if (l == null) {
5358 return;
5359 }
5360 mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, l);
5361 }
5362
5363 /**
5364 * Returns an array of all the mouse motion listeners
5365 * registered on this component.
5366 *
5367 * @return all of this component's <code>MouseMotionListener</code>s
5368 * or an empty array if no mouse motion
5369 * listeners are currently registered
5370 *
5371 * @see #addMouseMotionListener
5372 * @see #removeMouseMotionListener
5373 * @since 1.4
5374 */
5375 public synchronized MouseMotionListener[] getMouseMotionListeners() {
5376 return (MouseMotionListener[]) (getListeners(MouseMotionListener.class));
5377 }
5378
5379 /**
5380 * Adds the specified mouse wheel listener to receive mouse wheel events
5381 * from this component. Containers also receive mouse wheel events from
5382 * sub-components.
5383 * <p>
5384 * For information on how mouse wheel events are dispatched, see
5385 * the class description for {@link MouseWheelEvent}.
5386 * <p>
5387 * If l is <code>null</code>, no exception is thrown and no
5388 * action is performed.
5389 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5390 * >AWT Threading Issues</a> for details on AWT's threading model.
5391 *
5392 * @param l the mouse wheel listener
5393 * @see java.awt.event.MouseWheelEvent
5394 * @see java.awt.event.MouseWheelListener
5395 * @see #removeMouseWheelListener
5396 * @see #getMouseWheelListeners
5397 * @since 1.4
5398 */
5399 public synchronized void addMouseWheelListener(MouseWheelListener l) {
5400 if (l == null) {
5401 return;
5402 }
5403 mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,l);
5404 newEventsOnly = true;
5405
5406 // if this is a lightweight component, enable mouse events
5407 // in the native container.
5408 if (peer instanceof LightweightPeer) {
5409 parent.proxyEnableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
5410 }
5411 }
5412
5413 /**
5414 * Removes the specified mouse wheel listener so that it no longer
5415 * receives mouse wheel events from this component. This method performs
5416 * no function, nor does it throw an exception, if the listener
5417 * specified by the argument was not previously added to this component.
5418 * If l is null, no exception is thrown and no action is performed.
5419 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5420 * >AWT Threading Issues</a> for details on AWT's threading model.
5421 *
5422 * @param l the mouse wheel listener.
5423 * @see java.awt.event.MouseWheelEvent
5424 * @see java.awt.event.MouseWheelListener
5425 * @see #addMouseWheelListener
5426 * @see #getMouseWheelListeners
5427 * @since 1.4
5428 */
5429 public synchronized void removeMouseWheelListener(MouseWheelListener l) {
5430 if (l == null) {
5431 return;
5432 }
5433 mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, l);
5434 }
5435
5436 /**
5437 * Returns an array of all the mouse wheel listeners
5438 * registered on this component.
5439 *
5440 * @return all of this component's <code>MouseWheelListener</code>s
5441 * or an empty array if no mouse wheel
5442 * listeners are currently registered
5443 *
5444 * @see #addMouseWheelListener
5445 * @see #removeMouseWheelListener
5446 * @since 1.4
5447 */
5448 public synchronized MouseWheelListener[] getMouseWheelListeners() {
5449 return (MouseWheelListener[]) (getListeners(MouseWheelListener.class));
5450 }
5451
5452 /**
5453 * Adds the specified input method listener to receive
5454 * input method events from this component. A component will
5455 * only receive input method events from input methods
5456 * if it also overrides <code>getInputMethodRequests</code> to return an
5457 * <code>InputMethodRequests</code> instance.
5458 * If listener <code>l</code> is <code>null</code>,
5459 * no exception is thrown and no action is performed.
5460 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5461 * >AWT Threading Issues</a> for details on AWT's threading model.
5462 *
5463 * @param l the input method listener
5464 * @see java.awt.event.InputMethodEvent
5465 * @see java.awt.event.InputMethodListener
5466 * @see #removeInputMethodListener
5467 * @see #getInputMethodListeners
5468 * @see #getInputMethodRequests
5469 * @since 1.2
5470 */
5471 public synchronized void addInputMethodListener(InputMethodListener l) {
5472 if (l == null) {
5473 return;
5474 }
5475 inputMethodListener = AWTEventMulticaster.add(inputMethodListener, l);
5476 newEventsOnly = true;
5477 }
5478
5479 /**
5480 * Removes the specified input method listener so that it no longer
5481 * receives input method events from this component. This method performs
5482 * no function, nor does it throw an exception, if the listener
5483 * specified by the argument was not previously added to this component.
5484 * If listener <code>l</code> is <code>null</code>,
5485 * no exception is thrown and no action is performed.
5486 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
5487 * >AWT Threading Issues</a> for details on AWT's threading model.
5488 *
5489 * @param l the input method listener
5490 * @see java.awt.event.InputMethodEvent
5491 * @see java.awt.event.InputMethodListener
5492 * @see #addInputMethodListener
5493 * @see #getInputMethodListeners
5494 * @since 1.2
5495 */
5496 public synchronized void removeInputMethodListener(InputMethodListener l) {
5497 if (l == null) {
5498 return;
5499 }
5500 inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, l);
5501 }
5502
5503 /**
5504 * Returns an array of all the input method listeners
5505 * registered on this component.
5506 *
5507 * @return all of this component's <code>InputMethodListener</code>s
5508 * or an empty array if no input method
5509 * listeners are currently registered
5510 *
5511 * @see #addInputMethodListener
5512 * @see #removeInputMethodListener
5513 * @since 1.4
5514 */
5515 public synchronized InputMethodListener[] getInputMethodListeners() {
5516 return (InputMethodListener[]) (getListeners(InputMethodListener.class));
5517 }
5518
5519 /**
5520 * Returns an array of all the objects currently registered
5521 * as <code><em>Foo</em>Listener</code>s
5522 * upon this <code>Component</code>.
5523 * <code><em>Foo</em>Listener</code>s are registered using the
5524 * <code>add<em>Foo</em>Listener</code> method.
5525 *
5526 * <p>
5527 * You can specify the <code>listenerType</code> argument
5528 * with a class literal, such as
5529 * <code><em>Foo</em>Listener.class</code>.
5530 * For example, you can query a
5531 * <code>Component</code> <code>c</code>
5532 * for its mouse listeners with the following code:
5533 *
5534 * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre>
5535 *
5536 * If no such listeners exist, this method returns an empty array.
5537 *
5538 * @param listenerType the type of listeners requested; this parameter
5539 * should specify an interface that descends from
5540 * <code>java.util.EventListener</code>
5541 * @return an array of all objects registered as
5542 * <code><em>Foo</em>Listener</code>s on this component,
5543 * or an empty array if no such listeners have been added
5544 * @exception ClassCastException if <code>listenerType</code>
5545 * doesn't specify a class or interface that implements
5546 * <code>java.util.EventListener</code>
5547 *
5548 * @see #getComponentListeners
5549 * @see #getFocusListeners
5550 * @see #getHierarchyListeners
5551 * @see #getHierarchyBoundsListeners
5552 * @see #getKeyListeners
5553 * @see #getMouseListeners
5554 * @see #getMouseMotionListeners
5555 * @see #getMouseWheelListeners
5556 * @see #getInputMethodListeners
5557 * @see #getPropertyChangeListeners
5558 *
5559 * @since 1.3
5560 */
5561 public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
5562 EventListener l = null;
5563 if (listenerType == ComponentListener.class) {
5564 l = componentListener;
5565 } else if (listenerType == FocusListener.class) {
5566 l = focusListener;
5567 } else if (listenerType == HierarchyListener.class) {
5568 l = hierarchyListener;
5569 } else if (listenerType == HierarchyBoundsListener.class) {
5570 l = hierarchyBoundsListener;
5571 } else if (listenerType == KeyListener.class) {
5572 l = keyListener;
5573 } else if (listenerType == MouseListener.class) {
5574 l = mouseListener;
5575 } else if (listenerType == MouseMotionListener.class) {
5576 l = mouseMotionListener;
5577 } else if (listenerType == MouseWheelListener.class) {
5578 l = mouseWheelListener;
5579 } else if (listenerType == InputMethodListener.class) {
5580 l = inputMethodListener;
5581 } else if (listenerType == PropertyChangeListener.class) {
5582 return (T[])getPropertyChangeListeners();
5583 }
5584 return AWTEventMulticaster.getListeners(l, listenerType);
5585 }
5586
5587 /**
5588 * Gets the input method request handler which supports
5589 * requests from input methods for this component. A component
5590 * that supports on-the-spot text input must override this
5591 * method to return an <code>InputMethodRequests</code> instance.
5592 * At the same time, it also has to handle input method events.
5593 *
5594 * @return the input method request handler for this component,
5595 * <code>null</code> by default
5596 * @see #addInputMethodListener
5597 * @since 1.2
5598 */
5599 public InputMethodRequests getInputMethodRequests() {
5600 return null;
5601 }
5602
5603 /**
5604 * Gets the input context used by this component for handling
5605 * the communication with input methods when text is entered
5606 * in this component. By default, the input context used for
5607 * the parent component is returned. Components may
5608 * override this to return a private input context.
5609 *
5610 * @return the input context used by this component;
5611 * <code>null</code> if no context can be determined
5612 * @since 1.2
5613 */
5614 public InputContext getInputContext() {
5615 Container parent = this.parent;
5616 if (parent == null) {
5617 return null;
5618 } else {
5619 return parent.getInputContext();
5620 }
5621 }
5622
5623 /**
5624 * Enables the events defined by the specified event mask parameter
5625 * to be delivered to this component.
5626 * <p>
5627 * Event types are automatically enabled when a listener for
5628 * that event type is added to the component.
5629 * <p>
5630 * This method only needs to be invoked by subclasses of
5631 * <code>Component</code> which desire to have the specified event
5632 * types delivered to <code>processEvent</code> regardless of whether
5633 * or not a listener is registered.
5634 * @param eventsToEnable the event mask defining the event types
5635 * @see #processEvent
5636 * @see #disableEvents
5637 * @see AWTEvent
5638 * @since JDK1.1
5639 */
5640 protected final void enableEvents(long eventsToEnable) {
5641 long notifyAncestors = 0;
5642 synchronized (this) {
5643 if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0 &&
5644 hierarchyListener == null &&
5645 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0) {
5646 notifyAncestors |= AWTEvent.HIERARCHY_EVENT_MASK;
5647 }
5648 if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 &&
5649 hierarchyBoundsListener == null &&
5650 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0) {
5651 notifyAncestors |= AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK;
5652 }
5653 eventMask |= eventsToEnable;
5654 newEventsOnly = true;
5655 }
5656
5657 // if this is a lightweight component, enable mouse events
5658 // in the native container.
5659 if (peer instanceof LightweightPeer) {
5660 parent.proxyEnableEvents(eventMask);
5661 }
5662 if (notifyAncestors != 0) {
5663 synchronized (getTreeLock()) {
5664 adjustListeningChildrenOnParent(notifyAncestors, 1);
5665 }
5666 }
5667 }
5668
5669 /**
5670 * Disables the events defined by the specified event mask parameter
5671 * from being delivered to this component.
5672 * @param eventsToDisable the event mask defining the event types
5673 * @see #enableEvents
5674 * @since JDK1.1
5675 */
5676 protected final void disableEvents(long eventsToDisable) {
5677 long notifyAncestors = 0;
5678 synchronized (this) {
5679 if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0 &&
5680 hierarchyListener == null &&
5681 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
5682 notifyAncestors |= AWTEvent.HIERARCHY_EVENT_MASK;
5683 }
5684 if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)!=0 &&
5685 hierarchyBoundsListener == null &&
5686 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
5687 notifyAncestors |= AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK;
5688 }
5689 eventMask &= ~eventsToDisable;
5690 }
5691 if (notifyAncestors != 0) {
5692 synchronized (getTreeLock()) {
5693 adjustListeningChildrenOnParent(notifyAncestors, -1);
5694 }
5695 }
5696 }
5697
5698 transient EventQueueItem[] eventCache;
5699
5700 /**
5701 * @see #isCoalescingEnabled
5702 * @see #checkCoalescing
5703 */
5704 transient private boolean coalescingEnabled = checkCoalescing();
5705
5706 /**
5707 * Weak map of known coalesceEvent overriders.
5708 * Value indicates whether overriden.
5709 * Bootstrap classes are not included.
5710 */
5711 private static final Map<Class<?>, Boolean> coalesceMap =
5712 new java.util.WeakHashMap<Class<?>, Boolean>();
5713
5714 /**
5715 * Indicates whether this class overrides coalesceEvents.
5716 * It is assumed that all classes that are loaded from the bootstrap
5717 * do not.
5718 * The boostrap class loader is assumed to be represented by null.
5719 * We do not check that the method really overrides
5720 * (it might be static, private or package private).
5721 */
5722 private boolean checkCoalescing() {
5723 if (getClass().getClassLoader()==null) {
5724 return false;
5725 }
5726 final Class<? extends Component> clazz = getClass();
5727 synchronized (coalesceMap) {
5728 // Check cache.
5729 Boolean value = coalesceMap.get(clazz);
5730 if (value != null) {
5731 return value;
5732 }
5733
5734 // Need to check non-bootstraps.
5735 Boolean enabled = java.security.AccessController.doPrivileged(
5736 new java.security.PrivilegedAction<Boolean>() {
5737 public Boolean run() {
5738 return isCoalesceEventsOverriden(clazz);
5739 }
5740 }
5741 );
5742 coalesceMap.put(clazz, enabled);
5743 return enabled;
5744 }
5745 }
5746
5747 /**
5748 * Parameter types of coalesceEvents(AWTEvent,AWTEVent).
5749 */
5750 private static final Class[] coalesceEventsParams = {
5751 AWTEvent.class, AWTEvent.class
5752 };
5753
5754 /**
5755 * Indicates whether a class or its superclasses override coalesceEvents.
5756 * Must be called with lock on coalesceMap and privileged.
5757 * @see checkCoalsecing
5758 */
5759 private static boolean isCoalesceEventsOverriden(Class<?> clazz) {
5760 assert Thread.holdsLock(coalesceMap);
5761
5762 // First check superclass - we may not need to bother ourselves.
5763 Class<?> superclass = clazz.getSuperclass();
5764 if (superclass == null) {
5765 // Only occurs on implementations that
5766 // do not use null to represent the bootsrap class loader.
5767 return false;
5768 }
5769 if (superclass.getClassLoader() != null) {
5770 Boolean value = coalesceMap.get(superclass);
5771 if (value == null) {
5772 // Not done already - recurse.
5773 if (isCoalesceEventsOverriden(superclass)) {
5774 coalesceMap.put(superclass, true);
5775 return true;
5776 }
5777 } else if (value) {
5778 return true;
5779 }
5780 }
5781
5782 try {
5783 // Throws if not overriden.
5784 clazz.getDeclaredMethod(
5785 "coalesceEvents", coalesceEventsParams
5786 );
5787 return true;
5788 } catch (NoSuchMethodException e) {
5789 // Not present in this class.
5790 return false;
5791 }
5792 }
5793
5794 /**
5795 * Indicates whether coalesceEvents may do something.
5796 */
5797 final boolean isCoalescingEnabled() {
5798 return coalescingEnabled;
5799 }
5800
5801
5802 /**
5803 * Potentially coalesce an event being posted with an existing
5804 * event. This method is called by <code>EventQueue.postEvent</code>
5805 * if an event with the same ID as the event to be posted is found in
5806 * the queue (both events must have this component as their source).
5807 * This method either returns a coalesced event which replaces
5808 * the existing event (and the new event is then discarded), or
5809 * <code>null</code> to indicate that no combining should be done
5810 * (add the second event to the end of the queue). Either event
5811 * parameter may be modified and returned, as the other one is discarded
5812 * unless <code>null</code> is returned.
5813 * <p>
5814 * This implementation of <code>coalesceEvents</code> coalesces
5815 * two event types: mouse move (and drag) events,
5816 * and paint (and update) events.
5817 * For mouse move events the last event is always returned, causing
5818 * intermediate moves to be discarded. For paint events, the new
5819 * event is coalesced into a complex <code>RepaintArea</code> in the peer.
5820 * The new <code>AWTEvent</code> is always returned.
5821 *
5822 * @param existingEvent the event already on the <code>EventQueue</code>
5823 * @param newEvent the event being posted to the
5824 * <code>EventQueue</code>
5825 * @return a coalesced event, or <code>null</code> indicating that no
5826 * coalescing was done
5827 */
5828 protected AWTEvent coalesceEvents(AWTEvent existingEvent,
5829 AWTEvent newEvent) {
5830 return null;
5831 }
5832
5833 /**
5834 * Processes events occurring on this component. By default this
5835 * method calls the appropriate
5836 * <code>process&lt;event&nbsp;type&gt;Event</code>
5837 * method for the given class of event.
5838 * <p>Note that if the event parameter is <code>null</code>
5839 * the behavior is unspecified and may result in an
5840 * exception.
5841 *
5842 * @param e the event
5843 * @see #processComponentEvent
5844 * @see #processFocusEvent
5845 * @see #processKeyEvent
5846 * @see #processMouseEvent
5847 * @see #processMouseMotionEvent
5848 * @see #processInputMethodEvent
5849 * @see #processHierarchyEvent
5850 * @see #processMouseWheelEvent
5851 * @since JDK1.1
5852 */
5853 protected void processEvent(AWTEvent e) {
5854 if (e instanceof FocusEvent) {
5855 processFocusEvent((FocusEvent)e);
5856
5857 } else if (e instanceof MouseEvent) {
5858 switch(e.getID()) {
5859 case MouseEvent.MOUSE_PRESSED:
5860 case MouseEvent.MOUSE_RELEASED:
5861 case MouseEvent.MOUSE_CLICKED:
5862 case MouseEvent.MOUSE_ENTERED:
5863 case MouseEvent.MOUSE_EXITED:
5864 processMouseEvent((MouseEvent)e);
5865 break;
5866 case MouseEvent.MOUSE_MOVED:
5867 case MouseEvent.MOUSE_DRAGGED:
5868 processMouseMotionEvent((MouseEvent)e);
5869 break;
5870 case MouseEvent.MOUSE_WHEEL:
5871 processMouseWheelEvent((MouseWheelEvent)e);
5872 break;
5873 }
5874
5875 } else if (e instanceof KeyEvent) {
5876 processKeyEvent((KeyEvent)e);
5877
5878 } else if (e instanceof ComponentEvent) {
5879 processComponentEvent((ComponentEvent)e);
5880 } else if (e instanceof InputMethodEvent) {
5881 processInputMethodEvent((InputMethodEvent)e);
5882 } else if (e instanceof HierarchyEvent) {
5883 switch (e.getID()) {
5884 case HierarchyEvent.HIERARCHY_CHANGED:
5885 processHierarchyEvent((HierarchyEvent)e);
5886 break;
5887 case HierarchyEvent.ANCESTOR_MOVED:
5888 case HierarchyEvent.ANCESTOR_RESIZED:
5889 processHierarchyBoundsEvent((HierarchyEvent)e);
5890 break;
5891 }
5892 }
5893 }
5894
5895 /**
5896 * Processes component events occurring on this component by
5897 * dispatching them to any registered
5898 * <code>ComponentListener</code> objects.
5899 * <p>
5900 * This method is not called unless component events are
5901 * enabled for this component. Component events are enabled
5902 * when one of the following occurs:
5903 * <p><ul>
5904 * <li>A <code>ComponentListener</code> object is registered
5905 * via <code>addComponentListener</code>.
5906 * <li>Component events are enabled via <code>enableEvents</code>.
5907 * </ul>
5908 * <p>Note that if the event parameter is <code>null</code>
5909 * the behavior is unspecified and may result in an
5910 * exception.
5911 *
5912 * @param e the component event
5913 * @see java.awt.event.ComponentEvent
5914 * @see java.awt.event.ComponentListener
5915 * @see #addComponentListener
5916 * @see #enableEvents
5917 * @since JDK1.1
5918 */
5919 protected void processComponentEvent(ComponentEvent e) {
5920 ComponentListener listener = componentListener;
5921 if (listener != null) {
5922 int id = e.getID();
5923 switch(id) {
5924 case ComponentEvent.COMPONENT_RESIZED:
5925 listener.componentResized(e);
5926 break;
5927 case ComponentEvent.COMPONENT_MOVED:
5928 listener.componentMoved(e);
5929 break;
5930 case ComponentEvent.COMPONENT_SHOWN:
5931 listener.componentShown(e);
5932 break;
5933 case ComponentEvent.COMPONENT_HIDDEN:
5934 listener.componentHidden(e);
5935 break;
5936 }
5937 }
5938 }
5939
5940 /**
5941 * Processes focus events occurring on this component by
5942 * dispatching them to any registered
5943 * <code>FocusListener</code> objects.
5944 * <p>
5945 * This method is not called unless focus events are
5946 * enabled for this component. Focus events are enabled
5947 * when one of the following occurs:
5948 * <p><ul>
5949 * <li>A <code>FocusListener</code> object is registered
5950 * via <code>addFocusListener</code>.
5951 * <li>Focus events are enabled via <code>enableEvents</code>.
5952 * </ul>
5953 * <p>
5954 * If focus events are enabled for a <code>Component</code>,
5955 * the current <code>KeyboardFocusManager</code> determines
5956 * whether or not a focus event should be dispatched to
5957 * registered <code>FocusListener</code> objects. If the
5958 * events are to be dispatched, the <code>KeyboardFocusManager</code>
5959 * calls the <code>Component</code>'s <code>dispatchEvent</code>
5960 * method, which results in a call to the <code>Component</code>'s
5961 * <code>processFocusEvent</code> method.
5962 * <p>
5963 * If focus events are enabled for a <code>Component</code>, calling
5964 * the <code>Component</code>'s <code>dispatchEvent</code> method
5965 * with a <code>FocusEvent</code> as the argument will result in a
5966 * call to the <code>Component</code>'s <code>processFocusEvent</code>
5967 * method regardless of the current <code>KeyboardFocusManager</code>.
5968 * <p>
5969 * <p>Note that if the event parameter is <code>null</code>
5970 * the behavior is unspecified and may result in an
5971 * exception.
5972 *
5973 * @param e the focus event
5974 * @see java.awt.event.FocusEvent
5975 * @see java.awt.event.FocusListener
5976 * @see java.awt.KeyboardFocusManager
5977 * @see #addFocusListener
5978 * @see #enableEvents
5979 * @see #dispatchEvent
5980 * @since JDK1.1
5981 */
5982 protected void processFocusEvent(FocusEvent e) {
5983 FocusListener listener = focusListener;
5984 if (listener != null) {
5985 int id = e.getID();
5986 switch(id) {
5987 case FocusEvent.FOCUS_GAINED:
5988 listener.focusGained(e);
5989 break;
5990 case FocusEvent.FOCUS_LOST:
5991 listener.focusLost(e);
5992 break;
5993 }
5994 }
5995 }
5996
5997 /**
5998 * Processes key events occurring on this component by
5999 * dispatching them to any registered
6000 * <code>KeyListener</code> objects.
6001 * <p>
6002 * This method is not called unless key events are
6003 * enabled for this component. Key events are enabled
6004 * when one of the following occurs:
6005 * <p><ul>
6006 * <li>A <code>KeyListener</code> object is registered
6007 * via <code>addKeyListener</code>.
6008 * <li>Key events are enabled via <code>enableEvents</code>.
6009 * </ul>
6010 *
6011 * <p>
6012 * If key events are enabled for a <code>Component</code>,
6013 * the current <code>KeyboardFocusManager</code> determines
6014 * whether or not a key event should be dispatched to
6015 * registered <code>KeyListener</code> objects. The
6016 * <code>DefaultKeyboardFocusManager</code> will not dispatch
6017 * key events to a <code>Component</code> that is not the focus
6018 * owner or is not showing.
6019 * <p>
6020 * As of J2SE 1.4, <code>KeyEvent</code>s are redirected to
6021 * the focus owner. Please see the
6022 * <a href="doc-files/FocusSpec.html">Focus Specification</a>
6023 * for further information.
6024 * <p>
6025 * Calling a <code>Component</code>'s <code>dispatchEvent</code>
6026 * method with a <code>KeyEvent</code> as the argument will
6027 * result in a call to the <code>Component</code>'s
6028 * <code>processKeyEvent</code> method regardless of the
6029 * current <code>KeyboardFocusManager</code> as long as the
6030 * component is showing, focused, and enabled, and key events
6031 * are enabled on it.
6032 * <p>If the event parameter is <code>null</code>
6033 * the behavior is unspecified and may result in an
6034 * exception.
6035 *
6036 * @param e the key event
6037 * @see java.awt.event.KeyEvent
6038 * @see java.awt.event.KeyListener
6039 * @see java.awt.KeyboardFocusManager
6040 * @see java.awt.DefaultKeyboardFocusManager
6041 * @see #processEvent
6042 * @see #dispatchEvent
6043 * @see #addKeyListener
6044 * @see #enableEvents
6045 * @see #isShowing
6046 * @since JDK1.1
6047 */
6048 protected void processKeyEvent(KeyEvent e) {
6049 KeyListener listener = keyListener;
6050 if (listener != null) {
6051 int id = e.getID();
6052 switch(id) {
6053 case KeyEvent.KEY_TYPED:
6054 listener.keyTyped(e);
6055 break;
6056 case KeyEvent.KEY_PRESSED:
6057 listener.keyPressed(e);
6058 break;
6059 case KeyEvent.KEY_RELEASED:
6060 listener.keyReleased(e);
6061 break;
6062 }
6063 }
6064 }
6065
6066 /**
6067 * Processes mouse events occurring on this component by
6068 * dispatching them to any registered
6069 * <code>MouseListener</code> objects.
6070 * <p>
6071 * This method is not called unless mouse events are
6072 * enabled for this component. Mouse events are enabled
6073 * when one of the following occurs:
6074 * <p><ul>
6075 * <li>A <code>MouseListener</code> object is registered
6076 * via <code>addMouseListener</code>.
6077 * <li>Mouse events are enabled via <code>enableEvents</code>.
6078 * </ul>
6079 * <p>Note that if the event parameter is <code>null</code>
6080 * the behavior is unspecified and may result in an
6081 * exception.
6082 *
6083 * @param e the mouse event
6084 * @see java.awt.event.MouseEvent
6085 * @see java.awt.event.MouseListener
6086 * @see #addMouseListener
6087 * @see #enableEvents
6088 * @since JDK1.1
6089 */
6090 protected void processMouseEvent(MouseEvent e) {
6091 MouseListener listener = mouseListener;
6092 if (listener != null) {
6093 int id = e.getID();
6094 switch(id) {
6095 case MouseEvent.MOUSE_PRESSED:
6096 listener.mousePressed(e);
6097 break;
6098 case MouseEvent.MOUSE_RELEASED:
6099 listener.mouseReleased(e);
6100 break;
6101 case MouseEvent.MOUSE_CLICKED:
6102 listener.mouseClicked(e);
6103 break;
6104 case MouseEvent.MOUSE_EXITED:
6105 listener.mouseExited(e);
6106 break;
6107 case MouseEvent.MOUSE_ENTERED:
6108 listener.mouseEntered(e);
6109 break;
6110 }
6111 }
6112 }
6113
6114 /**
6115 * Processes mouse motion events occurring on this component by
6116 * dispatching them to any registered
6117 * <code>MouseMotionListener</code> objects.
6118 * <p>
6119 * This method is not called unless mouse motion events are
6120 * enabled for this component. Mouse motion events are enabled
6121 * when one of the following occurs:
6122 * <p><ul>
6123 * <li>A <code>MouseMotionListener</code> object is registered
6124 * via <code>addMouseMotionListener</code>.
6125 * <li>Mouse motion events are enabled via <code>enableEvents</code>.
6126 * </ul>
6127 * <p>Note that if the event parameter is <code>null</code>
6128 * the behavior is unspecified and may result in an
6129 * exception.
6130 *
6131 * @param e the mouse motion event
6132 * @see java.awt.event.MouseEvent
6133 * @see java.awt.event.MouseMotionListener
6134 * @see #addMouseMotionListener
6135 * @see #enableEvents
6136 * @since JDK1.1
6137 */
6138 protected void processMouseMotionEvent(MouseEvent e) {
6139 MouseMotionListener listener = mouseMotionListener;
6140 if (listener != null) {
6141 int id = e.getID();
6142 switch(id) {
6143 case MouseEvent.MOUSE_MOVED:
6144 listener.mouseMoved(e);
6145 break;
6146 case MouseEvent.MOUSE_DRAGGED:
6147 listener.mouseDragged(e);
6148 break;
6149 }
6150 }
6151 }
6152
6153 /**
6154 * Processes mouse wheel events occurring on this component by
6155 * dispatching them to any registered
6156 * <code>MouseWheelListener</code> objects.
6157 * <p>
6158 * This method is not called unless mouse wheel events are
6159 * enabled for this component. Mouse wheel events are enabled
6160 * when one of the following occurs:
6161 * <p><ul>
6162 * <li>A <code>MouseWheelListener</code> object is registered
6163 * via <code>addMouseWheelListener</code>.
6164 * <li>Mouse wheel events are enabled via <code>enableEvents</code>.
6165 * </ul>
6166 * <p>
6167 * For information on how mouse wheel events are dispatched, see
6168 * the class description for {@link MouseWheelEvent}.
6169 * <p>
6170 * Note that if the event parameter is <code>null</code>
6171 * the behavior is unspecified and may result in an
6172 * exception.
6173 *
6174 * @param e the mouse wheel event
6175 * @see java.awt.event.MouseWheelEvent
6176 * @see java.awt.event.MouseWheelListener
6177 * @see #addMouseWheelListener
6178 * @see #enableEvents
6179 * @since 1.4
6180 */
6181 protected void processMouseWheelEvent(MouseWheelEvent e) {
6182 MouseWheelListener listener = mouseWheelListener;
6183 if (listener != null) {
6184 int id = e.getID();
6185 switch(id) {
6186 case MouseEvent.MOUSE_WHEEL:
6187 listener.mouseWheelMoved(e);
6188 break;
6189 }
6190 }
6191 }
6192
6193 boolean postsOldMouseEvents() {
6194 return false;
6195 }
6196
6197 /**
6198 * Processes input method events occurring on this component by
6199 * dispatching them to any registered
6200 * <code>InputMethodListener</code> objects.
6201 * <p>
6202 * This method is not called unless input method events
6203 * are enabled for this component. Input method events are enabled
6204 * when one of the following occurs:
6205 * <p><ul>
6206 * <li>An <code>InputMethodListener</code> object is registered
6207 * via <code>addInputMethodListener</code>.
6208 * <li>Input method events are enabled via <code>enableEvents</code>.
6209 * </ul>
6210 * <p>Note that if the event parameter is <code>null</code>
6211 * the behavior is unspecified and may result in an
6212 * exception.
6213 *
6214 * @param e the input method event
6215 * @see java.awt.event.InputMethodEvent
6216 * @see java.awt.event.InputMethodListener
6217 * @see #addInputMethodListener
6218 * @see #enableEvents
6219 * @since 1.2
6220 */
6221 protected void processInputMethodEvent(InputMethodEvent e) {
6222 InputMethodListener listener = inputMethodListener;
6223 if (listener != null) {
6224 int id = e.getID();
6225 switch (id) {
6226 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
6227 listener.inputMethodTextChanged(e);
6228 break;
6229 case InputMethodEvent.CARET_POSITION_CHANGED:
6230 listener.caretPositionChanged(e);
6231 break;
6232 }
6233 }
6234 }
6235
6236 /**
6237 * Processes hierarchy events occurring on this component by
6238 * dispatching them to any registered
6239 * <code>HierarchyListener</code> objects.
6240 * <p>
6241 * This method is not called unless hierarchy events
6242 * are enabled for this component. Hierarchy events are enabled
6243 * when one of the following occurs:
6244 * <p><ul>
6245 * <li>An <code>HierarchyListener</code> object is registered
6246 * via <code>addHierarchyListener</code>.
6247 * <li>Hierarchy events are enabled via <code>enableEvents</code>.
6248 * </ul>
6249 * <p>Note that if the event parameter is <code>null</code>
6250 * the behavior is unspecified and may result in an
6251 * exception.
6252 *
6253 * @param e the hierarchy event
6254 * @see java.awt.event.HierarchyEvent
6255 * @see java.awt.event.HierarchyListener
6256 * @see #addHierarchyListener
6257 * @see #enableEvents
6258 * @since 1.3
6259 */
6260 protected void processHierarchyEvent(HierarchyEvent e) {
6261 HierarchyListener listener = hierarchyListener;
6262 if (listener != null) {
6263 int id = e.getID();
6264 switch (id) {
6265 case HierarchyEvent.HIERARCHY_CHANGED:
6266 listener.hierarchyChanged(e);
6267 break;
6268 }
6269 }
6270 }
6271
6272 /**
6273 * Processes hierarchy bounds events occurring on this component by
6274 * dispatching them to any registered
6275 * <code>HierarchyBoundsListener</code> objects.
6276 * <p>
6277 * This method is not called unless hierarchy bounds events
6278 * are enabled for this component. Hierarchy bounds events are enabled
6279 * when one of the following occurs:
6280 * <p><ul>
6281 * <li>An <code>HierarchyBoundsListener</code> object is registered
6282 * via <code>addHierarchyBoundsListener</code>.
6283 * <li>Hierarchy bounds events are enabled via <code>enableEvents</code>.
6284 * </ul>
6285 * <p>Note that if the event parameter is <code>null</code>
6286 * the behavior is unspecified and may result in an
6287 * exception.
6288 *
6289 * @param e the hierarchy event
6290 * @see java.awt.event.HierarchyEvent
6291 * @see java.awt.event.HierarchyBoundsListener
6292 * @see #addHierarchyBoundsListener
6293 * @see #enableEvents
6294 * @since 1.3
6295 */
6296 protected void processHierarchyBoundsEvent(HierarchyEvent e) {
6297 HierarchyBoundsListener listener = hierarchyBoundsListener;
6298 if (listener != null) {
6299 int id = e.getID();
6300 switch (id) {
6301 case HierarchyEvent.ANCESTOR_MOVED:
6302 listener.ancestorMoved(e);
6303 break;
6304 case HierarchyEvent.ANCESTOR_RESIZED:
6305 listener.ancestorResized(e);
6306 break;
6307 }
6308 }
6309 }
6310
6311 /**
6312 * @deprecated As of JDK version 1.1
6313 * replaced by processEvent(AWTEvent).
6314 */
6315 @Deprecated
6316 public boolean handleEvent(Event evt) {
6317 switch (evt.id) {
6318 case Event.MOUSE_ENTER:
6319 return mouseEnter(evt, evt.x, evt.y);
6320
6321 case Event.MOUSE_EXIT:
6322 return mouseExit(evt, evt.x, evt.y);
6323
6324 case Event.MOUSE_MOVE:
6325 return mouseMove(evt, evt.x, evt.y);
6326
6327 case Event.MOUSE_DOWN:
6328 return mouseDown(evt, evt.x, evt.y);
6329
6330 case Event.MOUSE_DRAG:
6331 return mouseDrag(evt, evt.x, evt.y);
6332
6333 case Event.MOUSE_UP:
6334 return mouseUp(evt, evt.x, evt.y);
6335
6336 case Event.KEY_PRESS:
6337 case Event.KEY_ACTION:
6338 return keyDown(evt, evt.key);
6339
6340 case Event.KEY_RELEASE:
6341 case Event.KEY_ACTION_RELEASE:
6342 return keyUp(evt, evt.key);
6343
6344 case Event.ACTION_EVENT:
6345 return action(evt, evt.arg);
6346 case Event.GOT_FOCUS:
6347 return gotFocus(evt, evt.arg);
6348 case Event.LOST_FOCUS:
6349 return lostFocus(evt, evt.arg);
6350 }
6351 return false;
6352 }
6353
6354 /**
6355 * @deprecated As of JDK version 1.1,
6356 * replaced by processMouseEvent(MouseEvent).
6357 */
6358 @Deprecated
6359 public boolean mouseDown(Event evt, int x, int y) {
6360 return false;
6361 }
6362
6363 /**
6364 * @deprecated As of JDK version 1.1,
6365 * replaced by processMouseMotionEvent(MouseEvent).
6366 */
6367 @Deprecated
6368 public boolean mouseDrag(Event evt, int x, int y) {
6369 return false;
6370 }
6371
6372 /**
6373 * @deprecated As of JDK version 1.1,
6374 * replaced by processMouseEvent(MouseEvent).
6375 */
6376 @Deprecated
6377 public boolean mouseUp(Event evt, int x, int y) {
6378 return false;
6379 }
6380
6381 /**
6382 * @deprecated As of JDK version 1.1,
6383 * replaced by processMouseMotionEvent(MouseEvent).
6384 */
6385 @Deprecated
6386 public boolean mouseMove(Event evt, int x, int y) {
6387 return false;
6388 }
6389
6390 /**
6391 * @deprecated As of JDK version 1.1,
6392 * replaced by processMouseEvent(MouseEvent).
6393 */
6394 @Deprecated
6395 public boolean mouseEnter(Event evt, int x, int y) {
6396 return false;
6397 }
6398
6399 /**
6400 * @deprecated As of JDK version 1.1,
6401 * replaced by processMouseEvent(MouseEvent).
6402 */
6403 @Deprecated
6404 public boolean mouseExit(Event evt, int x, int y) {
6405 return false;
6406 }
6407
6408 /**
6409 * @deprecated As of JDK version 1.1,
6410 * replaced by processKeyEvent(KeyEvent).
6411 */
6412 @Deprecated
6413 public boolean keyDown(Event evt, int key) {
6414 return false;
6415 }
6416
6417 /**
6418 * @deprecated As of JDK version 1.1,
6419 * replaced by processKeyEvent(KeyEvent).
6420 */
6421 @Deprecated
6422 public boolean keyUp(Event evt, int key) {
6423 return false;
6424 }
6425
6426 /**
6427 * @deprecated As of JDK version 1.1,
6428 * should register this component as ActionListener on component
6429 * which fires action events.
6430 */
6431 @Deprecated
6432 public boolean action(Event evt, Object what) {
6433 return false;
6434 }
6435
6436 /**
6437 * Makes this <code>Component</code> displayable by connecting it to a
6438 * native screen resource.
6439 * This method is called internally by the toolkit and should
6440 * not be called directly by programs.
6441 * @see #isDisplayable
6442 * @see #removeNotify
6443 * @since JDK1.0
6444 */
6445 public void addNotify() {
6446 synchronized (getTreeLock()) {
6447 ComponentPeer peer = this.peer;
6448 if (peer == null || peer instanceof LightweightPeer){
6449 if (peer == null) {
6450 // Update both the Component's peer variable and the local
6451 // variable we use for thread safety.
6452 this.peer = peer = getToolkit().createComponent(this);
6453 }
6454
6455 // This is a lightweight component which means it won't be
6456 // able to get window-related events by itself. If any
6457 // have been enabled, then the nearest native container must
6458 // be enabled.
6459 if (parent != null) {
6460 long mask = 0;
6461 if ((mouseListener != null) || ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)) {
6462 mask |= AWTEvent.MOUSE_EVENT_MASK;
6463 }
6464 if ((mouseMotionListener != null) ||
6465 ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) {
6466 mask |= AWTEvent.MOUSE_MOTION_EVENT_MASK;
6467 }
6468 if ((mouseWheelListener != null ) ||
6469 ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0)) {
6470 mask |= AWTEvent.MOUSE_WHEEL_EVENT_MASK;
6471 }
6472 if (focusListener != null || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0) {
6473 mask |= AWTEvent.FOCUS_EVENT_MASK;
6474 }
6475 if (keyListener != null || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0) {
6476 mask |= AWTEvent.KEY_EVENT_MASK;
6477 }
6478 if (mask != 0) {
6479 parent.proxyEnableEvents(mask);
6480 }
6481 }
6482 } else {
6483 // It's native. If the parent is lightweight it
6484 // will need some help.
6485 Container parent = this.parent;
6486 if (parent != null && parent.peer instanceof LightweightPeer) {
6487 nativeInLightFixer = new NativeInLightFixer();
6488 }
6489 }
6490 invalidate();
6491
6492 int npopups = (popups != null? popups.size() : 0);
6493 for (int i = 0 ; i < npopups ; i++) {
6494 PopupMenu popup = (PopupMenu)popups.elementAt(i);
6495 popup.addNotify();
6496 }
6497
6498 if (dropTarget != null) dropTarget.addNotify(peer);
6499
6500 peerFont = getFont();
6501
6502 if (getContainer() != null && !isAddNotifyComplete) {
6503 getContainer().increaseComponentCount(this);
6504 }
6505
6506
6507 // Update stacking order
6508 if (parent != null && parent.peer != null) {
6509 ContainerPeer parentContPeer = (ContainerPeer) parent.peer;
6510 // if our parent is lightweight and we are not
6511 // we should call restack on nearest heavyweight
6512 // container.
6513 if (parentContPeer instanceof LightweightPeer
6514 && ! (peer instanceof LightweightPeer))
6515 {
6516 Container hwParent = getNativeContainer();
6517 if (hwParent != null && hwParent.peer != null) {
6518 parentContPeer = (ContainerPeer) hwParent.peer;
6519 }
6520 }
6521 if (parentContPeer.isRestackSupported()) {
6522 parentContPeer.restack();
6523 }
6524 }
6525
6526 if (!isAddNotifyComplete) {
6527 addPropertyChangeListener("opaque", opaquePropertyChangeListener);
6528 mixOnShowing();
6529 }
6530
6531 isAddNotifyComplete = true;
6532
6533 if (hierarchyListener != null ||
6534 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 ||
6535 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)) {
6536 HierarchyEvent e =
6537 new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED,
6538 this, parent,
6539 HierarchyEvent.DISPLAYABILITY_CHANGED |
6540 ((isRecursivelyVisible())
6541 ? HierarchyEvent.SHOWING_CHANGED
6542 : 0));
6543 dispatchEvent(e);
6544 }
6545 }
6546 }
6547
6548 /**
6549 * Makes this <code>Component</code> undisplayable by destroying it native
6550 * screen resource.
6551 * <p>
6552 * This method is called by the toolkit internally and should
6553 * not be called directly by programs. Code overriding
6554 * this method should call <code>super.removeNotify</code> as
6555 * the first line of the overriding method.
6556 *
6557 * @see #isDisplayable
6558 * @see #addNotify
6559 * @since JDK1.0
6560 */
6561 public void removeNotify() {
6562 KeyboardFocusManager.clearMostRecentFocusOwner(this);
6563 if (KeyboardFocusManager.getCurrentKeyboardFocusManager().
6564 getPermanentFocusOwner() == this)
6565 {
6566 KeyboardFocusManager.getCurrentKeyboardFocusManager().
6567 setGlobalPermanentFocusOwner(null);
6568 }
6569
6570 synchronized (getTreeLock()) {
6571 if (isFocusOwner()
6572 && KeyboardFocusManager.isAutoFocusTransferEnabled()
6573 && !nextFocusHelper())
6574 {
6575 KeyboardFocusManager.getCurrentKeyboardFocusManager().
6576 clearGlobalFocusOwner();
6577 }
6578
6579 if (getContainer() != null && isAddNotifyComplete) {
6580 getContainer().decreaseComponentCount(this);
6581 }
6582
6583 int npopups = (popups != null? popups.size() : 0);
6584 for (int i = 0 ; i < npopups ; i++) {
6585 PopupMenu popup = (PopupMenu)popups.elementAt(i);
6586 popup.removeNotify();
6587 }
6588 // If there is any input context for this component, notify
6589 // that this component is being removed. (This has to be done
6590 // before hiding peer.)
6591 if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) {
6592 InputContext inputContext = getInputContext();
6593 if (inputContext != null) {
6594 inputContext.removeNotify(this);
6595 }
6596 }
6597
6598 if (nativeInLightFixer != null) {
6599 nativeInLightFixer.uninstall();
6600 }
6601
6602 ComponentPeer p = peer;
6603 if (p != null) {
6604 boolean isLightweight = isLightweight();
6605
6606 if (bufferStrategy instanceof FlipBufferStrategy) {
6607 ((FlipBufferStrategy)bufferStrategy).destroyBuffers();
6608 }
6609
6610 if (dropTarget != null) dropTarget.removeNotify(peer);
6611
6612 // Hide peer first to stop system events such as cursor moves.
6613 if (visible) {
6614 p.hide();
6615 }
6616
6617 peer = null; // Stop peer updates.
6618 peerFont = null;
6619
6620 Toolkit.getEventQueue().removeSourceEvents(this, false);
6621 KeyboardFocusManager.getCurrentKeyboardFocusManager().
6622 discardKeyEvents(this);
6623
6624 p.dispose();
6625
6626 mixOnHiding(isLightweight);
6627 removePropertyChangeListener("opaque", opaquePropertyChangeListener);
6628
6629 isAddNotifyComplete = false;
6630 }
6631
6632 if (hierarchyListener != null ||
6633 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 ||
6634 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)) {
6635 HierarchyEvent e =
6636 new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED,
6637 this, parent,
6638 HierarchyEvent.DISPLAYABILITY_CHANGED |
6639 ((isRecursivelyVisible())
6640 ? HierarchyEvent.SHOWING_CHANGED
6641 : 0));
6642 dispatchEvent(e);
6643 }
6644 }
6645 }
6646
6647 /**
6648 * @deprecated As of JDK version 1.1,
6649 * replaced by processFocusEvent(FocusEvent).
6650 */
6651 @Deprecated
6652 public boolean gotFocus(Event evt, Object what) {
6653 return false;
6654 }
6655
6656 /**
6657 * @deprecated As of JDK version 1.1,
6658 * replaced by processFocusEvent(FocusEvent).
6659 */
6660 @Deprecated
6661 public boolean lostFocus(Event evt, Object what) {
6662 return false;
6663 }
6664
6665 /**
6666 * Returns whether this <code>Component</code> can become the focus
6667 * owner.
6668 *
6669 * @return <code>true</code> if this <code>Component</code> is
6670 * focusable; <code>false</code> otherwise
6671 * @see #setFocusable
6672 * @since JDK1.1
6673 * @deprecated As of 1.4, replaced by <code>isFocusable()</code>.
6674 */
6675 @Deprecated
6676 public boolean isFocusTraversable() {
6677 if (isFocusTraversableOverridden == FOCUS_TRAVERSABLE_UNKNOWN) {
6678 isFocusTraversableOverridden = FOCUS_TRAVERSABLE_DEFAULT;
6679 }
6680 return focusable;
6681 }
6682
6683 /**
6684 * Returns whether this Component can be focused.
6685 *
6686 * @return <code>true</code> if this Component is focusable;
6687 * <code>false</code> otherwise.
6688 * @see #setFocusable
6689 * @since 1.4
6690 */
6691 public boolean isFocusable() {
6692 return isFocusTraversable();
6693 }
6694
6695 /**
6696 * Sets the focusable state of this Component to the specified value. This
6697 * value overrides the Component's default focusability.
6698 *
6699 * @param focusable indicates whether this Component is focusable
6700 * @see #isFocusable
6701 * @since 1.4
6702 * @beaninfo
6703 * bound: true
6704 */
6705 public void setFocusable(boolean focusable) {
6706 boolean oldFocusable;
6707 synchronized (this) {
6708 oldFocusable = this.focusable;
6709 this.focusable = focusable;
6710 }
6711 isFocusTraversableOverridden = FOCUS_TRAVERSABLE_SET;
6712
6713 firePropertyChange("focusable", oldFocusable, focusable);
6714 if (oldFocusable && !focusable) {
6715 if (isFocusOwner()) {
6716 autoTransferFocus(true);
6717 }
6718 KeyboardFocusManager.clearMostRecentFocusOwner(this);
6719 }
6720 }
6721
6722 final boolean isFocusTraversableOverridden() {
6723 return (isFocusTraversableOverridden != FOCUS_TRAVERSABLE_DEFAULT);
6724 }
6725
6726 /**
6727 * Sets the focus traversal keys for a given traversal operation for this
6728 * Component.
6729 * <p>
6730 * The default values for a Component's focus traversal keys are
6731 * implementation-dependent. Sun recommends that all implementations for a
6732 * particular native platform use the same default values. The
6733 * recommendations for Windows and Unix are listed below. These
6734 * recommendations are used in the Sun AWT implementations.
6735 *
6736 * <table border=1 summary="Recommended default values for a Component's focus traversal keys">
6737 * <tr>
6738 * <th>Identifier</th>
6739 * <th>Meaning</th>
6740 * <th>Default</th>
6741 * </tr>
6742 * <tr>
6743 * <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
6744 * <td>Normal forward keyboard traversal</td>
6745 * <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
6746 * </tr>
6747 * <tr>
6748 * <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
6749 * <td>Normal reverse keyboard traversal</td>
6750 * <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
6751 * </tr>
6752 * <tr>
6753 * <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
6754 * <td>Go up one focus traversal cycle</td>
6755 * <td>none</td>
6756 * </tr>
6757 * </table>
6758 *
6759 * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
6760 * recommended.
6761 * <p>
6762 * Using the AWTKeyStroke API, client code can specify on which of two
6763 * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
6764 * operation will occur. Regardless of which KeyEvent is specified,
6765 * however, all KeyEvents related to the focus traversal key, including the
6766 * associated KEY_TYPED event, will be consumed, and will not be dispatched
6767 * to any Component. It is a runtime error to specify a KEY_TYPED event as
6768 * mapping to a focus traversal operation, or to map the same event to
6769 * multiple default focus traversal operations.
6770 * <p>
6771 * If a value of null is specified for the Set, this Component inherits the
6772 * Set from its parent. If all ancestors of this Component have null
6773 * specified for the Set, then the current KeyboardFocusManager's default
6774 * Set is used.
6775 *
6776 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
6777 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
6778 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
6779 * @param keystrokes the Set of AWTKeyStroke for the specified operation
6780 * @see #getFocusTraversalKeys
6781 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
6782 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
6783 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
6784 * @throws IllegalArgumentException if id is not one of
6785 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
6786 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
6787 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes
6788 * contains null, or if any Object in keystrokes is not an
6789 * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
6790 * or if any keystroke already maps to another focus traversal
6791 * operation for this Component
6792 * @since 1.4
6793 * @beaninfo
6794 * bound: true
6795 */
6796 public void setFocusTraversalKeys(int id,
6797 Set<? extends AWTKeyStroke> keystrokes)
6798 {
6799 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH - 1) {
6800 throw new IllegalArgumentException("invalid focus traversal key identifier");
6801 }
6802
6803 setFocusTraversalKeys_NoIDCheck(id, keystrokes);
6804 }
6805
6806 /**
6807 * Returns the Set of focus traversal keys for a given traversal operation
6808 * for this Component. (See
6809 * <code>setFocusTraversalKeys</code> for a full description of each key.)
6810 * <p>
6811 * If a Set of traversal keys has not been explicitly defined for this
6812 * Component, then this Component's parent's Set is returned. If no Set
6813 * has been explicitly defined for any of this Component's ancestors, then
6814 * the current KeyboardFocusManager's default Set is returned.
6815 *
6816 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
6817 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
6818 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
6819 * @return the Set of AWTKeyStrokes for the specified operation. The Set
6820 * will be unmodifiable, and may be empty. null will never be
6821 * returned.
6822 * @see #setFocusTraversalKeys
6823 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
6824 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
6825 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
6826 * @throws IllegalArgumentException if id is not one of
6827 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
6828 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
6829 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
6830 * @since 1.4
6831 */
6832 public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
6833 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH - 1) {
6834 throw new IllegalArgumentException("invalid focus traversal key identifier");
6835 }
6836
6837 return getFocusTraversalKeys_NoIDCheck(id);
6838 }
6839
6840 // We define these methods so that Container does not need to repeat this
6841 // code. Container cannot call super.<method> because Container allows
6842 // DOWN_CYCLE_TRAVERSAL_KEY while Component does not. The Component method
6843 // would erroneously generate an IllegalArgumentException for
6844 // DOWN_CYCLE_TRAVERSAL_KEY.
6845 final void setFocusTraversalKeys_NoIDCheck(int id, Set<? extends AWTKeyStroke> keystrokes) {
6846 Set oldKeys;
6847
6848 synchronized (this) {
6849 if (focusTraversalKeys == null) {
6850 initializeFocusTraversalKeys();
6851 }
6852
6853 if (keystrokes != null) {
6854 for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
6855 Object obj = iter.next();
6856
6857 if (obj == null) {
6858 throw new IllegalArgumentException("cannot set null focus traversal key");
6859 }
6860
6861 // Fix for 6195828:
6862 //According to javadoc this method should throw IAE instead of ClassCastException
6863 if (!(obj instanceof AWTKeyStroke)) {
6864 throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
6865 }
6866 AWTKeyStroke keystroke = (AWTKeyStroke)obj;
6867
6868 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
6869 throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
6870 }
6871
6872 for (int i = 0; i < focusTraversalKeys.length; i++) {
6873 if (i == id) {
6874 continue;
6875 }
6876
6877 if (getFocusTraversalKeys_NoIDCheck(i).contains(keystroke))
6878 {
6879 throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
6880 }
6881 }
6882 }
6883 }
6884
6885 oldKeys = focusTraversalKeys[id];
6886 focusTraversalKeys[id] = (keystrokes != null)
6887 ? Collections.unmodifiableSet(new HashSet(keystrokes))
6888 : null;
6889 }
6890
6891 firePropertyChange(focusTraversalKeyPropertyNames[id], oldKeys,
6892 keystrokes);
6893 }
6894 final Set getFocusTraversalKeys_NoIDCheck(int id) {
6895 // Okay to return Set directly because it is an unmodifiable view
6896 Set keystrokes = (focusTraversalKeys != null)
6897 ? focusTraversalKeys[id]
6898 : null;
6899
6900 if (keystrokes != null) {
6901 return keystrokes;
6902 } else {
6903 Container parent = this.parent;
6904 if (parent != null) {
6905 return parent.getFocusTraversalKeys(id);
6906 } else {
6907 return KeyboardFocusManager.getCurrentKeyboardFocusManager().
6908 getDefaultFocusTraversalKeys(id);
6909 }
6910 }
6911 }
6912
6913 /**
6914 * Returns whether the Set of focus traversal keys for the given focus
6915 * traversal operation has been explicitly defined for this Component. If
6916 * this method returns <code>false</code>, this Component is inheriting the
6917 * Set from an ancestor, or from the current KeyboardFocusManager.
6918 *
6919 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
6920 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
6921 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
6922 * @return <code>true</code> if the the Set of focus traversal keys for the
6923 * given focus traversal operation has been explicitly defined for
6924 * this Component; <code>false</code> otherwise.
6925 * @throws IllegalArgumentException if id is not one of
6926 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
6927 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
6928 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
6929 * @since 1.4
6930 */
6931 public boolean areFocusTraversalKeysSet(int id) {
6932 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH - 1) {
6933 throw new IllegalArgumentException("invalid focus traversal key identifier");
6934 }
6935
6936 return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
6937 }
6938
6939 /**
6940 * Sets whether focus traversal keys are enabled for this Component.
6941 * Components for which focus traversal keys are disabled receive key
6942 * events for focus traversal keys. Components for which focus traversal
6943 * keys are enabled do not see these events; instead, the events are
6944 * automatically converted to traversal operations.
6945 *
6946 * @param focusTraversalKeysEnabled whether focus traversal keys are
6947 * enabled for this Component
6948 * @see #getFocusTraversalKeysEnabled
6949 * @see #setFocusTraversalKeys
6950 * @see #getFocusTraversalKeys
6951 * @since 1.4
6952 * @beaninfo
6953 * bound: true
6954 */
6955 public void setFocusTraversalKeysEnabled(boolean
6956 focusTraversalKeysEnabled) {
6957 boolean oldFocusTraversalKeysEnabled;
6958 synchronized (this) {
6959 oldFocusTraversalKeysEnabled = this.focusTraversalKeysEnabled;
6960 this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
6961 }
6962 firePropertyChange("focusTraversalKeysEnabled",
6963 oldFocusTraversalKeysEnabled,
6964 focusTraversalKeysEnabled);
6965 }
6966
6967 /**
6968 * Returns whether focus traversal keys are enabled for this Component.
6969 * Components for which focus traversal keys are disabled receive key
6970 * events for focus traversal keys. Components for which focus traversal
6971 * keys are enabled do not see these events; instead, the events are
6972 * automatically converted to traversal operations.
6973 *
6974 * @return whether focus traversal keys are enabled for this Component
6975 * @see #setFocusTraversalKeysEnabled
6976 * @see #setFocusTraversalKeys
6977 * @see #getFocusTraversalKeys
6978 * @since 1.4
6979 */
6980 public boolean getFocusTraversalKeysEnabled() {
6981 return focusTraversalKeysEnabled;
6982 }
6983
6984 /**
6985 * Requests that this Component get the input focus, and that this
6986 * Component's top-level ancestor become the focused Window. This
6987 * component must be displayable, focusable, visible and all of
6988 * its ancestors (with the exception of the top-level Window) must
6989 * be visible for the request to be granted. Every effort will be
6990 * made to honor the request; however, in some cases it may be
6991 * impossible to do so. Developers must never assume that this
6992 * Component is the focus owner until this Component receives a
6993 * FOCUS_GAINED event. If this request is denied because this
6994 * Component's top-level Window cannot become the focused Window,
6995 * the request will be remembered and will be granted when the
6996 * Window is later focused by the user.
6997 * <p>
6998 * This method cannot be used to set the focus owner to no Component at
6999 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner()</code>
7000 * instead.
7001 * <p>
7002 * Because the focus behavior of this method is platform-dependent,
7003 * developers are strongly encouraged to use
7004 * <code>requestFocusInWindow</code> when possible.
7005 *
7006 * <p>Note: Not all focus transfers result from invoking this method. As
7007 * such, a component may receive focus without this or any of the other
7008 * {@code requestFocus} methods of {@code Component} being invoked.
7009 *
7010 * @see #requestFocusInWindow
7011 * @see java.awt.event.FocusEvent
7012 * @see #addFocusListener
7013 * @see #isFocusable
7014 * @see #isDisplayable
7015 * @see KeyboardFocusManager#clearGlobalFocusOwner
7016 * @since JDK1.0
7017 */
7018 public void requestFocus() {
7019 requestFocusHelper(false, true);
7020 }
7021
7022 void requestFocus(CausedFocusEvent.Cause cause) {
7023 requestFocusHelper(false, true, cause);
7024 }
7025
7026 /**
7027 * Requests that this <code>Component</code> get the input focus,
7028 * and that this <code>Component</code>'s top-level ancestor
7029 * become the focused <code>Window</code>. This component must be
7030 * displayable, focusable, visible and all of its ancestors (with
7031 * the exception of the top-level Window) must be visible for the
7032 * request to be granted. Every effort will be made to honor the
7033 * request; however, in some cases it may be impossible to do
7034 * so. Developers must never assume that this component is the
7035 * focus owner until this component receives a FOCUS_GAINED
7036 * event. If this request is denied because this component's
7037 * top-level window cannot become the focused window, the request
7038 * will be remembered and will be granted when the window is later
7039 * focused by the user.
7040 * <p>
7041 * This method returns a boolean value. If <code>false</code> is returned,
7042 * the request is <b>guaranteed to fail</b>. If <code>true</code> is
7043 * returned, the request will succeed <b>unless</b> it is vetoed, or an
7044 * extraordinary event, such as disposal of the component's peer, occurs
7045 * before the request can be granted by the native windowing system. Again,
7046 * while a return value of <code>true</code> indicates that the request is
7047 * likely to succeed, developers must never assume that this component is
7048 * the focus owner until this component receives a FOCUS_GAINED event.
7049 * <p>
7050 * This method cannot be used to set the focus owner to no component at
7051 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner</code>
7052 * instead.
7053 * <p>
7054 * Because the focus behavior of this method is platform-dependent,
7055 * developers are strongly encouraged to use
7056 * <code>requestFocusInWindow</code> when possible.
7057 * <p>
7058 * Every effort will be made to ensure that <code>FocusEvent</code>s
7059 * generated as a
7060 * result of this request will have the specified temporary value. However,
7061 * because specifying an arbitrary temporary state may not be implementable
7062 * on all native windowing systems, correct behavior for this method can be
7063 * guaranteed only for lightweight <code>Component</code>s.
7064 * This method is not intended
7065 * for general use, but exists instead as a hook for lightweight component
7066 * libraries, such as Swing.
7067 *
7068 * <p>Note: Not all focus transfers result from invoking this method. As
7069 * such, a component may receive focus without this or any of the other
7070 * {@code requestFocus} methods of {@code Component} being invoked.
7071 *
7072 * @param temporary true if the focus change is temporary,
7073 * such as when the window loses the focus; for
7074 * more information on temporary focus changes see the
7075 *<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
7076 * @return <code>false</code> if the focus change request is guaranteed to
7077 * fail; <code>true</code> if it is likely to succeed
7078 * @see java.awt.event.FocusEvent
7079 * @see #addFocusListener
7080 * @see #isFocusable
7081 * @see #isDisplayable
7082 * @see KeyboardFocusManager#clearGlobalFocusOwner
7083 * @since 1.4
7084 */
7085 protected boolean requestFocus(boolean temporary) {
7086 return requestFocusHelper(temporary, true);
7087 }
7088
7089 boolean requestFocus(boolean temporary, CausedFocusEvent.Cause cause) {
7090 return requestFocusHelper(temporary, true, cause);
7091 }
7092 /**
7093 * Requests that this Component get the input focus, if this
7094 * Component's top-level ancestor is already the focused
7095 * Window. This component must be displayable, focusable, visible
7096 * and all of its ancestors (with the exception of the top-level
7097 * Window) must be visible for the request to be granted. Every
7098 * effort will be made to honor the request; however, in some
7099 * cases it may be impossible to do so. Developers must never
7100 * assume that this Component is the focus owner until this
7101 * Component receives a FOCUS_GAINED event.
7102 * <p>
7103 * This method returns a boolean value. If <code>false</code> is returned,
7104 * the request is <b>guaranteed to fail</b>. If <code>true</code> is
7105 * returned, the request will succeed <b>unless</b> it is vetoed, or an
7106 * extraordinary event, such as disposal of the Component's peer, occurs
7107 * before the request can be granted by the native windowing system. Again,
7108 * while a return value of <code>true</code> indicates that the request is
7109 * likely to succeed, developers must never assume that this Component is
7110 * the focus owner until this Component receives a FOCUS_GAINED event.
7111 * <p>
7112 * This method cannot be used to set the focus owner to no Component at
7113 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner()</code>
7114 * instead.
7115 * <p>
7116 * The focus behavior of this method can be implemented uniformly across
7117 * platforms, and thus developers are strongly encouraged to use this
7118 * method over <code>requestFocus</code> when possible. Code which relies
7119 * on <code>requestFocus</code> may exhibit different focus behavior on
7120 * different platforms.
7121 *
7122 * <p>Note: Not all focus transfers result from invoking this method. As
7123 * such, a component may receive focus without this or any of the other
7124 * {@code requestFocus} methods of {@code Component} being invoked.
7125 *
7126 * @return <code>false</code> if the focus change request is guaranteed to
7127 * fail; <code>true</code> if it is likely to succeed
7128 * @see #requestFocus
7129 * @see java.awt.event.FocusEvent
7130 * @see #addFocusListener
7131 * @see #isFocusable
7132 * @see #isDisplayable
7133 * @see KeyboardFocusManager#clearGlobalFocusOwner
7134 * @since 1.4
7135 */
7136 public boolean requestFocusInWindow() {
7137 return requestFocusHelper(false, false);
7138 }
7139
7140 boolean requestFocusInWindow(CausedFocusEvent.Cause cause) {
7141 return requestFocusHelper(false, false, cause);
7142 }
7143
7144 /**
7145 * Requests that this <code>Component</code> get the input focus,
7146 * if this <code>Component</code>'s top-level ancestor is already
7147 * the focused <code>Window</code>. This component must be
7148 * displayable, focusable, visible and all of its ancestors (with
7149 * the exception of the top-level Window) must be visible for the
7150 * request to be granted. Every effort will be made to honor the
7151 * request; however, in some cases it may be impossible to do
7152 * so. Developers must never assume that this component is the
7153 * focus owner until this component receives a FOCUS_GAINED event.
7154 * <p>
7155 * This method returns a boolean value. If <code>false</code> is returned,
7156 * the request is <b>guaranteed to fail</b>. If <code>true</code> is
7157 * returned, the request will succeed <b>unless</b> it is vetoed, or an
7158 * extraordinary event, such as disposal of the component's peer, occurs
7159 * before the request can be granted by the native windowing system. Again,
7160 * while a return value of <code>true</code> indicates that the request is
7161 * likely to succeed, developers must never assume that this component is
7162 * the focus owner until this component receives a FOCUS_GAINED event.
7163 * <p>
7164 * This method cannot be used to set the focus owner to no component at
7165 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner</code>
7166 * instead.
7167 * <p>
7168 * The focus behavior of this method can be implemented uniformly across
7169 * platforms, and thus developers are strongly encouraged to use this
7170 * method over <code>requestFocus</code> when possible. Code which relies
7171 * on <code>requestFocus</code> may exhibit different focus behavior on
7172 * different platforms.
7173 * <p>
7174 * Every effort will be made to ensure that <code>FocusEvent</code>s
7175 * generated as a
7176 * result of this request will have the specified temporary value. However,
7177 * because specifying an arbitrary temporary state may not be implementable
7178 * on all native windowing systems, correct behavior for this method can be
7179 * guaranteed only for lightweight components. This method is not intended
7180 * for general use, but exists instead as a hook for lightweight component
7181 * libraries, such as Swing.
7182 *
7183 * <p>Note: Not all focus transfers result from invoking this method. As
7184 * such, a component may receive focus without this or any of the other
7185 * {@code requestFocus} methods of {@code Component} being invoked.
7186 *
7187 * @param temporary true if the focus change is temporary,
7188 * such as when the window loses the focus; for
7189 * more information on temporary focus changes see the
7190 *<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
7191 * @return <code>false</code> if the focus change request is guaranteed to
7192 * fail; <code>true</code> if it is likely to succeed
7193 * @see #requestFocus
7194 * @see java.awt.event.FocusEvent
7195 * @see #addFocusListener
7196 * @see #isFocusable
7197 * @see #isDisplayable
7198 * @see KeyboardFocusManager#clearGlobalFocusOwner
7199 * @since 1.4
7200 */
7201 protected boolean requestFocusInWindow(boolean temporary) {
7202 return requestFocusHelper(temporary, false);
7203 }
7204
7205 boolean requestFocusInWindow(boolean temporary, CausedFocusEvent.Cause cause) {
7206 return requestFocusHelper(temporary, false, cause);
7207 }
7208
7209 final boolean requestFocusHelper(boolean temporary,
7210 boolean focusedWindowChangeAllowed) {
7211 return requestFocusHelper(temporary, focusedWindowChangeAllowed, CausedFocusEvent.Cause.UNKNOWN);
7212 }
7213
7214 final boolean requestFocusHelper(boolean temporary,
7215 boolean focusedWindowChangeAllowed,
7216 CausedFocusEvent.Cause cause)
7217 {
7218 if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) {
7219 if (focusLog.isLoggable(Level.FINEST)) {
7220 focusLog.log(Level.FINEST, "requestFocus is not accepted");
7221 }
7222 return false;
7223 }
7224
7225 // Update most-recent map
7226 KeyboardFocusManager.setMostRecentFocusOwner(this);
7227
7228 Component window = this;
7229 while ( (window != null) && !(window instanceof Window)) {
7230 if (!window.isVisible()) {
7231 if (focusLog.isLoggable(Level.FINEST)) {
7232 focusLog.log(Level.FINEST, "component is recurively invisible");
7233 }
7234 return false;
7235 }
7236 window = window.parent;
7237 }
7238
7239 ComponentPeer peer = this.peer;
7240 Component heavyweight = (peer instanceof LightweightPeer)
7241 ? getNativeContainer() : this;
7242 if (heavyweight == null || !heavyweight.isVisible()) {
7243 if (focusLog.isLoggable(Level.FINEST)) {
7244 focusLog.log(Level.FINEST, "Component is not a part of visible hierarchy");
7245 }
7246 return false;
7247 }
7248 peer = heavyweight.peer;
7249 if (peer == null) {
7250 if (focusLog.isLoggable(Level.FINEST)) {
7251 focusLog.log(Level.FINEST, "Peer is null");
7252 }
7253 return false;
7254 }
7255
7256 // Focus this Component
7257 long time = EventQueue.getMostRecentEventTime();
7258 boolean success = peer.requestFocus
7259 (this, temporary, focusedWindowChangeAllowed, time, cause);
7260 if (!success) {
7261 KeyboardFocusManager.getCurrentKeyboardFocusManager
7262 (appContext).dequeueKeyEvents(time, this);
7263 if (focusLog.isLoggable(Level.FINEST)) {
7264 focusLog.log(Level.FINEST, "Peer request failed");
7265 }
7266 } else {
7267 if (focusLog.isLoggable(Level.FINEST)) {
7268 focusLog.log(Level.FINEST, "Pass for " + this);
7269 }
7270 }
7271 return success;
7272 }
7273
7274 private boolean isRequestFocusAccepted(boolean temporary,
7275 boolean focusedWindowChangeAllowed,
7276 CausedFocusEvent.Cause cause)
7277 {
7278 if (!isFocusable() || !isVisible()) {
7279 if (focusLog.isLoggable(Level.FINEST)) {
7280 focusLog.log(Level.FINEST, "Not focusable or not visible");
7281 }
7282 return false;
7283 }
7284
7285 ComponentPeer peer = this.peer;
7286 if (peer == null) {
7287 if (focusLog.isLoggable(Level.FINEST)) {
7288 focusLog.log(Level.FINEST, "peer is null");
7289 }
7290 return false;
7291 }
7292
7293 Window window = getContainingWindow();
7294 if (window == null || !((Window)window).isFocusableWindow()) {
7295 if (focusLog.isLoggable(Level.FINEST)) {
7296 focusLog.log(Level.FINEST, "Component doesn't have toplevel");
7297 }
7298 return false;
7299 }
7300
7301 // We have passed all regular checks for focus request,
7302 // now let's call RequestFocusController and see what it says.
7303 Component focusOwner = KeyboardFocusManager.getMostRecentFocusOwner(window);
7304 if (focusOwner == null) {
7305 // sometimes most recent focus owner may be null, but focus owner is not
7306 // e.g. we reset most recent focus owner if user removes focus owner
7307 focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
7308 if (focusOwner != null && getContainingWindow(focusOwner) != window) {
7309 focusOwner = null;
7310 }
7311 }
7312
7313 if (focusOwner == this || focusOwner == null) {
7314 // Controller is supposed to verify focus transfers and for this it
7315 // should know both from and to components. And it shouldn't verify
7316 // transfers from when these components are equal.
7317 if (focusLog.isLoggable(Level.FINEST)) {
7318 focusLog.log(Level.FINEST, "focus owner is null or this");
7319 }
7320 return true;
7321 }
7322
7323 if (CausedFocusEvent.Cause.ACTIVATION == cause) {
7324 // we shouldn't call RequestFocusController in case we are
7325 // in activation. We do request focus on component which
7326 // has got temporary focus lost and then on component which is
7327 // most recent focus owner. But most recent focus owner can be
7328 // changed by requestFocsuXXX() call only, so this transfer has
7329 // been already approved.
7330 if (focusLog.isLoggable(Level.FINEST)) {
7331 focusLog.log(Level.FINEST, "cause is activation");
7332 }
7333 return true;
7334 }
7335
7336 boolean ret = Component.requestFocusController.acceptRequestFocus(focusOwner,
7337 this,
7338 temporary,
7339 focusedWindowChangeAllowed,
7340 cause);
7341 if (focusLog.isLoggable(Level.FINEST)) {
7342 focusLog.log(Level.FINEST, "RequestFocusController returns {0}", ret);
7343 }
7344
7345 return ret;
7346 }
7347
7348 private static RequestFocusController requestFocusController = new DummyRequestFocusController();
7349
7350 // Swing access this method through reflection to implement InputVerifier's functionality.
7351 // Perhaps, we should make this method public (later ;)
7352 private static class DummyRequestFocusController implements RequestFocusController {
7353 public boolean acceptRequestFocus(Component from, Component to,
7354 boolean temporary, boolean focusedWindowChangeAllowed,
7355 CausedFocusEvent.Cause cause)
7356 {
7357 return true;
7358 }
7359 };
7360
7361 synchronized static void setRequestFocusController(RequestFocusController requestController)
7362 {
7363 if (requestController == null) {
7364 requestFocusController = new DummyRequestFocusController();
7365 } else {
7366 requestFocusController = requestController;
7367 }
7368 }
7369
7370 private void autoTransferFocus(boolean clearOnFailure) {
7371 Component toTest = KeyboardFocusManager.
7372 getCurrentKeyboardFocusManager().getFocusOwner();
7373 if (toTest != this) {
7374 if (toTest != null) {
7375 toTest.autoTransferFocus(clearOnFailure);
7376 }
7377 return;
7378 }
7379
7380 // Check if there are pending focus requests. We shouldn't do
7381 // auto-transfer if user has already took care of this
7382 // component becoming ineligible to hold focus.
7383 if (!KeyboardFocusManager.isAutoFocusTransferEnabled()) {
7384 return;
7385 }
7386
7387 // the following code will execute only if this Component is the focus
7388 // owner
7389
7390 if (!(isDisplayable() && isVisible() && isEnabled() && isFocusable())) {
7391 doAutoTransfer(clearOnFailure);
7392 return;
7393 }
7394
7395 toTest = getParent();
7396
7397 while (toTest != null && !(toTest instanceof Window)) {
7398 if (!(toTest.isDisplayable() && toTest.isVisible() &&
7399 (toTest.isEnabled() || toTest.isLightweight()))) {
7400 doAutoTransfer(clearOnFailure);
7401 return;
7402 }
7403 toTest = toTest.getParent();
7404 }
7405 }
7406 private void doAutoTransfer(boolean clearOnFailure) {
7407 if (focusLog.isLoggable(Level.FINER)) {
7408 focusLog.log(Level.FINER, "this = " + this + ", clearOnFailure = " + clearOnFailure);
7409 }
7410 if (clearOnFailure) {
7411 if (!nextFocusHelper()) {
7412 if (focusLog.isLoggable(Level.FINER)) {
7413 focusLog.log(Level.FINER, "clear global focus owner");
7414 }
7415 KeyboardFocusManager.getCurrentKeyboardFocusManager().
7416 clearGlobalFocusOwner();
7417 }
7418 } else {
7419 transferFocus();
7420 }
7421 }
7422
7423 /**
7424 * Transfers the focus to the next component, as though this Component were
7425 * the focus owner.
7426 * @see #requestFocus()
7427 * @since JDK1.1
7428 */
7429 public void transferFocus() {
7430 nextFocus();
7431 }
7432
7433 /**
7434 * Returns the Container which is the focus cycle root of this Component's
7435 * focus traversal cycle. Each focus traversal cycle has only a single
7436 * focus cycle root and each Component which is not a Container belongs to
7437 * only a single focus traversal cycle. Containers which are focus cycle
7438 * roots belong to two cycles: one rooted at the Container itself, and one
7439 * rooted at the Container's nearest focus-cycle-root ancestor. For such
7440 * Containers, this method will return the Container's nearest focus-cycle-
7441 * root ancestor.
7442 *
7443 * @return this Component's nearest focus-cycle-root ancestor
7444 * @see Container#isFocusCycleRoot()
7445 * @since 1.4
7446 */
7447 public Container getFocusCycleRootAncestor() {
7448 Container rootAncestor = this.parent;
7449 while (rootAncestor != null && !rootAncestor.isFocusCycleRoot()) {
7450 rootAncestor = rootAncestor.parent;
7451 }
7452 return rootAncestor;
7453 }
7454
7455 /**
7456 * Returns whether the specified Container is the focus cycle root of this
7457 * Component's focus traversal cycle. Each focus traversal cycle has only
7458 * a single focus cycle root and each Component which is not a Container
7459 * belongs to only a single focus traversal cycle.
7460 *
7461 * @param container the Container to be tested
7462 * @return <code>true</code> if the specified Container is a focus-cycle-
7463 * root of this Component; <code>false</code> otherwise
7464 * @see Container#isFocusCycleRoot()
7465 * @since 1.4
7466 */
7467 public boolean isFocusCycleRoot(Container container) {
7468 Container rootAncestor = getFocusCycleRootAncestor();
7469 return (rootAncestor == container);
7470 }
7471
7472 /**
7473 * @deprecated As of JDK version 1.1,
7474 * replaced by transferFocus().
7475 */
7476 @Deprecated
7477 public void nextFocus() {
7478 nextFocusHelper();
7479 }
7480
7481 private boolean nextFocusHelper() {
7482 Component toFocus = preNextFocusHelper();
7483 if (focusLog.isLoggable(Level.FINER)) {
7484 focusLog.log(Level.FINER, "toFocus = " + toFocus);
7485 }
7486 if (isFocusOwner() && toFocus == this) {
7487 return false;
7488 }
7489 return postNextFocusHelper(toFocus, CausedFocusEvent.Cause.TRAVERSAL_FORWARD);
7490 }
7491
7492 Container getTraversalRoot() {
7493 return getFocusCycleRootAncestor();
7494 }
7495
7496 final Component preNextFocusHelper() {
7497 Container rootAncestor = getTraversalRoot();
7498 Component comp = this;
7499 while (rootAncestor != null &&
7500 !(rootAncestor.isShowing() &&
7501 rootAncestor.isFocusable() &&
7502 rootAncestor.isEnabled()))
7503 {
7504 comp = rootAncestor;
7505 rootAncestor = comp.getFocusCycleRootAncestor();
7506 }
7507 if (focusLog.isLoggable(Level.FINER)) {
7508 focusLog.log(Level.FINER, "comp = " + comp + ", root = " + rootAncestor);
7509 }
7510 if (rootAncestor != null) {
7511 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy();
7512 Component toFocus = policy.getComponentAfter(rootAncestor, comp);
7513 if (focusLog.isLoggable(Level.FINER)) {
7514 focusLog.log(Level.FINER, "component after is " + toFocus);
7515 }
7516 if (toFocus == null) {
7517 toFocus = policy.getDefaultComponent(rootAncestor);
7518 if (focusLog.isLoggable(Level.FINER)) {
7519 focusLog.log(Level.FINER, "default component is " + toFocus);
7520 }
7521 }
7522 if (toFocus == null) {
7523 Applet applet = EmbeddedFrame.getAppletIfAncestorOf(this);
7524 if (applet != null) {
7525 toFocus = applet;
7526 }
7527 }
7528 return toFocus;
7529 }
7530 return null;
7531 }
7532
7533 static boolean postNextFocusHelper(Component toFocus, CausedFocusEvent.Cause cause) {
7534 if (toFocus != null) {
7535 if (focusLog.isLoggable(Level.FINER)) {
7536 focusLog.log(Level.FINER, "Next component " + toFocus);
7537 }
7538 boolean res = toFocus.requestFocusInWindow(cause);
7539 if (focusLog.isLoggable(Level.FINER)) {
7540 focusLog.log(Level.FINER, "Request focus returned " + res);
7541 }
7542 return res;
7543 }
7544 return false;
7545 }
7546
7547 /**
7548 * Transfers the focus to the previous component, as though this Component
7549 * were the focus owner.
7550 * @see #requestFocus()
7551 * @since 1.4
7552 */
7553 public void transferFocusBackward() {
7554 Container rootAncestor = getTraversalRoot();
7555 Component comp = this;
7556 while (rootAncestor != null &&
7557 !(rootAncestor.isShowing() &&
7558 rootAncestor.isFocusable() &&
7559 rootAncestor.isEnabled()))
7560 {
7561 comp = rootAncestor;
7562 rootAncestor = comp.getFocusCycleRootAncestor();
7563 }
7564 if (rootAncestor != null) {
7565 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy();
7566 Component toFocus = policy.getComponentBefore(rootAncestor, comp);
7567 if (toFocus == null) {
7568 toFocus = policy.getDefaultComponent(rootAncestor);
7569 }
7570 if (toFocus != null) {
7571 toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD);
7572 }
7573 }
7574 }
7575
7576 /**
7577 * Transfers the focus up one focus traversal cycle. Typically, the focus
7578 * owner is set to this Component's focus cycle root, and the current focus
7579 * cycle root is set to the new focus owner's focus cycle root. If,
7580 * however, this Component's focus cycle root is a Window, then the focus
7581 * owner is set to the focus cycle root's default Component to focus, and
7582 * the current focus cycle root is unchanged.
7583 *
7584 * @see #requestFocus()
7585 * @see Container#isFocusCycleRoot()
7586 * @see Container#setFocusCycleRoot(boolean)
7587 * @since 1.4
7588 */
7589 public void transferFocusUpCycle() {
7590 Container rootAncestor;
7591 for (rootAncestor = getFocusCycleRootAncestor();
7592 rootAncestor != null && !(rootAncestor.isShowing() &&
7593 rootAncestor.isFocusable() &&
7594 rootAncestor.isEnabled());
7595 rootAncestor = rootAncestor.getFocusCycleRootAncestor()) {
7596 }
7597
7598 if (rootAncestor != null) {
7599 Container rootAncestorRootAncestor =
7600 rootAncestor.getFocusCycleRootAncestor();
7601 KeyboardFocusManager.getCurrentKeyboardFocusManager().
7602 setGlobalCurrentFocusCycleRoot(
7603 (rootAncestorRootAncestor != null)
7604 ? rootAncestorRootAncestor
7605 : rootAncestor);
7606 rootAncestor.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
7607 } else {
7608 Window window = getContainingWindow();
7609
7610 if (window != null) {
7611 Component toFocus = window.getFocusTraversalPolicy().
7612 getDefaultComponent(window);
7613 if (toFocus != null) {
7614 KeyboardFocusManager.getCurrentKeyboardFocusManager().
7615 setGlobalCurrentFocusCycleRoot(window);
7616 toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
7617 }
7618 }
7619 }
7620 }
7621
7622 /**
7623 * Returns <code>true</code> if this <code>Component</code> is the
7624 * focus owner. This method is obsolete, and has been replaced by
7625 * <code>isFocusOwner()</code>.
7626 *
7627 * @return <code>true</code> if this <code>Component</code> is the
7628 * focus owner; <code>false</code> otherwise
7629 * @since 1.2
7630 */
7631 public boolean hasFocus() {
7632 return (KeyboardFocusManager.getCurrentKeyboardFocusManager().
7633 getFocusOwner() == this);
7634 }
7635
7636 /**
7637 * Returns <code>true</code> if this <code>Component</code> is the
7638 * focus owner.
7639 *
7640 * @return <code>true</code> if this <code>Component</code> is the
7641 * focus owner; <code>false</code> otherwise
7642 * @since 1.4
7643 */
7644 public boolean isFocusOwner() {
7645 return hasFocus();
7646 }
7647
7648 /**
7649 * Adds the specified popup menu to the component.
7650 * @param popup the popup menu to be added to the component.
7651 * @see #remove(MenuComponent)
7652 * @exception NullPointerException if {@code popup} is {@code null}
7653 * @since JDK1.1
7654 */
7655 public void add(PopupMenu popup) {
7656 synchronized (getTreeLock()) {
7657 if (popup.parent != null) {
7658 popup.parent.remove(popup);
7659 }
7660 if (popups == null) {
7661 popups = new Vector();
7662 }
7663 popups.addElement(popup);
7664 popup.parent = this;
7665
7666 if (peer != null) {
7667 if (popup.peer == null) {
7668 popup.addNotify();
7669 }
7670 }
7671 }
7672 }
7673
7674 /**
7675 * Removes the specified popup menu from the component.
7676 * @param popup the popup menu to be removed
7677 * @see #add(PopupMenu)
7678 * @since JDK1.1
7679 */
7680 public void remove(MenuComponent popup) {
7681 synchronized (getTreeLock()) {
7682 if (popups == null) {
7683 return;
7684 }
7685 int index = popups.indexOf(popup);
7686 if (index >= 0) {
7687 PopupMenu pmenu = (PopupMenu)popup;
7688 if (pmenu.peer != null) {
7689 pmenu.removeNotify();
7690 }
7691 pmenu.parent = null;
7692 popups.removeElementAt(index);
7693 if (popups.size() == 0) {
7694 popups = null;
7695 }
7696 }
7697 }
7698 }
7699
7700 /**
7701 * Returns a string representing the state of this component. This
7702 * method is intended to be used only for debugging purposes, and the
7703 * content and format of the returned string may vary between
7704 * implementations. The returned string may be empty but may not be
7705 * <code>null</code>.
7706 *
7707 * @return a string representation of this component's state
7708 * @since JDK1.0
7709 */
7710 protected String paramString() {
7711 String thisName = getName();
7712 String str = (thisName != null? thisName : "") + "," + x + "," + y + "," + width + "x" + height;
7713 if (!valid) {
7714 str += ",invalid";
7715 }
7716 if (!visible) {
7717 str += ",hidden";
7718 }
7719 if (!enabled) {
7720 str += ",disabled";
7721 }
7722 return str;
7723 }
7724
7725 /**
7726 * Returns a string representation of this component and its values.
7727 * @return a string representation of this component
7728 * @since JDK1.0
7729 */
7730 public String toString() {
7731 return getClass().getName() + "[" + paramString() + "]";
7732 }
7733
7734 /**
7735 * Prints a listing of this component to the standard system output
7736 * stream <code>System.out</code>.
7737 * @see java.lang.System#out
7738 * @since JDK1.0
7739 */
7740 public void list() {
7741 list(System.out, 0);
7742 }
7743
7744 /**
7745 * Prints a listing of this component to the specified output
7746 * stream.
7747 * @param out a print stream
7748 * @since JDK1.0
7749 */
7750 public void list(PrintStream out) {
7751 list(out, 0);
7752 }
7753
7754 /**
7755 * Prints out a list, starting at the specified indentation, to the
7756 * specified print stream.
7757 * @param out a print stream
7758 * @param indent number of spaces to indent
7759 * @see java.io.PrintStream#println(java.lang.Object)
7760 * @since JDK1.0
7761 */
7762 public void list(PrintStream out, int indent) {
7763 for (int i = 0 ; i < indent ; i++) {
7764 out.print(" ");
7765 }
7766 out.println(this);
7767 }
7768
7769 /**
7770 * Prints a listing to the specified print writer.
7771 * @param out the print writer to print to
7772 * @since JDK1.1
7773 */
7774 public void list(PrintWriter out) {
7775 list(out, 0);
7776 }
7777
7778 /**
7779 * Prints out a list, starting at the specified indentation, to
7780 * the specified print writer.
7781 * @param out the print writer to print to
7782 * @param indent the number of spaces to indent
7783 * @see java.io.PrintStream#println(java.lang.Object)
7784 * @since JDK1.1
7785 */
7786 public void list(PrintWriter out, int indent) {
7787 for (int i = 0 ; i < indent ; i++) {
7788 out.print(" ");
7789 }
7790 out.println(this);
7791 }
7792
7793 /*
7794 * Fetches the native container somewhere higher up in the component
7795 * tree that contains this component.
7796 */
7797 Container getNativeContainer() {
7798 Container p = parent;
7799 while (p != null && p.peer instanceof LightweightPeer) {
7800 p = p.getParent();
7801 }
7802 return p;
7803 }
7804
7805 /**
7806 * Adds a PropertyChangeListener to the listener list. The listener is
7807 * registered for all bound properties of this class, including the
7808 * following:
7809 * <ul>
7810 * <li>this Component's font ("font")</li>
7811 * <li>this Component's background color ("background")</li>
7812 * <li>this Component's foreground color ("foreground")</li>
7813 * <li>this Component's focusability ("focusable")</li>
7814 * <li>this Component's focus traversal keys enabled state
7815 * ("focusTraversalKeysEnabled")</li>
7816 * <li>this Component's Set of FORWARD_TRAVERSAL_KEYS
7817 * ("forwardFocusTraversalKeys")</li>
7818 * <li>this Component's Set of BACKWARD_TRAVERSAL_KEYS
7819 * ("backwardFocusTraversalKeys")</li>
7820 * <li>this Component's Set of UP_CYCLE_TRAVERSAL_KEYS
7821 * ("upCycleFocusTraversalKeys")</li>
7822 * <li>this Component's preferred size ("preferredSize")</li>
7823 * <li>this Component's minimum size ("minimumSize")</li>
7824 * <li>this Component's maximum size ("maximumSize")</li>
7825 * <li>this Component's name ("name")</li>
7826 * </ul>
7827 * Note that if this <code>Component</code> is inheriting a bound property, then no
7828 * event will be fired in response to a change in the inherited property.
7829 * <p>
7830 * If <code>listener</code> is <code>null</code>,
7831 * no exception is thrown and no action is performed.
7832 *
7833 * @param listener the property change listener to be added
7834 *
7835 * @see #removePropertyChangeListener
7836 * @see #getPropertyChangeListeners
7837 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
7838 */
7839 public synchronized void addPropertyChangeListener(
7840 PropertyChangeListener listener) {
7841 if (listener == null) {
7842 return;
7843 }
7844 if (changeSupport == null) {
7845 changeSupport = new PropertyChangeSupport(this);
7846 }
7847 changeSupport.addPropertyChangeListener(listener);
7848 }
7849
7850 /**
7851 * Removes a PropertyChangeListener from the listener list. This method
7852 * should be used to remove PropertyChangeListeners that were registered
7853 * for all bound properties of this class.
7854 * <p>
7855 * If listener is null, no exception is thrown and no action is performed.
7856 *
7857 * @param listener the PropertyChangeListener to be removed
7858 *
7859 * @see #addPropertyChangeListener
7860 * @see #getPropertyChangeListeners
7861 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
7862 */
7863 public synchronized void removePropertyChangeListener(
7864 PropertyChangeListener listener) {
7865 if (listener == null || changeSupport == null) {
7866 return;
7867 }
7868 changeSupport.removePropertyChangeListener(listener);
7869 }
7870
7871 /**
7872 * Returns an array of all the property change listeners
7873 * registered on this component.
7874 *
7875 * @return all of this component's <code>PropertyChangeListener</code>s
7876 * or an empty array if no property change
7877 * listeners are currently registered
7878 *
7879 * @see #addPropertyChangeListener
7880 * @see #removePropertyChangeListener
7881 * @see #getPropertyChangeListeners(java.lang.String)
7882 * @see java.beans.PropertyChangeSupport#getPropertyChangeListeners
7883 * @since 1.4
7884 */
7885 public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
7886 if (changeSupport == null) {
7887 return new PropertyChangeListener[0];
7888 }
7889 return changeSupport.getPropertyChangeListeners();
7890 }
7891
7892 /**
7893 * Adds a PropertyChangeListener to the listener list for a specific
7894 * property. The specified property may be user-defined, or one of the
7895 * following:
7896 * <ul>
7897 * <li>this Component's font ("font")</li>
7898 * <li>this Component's background color ("background")</li>
7899 * <li>this Component's foreground color ("foreground")</li>
7900 * <li>this Component's focusability ("focusable")</li>
7901 * <li>this Component's focus traversal keys enabled state
7902 * ("focusTraversalKeysEnabled")</li>
7903 * <li>this Component's Set of FORWARD_TRAVERSAL_KEYS
7904 * ("forwardFocusTraversalKeys")</li>
7905 * <li>this Component's Set of BACKWARD_TRAVERSAL_KEYS
7906 * ("backwardFocusTraversalKeys")</li>
7907 * <li>this Component's Set of UP_CYCLE_TRAVERSAL_KEYS
7908 * ("upCycleFocusTraversalKeys")</li>
7909 * </ul>
7910 * Note that if this <code>Component</code> is inheriting a bound property, then no
7911 * event will be fired in response to a change in the inherited property.
7912 * <p>
7913 * If <code>propertyName</code> or <code>listener</code> is <code>null</code>,
7914 * no exception is thrown and no action is taken.
7915 *
7916 * @param propertyName one of the property names listed above
7917 * @param listener the property change listener to be added
7918 *
7919 * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
7920 * @see #getPropertyChangeListeners(java.lang.String)
7921 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
7922 */
7923 public synchronized void addPropertyChangeListener(
7924 String propertyName,
7925 PropertyChangeListener listener) {
7926 if (listener == null) {
7927 return;
7928 }
7929 if (changeSupport == null) {
7930 changeSupport = new PropertyChangeSupport(this);
7931 }
7932 changeSupport.addPropertyChangeListener(propertyName, listener);
7933 }
7934
7935 /**
7936 * Removes a <code>PropertyChangeListener</code> from the listener
7937 * list for a specific property. This method should be used to remove
7938 * <code>PropertyChangeListener</code>s
7939 * that were registered for a specific bound property.
7940 * <p>
7941 * If <code>propertyName</code> or <code>listener</code> is <code>null</code>,
7942 * no exception is thrown and no action is taken.
7943 *
7944 * @param propertyName a valid property name
7945 * @param listener the PropertyChangeListener to be removed
7946 *
7947 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
7948 * @see #getPropertyChangeListeners(java.lang.String)
7949 * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
7950 */
7951 public synchronized void removePropertyChangeListener(
7952 String propertyName,
7953 PropertyChangeListener listener) {
7954 if (listener == null || changeSupport == null) {
7955 return;
7956 }
7957 changeSupport.removePropertyChangeListener(propertyName, listener);
7958 }
7959
7960 /**
7961 * Returns an array of all the listeners which have been associated
7962 * with the named property.
7963 *
7964 * @return all of the <code>PropertyChangeListener</code>s associated with
7965 * the named property; if no such listeners have been added or
7966 * if <code>propertyName</code> is <code>null</code>, an empty
7967 * array is returned
7968 *
7969 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
7970 * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
7971 * @see #getPropertyChangeListeners
7972 * @since 1.4
7973 */
7974 public synchronized PropertyChangeListener[] getPropertyChangeListeners(
7975 String propertyName) {
7976 if (changeSupport == null) {
7977 return new PropertyChangeListener[0];
7978 }
7979 return changeSupport.getPropertyChangeListeners(propertyName);
7980 }
7981
7982 /**
7983 * Support for reporting bound property changes for Object properties.
7984 * This method can be called when a bound property has changed and it will
7985 * send the appropriate PropertyChangeEvent to any registered
7986 * PropertyChangeListeners.
7987 *
7988 * @param propertyName the property whose value has changed
7989 * @param oldValue the property's previous value
7990 * @param newValue the property's new value
7991 */
7992 protected void firePropertyChange(String propertyName,
7993 Object oldValue, Object newValue) {
7994 PropertyChangeSupport changeSupport = this.changeSupport;
7995 if (changeSupport == null ||
7996 (oldValue != null && newValue != null && oldValue.equals(newValue))) {
7997 return;
7998 }
7999 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
8000 }
8001
8002 /**
8003 * Support for reporting bound property changes for boolean properties.
8004 * This method can be called when a bound property has changed and it will
8005 * send the appropriate PropertyChangeEvent to any registered
8006 * PropertyChangeListeners.
8007 *
8008 * @param propertyName the property whose value has changed
8009 * @param oldValue the property's previous value
8010 * @param newValue the property's new value
8011 * @since 1.4
8012 */
8013 protected void firePropertyChange(String propertyName,
8014 boolean oldValue, boolean newValue) {
8015 PropertyChangeSupport changeSupport = this.changeSupport;
8016 if (changeSupport == null || oldValue == newValue) {
8017 return;
8018 }
8019 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
8020 }
8021
8022 /**
8023 * Support for reporting bound property changes for integer properties.
8024 * This method can be called when a bound property has changed and it will
8025 * send the appropriate PropertyChangeEvent to any registered
8026 * PropertyChangeListeners.
8027 *
8028 * @param propertyName the property whose value has changed
8029 * @param oldValue the property's previous value
8030 * @param newValue the property's new value
8031 * @since 1.4
8032 */
8033 protected void firePropertyChange(String propertyName,
8034 int oldValue, int newValue) {
8035 PropertyChangeSupport changeSupport = this.changeSupport;
8036 if (changeSupport == null || oldValue == newValue) {
8037 return;
8038 }
8039 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
8040 }
8041
8042 /**
8043 * Reports a bound property change.
8044 *
8045 * @param propertyName the programmatic name of the property
8046 * that was changed
8047 * @param oldValue the old value of the property (as a byte)
8048 * @param newValue the new value of the property (as a byte)
8049 * @see #firePropertyChange(java.lang.String, java.lang.Object,
8050 * java.lang.Object)
8051 * @since 1.5
8052 */
8053 public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {
8054 if (changeSupport == null || oldValue == newValue) {
8055 return;
8056 }
8057 firePropertyChange(propertyName, Byte.valueOf(oldValue), Byte.valueOf(newValue));
8058 }
8059
8060 /**
8061 * Reports a bound property change.
8062 *
8063 * @param propertyName the programmatic name of the property
8064 * that was changed
8065 * @param oldValue the old value of the property (as a char)
8066 * @param newValue the new value of the property (as a char)
8067 * @see #firePropertyChange(java.lang.String, java.lang.Object,
8068 * java.lang.Object)
8069 * @since 1.5
8070 */
8071 public void firePropertyChange(String propertyName, char oldValue, char newValue) {
8072 if (changeSupport == null || oldValue == newValue) {
8073 return;
8074 }
8075 firePropertyChange(propertyName, new Character(oldValue), new Character(newValue));
8076 }
8077
8078 /**
8079 * Reports a bound property change.
8080 *
8081 * @param propertyName the programmatic name of the property
8082 * that was changed
8083 * @param oldValue the old value of the property (as a short)
8084 * @param newValue the old value of the property (as a short)
8085 * @see #firePropertyChange(java.lang.String, java.lang.Object,
8086 * java.lang.Object)
8087 * @since 1.5
8088 */
8089 public void firePropertyChange(String propertyName, short oldValue, short newValue) {
8090 if (changeSupport == null || oldValue == newValue) {
8091 return;
8092 }
8093 firePropertyChange(propertyName, Short.valueOf(oldValue), Short.valueOf(newValue));
8094 }
8095
8096
8097 /**
8098 * Reports a bound property change.
8099 *
8100 * @param propertyName the programmatic name of the property
8101 * that was changed
8102 * @param oldValue the old value of the property (as a long)
8103 * @param newValue the new value of the property (as a long)
8104 * @see #firePropertyChange(java.lang.String, java.lang.Object,
8105 * java.lang.Object)
8106 * @since 1.5
8107 */
8108 public void firePropertyChange(String propertyName, long oldValue, long newValue) {
8109 if (changeSupport == null || oldValue == newValue) {
8110 return;
8111 }
8112 firePropertyChange(propertyName, Long.valueOf(oldValue), Long.valueOf(newValue));
8113 }
8114
8115 /**
8116 * Reports a bound property change.
8117 *
8118 * @param propertyName the programmatic name of the property
8119 * that was changed
8120 * @param oldValue the old value of the property (as a float)
8121 * @param newValue the new value of the property (as a float)
8122 * @see #firePropertyChange(java.lang.String, java.lang.Object,
8123 * java.lang.Object)
8124 * @since 1.5
8125 */
8126 public void firePropertyChange(String propertyName, float oldValue, float newValue) {
8127 if (changeSupport == null || oldValue == newValue) {
8128 return;
8129 }
8130 firePropertyChange(propertyName, Float.valueOf(oldValue), Float.valueOf(newValue));
8131 }
8132
8133 /**
8134 * Reports a bound property change.
8135 *
8136 * @param propertyName the programmatic name of the property
8137 * that was changed
8138 * @param oldValue the old value of the property (as a double)
8139 * @param newValue the new value of the property (as a double)
8140 * @see #firePropertyChange(java.lang.String, java.lang.Object,
8141 * java.lang.Object)
8142 * @since 1.5
8143 */
8144 public void firePropertyChange(String propertyName, double oldValue, double newValue) {
8145 if (changeSupport == null || oldValue == newValue) {
8146 return;
8147 }
8148 firePropertyChange(propertyName, Double.valueOf(oldValue), Double.valueOf(newValue));
8149 }
8150
8151
8152 // Serialization support.
8153
8154 /**
8155 * Component Serialized Data Version.
8156 *
8157 * @serial
8158 */
8159 private int componentSerializedDataVersion = 4;
8160
8161 /**
8162 * This hack is for Swing serialization. It will invoke
8163 * the Swing package private method <code>compWriteObjectNotify</code>.
8164 */
8165 private void doSwingSerialization() {
8166 Package swingPackage = Package.getPackage("javax.swing");
8167 // For Swing serialization to correctly work Swing needs to
8168 // be notified before Component does it's serialization. This
8169 // hack accomodates this.
8170 //
8171 // Swing classes MUST be loaded by the bootstrap class loader,
8172 // otherwise we don't consider them.
8173 for (Class klass = Component.this.getClass(); klass != null;
8174 klass = klass.getSuperclass()) {
8175 if (klass.getPackage() == swingPackage &&
8176 klass.getClassLoader() == null) {
8177 final Class swingClass = klass;
8178 // Find the first override of the compWriteObjectNotify method
8179 Method[] methods = (Method[])AccessController.doPrivileged(
8180 new PrivilegedAction() {
8181 public Object run() {
8182 return swingClass.getDeclaredMethods();
8183 }
8184 });
8185 for (int counter = methods.length - 1; counter >= 0;
8186 counter--) {
8187 final Method method = methods[counter];
8188 if (method.getName().equals("compWriteObjectNotify")){
8189 // We found it, use doPrivileged to make it accessible
8190 // to use.
8191 AccessController.doPrivileged(new PrivilegedAction() {
8192 public Object run() {
8193 method.setAccessible(true);
8194 return null;
8195 }
8196 });
8197 // Invoke the method
8198 try {
8199 method.invoke(this, (Object[]) null);
8200 } catch (IllegalAccessException iae) {
8201 } catch (InvocationTargetException ite) {
8202 }
8203 // We're done, bail.
8204 return;
8205 }
8206 }
8207 }
8208 }
8209 }
8210
8211 /**
8212 * Writes default serializable fields to stream. Writes
8213 * a variety of serializable listeners as optional data.
8214 * The non-serializable listeners are detected and
8215 * no attempt is made to serialize them.
8216 *
8217 * @param s the <code>ObjectOutputStream</code> to write
8218 * @serialData <code>null</code> terminated sequence of
8219 * 0 or more pairs; the pair consists of a <code>String</code>
8220 * and an <code>Object</code>; the <code>String</code> indicates
8221 * the type of object and is one of the following (as of 1.4):
8222 * <code>componentListenerK</code> indicating an
8223 * <code>ComponentListener</code> object;
8224 * <code>focusListenerK</code> indicating an
8225 * <code>FocusListener</code> object;
8226 * <code>keyListenerK</code> indicating an
8227 * <code>KeyListener</code> object;
8228 * <code>mouseListenerK</code> indicating an
8229 * <code>MouseListener</code> object;
8230 * <code>mouseMotionListenerK</code> indicating an
8231 * <code>MouseMotionListener</code> object;
8232 * <code>inputMethodListenerK</code> indicating an
8233 * <code>InputMethodListener</code> object;
8234 * <code>hierarchyListenerK</code> indicating an
8235 * <code>HierarchyListener</code> object;
8236 * <code>hierarchyBoundsListenerK</code> indicating an
8237 * <code>HierarchyBoundsListener</code> object;
8238 * <code>mouseWheelListenerK</code> indicating an
8239 * <code>MouseWheelListener</code> object
8240 * @serialData an optional <code>ComponentOrientation</code>
8241 * (after <code>inputMethodListener</code>, as of 1.2)
8242 *
8243 * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
8244 * @see #componentListenerK
8245 * @see #focusListenerK
8246 * @see #keyListenerK
8247 * @see #mouseListenerK
8248 * @see #mouseMotionListenerK
8249 * @see #inputMethodListenerK
8250 * @see #hierarchyListenerK
8251 * @see #hierarchyBoundsListenerK
8252 * @see #mouseWheelListenerK
8253 * @see #readObject(ObjectInputStream)
8254 */
8255 private void writeObject(ObjectOutputStream s)
8256 throws IOException
8257 {
8258 doSwingSerialization();
8259
8260 s.defaultWriteObject();
8261
8262 AWTEventMulticaster.save(s, componentListenerK, componentListener);
8263 AWTEventMulticaster.save(s, focusListenerK, focusListener);
8264 AWTEventMulticaster.save(s, keyListenerK, keyListener);
8265 AWTEventMulticaster.save(s, mouseListenerK, mouseListener);
8266 AWTEventMulticaster.save(s, mouseMotionListenerK, mouseMotionListener);
8267 AWTEventMulticaster.save(s, inputMethodListenerK, inputMethodListener);
8268
8269 s.writeObject(null);
8270 s.writeObject(componentOrientation);
8271
8272 AWTEventMulticaster.save(s, hierarchyListenerK, hierarchyListener);
8273 AWTEventMulticaster.save(s, hierarchyBoundsListenerK,
8274 hierarchyBoundsListener);
8275 s.writeObject(null);
8276
8277 AWTEventMulticaster.save(s, mouseWheelListenerK, mouseWheelListener);
8278 s.writeObject(null);
8279
8280 }
8281
8282 /**
8283 * Reads the <code>ObjectInputStream</code> and if it isn't
8284 * <code>null</code> adds a listener to receive a variety
8285 * of events fired by the component.
8286 * Unrecognized keys or values will be ignored.
8287 *
8288 * @param s the <code>ObjectInputStream</code> to read
8289 * @see #writeObject(ObjectOutputStream)
8290 */
8291 private void readObject(ObjectInputStream s)
8292 throws ClassNotFoundException, IOException
8293 {
8294 s.defaultReadObject();
8295
8296 appContext = AppContext.getAppContext();
8297 coalescingEnabled = checkCoalescing();
8298 if (componentSerializedDataVersion < 4) {
8299 // These fields are non-transient and rely on default
8300 // serialization. However, the default values are insufficient,
8301 // so we need to set them explicitly for object data streams prior
8302 // to 1.4.
8303 focusable = true;
8304 isFocusTraversableOverridden = FOCUS_TRAVERSABLE_UNKNOWN;
8305 initializeFocusTraversalKeys();
8306 focusTraversalKeysEnabled = true;
8307 }
8308
8309 Object keyOrNull;
8310 while(null != (keyOrNull = s.readObject())) {
8311 String key = ((String)keyOrNull).intern();
8312
8313 if (componentListenerK == key)
8314 addComponentListener((ComponentListener)(s.readObject()));
8315
8316 else if (focusListenerK == key)
8317 addFocusListener((FocusListener)(s.readObject()));
8318
8319 else if (keyListenerK == key)
8320 addKeyListener((KeyListener)(s.readObject()));
8321
8322 else if (mouseListenerK == key)
8323 addMouseListener((MouseListener)(s.readObject()));
8324
8325 else if (mouseMotionListenerK == key)
8326 addMouseMotionListener((MouseMotionListener)(s.readObject()));
8327
8328 else if (inputMethodListenerK == key)
8329 addInputMethodListener((InputMethodListener)(s.readObject()));
8330
8331 else // skip value for unrecognized key
8332 s.readObject();
8333
8334 }
8335
8336 // Read the component's orientation if it's present
8337 Object orient = null;
8338
8339 try {
8340 orient = s.readObject();
8341 } catch (java.io.OptionalDataException e) {
8342 // JDK 1.1 instances will not have this optional data.
8343 // e.eof will be true to indicate that there is no more
8344 // data available for this object.
8345 // If e.eof is not true, throw the exception as it
8346 // might have been caused by reasons unrelated to
8347 // componentOrientation.
8348
8349 if (!e.eof) {
8350 throw (e);
8351 }
8352 }
8353
8354 if (orient != null) {
8355 componentOrientation = (ComponentOrientation)orient;
8356 } else {
8357 componentOrientation = ComponentOrientation.UNKNOWN;
8358 }
8359
8360 try {
8361 while(null != (keyOrNull = s.readObject())) {
8362 String key = ((String)keyOrNull).intern();
8363
8364 if (hierarchyListenerK == key) {
8365 addHierarchyListener((HierarchyListener)(s.readObject()));
8366 }
8367 else if (hierarchyBoundsListenerK == key) {
8368 addHierarchyBoundsListener((HierarchyBoundsListener)
8369 (s.readObject()));
8370 }
8371 else {
8372 // skip value for unrecognized key
8373 s.readObject();
8374 }
8375 }
8376 } catch (java.io.OptionalDataException e) {
8377 // JDK 1.1/1.2 instances will not have this optional data.
8378 // e.eof will be true to indicate that there is no more
8379 // data available for this object.
8380 // If e.eof is not true, throw the exception as it
8381 // might have been caused by reasons unrelated to
8382 // hierarchy and hierarchyBounds listeners.
8383
8384 if (!e.eof) {
8385 throw (e);
8386 }
8387 }
8388
8389 try {
8390 while (null != (keyOrNull = s.readObject())) {
8391 String key = ((String)keyOrNull).intern();
8392
8393 if (mouseWheelListenerK == key) {
8394 addMouseWheelListener((MouseWheelListener)(s.readObject()));
8395 }
8396 else {
8397 // skip value for unrecognized key
8398 s.readObject();
8399 }
8400 }
8401 } catch (java.io.OptionalDataException e) {
8402 // pre-1.3 instances will not have this optional data.
8403 // e.eof will be true to indicate that there is no more
8404 // data available for this object.
8405 // If e.eof is not true, throw the exception as it
8406 // might have been caused by reasons unrelated to
8407 // mouse wheel listeners
8408
8409 if (!e.eof) {
8410 throw (e);
8411 }
8412 }
8413
8414 if (popups != null) {
8415 int npopups = popups.size();
8416 for (int i = 0 ; i < npopups ; i++) {
8417 PopupMenu popup = (PopupMenu)popups.elementAt(i);
8418 popup.parent = this;
8419 }
8420 }
8421 }
8422
8423 /**
8424 * Sets the language-sensitive orientation that is to be used to order
8425 * the elements or text within this component. Language-sensitive
8426 * <code>LayoutManager</code> and <code>Component</code>
8427 * subclasses will use this property to
8428 * determine how to lay out and draw components.
8429 * <p>
8430 * At construction time, a component's orientation is set to
8431 * <code>ComponentOrientation.UNKNOWN</code>,
8432 * indicating that it has not been specified
8433 * explicitly. The UNKNOWN orientation behaves the same as
8434 * <code>ComponentOrientation.LEFT_TO_RIGHT</code>.
8435 * <p>
8436 * To set the orientation of a single component, use this method.
8437 * To set the orientation of an entire component
8438 * hierarchy, use
8439 * {@link #applyComponentOrientation applyComponentOrientation}.
8440 *
8441 * @see ComponentOrientation
8442 *
8443 * @author Laura Werner, IBM
8444 * @beaninfo
8445 * bound: true
8446 */
8447 public void setComponentOrientation(ComponentOrientation o) {
8448 ComponentOrientation oldValue = componentOrientation;
8449 componentOrientation = o;
8450
8451 // This is a bound property, so report the change to
8452 // any registered listeners. (Cheap if there are none.)
8453 firePropertyChange("componentOrientation", oldValue, o);
8454
8455 // This could change the preferred size of the Component.
8456 if (valid) {
8457 invalidate();
8458 }
8459 }
8460
8461 /**
8462 * Retrieves the language-sensitive orientation that is to be used to order
8463 * the elements or text within this component. <code>LayoutManager</code>
8464 * and <code>Component</code>
8465 * subclasses that wish to respect orientation should call this method to
8466 * get the component's orientation before performing layout or drawing.
8467 *
8468 * @see ComponentOrientation
8469 *
8470 * @author Laura Werner, IBM
8471 */
8472 public ComponentOrientation getComponentOrientation() {
8473 return componentOrientation;
8474 }
8475
8476 /**
8477 * Sets the <code>ComponentOrientation</code> property of this component
8478 * and all components contained within it.
8479 *
8480 * @param orientation the new component orientation of this component and
8481 * the components contained within it.
8482 * @exception NullPointerException if <code>orientation</code> is null.
8483 * @see #setComponentOrientation
8484 * @see #getComponentOrientation
8485 * @since 1.4
8486 */
8487 public void applyComponentOrientation(ComponentOrientation orientation) {
8488 if (orientation == null) {
8489 throw new NullPointerException();
8490 }
8491 setComponentOrientation(orientation);
8492 }
8493
8494 transient NativeInLightFixer nativeInLightFixer;
8495
8496 /**
8497 * Checks that this component meets the prerequesites to be focus owner:
8498 * - it is enabled, visible, focusable
8499 * - it's parents are all enabled and showing
8500 * - top-level window is focusable
8501 * - if focus cycle root has DefaultFocusTraversalPolicy then it also checks that this policy accepts
8502 * this component as focus owner
8503 * @since 1.5
8504 */
8505 final boolean canBeFocusOwner() {
8506 // - it is enabled, visible, focusable
8507 if (!(isEnabled() && isDisplayable() && isVisible() && isFocusable())) {
8508 return false;
8509 }
8510
8511 // - it's parents are all enabled and showing
8512 synchronized(getTreeLock()) {
8513 if (parent != null) {
8514 return parent.canContainFocusOwner(this);
8515 }
8516 }
8517 return true;
8518 }
8519
8520 /**
8521 * This odd class is to help out a native component that has been
8522 * embedded in a lightweight component. Moving lightweight
8523 * components around and changing their visibility is not seen
8524 * by the native window system. This is a feature for lightweights,
8525 * but a problem for native components that depend upon the
8526 * lightweights. An instance of this class listens to the lightweight
8527 * parents of an associated native component (the outer class).
8528 *
8529 * @author Timothy Prinzing
8530 */
8531 final class NativeInLightFixer implements ComponentListener, ContainerListener {
8532
8533 NativeInLightFixer() {
8534 lightParents = new Vector();
8535 install(parent);
8536 }
8537
8538 void install(Container parent) {
8539 lightParents.clear();
8540 Container p = parent;
8541 boolean isLwParentsVisible = true;
8542 // stash a reference to the components that are being observed so that
8543 // we can reliably remove ourself as a listener later.
8544 for (; p.peer instanceof LightweightPeer; p = p.parent) {
8545
8546 // register listeners and stash a reference
8547 p.addComponentListener(this);
8548 p.addContainerListener(this);
8549 lightParents.addElement(p);
8550 isLwParentsVisible &= p.isVisible();
8551 }
8552 // register with the native host (native parent of associated native)
8553 // to get notified if the top-level lightweight is removed.
8554 nativeHost = p;
8555 p.addContainerListener(this);
8556
8557 // kick start the fixup. Since the event isn't looked at
8558 // we can simulate movement notification.
8559 componentMoved(null);
8560 if (!isLwParentsVisible) {
8561 synchronized (getTreeLock()) {
8562 if (peer != null) {
8563 peer.hide();
8564 }
8565 }
8566 }
8567 }
8568
8569 void uninstall() {
8570 if (nativeHost != null) {
8571 removeReferences();
8572 }
8573 }
8574
8575 // --- ComponentListener -------------------------------------------
8576
8577 /**
8578 * Invoked when one of the lightweight parents has been resized.
8579 * This doesn't change the position of the native child so it
8580 * is ignored.
8581 */
8582 public void componentResized(ComponentEvent e) {
8583 }
8584
8585 /**
8586 * Invoked when one of the lightweight parents has been moved.
8587 * The native peer must be told of the new position which is
8588 * relative to the native container that is hosting the
8589 * lightweight components.
8590 */
8591 public void componentMoved(ComponentEvent e) {
8592 synchronized (getTreeLock()) {
8593 int nativeX = x;
8594 int nativeY = y;
8595 for(Component c = parent; (c != null) &&
8596 (c.peer instanceof LightweightPeer);
8597 c = c.parent) {
8598
8599 nativeX += c.x;
8600 nativeY += c.y;
8601 }
8602 if (peer != null) {
8603 peer.setBounds(nativeX, nativeY, width, height,
8604 ComponentPeer.SET_LOCATION);
8605 }
8606 }
8607 }
8608
8609 /**
8610 * Invoked when a lightweight parent component has been
8611 * shown. The associated native component must also be
8612 * shown if it hasn't had an overriding hide done on it.
8613 */
8614 public void componentShown(ComponentEvent e) {
8615 if (shouldShow()) {
8616 synchronized (getTreeLock()) {
8617 if (peer != null) {
8618 peer.show();
8619 }
8620 }
8621 }
8622 }
8623
8624 /**
8625 * Invoked when one of the lightweight parents become visible.
8626 * Returns true if component and all its lightweight
8627 * parents are visible.
8628 */
8629 private boolean shouldShow() {
8630 boolean isLwParentsVisible = visible;
8631 for (int i = lightParents.size() - 1;
8632 i >= 0 && isLwParentsVisible;
8633 i--)
8634 {
8635 isLwParentsVisible &=
8636 ((Container) lightParents.elementAt(i)).isVisible();
8637 }
8638 return isLwParentsVisible;
8639 }
8640
8641 /**
8642 * Invoked when component has been hidden.
8643 */
8644 public void componentHidden(ComponentEvent e) {
8645 if (visible) {
8646 synchronized (getTreeLock()) {
8647 if (peer != null) {
8648 peer.hide();
8649 }
8650 }
8651 }
8652 }
8653
8654 // --- ContainerListener ------------------------------------
8655
8656 /**
8657 * Invoked when a component has been added to a lightweight
8658 * parent. This doesn't effect the native component.
8659 */
8660 public void componentAdded(ContainerEvent e) {
8661 }
8662
8663 /**
8664 * Invoked when a lightweight parent has been removed.
8665 * This means the services of this listener are no longer
8666 * required and it should remove all references (ie
8667 * registered listeners).
8668 */
8669 public void componentRemoved(ContainerEvent e) {
8670 Component c = e.getChild();
8671 if (c == Component.this) {
8672 removeReferences();
8673 } else {
8674 int n = lightParents.size();
8675 for (int i = 0; i < n; i++) {
8676 Container p = (Container) lightParents.elementAt(i);
8677 if (p == c) {
8678 removeReferences();
8679 break;
8680 }
8681 }
8682 }
8683 }
8684
8685 /**
8686 * Removes references to this object so it can be
8687 * garbage collected.
8688 */
8689 void removeReferences() {
8690 int n = lightParents.size();
8691 for (int i = 0; i < n; i++) {
8692 Container c = (Container) lightParents.elementAt(i);
8693 c.removeComponentListener(this);
8694 c.removeContainerListener(this);
8695 }
8696 nativeHost.removeContainerListener(this);
8697 lightParents.clear();
8698 nativeHost = null;
8699 }
8700
8701 Vector lightParents;
8702 Container nativeHost;
8703 }
8704
8705 /**
8706 * Returns the <code>Window</code> ancestor of the component.
8707 * @return Window ancestor of the component or component by itself if it is Window;
8708 * null, if component is not a part of window hierarchy
8709 */
8710 Window getContainingWindow() {
8711 return getContainingWindow(this);
8712 }
8713 /**
8714 * Returns the <code>Window</code> ancestor of the component <code>comp</code>.
8715 * @return Window ancestor of the component or component by itself if it is Window;
8716 * null, if component is not a part of window hierarchy
8717 */
8718 static Window getContainingWindow(Component comp) {
8719 while (comp != null && !(comp instanceof Window)) {
8720 comp = comp.getParent();
8721 }
8722
8723 return (Window)comp;
8724 }
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736 /**
8737 * Initialize JNI field and method IDs
8738 */
8739 private static native void initIDs();
8740
8741 /*
8742 * --- Accessibility Support ---
8743 *
8744 * Component will contain all of the methods in interface Accessible,
8745 * though it won't actually implement the interface - that will be up
8746 * to the individual objects which extend Component.
8747 */
8748
8749 AccessibleContext accessibleContext = null;
8750
8751 /**
8752 * Gets the <code>AccessibleContext</code> associated
8753 * with this <code>Component</code>.
8754 * The method implemented by this base
8755 * class returns null. Classes that extend <code>Component</code>
8756 * should implement this method to return the
8757 * <code>AccessibleContext</code> associated with the subclass.
8758 *
8759 *
8760 * @return the <code>AccessibleContext</code> of this
8761 * <code>Component</code>
8762 * @since 1.3
8763 */
8764 public AccessibleContext getAccessibleContext() {
8765 return accessibleContext;
8766 }
8767
8768 /**
8769 * Inner class of Component used to provide default support for
8770 * accessibility. This class is not meant to be used directly by
8771 * application developers, but is instead meant only to be
8772 * subclassed by component developers.
8773 * <p>
8774 * The class used to obtain the accessible role for this object.
8775 * @since 1.3
8776 */
8777 protected abstract class AccessibleAWTComponent extends AccessibleContext
8778 implements Serializable, AccessibleComponent {
8779
8780 private static final long serialVersionUID = 642321655757800191L;
8781
8782 /**
8783 * Though the class is abstract, this should be called by
8784 * all sub-classes.
8785 */
8786 protected AccessibleAWTComponent() {
8787 }
8788
8789 protected ComponentListener accessibleAWTComponentHandler = null;
8790 protected FocusListener accessibleAWTFocusHandler = null;
8791
8792 /**
8793 * Fire PropertyChange listener, if one is registered,
8794 * when shown/hidden..
8795 * @since 1.3
8796 */
8797 protected class AccessibleAWTComponentHandler implements ComponentListener {
8798 public void componentHidden(ComponentEvent e) {
8799 if (accessibleContext != null) {
8800 accessibleContext.firePropertyChange(
8801 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
8802 AccessibleState.VISIBLE, null);
8803 }
8804 }
8805
8806 public void componentShown(ComponentEvent e) {
8807 if (accessibleContext != null) {
8808 accessibleContext.firePropertyChange(
8809 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
8810 null, AccessibleState.VISIBLE);
8811 }
8812 }
8813
8814 public void componentMoved(ComponentEvent e) {
8815 }
8816
8817 public void componentResized(ComponentEvent e) {
8818 }
8819 } // inner class AccessibleAWTComponentHandler
8820
8821
8822 /**
8823 * Fire PropertyChange listener, if one is registered,
8824 * when focus events happen
8825 * @since 1.3
8826 */
8827 protected class AccessibleAWTFocusHandler implements FocusListener {
8828 public void focusGained(FocusEvent event) {
8829 if (accessibleContext != null) {
8830 accessibleContext.firePropertyChange(
8831 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
8832 null, AccessibleState.FOCUSED);
8833 }
8834 }
8835 public void focusLost(FocusEvent event) {
8836 if (accessibleContext != null) {
8837 accessibleContext.firePropertyChange(
8838 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
8839 AccessibleState.FOCUSED, null);
8840 }
8841 }
8842 } // inner class AccessibleAWTFocusHandler
8843
8844
8845 /**
8846 * Adds a <code>PropertyChangeListener</code> to the listener list.
8847 *
8848 * @param listener the property change listener to be added
8849 */
8850 public void addPropertyChangeListener(PropertyChangeListener listener) {
8851 if (accessibleAWTComponentHandler == null) {
8852 accessibleAWTComponentHandler = new AccessibleAWTComponentHandler();
8853 Component.this.addComponentListener(accessibleAWTComponentHandler);
8854 }
8855 if (accessibleAWTFocusHandler == null) {
8856 accessibleAWTFocusHandler = new AccessibleAWTFocusHandler();
8857 Component.this.addFocusListener(accessibleAWTFocusHandler);
8858 }
8859 super.addPropertyChangeListener(listener);
8860 }
8861
8862 /**
8863 * Remove a PropertyChangeListener from the listener list.
8864 * This removes a PropertyChangeListener that was registered
8865 * for all properties.
8866 *
8867 * @param listener The PropertyChangeListener to be removed
8868 */
8869 public void removePropertyChangeListener(PropertyChangeListener listener) {
8870 if (accessibleAWTComponentHandler != null) {
8871 Component.this.removeComponentListener(accessibleAWTComponentHandler);
8872 accessibleAWTComponentHandler = null;
8873 }
8874 if (accessibleAWTFocusHandler != null) {
8875 Component.this.removeFocusListener(accessibleAWTFocusHandler);
8876 accessibleAWTFocusHandler = null;
8877 }
8878 super.removePropertyChangeListener(listener);
8879 }
8880
8881 // AccessibleContext methods
8882 //
8883 /**
8884 * Gets the accessible name of this object. This should almost never
8885 * return <code>java.awt.Component.getName()</code>,
8886 * as that generally isn't a localized name,
8887 * and doesn't have meaning for the user. If the
8888 * object is fundamentally a text object (e.g. a menu item), the
8889 * accessible name should be the text of the object (e.g. "save").
8890 * If the object has a tooltip, the tooltip text may also be an
8891 * appropriate String to return.
8892 *
8893 * @return the localized name of the object -- can be
8894 * <code>null</code> if this
8895 * object does not have a name
8896 * @see javax.accessibility.AccessibleContext#setAccessibleName
8897 */
8898 public String getAccessibleName() {
8899 return accessibleName;
8900 }
8901
8902 /**
8903 * Gets the accessible description of this object. This should be
8904 * a concise, localized description of what this object is - what
8905 * is its meaning to the user. If the object has a tooltip, the
8906 * tooltip text may be an appropriate string to return, assuming
8907 * it contains a concise description of the object (instead of just
8908 * the name of the object - e.g. a "Save" icon on a toolbar that
8909 * had "save" as the tooltip text shouldn't return the tooltip
8910 * text as the description, but something like "Saves the current
8911 * text document" instead).
8912 *
8913 * @return the localized description of the object -- can be
8914 * <code>null</code> if this object does not have a description
8915 * @see javax.accessibility.AccessibleContext#setAccessibleDescription
8916 */
8917 public String getAccessibleDescription() {
8918 return accessibleDescription;
8919 }
8920
8921 /**
8922 * Gets the role of this object.
8923 *
8924 * @return an instance of <code>AccessibleRole</code>
8925 * describing the role of the object
8926 * @see javax.accessibility.AccessibleRole
8927 */
8928 public AccessibleRole getAccessibleRole() {
8929 return AccessibleRole.AWT_COMPONENT;
8930 }
8931
8932 /**
8933 * Gets the state of this object.
8934 *
8935 * @return an instance of <code>AccessibleStateSet</code>
8936 * containing the current state set of the object
8937 * @see javax.accessibility.AccessibleState
8938 */
8939 public AccessibleStateSet getAccessibleStateSet() {
8940 return Component.this.getAccessibleStateSet();
8941 }
8942
8943 /**
8944 * Gets the <code>Accessible</code> parent of this object.
8945 * If the parent of this object implements <code>Accessible</code>,
8946 * this method should simply return <code>getParent</code>.
8947 *
8948 * @return the <code>Accessible</code> parent of this
8949 * object -- can be <code>null</code> if this
8950 * object does not have an <code>Accessible</code> parent
8951 */
8952 public Accessible getAccessibleParent() {
8953 if (accessibleParent != null) {
8954 return accessibleParent;
8955 } else {
8956 Container parent = getParent();
8957 if (parent instanceof Accessible) {
8958 return (Accessible) parent;
8959 }
8960 }
8961 return null;
8962 }
8963
8964 /**
8965 * Gets the index of this object in its accessible parent.
8966 *
8967 * @return the index of this object in its parent; or -1 if this
8968 * object does not have an accessible parent
8969 * @see #getAccessibleParent
8970 */
8971 public int getAccessibleIndexInParent() {
8972 return Component.this.getAccessibleIndexInParent();
8973 }
8974
8975 /**
8976 * Returns the number of accessible children in the object. If all
8977 * of the children of this object implement <code>Accessible</code>,
8978 * then this method should return the number of children of this object.
8979 *
8980 * @return the number of accessible children in the object
8981 */
8982 public int getAccessibleChildrenCount() {
8983 return 0; // Components don't have children
8984 }
8985
8986 /**
8987 * Returns the nth <code>Accessible</code> child of the object.
8988 *
8989 * @param i zero-based index of child
8990 * @return the nth <code>Accessible</code> child of the object
8991 */
8992 public Accessible getAccessibleChild(int i) {
8993 return null; // Components don't have children
8994 }
8995
8996 /**
8997 * Returns the locale of this object.
8998 *
8999 * @return the locale of this object
9000 */
9001 public Locale getLocale() {
9002 return Component.this.getLocale();
9003 }
9004
9005 /**
9006 * Gets the <code>AccessibleComponent</code> associated
9007 * with this object if one exists.
9008 * Otherwise return <code>null</code>.
9009 *
9010 * @return the component
9011 */
9012 public AccessibleComponent getAccessibleComponent() {
9013 return this;
9014 }
9015
9016
9017 // AccessibleComponent methods
9018 //
9019 /**
9020 * Gets the background color of this object.
9021 *
9022 * @return the background color, if supported, of the object;
9023 * otherwise, <code>null</code>
9024 */
9025 public Color getBackground() {
9026 return Component.this.getBackground();
9027 }
9028
9029 /**
9030 * Sets the background color of this object.
9031 * (For transparency, see <code>isOpaque</code>.)
9032 *
9033 * @param c the new <code>Color</code> for the background
9034 * @see Component#isOpaque
9035 */
9036 public void setBackground(Color c) {
9037 Component.this.setBackground(c);
9038 }
9039
9040 /**
9041 * Gets the foreground color of this object.
9042 *
9043 * @return the foreground color, if supported, of the object;
9044 * otherwise, <code>null</code>
9045 */
9046 public Color getForeground() {
9047 return Component.this.getForeground();
9048 }
9049
9050 /**
9051 * Sets the foreground color of this object.
9052 *
9053 * @param c the new <code>Color</code> for the foreground
9054 */
9055 public void setForeground(Color c) {
9056 Component.this.setForeground(c);
9057 }
9058
9059 /**
9060 * Gets the <code>Cursor</code> of this object.
9061 *
9062 * @return the <code>Cursor</code>, if supported,
9063 * of the object; otherwise, <code>null</code>
9064 */
9065 public Cursor getCursor() {
9066 return Component.this.getCursor();
9067 }
9068
9069 /**
9070 * Sets the <code>Cursor</code> of this object.
9071 * <p>
9072 * The method may have no visual effect if the Java platform
9073 * implementation and/or the native system do not support
9074 * changing the mouse cursor shape.
9075 * @param cursor the new <code>Cursor</code> for the object
9076 */
9077 public void setCursor(Cursor cursor) {
9078 Component.this.setCursor(cursor);
9079 }
9080
9081 /**
9082 * Gets the <code>Font</code> of this object.
9083 *
9084 * @return the <code>Font</code>, if supported,
9085 * for the object; otherwise, <code>null</code>
9086 */
9087 public Font getFont() {
9088 return Component.this.getFont();
9089 }
9090
9091 /**
9092 * Sets the <code>Font</code> of this object.
9093 *
9094 * @param f the new <code>Font</code> for the object
9095 */
9096 public void setFont(Font f) {
9097 Component.this.setFont(f);
9098 }
9099
9100 /**
9101 * Gets the <code>FontMetrics</code> of this object.
9102 *
9103 * @param f the <code>Font</code>
9104 * @return the <code>FontMetrics</code>, if supported,
9105 * the object; otherwise, <code>null</code>
9106 * @see #getFont
9107 */
9108 public FontMetrics getFontMetrics(Font f) {
9109 if (f == null) {
9110 return null;
9111 } else {
9112 return Component.this.getFontMetrics(f);
9113 }
9114 }
9115
9116 /**
9117 * Determines if the object is enabled.
9118 *
9119 * @return true if object is enabled; otherwise, false
9120 */
9121 public boolean isEnabled() {
9122 return Component.this.isEnabled();
9123 }
9124
9125 /**
9126 * Sets the enabled state of the object.
9127 *
9128 * @param b if true, enables this object; otherwise, disables it
9129 */
9130 public void setEnabled(boolean b) {
9131 boolean old = Component.this.isEnabled();
9132 Component.this.setEnabled(b);
9133 if (b != old) {
9134 if (accessibleContext != null) {
9135 if (b) {
9136 accessibleContext.firePropertyChange(
9137 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
9138 null, AccessibleState.ENABLED);
9139 } else {
9140 accessibleContext.firePropertyChange(
9141 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
9142 AccessibleState.ENABLED, null);
9143 }
9144 }
9145 }
9146 }
9147
9148 /**
9149 * Determines if the object is visible. Note: this means that the
9150 * object intends to be visible; however, it may not in fact be
9151 * showing on the screen because one of the objects that this object
9152 * is contained by is not visible. To determine if an object is
9153 * showing on the screen, use <code>isShowing</code>.
9154 *
9155 * @return true if object is visible; otherwise, false
9156 */
9157 public boolean isVisible() {
9158 return Component.this.isVisible();
9159 }
9160
9161 /**
9162 * Sets the visible state of the object.
9163 *
9164 * @param b if true, shows this object; otherwise, hides it
9165 */
9166 public void setVisible(boolean b) {
9167 boolean old = Component.this.isVisible();
9168 Component.this.setVisible(b);
9169 if (b != old) {
9170 if (accessibleContext != null) {
9171 if (b) {
9172 accessibleContext.firePropertyChange(
9173 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
9174 null, AccessibleState.VISIBLE);
9175 } else {
9176 accessibleContext.firePropertyChange(
9177 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
9178 AccessibleState.VISIBLE, null);
9179 }
9180 }
9181 }
9182 }
9183
9184 /**
9185 * Determines if the object is showing. This is determined by checking
9186 * the visibility of the object and ancestors of the object. Note:
9187 * this will return true even if the object is obscured by another
9188 * (for example, it happens to be underneath a menu that was pulled
9189 * down).
9190 *
9191 * @return true if object is showing; otherwise, false
9192 */
9193 public boolean isShowing() {
9194 return Component.this.isShowing();
9195 }
9196
9197 /**
9198 * Checks whether the specified point is within this object's bounds,
9199 * where the point's x and y coordinates are defined to be relative to
9200 * the coordinate system of the object.
9201 *
9202 * @param p the <code>Point</code> relative to the
9203 * coordinate system of the object
9204 * @return true if object contains <code>Point</code>; otherwise false
9205 */
9206 public boolean contains(Point p) {
9207 return Component.this.contains(p);
9208 }
9209
9210 /**
9211 * Returns the location of the object on the screen.
9212 *
9213 * @return location of object on screen -- can be
9214 * <code>null</code> if this object is not on the screen
9215 */
9216 public Point getLocationOnScreen() {
9217 synchronized (Component.this.getTreeLock()) {
9218 if (Component.this.isShowing()) {
9219 return Component.this.getLocationOnScreen();
9220 } else {
9221 return null;
9222 }
9223 }
9224 }
9225
9226 /**
9227 * Gets the location of the object relative to the parent in the form
9228 * of a point specifying the object's top-left corner in the screen's
9229 * coordinate space.
9230 *
9231 * @return an instance of Point representing the top-left corner of
9232 * the object's bounds in the coordinate space of the screen;
9233 * <code>null</code> if this object or its parent are not on the screen
9234 */
9235 public Point getLocation() {
9236 return Component.this.getLocation();
9237 }
9238
9239 /**
9240 * Sets the location of the object relative to the parent.
9241 * @param p the coordinates of the object
9242 */
9243 public void setLocation(Point p) {
9244 Component.this.setLocation(p);
9245 }
9246
9247 /**
9248 * Gets the bounds of this object in the form of a Rectangle object.
9249 * The bounds specify this object's width, height, and location
9250 * relative to its parent.
9251 *
9252 * @return a rectangle indicating this component's bounds;
9253 * <code>null</code> if this object is not on the screen
9254 */
9255 public Rectangle getBounds() {
9256 return Component.this.getBounds();
9257 }
9258
9259 /**
9260 * Sets the bounds of this object in the form of a
9261 * <code>Rectangle</code> object.
9262 * The bounds specify this object's width, height, and location
9263 * relative to its parent.
9264 *
9265 * @param r a rectangle indicating this component's bounds
9266 */
9267 public void setBounds(Rectangle r) {
9268 Component.this.setBounds(r);
9269 }
9270
9271 /**
9272 * Returns the size of this object in the form of a
9273 * <code>Dimension</code> object. The height field of the
9274 * <code>Dimension</code> object contains this objects's
9275 * height, and the width field of the <code>Dimension</code>
9276 * object contains this object's width.
9277 *
9278 * @return a <code>Dimension</code> object that indicates
9279 * the size of this component; <code>null</code> if
9280 * this object is not on the screen
9281 */
9282 public Dimension getSize() {
9283 return Component.this.getSize();
9284 }
9285
9286 /**
9287 * Resizes this object so that it has width and height.
9288 *
9289 * @param d - the dimension specifying the new size of the object
9290 */
9291 public void setSize(Dimension d) {
9292 Component.this.setSize(d);
9293 }
9294
9295 /**
9296 * Returns the <code>Accessible</code> child,
9297 * if one exists, contained at the local
9298 * coordinate <code>Point</code>. Otherwise returns
9299 * <code>null</code>.
9300 *
9301 * @param p the point defining the top-left corner of
9302 * the <code>Accessible</code>, given in the
9303 * coordinate space of the object's parent
9304 * @return the <code>Accessible</code>, if it exists,
9305 * at the specified location; else <code>null</code>
9306 */
9307 public Accessible getAccessibleAt(Point p) {
9308 return null; // Components don't have children
9309 }
9310
9311 /**
9312 * Returns whether this object can accept focus or not.
9313 *
9314 * @return true if object can accept focus; otherwise false
9315 */
9316 public boolean isFocusTraversable() {
9317 return Component.this.isFocusTraversable();
9318 }
9319
9320 /**
9321 * Requests focus for this object.
9322 */
9323 public void requestFocus() {
9324 Component.this.requestFocus();
9325 }
9326
9327 /**
9328 * Adds the specified focus listener to receive focus events from this
9329 * component.
9330 *
9331 * @param l the focus listener
9332 */
9333 public void addFocusListener(FocusListener l) {
9334 Component.this.addFocusListener(l);
9335 }
9336
9337 /**
9338 * Removes the specified focus listener so it no longer receives focus
9339 * events from this component.
9340 *
9341 * @param l the focus listener
9342 */
9343 public void removeFocusListener(FocusListener l) {
9344 Component.this.removeFocusListener(l);
9345 }
9346
9347 } // inner class AccessibleAWTComponent
9348
9349
9350 /**
9351 * Gets the index of this object in its accessible parent.
9352 * If this object does not have an accessible parent, returns
9353 * -1.
9354 *
9355 * @return the index of this object in its accessible parent
9356 */
9357 int getAccessibleIndexInParent() {
9358 synchronized (getTreeLock()) {
9359 int index = -1;
9360 Container parent = this.getParent();
9361 if (parent != null && parent instanceof Accessible) {
9362 Component ca[] = parent.getComponents();
9363 for (int i = 0; i < ca.length; i++) {
9364 if (ca[i] instanceof Accessible) {
9365 index++;
9366 }
9367 if (this.equals(ca[i])) {
9368 return index;
9369 }
9370 }
9371 }
9372 return -1;
9373 }
9374 }
9375
9376 /**
9377 * Gets the current state set of this object.
9378 *
9379 * @return an instance of <code>AccessibleStateSet</code>
9380 * containing the current state set of the object
9381 * @see AccessibleState
9382 */
9383 AccessibleStateSet getAccessibleStateSet() {
9384 synchronized (getTreeLock()) {
9385 AccessibleStateSet states = new AccessibleStateSet();
9386 if (this.isEnabled()) {
9387 states.add(AccessibleState.ENABLED);
9388 }
9389 if (this.isFocusTraversable()) {
9390 states.add(AccessibleState.FOCUSABLE);
9391 }
9392 if (this.isVisible()) {
9393 states.add(AccessibleState.VISIBLE);
9394 }
9395 if (this.isShowing()) {
9396 states.add(AccessibleState.SHOWING);
9397 }
9398 if (this.isFocusOwner()) {
9399 states.add(AccessibleState.FOCUSED);
9400 }
9401 if (this instanceof Accessible) {
9402 AccessibleContext ac = ((Accessible) this).getAccessibleContext();
9403 if (ac != null) {
9404 Accessible ap = ac.getAccessibleParent();
9405 if (ap != null) {
9406 AccessibleContext pac = ap.getAccessibleContext();
9407 if (pac != null) {
9408 AccessibleSelection as = pac.getAccessibleSelection();
9409 if (as != null) {
9410 states.add(AccessibleState.SELECTABLE);
9411 int i = ac.getAccessibleIndexInParent();
9412 if (i >= 0) {
9413 if (as.isAccessibleChildSelected(i)) {
9414 states.add(AccessibleState.SELECTED);
9415 }
9416 }
9417 }
9418 }
9419 }
9420 }
9421 }
9422 if (Component.isInstanceOf(this, "javax.swing.JComponent")) {
9423 if (((javax.swing.JComponent) this).isOpaque()) {
9424 states.add(AccessibleState.OPAQUE);
9425 }
9426 }
9427 return states;
9428 }
9429 }
9430
9431 /**
9432 * Checks that the given object is instance of the given class.
9433 * @param obj Object to be checked
9434 * @param className The name of the class. Must be fully-qualified class name.
9435 * @return true, if this object is instanceof given class,
9436 * false, otherwise, or if obj or className is null
9437 */
9438 static boolean isInstanceOf(Object obj, String className) {
9439 if (obj == null) return false;
9440 if (className == null) return false;
9441
9442 Class cls = obj.getClass();
9443 while (cls != null) {
9444 if (cls.getName().equals(className)) {
9445 return true;
9446 }
9447 cls = cls.getSuperclass();
9448 }
9449 return false;
9450 }
9451
9452
9453 // ************************** MIXING CODE *******************************
9454
9455 /**
9456 * Applies the shape to the component
9457 * @param shape Shape to be applied to the component
9458 */
9459 void applyCompoundShape(Region shape) {
9460 checkTreeLock();
9461 if (!isLightweight()) {
9462 ComponentPeer peer = getPeer();
9463 if (peer != null) {
9464 // The Region class has some optimizations. That's why
9465 // we should manually check whether it's empty and
9466 // substitute the object ourselves. Otherwise we end up
9467 // with some incorrect Region object with loX being
9468 // greater than the hiX for instance.
9469 if (shape.isEmpty()) {
9470 shape = Region.getInstanceXYWH(0, 0, 0, 0);
9471 }
9472
9473 // Note: the shape is not really copied/cloned. We create
9474 // the Region object ourselves, so there's no any possibility
9475 // to modify the object outside of the mixing code.
9476 this.compoundShape = shape;
9477
9478 if (isValid()) {
9479 Point compAbsolute = getLocationOnWindow();
9480
9481 if (mixingLog.isLoggable(Level.FINER)) {
9482 mixingLog.fine("this = " + this +
9483 "; compAbsolute=" + compAbsolute + "; shape=" + shape);
9484 }
9485
9486 peer.applyShape(shape.getTranslatedRegion(-compAbsolute.x, -compAbsolute.y));
9487 }
9488 }
9489 }
9490 }
9491
9492 /**
9493 * Returns the shape previously set with applyCompoundShape().
9494 * If the component is LW or no shape was applied yet,
9495 * the method returns the normal shape.
9496 */
9497 private Region getAppliedShape() {
9498 checkTreeLock();
9499 //XXX: if we allow LW components to have a shape, this must be changed
9500 return (this.compoundShape == null || isLightweight()) ? getNormalShape() : this.compoundShape;
9501 }
9502
9503 Point getLocationOnWindow() {
9504 checkTreeLock();
9505 Point curLocation = getLocation();
9506
9507 for (Container parent = getContainer();
9508 parent != null;
9509 parent = parent.getContainer())
9510 {
9511 curLocation.x += parent.getX();
9512 curLocation.y += parent.getY();
9513 }
9514
9515 return curLocation;
9516 }
9517
9518 /**
9519 * Returns the full shape of the component located in window coordinates
9520 */
9521 final Region getNormalShape() {
9522 checkTreeLock();
9523 //XXX: we may take into account a user-specified shape for this component
9524 Point compAbsolute = getLocationOnWindow();
9525 return
9526 Region.getInstanceXYWH(
9527 compAbsolute.x,
9528 compAbsolute.y,
9529 getWidth(),
9530 getHeight()
9531 );
9532 }
9533
9534 private int getSiblingIndexAbove() {
9535 checkTreeLock();
9536 Container parent = getContainer();
9537 if (parent == null) {
9538 return -1;
9539 }
9540
9541 int nextAbove = parent.getComponentZOrder(this) - 1;
9542
9543 return nextAbove < 0 ? -1 : nextAbove;
9544 }
9545
9546 private int getSiblingIndexBelow() {
9547 checkTreeLock();
9548 Container parent = getContainer();
9549 if (parent == null) {
9550 return -1;
9551 }
9552
9553 int nextBelow = parent.getComponentZOrder(this) + 1;
9554
9555 return nextBelow >= parent.getComponentCount() ? -1 : nextBelow;
9556 }
9557
9558 private Region calculateCurrentShape() {
9559 checkTreeLock();
9560 Region s = getNormalShape();
9561
9562 if (mixingLog.isLoggable(Level.FINE)) {
9563 mixingLog.fine("this = " + this + "; normalShape=" + s);
9564 }
9565
9566 if (getContainer() != null) {
9567 Component comp = this;
9568 Container cont = comp.getContainer();
9569
9570 while (cont != null) {
9571 for (int index = comp.getSiblingIndexAbove(); index != -1; --index) {
9572 /* It is assumed that:
9573 *
9574 * getComponent(getContainer().getComponentZOrder(comp)) == comp
9575 *
9576 * The assumption has been made according to the current
9577 * implementation of the Container class.
9578 */
9579 Component c = cont.getComponent(index);
9580 if (c.isLightweight() && c.isShowing() && c.isOpaque()) {
9581 s = s.getDifference(c.getNormalShape());
9582 }
9583 }
9584
9585 if (cont.isLightweight()) {
9586 s = s.getIntersection(cont.getNormalShape());
9587 } else {
9588 break;
9589 }
9590
9591 comp = cont;
9592 cont = cont.getContainer();
9593 }
9594 }
9595
9596 if (mixingLog.isLoggable(Level.FINE)) {
9597 mixingLog.fine("currentShape=" + s);
9598 }
9599
9600 return s;
9601 }
9602
9603 void applyCurrentShape() {
9604 checkTreeLock();
9605 if (!isValid()) {
9606 return; // Because applyCompoundShape() ignores such components anyway
9607 }
9608 if (mixingLog.isLoggable(Level.FINE)) {
9609 mixingLog.fine("this = " + this);
9610 }
9611 applyCompoundShape(calculateCurrentShape());
9612 }
9613
9614 final void subtractAndApplyShape(Region s) {
9615 checkTreeLock();
9616
9617 if (mixingLog.isLoggable(Level.FINE)) {
9618 mixingLog.fine("this = " + this + "; s=" + s);
9619 }
9620
9621 applyCompoundShape(getAppliedShape().getDifference(s));
9622 }
9623
9624 void mixOnShowing() {
9625 synchronized (getTreeLock()) {
9626 if (mixingLog.isLoggable(Level.FINE)) {
9627 mixingLog.fine("this = " + this);
9628 }
9629 if (isLightweight()) {
9630 Container parent = getContainer();
9631 if (parent != null && isShowing() && isOpaque()) {
9632 parent.recursiveSubtractAndApplyShape(getNormalShape(), getSiblingIndexBelow());
9633 }
9634 } else {
9635 applyCurrentShape();
9636 }
9637 }
9638 }
9639
9640 void mixOnHiding(boolean isLightweight) {
9641 // We cannot be sure that the peer exists at this point, so we need the argument
9642 // to find out whether the hiding component is (well, actually was) a LW or a HW.
9643 synchronized (getTreeLock()) {
9644 if (mixingLog.isLoggable(Level.FINE)) {
9645 mixingLog.fine("this = " + this + "; isLightweight = " + isLightweight);
9646 }
9647 if (isLightweight) {
9648 Container parent = getContainer();
9649 if (parent != null) {
9650 parent.recursiveApplyCurrentShape(getSiblingIndexBelow());
9651 }
9652 } //XXX: else applyNormalShape() ???
9653 }
9654 }
9655
9656 void mixOnReshaping() {
9657 synchronized (getTreeLock()) {
9658 if (mixingLog.isLoggable(Level.FINE)) {
9659 mixingLog.fine("this = " + this);
9660 }
9661 if (isLightweight()) {
9662 Container parent = getContainer();
9663 if (parent != null) {
9664 parent.recursiveApplyCurrentShape(parent.getComponentZOrder(this));
9665 }
9666 } else {
9667 applyCurrentShape();
9668 }
9669 }
9670 }
9671
9672 void mixOnZOrderChanging(int oldZorder, int newZorder) {
9673 synchronized (getTreeLock()) {
9674 boolean becameHigher = newZorder < oldZorder;
9675 Container parent = getContainer();
9676
9677 if (mixingLog.isLoggable(Level.FINE)) {
9678 mixingLog.fine("this = " + this +
9679 "; oldZorder=" + oldZorder + "; newZorder=" + newZorder + "; parent=" + parent);
9680 }
9681
9682 if (isLightweight()) {
9683 if (becameHigher) {
9684 if (parent != null && isShowing() && isOpaque()) {
9685 parent.recursiveSubtractAndApplyShape(getNormalShape(), getSiblingIndexBelow(), oldZorder);
9686 }
9687 } else {
9688 if (parent != null) {
9689 parent.recursiveApplyCurrentShape(oldZorder, newZorder);
9690 }
9691 }
9692 } else {
9693 if (becameHigher) {
9694 applyCurrentShape();
9695 } else {
9696 if (parent != null) {
9697 Region shape = getAppliedShape();
9698
9699 for (int index = oldZorder; index < newZorder; index++) {
9700 Component c = parent.getComponent(index);
9701 if (c.isLightweight() && c.isShowing() && c.isOpaque()) {
9702 shape = shape.getDifference(c.getNormalShape());
9703 }
9704 }
9705 applyCompoundShape(shape);
9706 }
9707 }
9708 }
9709 }
9710 }
9711
9712 void mixOnOpaqueChanging() {
9713 if (mixingLog.isLoggable(Level.FINE)) {
9714 mixingLog.fine("this = " + this);
9715 }
9716 if (isOpaque()) {
9717 mixOnShowing();
9718 } else {
9719 mixOnHiding(isLightweight());
9720 }
9721 }
9722
9723 // ****************** END OF MIXING CODE ********************************
9724}