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