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