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