1 /* Component.java -- a graphics component
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006
3 Free Software Foundation
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
38
39
40 package java.awt;
41
42 import java.awt.dnd.DropTarget;
43 import java.awt.event.ActionEvent;
44 import java.awt.event.AdjustmentEvent;
45 import java.awt.event.ComponentEvent;
46 import java.awt.event.ComponentListener;
47 import java.awt.event.FocusEvent;
48 import java.awt.event.FocusListener;
49 import java.awt.event.HierarchyBoundsListener;
50 import java.awt.event.HierarchyEvent;
51 import java.awt.event.HierarchyListener;
52 import java.awt.event.InputEvent;
53 import java.awt.event.InputMethodEvent;
54 import java.awt.event.InputMethodListener;
55 import java.awt.event.KeyEvent;
56 import java.awt.event.KeyListener;
57 import java.awt.event.MouseEvent;
58 import java.awt.event.MouseListener;
59 import java.awt.event.MouseMotionListener;
60 import java.awt.event.MouseWheelEvent;
61 import java.awt.event.MouseWheelListener;
62 import java.awt.event.PaintEvent;
63 import java.awt.event.WindowEvent;
64 import java.awt.im.InputContext;
65 import java.awt.im.InputMethodRequests;
66 import java.awt.image.BufferStrategy;
67 import java.awt.image.ColorModel;
68 import java.awt.image.ImageObserver;
69 import java.awt.image.ImageProducer;
70 import java.awt.image.VolatileImage;
71 import java.awt.peer.ComponentPeer;
72 import java.awt.peer.LightweightPeer;
73 import java.beans.PropertyChangeListener;
74 import java.beans.PropertyChangeSupport;
75 import java.io.IOException;
76 import java.io.ObjectInputStream;
77 import java.io.ObjectOutputStream;
78 import java.io.PrintStream;
79 import java.io.PrintWriter;
80 import java.io.Serializable;
81 import java.lang.reflect.Array;
82 import java.util.Collections;
83 import java.util.EventListener;
84 import java.util.HashSet;
85 import java.util.Iterator;
86 import java.util.Locale;
87 import java.util.Set;
88 import java.util.Vector;
89
90 import javax.accessibility.Accessible;
91 import javax.accessibility.AccessibleComponent;
92 import javax.accessibility.AccessibleContext;
93 import javax.accessibility.AccessibleRole;
94 import javax.accessibility.AccessibleState;
95 import javax.accessibility.AccessibleStateSet;
96
97 /**
98 * The root of all evil. All graphical representations are subclasses of this
99 * giant class, which is designed for screen display and user interaction.
100 * This class can be extended directly to build a lightweight component (one
101 * not associated with a native window); lightweight components must reside
102 * inside a heavyweight window.
103 *
104 * <p>This class is Serializable, which has some big implications. A user can
105 * save the state of all graphical components in one VM, and reload them in
106 * another. Note that this class will only save Serializable listeners, and
107 * ignore the rest, without causing any serialization exceptions. However, by
108 * making a listener serializable, and adding it to another element, you link
109 * in that entire element to the state of this component. To get around this,
110 * use the idiom shown in the example below - make listeners non-serializable
111 * in inner classes, rather than using this object itself as the listener, if
112 * external objects do not need to save the state of this object.
113 *
114 * <pre>
115 * import java.awt.*;
116 * import java.awt.event.*;
117 * import java.io.Serializable;
118 * class MyApp implements Serializable
119 * {
120 * BigObjectThatShouldNotBeSerializedWithAButton bigOne;
121 * // Serializing aButton will not suck in an instance of MyApp, with its
122 * // accompanying field bigOne.
123 * Button aButton = new Button();
124 * class MyActionListener implements ActionListener
125 * {
126 * public void actionPerformed(ActionEvent e)
127 * {
128 * System.out.println("Hello There");
129 * }
130 * }
131 * MyApp()
132 * {
133 * aButton.addActionListener(new MyActionListener());
134 * }
135 * }
136 * </pre>
137 *
138 * <p>Status: Incomplete. The event dispatch mechanism is implemented. All
139 * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly
140 * incomplete or only stubs; except for methods relating to the Drag and
141 * Drop, Input Method, and Accessibility frameworks: These methods are
142 * present but commented out.
143 *
144 * @author original author unknown
145 * @author Eric Blake (ebb9@email.byu.edu)
146 * @since 1.0
147 * @status still missing 1.4 support
148 */
149 public abstract class Component
150 implements ImageObserver, MenuContainer, Serializable
151 {
152 // Word to the wise - this file is huge. Search for '\f' (^L) for logical
153 // sectioning by fields, public API, private API, and nested classes.
154
155
156 /**
157 * Compatible with JDK 1.0+.
158 */
159 private static final long serialVersionUID = -7644114512714619750L;
160
161 /**
162 * Constant returned by the <code>getAlignmentY</code> method to indicate
163 * that the component wishes to be aligned to the top relative to
164 * other components.
165 *
166 * @see #getAlignmentY()
167 */
168 public static final float TOP_ALIGNMENT = 0;
169
170 /**
171 * Constant returned by the <code>getAlignmentY</code> and
172 * <code>getAlignmentX</code> methods to indicate
173 * that the component wishes to be aligned to the center relative to
174 * other components.
175 *
176 * @see #getAlignmentX()
177 * @see #getAlignmentY()
178 */
179 public static final float CENTER_ALIGNMENT = 0.5f;
180
181 /**
182 * Constant returned by the <code>getAlignmentY</code> method to indicate
183 * that the component wishes to be aligned to the bottom relative to
184 * other components.
185 *
186 * @see #getAlignmentY()
187 */
188 public static final float BOTTOM_ALIGNMENT = 1;
189
190 /**
191 * Constant returned by the <code>getAlignmentX</code> method to indicate
192 * that the component wishes to be aligned to the right relative to
193 * other components.
194 *
195 * @see #getAlignmentX()
196 */
197 public static final float RIGHT_ALIGNMENT = 1;
198
199 /**
200 * Constant returned by the <code>getAlignmentX</code> method to indicate
201 * that the component wishes to be aligned to the left relative to
202 * other components.
203 *
204 * @see #getAlignmentX()
205 */
206 public static final float LEFT_ALIGNMENT = 0;
207
208 /**
209 * Make the treelock a String so that it can easily be identified
210 * in debug dumps. We clone the String in order to avoid a conflict in
211 * the unlikely event that some other package uses exactly the same string
212 * as a lock object.
213 */
214 static final Object treeLock = new String("AWT_TREE_LOCK");
215
216 // Serialized fields from the serialization spec.
217
218 /**
219 * The x position of the component in the parent's coordinate system.
220 *
221 * @see #getLocation()
222 * @serial the x position
223 */
224 int x;
225
226 /**
227 * The y position of the component in the parent's coordinate system.
228 *
229 * @see #getLocation()
230 * @serial the y position
231 */
232 int y;
233
234 /**
235 * The component width.
236 *
237 * @see #getSize()
238 * @serial the width
239 */
240 int width;
241
242 /**
243 * The component height.
244 *
245 * @see #getSize()
246 * @serial the height
247 */
248 int height;
249
250 /**
251 * The foreground color for the component. This may be null.
252 *
253 * @see #getForeground()
254 * @see #setForeground(Color)
255 * @serial the foreground color
256 */
257 Color foreground;
258
259 /**
260 * The background color for the component. This may be null.
261 *
262 * @see #getBackground()
263 * @see #setBackground(Color)
264 * @serial the background color
265 */
266 Color background;
267
268 /**
269 * The default font used in the component. This may be null.
270 *
271 * @see #getFont()
272 * @see #setFont(Font)
273 * @serial the font
274 */
275 Font font;
276
277 /**
278 * The font in use by the peer, or null if there is no peer.
279 *
280 * @serial the peer's font
281 */
282 Font peerFont;
283
284 /**
285 * The cursor displayed when the pointer is over this component. This may
286 * be null.
287 *
288 * @see #getCursor()
289 * @see #setCursor(Cursor)
290 */
291 Cursor cursor;
292
293 /**
294 * The locale for the component.
295 *
296 * @see #getLocale()
297 * @see #setLocale(Locale)
298 */
299 Locale locale = Locale.getDefault ();
300
301 /**
302 * True if the object should ignore repaint events (usually because it is
303 * not showing).
304 *
305 * @see #getIgnoreRepaint()
306 * @see #setIgnoreRepaint(boolean)
307 * @serial true to ignore repaints
308 * @since 1.4
309 */
310 boolean ignoreRepaint;
311
312 /**
313 * True when the object is visible (although it is only showing if all
314 * ancestors are likewise visible). For component, this defaults to true.
315 *
316 * @see #isVisible()
317 * @see #setVisible(boolean)
318 * @serial true if visible
319 */
320 boolean visible = true;
321
322 /**
323 * True if the object is enabled, meaning it can interact with the user.
324 * For component, this defaults to true.
325 *
326 * @see #isEnabled()
327 * @see #setEnabled(boolean)
328 * @serial true if enabled
329 */
330 boolean enabled = true;
331
332 /**
333 * True if the object is valid. This is set to false any time a size
334 * adjustment means the component need to be layed out again.
335 *
336 * @see #isValid()
337 * @see #validate()
338 * @see #invalidate()
339 * @serial true if layout is valid
340 */
341 boolean valid;
342
343 /**
344 * The DropTarget for drag-and-drop operations.
345 *
346 * @see #getDropTarget()
347 * @see #setDropTarget(DropTarget)
348 * @serial the drop target, or null
349 * @since 1.2
350 */
351 DropTarget dropTarget;
352
353 /**
354 * The list of popup menus for this component.
355 *
356 * @see #add(PopupMenu)
357 * @serial the list of popups
358 */
359 Vector popups;
360
361 /**
362 * The component's name. May be null, in which case a default name is
363 * generated on the first use.
364 *
365 * @see #getName()
366 * @see #setName(String)
367 * @serial the name
368 */
369 String name;
370
371 /**
372 * True once the user has set the name. Note that the user may set the name
373 * to null.
374 *
375 * @see #name
376 * @see #getName()
377 * @see #setName(String)
378 * @serial true if the name has been explicitly set
379 */
380 boolean nameExplicitlySet;
381
382 /**
383 * Indicates if the object can be focused. Defaults to true for components.
384 *
385 * @see #isFocusable()
386 * @see #setFocusable(boolean)
387 * @since 1.4
388 */
389 boolean focusable = true;
390
391 /**
392 * Tracks whether this component's {@link #isFocusTraversable}
393 * method has been overridden.
394 *
395 * @since 1.4
396 */
397 int isFocusTraversableOverridden;
398
399 /**
400 * The focus traversal keys, if not inherited from the parent or
401 * default keyboard focus manager. These sets will contain only
402 * AWTKeyStrokes that represent press and release events to use as
403 * focus control.
404 *
405 * @see #getFocusTraversalKeys(int)
406 * @see #setFocusTraversalKeys(int, Set)
407 * @since 1.4
408 */
409 Set[] focusTraversalKeys;
410
411 /**
412 * True if focus traversal keys are enabled. This defaults to true for
413 * Component. If this is true, keystrokes in focusTraversalKeys are trapped
414 * and processed automatically rather than being passed on to the component.
415 *
416 * @see #getFocusTraversalKeysEnabled()
417 * @see #setFocusTraversalKeysEnabled(boolean)
418 * @since 1.4
419 */
420 boolean focusTraversalKeysEnabled = true;
421
422 /**
423 * Cached information on the minimum size. Should have been transient.
424 *
425 * @serial ignore
426 */
427 Dimension minSize;
428
429 /**
430 * Cached information on the preferred size. Should have been transient.
431 *
432 * @serial ignore
433 */
434 Dimension prefSize;
435
436 /**
437 * Set to true if an event is to be handled by this component, false if
438 * it is to be passed up the hierarcy.
439 *
440 * @see #dispatchEvent(AWTEvent)
441 * @serial true to process event locally
442 */
443 boolean newEventsOnly;
444
445 /**
446 * Set by subclasses to enable event handling of particular events, and
447 * left alone when modifying listeners. For component, this defaults to
448 * enabling only input methods.
449 *
450 * @see #enableInputMethods(boolean)
451 * @see AWTEvent
452 * @serial the mask of events to process
453 */
454 long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK;
455
456 /**
457 * Describes all registered PropertyChangeListeners.
458 *
459 * @see #addPropertyChangeListener(PropertyChangeListener)
460 * @see #removePropertyChangeListener(PropertyChangeListener)
461 * @see #firePropertyChange(String, Object, Object)
462 * @serial the property change listeners
463 * @since 1.2
464 */
465 PropertyChangeSupport changeSupport;
466
467 /**
468 * True if the component has been packed (layed out).
469 *
470 * @serial true if this is packed
471 */
472 boolean isPacked;
473
474 /**
475 * The serialization version for this class. Currently at version 4.
476 *
477 * XXX How do we handle prior versions?
478 *
479 * @serial the serialization version
480 */
481 int componentSerializedDataVersion = 4;
482
483 /**
484 * The accessible context associated with this component. This is only set
485 * by subclasses.
486 *
487 * @see #getAccessibleContext()
488 * @serial the accessibility context
489 * @since 1.2
490 */
491 AccessibleContext accessibleContext;
492
493
494 // Guess what - listeners are special cased in serialization. See
495 // readObject and writeObject.
496
497 /** Component listener chain. */
498 transient ComponentListener componentListener;
499
500 /** Focus listener chain. */
501 transient FocusListener focusListener;
502
503 /** Key listener chain. */
504 transient KeyListener keyListener;
505
506 /** Mouse listener chain. */
507 transient MouseListener mouseListener;
508
509 /** Mouse motion listener chain. */
510 transient MouseMotionListener mouseMotionListener;
511
512 /**
513 * Mouse wheel listener chain.
514 *
515 * @since 1.4
516 */
517 transient MouseWheelListener mouseWheelListener;
518
519 /**
520 * Input method listener chain.
521 *
522 * @since 1.2
523 */
524 transient InputMethodListener inputMethodListener;
525
526 /**
527 * Hierarcy listener chain.
528 *
529 * @since 1.3
530 */
531 transient HierarchyListener hierarchyListener;
532
533 /**
534 * Hierarcy bounds listener chain.
535 *
536 * @since 1.3
537 */
538 transient HierarchyBoundsListener hierarchyBoundsListener;
539
540 // Anything else is non-serializable, and should be declared "transient".
541
542 /** The parent. */
543 transient Container parent;
544
545 /** The associated native peer. */
546 transient ComponentPeer peer;
547
548 /** The preferred component orientation. */
549 transient ComponentOrientation orientation = ComponentOrientation.UNKNOWN;
550
551 /**
552 * The associated graphics configuration.
553 *
554 * @since 1.4
555 */
556 transient GraphicsConfiguration graphicsConfig;
557
558 /**
559 * The buffer strategy for repainting.
560 *
561 * @since 1.4
562 */
563 transient BufferStrategy bufferStrategy;
564
565 /**
566 * true if requestFocus was called on this component when its
567 * top-level ancestor was not focusable.
568 */
569 private transient FocusEvent pendingFocusRequest = null;
570
571 /**
572 * The system properties that affect image updating.
573 */
574 private static transient boolean incrementalDraw;
575 private static transient Long redrawRate;
576
577 static
578 {
579 incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
580 redrawRate = Long.getLong ("awt.image.redrawrate");
581 }
582
583 // Public and protected API.
584
585 /**
586 * Default constructor for subclasses. When Component is extended directly,
587 * it forms a lightweight component that must be hosted in an opaque native
588 * container higher in the tree.
589 */
590 protected Component()
591 {
592 // Nothing to do here.
593 }
594
595 /**
596 * Returns the name of this component.
597 *
598 * @return the name of this component
599 * @see #setName(String)
600 * @since 1.1
601 */
602 public String getName()
603 {
604 if (name == null && ! nameExplicitlySet)
605 name = generateName();
606 return name;
607 }
608
609 /**
610 * Sets the name of this component to the specified name.
611 *
612 * @param name the new name of this component
613 * @see #getName()
614 * @since 1.1
615 */
616 public void setName(String name)
617 {
618 nameExplicitlySet = true;
619 this.name = name;
620 }
621
622 /**
623 * Returns the parent of this component.
624 *
625 * @return the parent of this component
626 */
627 public Container getParent()
628 {
629 return parent;
630 }
631
632 /**
633 * Returns the native windowing system peer for this component. Only the
634 * platform specific implementation code should call this method.
635 *
636 * @return the peer for this component
637 * @deprecated user programs should not directly manipulate peers; use
638 * {@link #isDisplayable()} instead
639 */
640 // Classpath's Gtk peers rely on this.
641 public ComponentPeer getPeer()
642 {
643 return peer;
644 }
645
646 /**
647 * Set the associated drag-and-drop target, which receives events when this
648 * is enabled.
649 *
650 * @param dt the new drop target
651 * @see #isEnabled()
652 */
653 public void setDropTarget(DropTarget dt)
654 {
655 this.dropTarget = dt;
656 }
657
658 /**
659 * Gets the associated drag-and-drop target, if there is one.
660 *
661 * @return the drop target
662 */
663 public DropTarget getDropTarget()
664 {
665 return dropTarget;
666 }
667
668 /**
669 * Returns the graphics configuration of this component, if there is one.
670 * If it has not been set, it is inherited from the parent.
671 *
672 * @return the graphics configuration, or null
673 * @since 1.3
674 */
675 public GraphicsConfiguration getGraphicsConfiguration()
676 {
677 return getGraphicsConfigurationImpl();
678 }
679
680 /**
681 * Returns the object used for synchronization locks on this component
682 * when performing tree and layout functions.
683 *
684 * @return the synchronization lock for this component
685 */
686 public final Object getTreeLock()
687 {
688 return treeLock;
689 }
690
691 /**
692 * Returns the toolkit in use for this component. The toolkit is associated
693 * with the frame this component belongs to.
694 *
695 * @return the toolkit for this component
696 */
697 public Toolkit getToolkit()
698 {
699 if (peer != null)
700 {
701 Toolkit tk = peer.getToolkit();
702 if (tk != null)
703 return tk;
704 }
705 // Get toolkit for lightweight component.
706 if (parent != null)
707 return parent.getToolkit();
708 return Toolkit.getDefaultToolkit();
709 }
710
711 /**
712 * Tests whether or not this component is valid. A invalid component needs
713 * to have its layout redone.
714 *
715 * @return true if this component is valid
716 * @see #validate()
717 * @see #invalidate()
718 */
719 public boolean isValid()
720 {
721 return valid;
722 }
723
724 /**
725 * Tests if the component is displayable. It must be connected to a native
726 * screen resource. This reduces to checking that peer is not null. A
727 * containment hierarchy is made displayable when a window is packed or
728 * made visible.
729 *
730 * @return true if the component is displayable
731 * @see Container#add(Component)
732 * @see Container#remove(Component)
733 * @see Window#pack()
734 * @see Window#show()
735 * @see Window#dispose()
736 * @since 1.2
737 */
738 public boolean isDisplayable()
739 {
740 return peer != null;
741 }
742
743 /**
744 * Tests whether or not this component is visible. Except for top-level
745 * frames, components are initially visible.
746 *
747 * @return true if the component is visible
748 * @see #setVisible(boolean)
749 */
750 public boolean isVisible()
751 {
752 return visible;
753 }
754
755 /**
756 * Tests whether or not this component is actually being shown on
757 * the screen. This will be true if and only if it this component is
758 * visible and its parent components are all visible.
759 *
760 * @return true if the component is showing on the screen
761 * @see #setVisible(boolean)
762 */
763 public boolean isShowing()
764 {
765 if (! visible || peer == null)
766 return false;
767
768 return parent == null ? false : parent.isShowing();
769 }
770
771 /**
772 * Tests whether or not this component is enabled. Components are enabled
773 * by default, and must be enabled to receive user input or generate events.
774 *
775 * @return true if the component is enabled
776 * @see #setEnabled(boolean)
777 */
778 public boolean isEnabled()
779 {
780 return enabled;
781 }
782
783 /**
784 * Enables or disables this component. The component must be enabled to
785 * receive events (except that lightweight components always receive mouse
786 * events).
787 *
788 * @param enabled true to enable this component
789 *
790 * @see #isEnabled()
791 * @see #isLightweight()
792 *
793 * @since 1.1
794 */
795 public void setEnabled(boolean enabled)
796 {
797 enable(enabled);
798 }
799
800 /**
801 * Enables this component.
802 *
803 * @deprecated use {@link #setEnabled(boolean)} instead
804 */
805 public void enable()
806 {
807 this.enabled = true;
808 if (peer != null)
809 peer.setEnabled (true);
810 }
811
812 /**
813 * Enables or disables this component.
814 *
815 * @param enabled true to enable this component
816 *
817 * @deprecated use {@link #setEnabled(boolean)} instead
818 */
819 public void enable(boolean enabled)
820 {
821 if (enabled)
822 enable();
823 else
824 disable();
825 }
826
827 /**
828 * Disables this component.
829 *
830 * @deprecated use {@link #setEnabled(boolean)} instead
831 */
832 public void disable()
833 {
834 this.enabled = false;
835 if (peer != null)
836 peer.setEnabled (false);
837 }
838
839 /**
840 * Checks if this image is painted to an offscreen image buffer that is
841 * later copied to screen (double buffering reduces flicker). This version
842 * returns false, so subclasses must override it if they provide double
843 * buffering.
844 *
845 * @return true if this is double buffered; defaults to false
846 */
847 public boolean isDoubleBuffered()
848 {
849 return false;
850 }
851
852 /**
853 * Enables or disables input method support for this component. By default,
854 * components have this enabled. Input methods are given the opportunity
855 * to process key events before this component and its listeners.
856 *
857 * @param enable true to enable input method processing
858 * @see #processKeyEvent(KeyEvent)
859 * @since 1.2
860 */
861 public void enableInputMethods(boolean enable)
862 {
863 if (enable)
864 eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK;
865 else
866 eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK;
867 }
868
869 /**
870 * Makes this component visible or invisible. Note that it wtill might
871 * not show the component, if a parent is invisible.
872 *
873 * @param visible true to make this component visible
874 *
875 * @see #isVisible()
876 *
877 * @since 1.1
878 */
879 public void setVisible(boolean visible)
880 {
881 // Inspection by subclassing shows that Sun's implementation calls
882 // show(boolean) which then calls show() or hide(). It is the show()
883 // method that is overriden in subclasses like Window.
884 show(visible);
885 }
886
887 /**
888 * Makes this component visible on the screen.
889 *
890 * @deprecated use {@link #setVisible(boolean)} instead
891 */
892 public void show()
893 {
894 // We must set visible before showing the peer. Otherwise the
895 // peer could post paint events before visible is true, in which
896 // case lightweight components are not initially painted --
897 // Container.paint first calls isShowing () before painting itself
898 // and its children.
899 if(!isVisible())
900 {
901 this.visible = true;
902 // Avoid NullPointerExceptions by creating a local reference.
903 ComponentPeer currentPeer=peer;
904 if (currentPeer != null)
905 currentPeer.show();
906
907 // The JDK repaints the component before invalidating the parent.
908 // So do we.
909 if (isShowing() && isLightweight())
910 repaint();
911 // Invalidate the parent if we have one. The component itself must
912 // not be invalidated. We also avoid NullPointerException with
913 // a local reference here.
914 Container currentParent = parent;
915 if (currentParent != null)
916 currentParent.invalidate();
917
918 ComponentEvent ce =
919 new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
920 getToolkit().getSystemEventQueue().postEvent(ce);
921 }
922 }
923
924 /**
925 * Makes this component visible or invisible.
926 *
927 * @param visible true to make this component visible
928 *
929 * @deprecated use {@link #setVisible(boolean)} instead
930 */
931 public void show(boolean visible)
932 {
933 if (visible)
934 show();
935 else
936 hide();
937 }
938
939 /**
940 * Hides this component so that it is no longer shown on the screen.
941 *
942 * @deprecated use {@link #setVisible(boolean)} instead
943 */
944 public void hide()
945 {
946 if (isVisible())
947 {
948 // Avoid NullPointerExceptions by creating a local reference.
949 ComponentPeer currentPeer=peer;
950 if (currentPeer != null)
951 currentPeer.setVisible(false);
952 boolean wasShowing = isShowing();
953 this.visible = false;
954
955 // The JDK repaints the component before invalidating the parent.
956 // So do we.
957 if (wasShowing)
958 repaint();
959 // Invalidate the parent if we have one. The component itself must
960 // not be invalidated. We also avoid NullPointerException with
961 // a local reference here.
962 Container currentParent = parent;
963 if (currentParent != null)
964 currentParent.invalidate();
965
966 ComponentEvent ce =
967 new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
968 getToolkit().getSystemEventQueue().postEvent(ce);
969 }
970 }
971
972 /**
973 * Returns this component's foreground color. If not set, this is inherited
974 * from the parent.
975 *
976 * @return this component's foreground color, or null
977 * @see #setForeground(Color)
978 */
979 public Color getForeground()
980 {
981 if (foreground != null)
982 return foreground;
983 return parent == null ? null : parent.getForeground();
984 }
985
986 /**
987 * Sets this component's foreground color to the specified color. This is a
988 * bound property.
989 *
990 * @param c the new foreground color
991 * @see #getForeground()
992 */
993 public void setForeground(Color c)
994 {
995 if (peer != null)
996 peer.setForeground(c);
997
998 Color previous = foreground;
999 foreground = c;
1000 firePropertyChange("foreground", previous, c);
1001 }
1002
1003 /**
1004 * Tests if the foreground was explicitly set, or just inherited from the
1005 * parent.
1006 *
1007 * @return true if the foreground has been set
1008 * @since 1.4
1009 */
1010 public boolean isForegroundSet()
1011 {
1012 return foreground != null;
1013 }
1014
1015 /**
1016 * Returns this component's background color. If not set, this is inherited
1017 * from the parent.
1018 *
1019 * @return the background color of the component, or null
1020 * @see #setBackground(Color)
1021 */
1022 public Color getBackground()
1023 {
1024 if (background != null)
1025 return background;
1026 return parent == null ? null : parent.getBackground();
1027 }
1028
1029 /**
1030 * Sets this component's background color to the specified color. The parts
1031 * of the component affected by the background color may by system dependent.
1032 * This is a bound property.
1033 *
1034 * @param c the new background color
1035 * @see #getBackground()
1036 */
1037 public void setBackground(Color c)
1038 {
1039 // return if the background is already set to that color.
1040 if ((c != null) && c.equals(background))
1041 return;
1042
1043 Color previous = background;
1044 background = c;
1045 if (peer != null && c != null)
1046 peer.setBackground(c);
1047 firePropertyChange("background", previous, c);
1048 }
1049
1050 /**
1051 * Tests if the background was explicitly set, or just inherited from the
1052 * parent.
1053 *
1054 * @return true if the background has been set
1055 * @since 1.4
1056 */
1057 public boolean isBackgroundSet()
1058 {
1059 return background != null;
1060 }
1061
1062 /**
1063 * Returns the font in use for this component. If not set, this is inherited
1064 * from the parent.
1065 *
1066 * @return the font for this component
1067 * @see #setFont(Font)
1068 */
1069 public Font getFont()
1070 {
1071 Font f = font;
1072 if (f != null)
1073 return f;
1074
1075 Component p = parent;
1076 if (p != null)
1077 return p.getFont();
1078 return null;
1079 }
1080
1081 /**
1082 * Sets the font for this component to the specified font. This is a bound
1083 * property.
1084 *
1085 * @param newFont the new font for this component
1086 *
1087 * @see #getFont()
1088 */
1089 public void setFont(Font newFont)
1090 {
1091 if((newFont != null && (font == null || !font.equals(newFont)))
1092 || newFont == null)
1093 {
1094 Font oldFont = font;
1095 font = newFont;
1096 if (peer != null)
1097 peer.setFont(font);
1098 firePropertyChange("font", oldFont, newFont);
1099 invalidate();
1100 }
1101 }
1102
1103 /**
1104 * Tests if the font was explicitly set, or just inherited from the parent.
1105 *
1106 * @return true if the font has been set
1107 * @since 1.4
1108 */
1109 public boolean isFontSet()
1110 {
1111 return font != null;
1112 }
1113
1114 /**
1115 * Returns the locale for this component. If this component does not
1116 * have a locale, the locale of the parent component is returned.
1117 *
1118 * @return the locale for this component
1119 * @throws IllegalComponentStateException if it has no locale or parent
1120 * @see #setLocale(Locale)
1121 * @since 1.1
1122 */
1123 public Locale getLocale()
1124 {
1125 if (locale != null)
1126 return locale;
1127 if (parent == null)
1128 throw new IllegalComponentStateException
1129 ("Component has no parent: can't determine Locale");
1130 return parent.getLocale();
1131 }
1132
1133 /**
1134 * Sets the locale for this component to the specified locale. This is a
1135 * bound property.
1136 *
1137 * @param newLocale the new locale for this component
1138 */
1139 public void setLocale(Locale newLocale)
1140 {
1141 if (locale == newLocale)
1142 return;
1143
1144 Locale oldLocale = locale;
1145 locale = newLocale;
1146 firePropertyChange("locale", oldLocale, newLocale);
1147 // New writing/layout direction or more/less room for localized labels.
1148 invalidate();
1149 }
1150
1151 /**
1152 * Returns the color model of the device this componet is displayed on.
1153 *
1154 * @return this object's color model
1155 * @see Toolkit#getColorModel()
1156 */
1157 public ColorModel getColorModel()
1158 {
1159 GraphicsConfiguration config = getGraphicsConfiguration();
1160 return config != null ? config.getColorModel()
1161 : getToolkit().getColorModel();
1162 }
1163
1164 /**
1165 * Returns the location of this component's top left corner relative to
1166 * its parent component. This may be outdated, so for synchronous behavior,
1167 * you should use a component listner.
1168 *
1169 * @return the location of this component
1170 * @see #setLocation(int, int)
1171 * @see #getLocationOnScreen()
1172 * @since 1.1
1173 */
1174 public Point getLocation()
1175 {
1176 return location ();
1177 }
1178
1179 /**
1180 * Returns the location of this component's top left corner in screen
1181 * coordinates.
1182 *
1183 * @return the location of this component in screen coordinates
1184 * @throws IllegalComponentStateException if the component is not showing
1185 */
1186 public Point getLocationOnScreen()
1187 {
1188 if (! isShowing())
1189 throw new IllegalComponentStateException("component "
1190 + getClass().getName()
1191 + " not showing");
1192 // We know peer != null here.
1193 return peer.getLocationOnScreen();
1194 }
1195
1196 /**
1197 * Returns the location of this component's top left corner relative to
1198 * its parent component.
1199 *
1200 * @return the location of this component
1201 * @deprecated use {@link #getLocation()} instead
1202 */
1203 public Point location()
1204 {
1205 return new Point (x, y);
1206 }
1207
1208 /**
1209 * Moves this component to the specified location, relative to the parent's
1210 * coordinates. The coordinates are the new upper left corner of this
1211 * component.
1212 *
1213 * @param x the new X coordinate of this component
1214 * @param y the new Y coordinate of this component
1215 * @see #getLocation()
1216 * @see #setBounds(int, int, int, int)
1217 */
1218 public void setLocation(int x, int y)
1219 {
1220 move (x, y);
1221 }
1222
1223 /**
1224 * Moves this component to the specified location, relative to the parent's
1225 * coordinates. The coordinates are the new upper left corner of this
1226 * component.
1227 *
1228 * @param x the new X coordinate of this component
1229 * @param y the new Y coordinate of this component
1230 * @deprecated use {@link #setLocation(int, int)} instead
1231 */
1232 public void move(int x, int y)
1233 {
1234 setBounds(x, y, this.width, this.height);
1235 }
1236
1237 /**
1238 * Moves this component to the specified location, relative to the parent's
1239 * coordinates. The coordinates are the new upper left corner of this
1240 * component.
1241 *
1242 * @param p new coordinates for this component
1243 * @throws NullPointerException if p is null
1244 * @see #getLocation()
1245 * @see #setBounds(int, int, int, int)
1246 * @since 1.1
1247 */
1248 public void setLocation(Point p)
1249 {
1250 setLocation(p.x, p.y);
1251 }
1252
1253 /**
1254 * Returns the size of this object.
1255 *
1256 * @return the size of this object
1257 * @see #setSize(int, int)
1258 * @since 1.1
1259 */
1260 public Dimension getSize()
1261 {
1262 return size ();
1263 }
1264
1265 /**
1266 * Returns the size of this object.
1267 *
1268 * @return the size of this object
1269 * @deprecated use {@link #getSize()} instead
1270 */
1271 public Dimension size()
1272 {
1273 return new Dimension (width, height);
1274 }
1275
1276 /**
1277 * Sets the size of this component to the specified width and height.
1278 *
1279 * @param width the new width of this component
1280 * @param height the new height of this component
1281 * @see #getSize()
1282 * @see #setBounds(int, int, int, int)
1283 */
1284 public void setSize(int width, int height)
1285 {
1286 resize (width, height);
1287 }
1288
1289 /**
1290 * Sets the size of this component to the specified value.
1291 *
1292 * @param width the new width of the component
1293 * @param height the new height of the component
1294 * @deprecated use {@link #setSize(int, int)} instead
1295 */
1296 public void resize(int width, int height)
1297 {
1298 setBounds(this.x, this.y, width, height);
1299 }
1300
1301 /**
1302 * Sets the size of this component to the specified value.
1303 *
1304 * @param d the new size of this component
1305 * @throws NullPointerException if d is null
1306 * @see #setSize(int, int)
1307 * @see #setBounds(int, int, int, int)
1308 * @since 1.1
1309 */
1310 public void setSize(Dimension d)
1311 {
1312 resize (d);
1313 }
1314
1315 /**
1316 * Sets the size of this component to the specified value.
1317 *
1318 * @param d the new size of this component
1319 * @throws NullPointerException if d is null
1320 * @deprecated use {@link #setSize(Dimension)} instead
1321 */
1322 public void resize(Dimension d)
1323 {
1324 resize (d.width, d.height);
1325 }
1326
1327 /**
1328 * Returns a bounding rectangle for this component. Note that the
1329 * returned rectange is relative to this component's parent, not to
1330 * the screen.
1331 *
1332 * @return the bounding rectangle for this component
1333 * @see #setBounds(int, int, int, int)
1334 * @see #getLocation()
1335 * @see #getSize()
1336 */
1337 public Rectangle getBounds()
1338 {
1339 return bounds ();
1340 }
1341
1342 /**
1343 * Returns a bounding rectangle for this component. Note that the
1344 * returned rectange is relative to this component's parent, not to
1345 * the screen.
1346 *
1347 * @return the bounding rectangle for this component
1348 * @deprecated use {@link #getBounds()} instead
1349 */
1350 public Rectangle bounds()
1351 {
1352 return new Rectangle (x, y, width, height);
1353 }
1354
1355 /**
1356 * Sets the bounding rectangle for this component to the specified values.
1357 * Note that these coordinates are relative to the parent, not to the screen.
1358 *
1359 * @param x the X coordinate of the upper left corner of the rectangle
1360 * @param y the Y coordinate of the upper left corner of the rectangle
1361 * @param w the width of the rectangle
1362 * @param h the height of the rectangle
1363 * @see #getBounds()
1364 * @see #setLocation(int, int)
1365 * @see #setLocation(Point)
1366 * @see #setSize(int, int)
1367 * @see #setSize(Dimension)
1368 * @since 1.1
1369 */
1370 public void setBounds(int x, int y, int w, int h)
1371 {
1372 reshape (x, y, w, h);
1373 }
1374
1375 /**
1376 * Sets the bounding rectangle for this component to the specified values.
1377 * Note that these coordinates are relative to the parent, not to the screen.
1378 *
1379 * @param x the X coordinate of the upper left corner of the rectangle
1380 * @param y the Y coordinate of the upper left corner of the rectangle
1381 * @param width the width of the rectangle
1382 * @param height the height of the rectangle
1383 * @deprecated use {@link #setBounds(int, int, int, int)} instead
1384 */
1385 public void reshape(int x, int y, int width, int height)
1386 {
1387 int oldx = this.x;
1388 int oldy = this.y;
1389 int oldwidth = this.width;
1390 int oldheight = this.height;
1391
1392 if (this.x == x && this.y == y && this.width == width
1393 && this.height == height)
1394 return;
1395
1396 invalidate();
1397
1398 this.x = x;
1399 this.y = y;
1400 this.width = width;
1401 this.height = height;
1402 if (peer != null)
1403 peer.setBounds (x, y, width, height);
1404
1405 // Erase old bounds and repaint new bounds for lightweights.
1406 if (isLightweight() && isShowing())
1407 {
1408 if (parent != null)
1409 {
1410 Rectangle oldBounds = new Rectangle(oldx, oldy, oldwidth,
1411 oldheight);
1412 Rectangle newBounds = new Rectangle(x, y, width, height);
1413 Rectangle destroyed = oldBounds.union(newBounds);
1414 if (!destroyed.isEmpty())
1415 parent.repaint(0, destroyed.x, destroyed.y, destroyed.width,
1416 destroyed.height);
1417 }
1418 }
1419
1420 // Only post event if this component is visible and has changed size.
1421 if (isShowing ()
1422 && (oldx != x || oldy != y))
1423 {
1424 ComponentEvent ce = new ComponentEvent(this,
1425 ComponentEvent.COMPONENT_MOVED);
1426 getToolkit().getSystemEventQueue().postEvent(ce);
1427 }
1428 if (isShowing ()
1429 && (oldwidth != width || oldheight != height))
1430 {
1431 ComponentEvent ce = new ComponentEvent(this,
1432 ComponentEvent.COMPONENT_RESIZED);
1433 getToolkit().getSystemEventQueue().postEvent(ce);
1434 }
1435 }
1436
1437 /**
1438 * Sets the bounding rectangle for this component to the specified
1439 * rectangle. Note that these coordinates are relative to the parent, not
1440 * to the screen.
1441 *
1442 * @param r the new bounding rectangle
1443 * @throws NullPointerException if r is null
1444 * @see #getBounds()
1445 * @see #setLocation(Point)
1446 * @see #setSize(Dimension)
1447 * @since 1.1
1448 */
1449 public void setBounds(Rectangle r)
1450 {
1451 setBounds (r.x, r.y, r.width, r.height);
1452 }
1453
1454 /**
1455 * Gets the x coordinate of the upper left corner. This is more efficient
1456 * than getBounds().x or getLocation().x.
1457 *
1458 * @return the current x coordinate
1459 * @since 1.2
1460 */
1461 public int getX()
1462 {
1463 return x;
1464 }
1465
1466 /**
1467 * Gets the y coordinate of the upper left corner. This is more efficient
1468 * than getBounds().y or getLocation().y.
1469 *
1470 * @return the current y coordinate
1471 * @since 1.2
1472 */
1473 public int getY()
1474 {
1475 return y;
1476 }
1477
1478 /**
1479 * Gets the width of the component. This is more efficient than
1480 * getBounds().width or getSize().width.
1481 *
1482 * @return the current width
1483 * @since 1.2
1484 */
1485 public int getWidth()
1486 {
1487 return width;
1488 }
1489
1490 /**
1491 * Gets the height of the component. This is more efficient than
1492 * getBounds().height or getSize().height.
1493 *
1494 * @return the current width
1495 * @since 1.2
1496 */
1497 public int getHeight()
1498 {
1499 return height;
1500 }
1501
1502 /**
1503 * Returns the bounds of this component. This allows reuse of an existing
1504 * rectangle, if r is non-null.
1505 *
1506 * @param r the rectangle to use, or null
1507 * @return the bounds
1508 */
1509 public Rectangle getBounds(Rectangle r)
1510 {
1511 if (r == null)
1512 r = new Rectangle();
1513 r.x = x;
1514 r.y = y;
1515 r.width = width;
1516 r.height = height;
1517 return r;
1518 }
1519
1520 /**
1521 * Returns the size of this component. This allows reuse of an existing
1522 * dimension, if d is non-null.
1523 *
1524 * @param d the dimension to use, or null
1525 * @return the size
1526 */
1527 public Dimension getSize(Dimension d)
1528 {
1529 if (d == null)
1530 d = new Dimension();
1531 d.width = width;
1532 d.height = height;
1533 return d;
1534 }
1535
1536 /**
1537 * Returns the location of this component. This allows reuse of an existing
1538 * point, if p is non-null.
1539 *
1540 * @param p the point to use, or null
1541 * @return the location
1542 */
1543 public Point getLocation(Point p)
1544 {
1545 if (p == null)
1546 p = new Point();
1547 p.x = x;
1548 p.y = y;
1549 return p;
1550 }
1551
1552 /**
1553 * Tests if this component is opaque. All "heavyweight" (natively-drawn)
1554 * components are opaque. A component is opaque if it draws all pixels in
1555 * the bounds; a lightweight component is partially transparent if it lets
1556 * pixels underneath show through. Subclasses that guarantee that all pixels
1557 * will be drawn should override this.
1558 *
1559 * @return true if this is opaque
1560 * @see #isLightweight()
1561 * @since 1.2
1562 */
1563 public boolean isOpaque()
1564 {
1565 return ! isLightweight();
1566 }
1567
1568 /**
1569 * Return whether the component is lightweight. That means the component has
1570 * no native peer, but is displayable. This applies to subclasses of
1571 * Component not in this package, such as javax.swing.
1572 *
1573 * @return true if the component has a lightweight peer
1574 * @see #isDisplayable()
1575 * @since 1.2
1576 */
1577 public boolean isLightweight()
1578 {
1579 return peer instanceof LightweightPeer;
1580 }
1581
1582 /**
1583 * Returns the component's preferred size.
1584 *
1585 * @return the component's preferred size
1586 * @see #getMinimumSize()
1587 * @see LayoutManager
1588 */
1589 public Dimension getPreferredSize()
1590 {
1591 return preferredSize();
1592 }
1593
1594 /**
1595 * Returns the component's preferred size.
1596 *
1597 * @return the component's preferred size
1598 * @deprecated use {@link #getPreferredSize()} instead
1599 */
1600 public Dimension preferredSize()
1601 {
1602 if (prefSize == null)
1603 {
1604 if (peer == null)
1605 prefSize = minimumSize();
1606 else
1607 prefSize = peer.getPreferredSize();
1608 }
1609 return prefSize;
1610 }
1611
1612 /**
1613 * Returns the component's minimum size.
1614 *
1615 * @return the component's minimum size
1616 * @see #getPreferredSize()
1617 * @see LayoutManager
1618 */
1619 public Dimension getMinimumSize()
1620 {
1621 return minimumSize();
1622 }
1623
1624 /**
1625 * Returns the component's minimum size.
1626 *
1627 * @return the component's minimum size
1628 * @deprecated use {@link #getMinimumSize()} instead
1629 */
1630 public Dimension minimumSize()
1631 {
1632 if (minSize == null)
1633 minSize = (peer != null ? peer.getMinimumSize()
1634 : new Dimension(width, height));
1635 return minSize;
1636 }
1637
1638 /**
1639 * Returns the component's maximum size.
1640 *
1641 * @return the component's maximum size
1642 * @see #getMinimumSize()
1643 * @see #getPreferredSize()
1644 * @see LayoutManager
1645 */
1646 public Dimension getMaximumSize()
1647 {
1648 return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
1649 }
1650
1651 /**
1652 * Returns the preferred horizontal alignment of this component. The value
1653 * returned will be between {@link #LEFT_ALIGNMENT} and
1654 * {@link #RIGHT_ALIGNMENT}, inclusive.
1655 *
1656 * @return the preferred horizontal alignment of this component
1657 */
1658 public float getAlignmentX()
1659 {
1660 return CENTER_ALIGNMENT;
1661 }
1662
1663 /**
1664 * Returns the preferred vertical alignment of this component. The value
1665 * returned will be between {@link #TOP_ALIGNMENT} and
1666 * {@link #BOTTOM_ALIGNMENT}, inclusive.
1667 *
1668 * @return the preferred vertical alignment of this component
1669 */
1670 public float getAlignmentY()
1671 {
1672 return CENTER_ALIGNMENT;
1673 }
1674
1675 /**
1676 * Calls the layout manager to re-layout the component. This is called
1677 * during validation of a container in most cases.
1678 *
1679 * @see #validate()
1680 * @see LayoutManager
1681 */
1682 public void doLayout()
1683 {
1684 layout ();
1685 }
1686
1687 /**
1688 * Calls the layout manager to re-layout the component. This is called
1689 * during validation of a container in most cases.
1690 *
1691 * @deprecated use {@link #doLayout()} instead
1692 */
1693 public void layout()
1694 {
1695 // Nothing to do unless we're a container.
1696 }
1697
1698 /**
1699 * Called to ensure that the layout for this component is valid. This is
1700 * usually called on containers.
1701 *
1702 * @see #invalidate()
1703 * @see #doLayout()
1704 * @see LayoutManager
1705 * @see Container#validate()
1706 */
1707 public void validate()
1708 {
1709 valid = true;
1710 }
1711
1712 /**
1713 * Invalidates this component and all of its parent components. This will
1714 * cause them to have their layout redone. This is called frequently, so
1715 * make it fast.
1716 */
1717 public void invalidate()
1718 {
1719 valid = false;
1720 prefSize = null;
1721 minSize = null;
1722 if (parent != null && parent.isValid())
1723 parent.invalidate();
1724 }
1725
1726 /**
1727 * Returns a graphics object for this component. Returns <code>null</code>
1728 * if this component is not currently displayed on the screen.
1729 *
1730 * @return a graphics object for this component
1731 * @see #paint(Graphics)
1732 */
1733 public Graphics getGraphics()
1734 {
1735 if (peer != null)
1736 {
1737 Graphics gfx = peer.getGraphics();
1738 // Create peer for lightweights.
1739 if (gfx == null && parent != null)
1740 {
1741 gfx = parent.getGraphics();
1742 Rectangle bounds = getBounds();
1743 gfx.setClip(bounds);
1744 gfx.translate(bounds.x, bounds.y);
1745 return gfx;
1746 }
1747 gfx.setFont(font);
1748 return gfx;
1749 }
1750 return null;
1751 }
1752
1753 /**
1754 * Returns the font metrics for the specified font in this component.
1755 *
1756 * @param font the font to retrieve metrics for
1757 * @return the font metrics for the specified font
1758 * @throws NullPointerException if font is null
1759 * @see #getFont()
1760 * @see Toolkit#getFontMetrics(Font)
1761 */
1762 public FontMetrics getFontMetrics(Font font)
1763 {
1764 return peer == null ? getToolkit().getFontMetrics(font)
1765 : peer.getFontMetrics(font);
1766 }
1767
1768 /**
1769 * Sets the cursor for this component to the specified cursor. The cursor
1770 * is displayed when the point is contained by the component, and the
1771 * component is visible, displayable, and enabled. This is inherited by
1772 * subcomponents unless they set their own cursor.
1773 *
1774 * @param cursor the new cursor for this component
1775 * @see #isEnabled()
1776 * @see #isShowing()
1777 * @see #getCursor()
1778 * @see #contains(int, int)
1779 * @see Toolkit#createCustomCursor(Image, Point, String)
1780 */
1781 public void setCursor(Cursor cursor)
1782 {
1783 this.cursor = cursor;
1784 if (peer != null)
1785 peer.setCursor(cursor);
1786 }
1787
1788 /**
1789 * Returns the cursor for this component. If not set, this is inherited
1790 * from the parent, or from Cursor.getDefaultCursor().
1791 *
1792 * @return the cursor for this component
1793 */
1794 public Cursor getCursor()
1795 {
1796 if (cursor != null)
1797 return cursor;
1798 return parent != null ? parent.getCursor() : Cursor.getDefaultCursor();
1799 }
1800
1801 /**
1802 * Tests if the cursor was explicitly set, or just inherited from the parent.
1803 *
1804 * @return true if the cursor has been set
1805 * @since 1.4
1806 */
1807 public boolean isCursorSet()
1808 {
1809 return cursor != null;
1810 }
1811
1812 /**
1813 * Paints this component on the screen. The clipping region in the graphics
1814 * context will indicate the region that requires painting. This is called
1815 * whenever the component first shows, or needs to be repaired because
1816 * something was temporarily drawn on top. It is not necessary for
1817 * subclasses to call <code>super.paint(g)</code>. Components with no area
1818 * are not painted.
1819 *
1820 * @param g the graphics context for this paint job
1821 * @see #update(Graphics)
1822 */
1823 public void paint(Graphics g)
1824 {
1825 // This is a callback method and is meant to be overridden by subclasses
1826 // that want to perform custom painting.
1827 }
1828
1829 /**
1830 * Updates this component. This is called in response to
1831 * <code>repaint</code>. This method fills the component with the
1832 * background color, then sets the foreground color of the specified
1833 * graphics context to the foreground color of this component and calls
1834 * the <code>paint()</code> method. The coordinates of the graphics are
1835 * relative to this component. Subclasses should call either
1836 * <code>super.update(g)</code> or <code>paint(g)</code>.
1837 *
1838 * @param g the graphics context for this update
1839 *
1840 * @see #paint(Graphics)
1841 * @see #repaint()
1842 *
1843 * @specnote In contrast to what the spec says, tests show that the exact
1844 * behaviour is to clear the background on lightweight and
1845 * top-level components only. Heavyweight components are not
1846 * affected by this method and only call paint().
1847 */
1848 public void update(Graphics g)
1849 {
1850 // Tests show that the clearing of the background is only done in
1851 // two cases:
1852 // - If the component is lightweight (yes this is in contrast to the spec).
1853 // or
1854 // - If the component is a toplevel container.
1855 if (isLightweight() || getParent() == null)
1856 {
1857 Rectangle clip = g.getClipBounds();
1858 if (clip == null)
1859 g.clearRect(0, 0, width, height);
1860 else
1861 g.clearRect(clip.x, clip.y, clip.width, clip.height);
1862 }
1863 paint(g);
1864 }
1865
1866 /**
1867 * Paints this entire component, including any sub-components.
1868 *
1869 * @param g the graphics context for this paint job
1870 *
1871 * @see #paint(Graphics)
1872 */
1873 public void paintAll(Graphics g)
1874 {
1875 if (! visible)
1876 return;
1877 paint(g);
1878 }
1879
1880 /**
1881 * Repaint this entire component. The <code>update()</code> method
1882 * on this component will be called as soon as possible.
1883 *
1884 * @see #update(Graphics)
1885 * @see #repaint(long, int, int, int, int)
1886 */
1887 public void repaint()
1888 {
1889 repaint(0, 0, 0, width, height);
1890 }
1891
1892 /**
1893 * Repaint this entire component. The <code>update()</code> method on this
1894 * component will be called in approximate the specified number of
1895 * milliseconds.
1896 *
1897 * @param tm milliseconds before this component should be repainted
1898 * @see #paint(Graphics)
1899 * @see #repaint(long, int, int, int, int)
1900 */
1901 public void repaint(long tm)
1902 {
1903 repaint(tm, 0, 0, width, height);
1904 }
1905
1906 /**
1907 * Repaints the specified rectangular region within this component. The
1908 * <code>update</code> method on this component will be called as soon as
1909 * possible. The coordinates are relative to this component.
1910 *
1911 * @param x the X coordinate of the upper left of the region to repaint
1912 * @param y the Y coordinate of the upper left of the region to repaint
1913 * @param w the width of the region to repaint
1914 * @param h the height of the region to repaint
1915 * @see #update(Graphics)
1916 * @see #repaint(long, int, int, int, int)
1917 */
1918 public void repaint(int x, int y, int w, int h)
1919 {
1920 repaint(0, x, y, w, h);
1921 }
1922
1923 /**
1924 * Repaints the specified rectangular region within this component. The
1925 * <code>update</code> method on this component will be called in
1926 * approximately the specified number of milliseconds. The coordinates
1927 * are relative to this component.
1928 *
1929 * @param tm milliseconds before this component should be repainted
1930 * @param x the X coordinate of the upper left of the region to repaint
1931 * @param y the Y coordinate of the upper left of the region to repaint
1932 * @param width the width of the region to repaint
1933 * @param height the height of the region to repaint
1934 * @see #update(Graphics)
1935 */
1936 public void repaint(long tm, int x, int y, int width, int height)
1937 {
1938 if (isShowing())
1939 {
1940 ComponentPeer p = peer;
1941 if (p != null)
1942 p.repaint(tm, x, y, width, height);
1943 }
1944 }
1945
1946 /**
1947 * Prints this component. This method is provided so that printing can be
1948 * done in a different manner from painting. However, the implementation
1949 * in this class simply calls the <code>paint()</code> method.
1950 *
1951 * @param g the graphics context of the print device
1952 *
1953 * @see #paint(Graphics)
1954 */
1955 public void print(Graphics g)
1956 {
1957 paint(g);
1958 }
1959
1960 /**
1961 * Prints this component, including all sub-components. This method is
1962 * provided so that printing can be done in a different manner from
1963 * painting. However, the implementation in this class simply calls the
1964 * <code>paintAll()</code> method.
1965 *
1966 * @param g the graphics context of the print device
1967 *
1968 * @see #paintAll(Graphics)
1969 */
1970 public void printAll(Graphics g)
1971 {
1972 paintAll(g);
1973 }
1974
1975 /**
1976 * Called when an image has changed so that this component is repainted.
1977 * This incrementally draws an image as more bits are available, when
1978 * possible. Incremental drawing is enabled if the system property
1979 * <code>awt.image.incrementalDraw</code> is not present or is true, in which
1980 * case the redraw rate is set to 100ms or the value of the system property
1981 * <code>awt.image.redrawrate</code>.
1982 *
1983 * <p>The coordinate system used depends on the particular flags.
1984 *
1985 * @param img the image that has been updated
1986 * @param flags tlags as specified in <code>ImageObserver</code>
1987 * @param x the X coordinate
1988 * @param y the Y coordinate
1989 * @param w the width
1990 * @param h the height
1991 * @return false if the image is completely loaded, loading has been
1992 * aborted, or an error has occurred. true if more updates are
1993 * required.
1994 * @see ImageObserver
1995 * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
1996 * @see Graphics#drawImage(Image, int, int, ImageObserver)
1997 * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
1998 * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
1999 * @see ImageObserver#imageUpdate(Image, int, int, int, int, int)
2000 */
2001 public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
2002 {
2003 if ((flags & (FRAMEBITS | ALLBITS)) != 0)
2004 repaint();
2005 else if ((flags & SOMEBITS) != 0)
2006 {
2007 if (incrementalDraw)
2008 {
2009 if (redrawRate != null)
2010 {
2011 long tm = redrawRate.longValue();
2012 if (tm < 0)
2013 tm = 0;
2014 repaint(tm);
2015 }
2016 else
2017 repaint(100);
2018 }
2019 }
2020 return (flags & (ALLBITS | ABORT | ERROR)) == 0;
2021 }
2022
2023 /**
2024 * Creates an image from the specified producer.
2025 *
2026 * @param producer the image procedure to create the image from
2027 * @return the resulting image
2028 */
2029 public Image createImage(ImageProducer producer)
2030 {
2031 // Sun allows producer to be null.
2032 if (peer != null)
2033 return peer.createImage(producer);
2034 else
2035 return getToolkit().createImage(producer);
2036 }
2037
2038 /**
2039 * Creates an image with the specified width and height for use in
2040 * double buffering. Headless environments do not support images.
2041 *
2042 * @param width the width of the image
2043 * @param height the height of the image
2044 * @return the requested image, or null if it is not supported
2045 */
2046 public Image createImage (int width, int height)
2047 {
2048 Image returnValue = null;
2049 if (!GraphicsEnvironment.isHeadless ())
2050 {
2051 if (isLightweight () && parent != null)
2052 returnValue = parent.createImage (width, height);
2053 else if (peer != null)
2054 returnValue = peer.createImage (width, height);
2055 }
2056 return returnValue;
2057 }
2058
2059 /**
2060 * Creates an image with the specified width and height for use in
2061 * double buffering. Headless environments do not support images.
2062 *
2063 * @param width the width of the image
2064 * @param height the height of the image
2065 * @return the requested image, or null if it is not supported
2066 * @since 1.4
2067 */
2068 public VolatileImage createVolatileImage(int width, int height)
2069 {
2070 if (GraphicsEnvironment.isHeadless())
2071 return null;
2072 GraphicsConfiguration config = getGraphicsConfiguration();
2073 return config == null ? null
2074 : config.createCompatibleVolatileImage(width, height);
2075 }
2076
2077 /**
2078 * Creates an image with the specified width and height for use in
2079 * double buffering. Headless environments do not support images. The image
2080 * will support the specified capabilities.
2081 *
2082 * @param width the width of the image
2083 * @param height the height of the image
2084 * @param caps the requested capabilities
2085 * @return the requested image, or null if it is not supported
2086 * @throws AWTException if a buffer with the capabilities cannot be created
2087 * @since 1.4
2088 */
2089 public VolatileImage createVolatileImage(int width, int height,
2090 ImageCapabilities caps)
2091 throws AWTException
2092 {
2093 if (GraphicsEnvironment.isHeadless())
2094 return null;
2095 GraphicsConfiguration config = getGraphicsConfiguration();
2096 return config == null ? null
2097 : config.createCompatibleVolatileImage(width, height, caps);
2098 }
2099
2100 /**
2101 * Prepares the specified image for rendering on this component.
2102 *
2103 * @param image the image to prepare for rendering
2104 * @param observer the observer to notify of image preparation status
2105 * @return true if the image is already fully prepared
2106 * @throws NullPointerException if image is null
2107 */
2108 public boolean prepareImage(Image image, ImageObserver observer)
2109 {
2110 return prepareImage(image, image.getWidth(observer),
2111 image.getHeight(observer), observer);
2112 }
2113
2114 /**
2115 * Prepares the specified image for rendering on this component at the
2116 * specified scaled width and height
2117 *
2118 * @param image the image to prepare for rendering
2119 * @param width the scaled width of the image
2120 * @param height the scaled height of the image
2121 * @param observer the observer to notify of image preparation status
2122 * @return true if the image is already fully prepared
2123 */
2124 public boolean prepareImage(Image image, int width, int height,
2125 ImageObserver observer)
2126 {
2127 if (peer != null)
2128 return peer.prepareImage(image, width, height, observer);
2129 else
2130 return getToolkit().prepareImage(image, width, height, observer);
2131 }
2132
2133 /**
2134 * Returns the status of the loading of the specified image. The value
2135 * returned will be those flags defined in <code>ImageObserver</code>.
2136 *
2137 * @param image the image to check on
2138 * @param observer the observer to notify of image loading progress
2139 * @return the image observer flags indicating the status of the load
2140 * @see #prepareImage(Image, int, int, ImageObserver)
2141 * @see Toolkit#checkImage(Image, int, int, ImageObserver)
2142 * @throws NullPointerException if image is null
2143 */
2144 public int checkImage(Image image, ImageObserver observer)
2145 {
2146 return checkImage(image, -1, -1, observer);
2147 }
2148
2149 /**
2150 * Returns the status of the loading of the specified image. The value
2151 * returned will be those flags defined in <code>ImageObserver</code>.
2152 *
2153 * @param image the image to check on
2154 * @param width the scaled image width
2155 * @param height the scaled image height
2156 * @param observer the observer to notify of image loading progress
2157 * @return the image observer flags indicating the status of the load
2158 * @see #prepareImage(Image, int, int, ImageObserver)
2159 * @see Toolkit#checkImage(Image, int, int, ImageObserver)
2160 */
2161 public int checkImage(Image image, int width, int height,
2162 ImageObserver observer)
2163 {
2164 if (peer != null)
2165 return peer.checkImage(image, width, height, observer);
2166 return getToolkit().checkImage(image, width, height, observer);
2167 }
2168
2169 /**
2170 * Sets whether paint messages delivered by the operating system should be
2171 * ignored. This does not affect messages from AWT, except for those
2172 * triggered by OS messages. Setting this to true can allow faster
2173 * performance in full-screen mode or page-flipping.
2174 *
2175 * @param ignoreRepaint the new setting for ignoring repaint events
2176 * @see #getIgnoreRepaint()
2177 * @see BufferStrategy
2178 * @see GraphicsDevice#setFullScreenWindow(Window)
2179 * @since 1.4
2180 */
2181 public void setIgnoreRepaint(boolean ignoreRepaint)
2182 {
2183 this.ignoreRepaint = ignoreRepaint;
2184 }
2185
2186 /**
2187 * Test whether paint events from the operating system are ignored.
2188 *
2189 * @return the status of ignoring paint events
2190 * @see #setIgnoreRepaint(boolean)
2191 * @since 1.4
2192 */
2193 public boolean getIgnoreRepaint()
2194 {
2195 return ignoreRepaint;
2196 }
2197
2198 /**
2199 * Tests whether or not the specified point is contained within this
2200 * component. Coordinates are relative to this component.
2201 *
2202 * @param x the X coordinate of the point to test
2203 * @param y the Y coordinate of the point to test
2204 * @return true if the point is within this component
2205 * @see #getComponentAt(int, int)
2206 */
2207 public boolean contains(int x, int y)
2208 {
2209 return inside (x, y);
2210 }
2211
2212 /**
2213 * Tests whether or not the specified point is contained within this
2214 * component. Coordinates are relative to this component.
2215 *
2216 * @param x the X coordinate of the point to test
2217 * @param y the Y coordinate of the point to test
2218 * @return true if the point is within this component
2219 * @deprecated use {@link #contains(int, int)} instead
2220 */
2221 public boolean inside(int x, int y)
2222 {
2223 return x >= 0 && y >= 0 && x < width && y < height;
2224 }
2225
2226 /**
2227 * Tests whether or not the specified point is contained within this
2228 * component. Coordinates are relative to this component.
2229 *
2230 * @param p the point to test
2231 * @return true if the point is within this component
2232 * @throws NullPointerException if p is null
2233 * @see #getComponentAt(Point)
2234 * @since 1.1
2235 */
2236 public boolean contains(Point p)
2237 {
2238 return contains (p.x, p.y);
2239 }
2240
2241 /**
2242 * Returns the component occupying the position (x,y). This will either
2243 * be this component, an immediate child component, or <code>null</code>
2244 * if neither of the first two occupies the specified location.
2245 *
2246 * @param x the X coordinate to search for components at
2247 * @param y the Y coordinate to search for components at
2248 * @return the component at the specified location, or null
2249 * @see #contains(int, int)
2250 */
2251 public Component getComponentAt(int x, int y)
2252 {
2253 return locate (x, y);
2254 }
2255
2256 /**
2257 * Returns the component occupying the position (x,y). This will either
2258 * be this component, an immediate child component, or <code>null</code>
2259 * if neither of the first two occupies the specified location.
2260 *
2261 * @param x the X coordinate to search for components at
2262 * @param y the Y coordinate to search for components at
2263 * @return the component at the specified location, or null
2264 * @deprecated use {@link #getComponentAt(int, int)} instead
2265 */
2266 public Component locate(int x, int y)
2267 {
2268 return contains (x, y) ? this : null;
2269 }
2270
2271 /**
2272 * Returns the component occupying the position (x,y). This will either
2273 * be this component, an immediate child component, or <code>null</code>
2274 * if neither of the first two occupies the specified location.
2275 *
2276 * @param p the point to search for components at
2277 * @return the component at the specified location, or null
2278 * @throws NullPointerException if p is null
2279 * @see #contains(Point)
2280 * @since 1.1
2281 */
2282 public Component getComponentAt(Point p)
2283 {
2284 return getComponentAt (p.x, p.y);
2285 }
2286
2287 /**
2288 * AWT 1.0 event delivery.
2289 *
2290 * Deliver an AWT 1.0 event to this Component. This method simply
2291 * calls {@link #postEvent}.
2292 *
2293 * @param e the event to deliver
2294 * @deprecated use {@link #dispatchEvent (AWTEvent)} instead
2295 */
2296 public void deliverEvent (Event e)
2297 {
2298 postEvent (e);
2299 }
2300
2301 /**
2302 * Forwards AWT events to processEvent() if:<ul>
2303 * <li>Events have been enabled for this type of event via
2304 * <code>enableEvents()</code></li>,
2305 * <li>There is at least one registered listener for this type of event</li>
2306 * </ul>
2307 *
2308 * @param e the event to dispatch
2309 */
2310 public final void dispatchEvent(AWTEvent e)
2311 {
2312 Event oldEvent = translateEvent(e);
2313 if (oldEvent != null)
2314 postEvent (oldEvent);
2315
2316 // Give toolkit a chance to dispatch the event
2317 // to globally registered listeners.
2318 Toolkit.getDefaultToolkit().globalDispatchEvent(e);
2319
2320 // Some subclasses in the AWT package need to override this behavior,
2321 // hence the use of dispatchEventImpl().
2322 dispatchEventImpl(e);
2323 }
2324
2325 /**
2326 * AWT 1.0 event handler.
2327 *
2328 * This method simply calls handleEvent and returns the result.
2329 *
2330 * @param e the event to handle
2331 * @return true if the event was handled, false otherwise
2332 * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
2333 */
2334 public boolean postEvent (Event e)
2335 {
2336 boolean handled = handleEvent (e);
2337
2338 if (!handled && getParent() != null)
2339 // FIXME: need to translate event coordinates to parent's
2340 // coordinate space.
2341 handled = getParent ().postEvent (e);
2342
2343 return handled;
2344 }
2345
2346 /**
2347 * Adds the specified listener to this component. This is harmless if the
2348 * listener is null, but if the listener has already been registered, it
2349 * will now be registered twice.
2350 *
2351 * @param listener the new listener to add
2352 * @see ComponentEvent
2353 * @see #removeComponentListener(ComponentListener)
2354 * @see #getComponentListeners()
2355 * @since 1.1
2356 */
2357 public synchronized void addComponentListener(ComponentListener listener)
2358 {
2359 componentListener = AWTEventMulticaster.add(componentListener, listener);
2360 if (componentListener != null)
2361 enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
2362 }
2363
2364 /**
2365 * Removes the specified listener from the component. This is harmless if
2366 * the listener was not previously registered.
2367 *
2368 * @param listener the listener to remove
2369 * @see ComponentEvent
2370 * @see #addComponentListener(ComponentListener)
2371 * @see #getComponentListeners()
2372 * @since 1.1
2373 */
2374 public synchronized void removeComponentListener(ComponentListener listener)
2375 {
2376 componentListener = AWTEventMulticaster.remove(componentListener, listener);
2377 }
2378
2379 /**
2380 * Returns an array of all specified listeners registered on this component.
2381 *
2382 * @return an array of listeners
2383 * @see #addComponentListener(ComponentListener)
2384 * @see #removeComponentListener(ComponentListener)
2385 * @since 1.4
2386 */
2387 public synchronized ComponentListener[] getComponentListeners()
2388 {
2389 return (ComponentListener[])
2390 AWTEventMulticaster.getListeners(componentListener,
2391 ComponentListener.class);
2392 }
2393
2394 /**
2395 * Adds the specified listener to this component. This is harmless if the
2396 * listener is null, but if the listener has already been registered, it
2397 * will now be registered twice.
2398 *
2399 * @param listener the new listener to add
2400 * @see FocusEvent
2401 * @see #removeFocusListener(FocusListener)
2402 * @see #getFocusListeners()
2403 * @since 1.1
2404 */
2405 public synchronized void addFocusListener(FocusListener listener)
2406 {
2407 focusListener = AWTEventMulticaster.add(focusListener, listener);
2408 if (focusListener != null)
2409 enableEvents(AWTEvent.FOCUS_EVENT_MASK);
2410 }
2411
2412 /**
2413 * Removes the specified listener from the component. This is harmless if
2414 * the listener was not previously registered.
2415 *
2416 * @param listener the listener to remove
2417 * @see FocusEvent
2418 * @see #addFocusListener(FocusListener)
2419 * @see #getFocusListeners()
2420 * @since 1.1
2421 */
2422 public synchronized void removeFocusListener(FocusListener listener)
2423 {
2424 focusListener = AWTEventMulticaster.remove(focusListener, listener);
2425 }
2426
2427 /**
2428 * Returns an array of all specified listeners registered on this component.
2429 *
2430 * @return an array of listeners
2431 * @see #addFocusListener(FocusListener)
2432 * @see #removeFocusListener(FocusListener)
2433 * @since 1.4
2434 */
2435 public synchronized FocusListener[] getFocusListeners()
2436 {
2437 return (FocusListener[])
2438 AWTEventMulticaster.getListeners(focusListener, FocusListener.class);
2439 }
2440
2441 /**
2442 * Adds the specified listener to this component. This is harmless if the
2443 * listener is null, but if the listener has already been registered, it
2444 * will now be registered twice.
2445 *
2446 * @param listener the new listener to add
2447 * @see HierarchyEvent
2448 * @see #removeHierarchyListener(HierarchyListener)
2449 * @see #getHierarchyListeners()
2450 * @since 1.3
2451 */
2452 public synchronized void addHierarchyListener(HierarchyListener listener)
2453 {
2454 hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener);
2455 if (hierarchyListener != null)
2456 enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
2457 }
2458
2459 /**
2460 * Removes the specified listener from the component. This is harmless if
2461 * the listener was not previously registered.
2462 *
2463 * @param listener the listener to remove
2464 * @see HierarchyEvent
2465 * @see #addHierarchyListener(HierarchyListener)
2466 * @see #getHierarchyListeners()
2467 * @since 1.3
2468 */
2469 public synchronized void removeHierarchyListener(HierarchyListener listener)
2470 {
2471 hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
2472 }
2473
2474 /**
2475 * Returns an array of all specified listeners registered on this component.
2476 *
2477 * @return an array of listeners
2478 * @see #addHierarchyListener(HierarchyListener)
2479 * @see #removeHierarchyListener(HierarchyListener)
2480 * @since 1.4
2481 */
2482 public synchronized HierarchyListener[] getHierarchyListeners()
2483 {
2484 return (HierarchyListener[])
2485 AWTEventMulticaster.getListeners(hierarchyListener,
2486 HierarchyListener.class);
2487 }
2488
2489 /**
2490 * Adds the specified listener to this component. This is harmless if the
2491 * listener is null, but if the listener has already been registered, it
2492 * will now be registered twice.
2493 *
2494 * @param listener the new listener to add
2495 * @see HierarchyEvent
2496 * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
2497 * @see #getHierarchyBoundsListeners()
2498 * @since 1.3
2499 */
2500 public synchronized void
2501 addHierarchyBoundsListener(HierarchyBoundsListener listener)
2502 {
2503 hierarchyBoundsListener =
2504 AWTEventMulticaster.add(hierarchyBoundsListener, listener);
2505 if (hierarchyBoundsListener != null)
2506 enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
2507 }
2508
2509 /**
2510 * Removes the specified listener from the component. This is harmless if
2511 * the listener was not previously registered.
2512 *
2513 * @param listener the listener to remove
2514 * @see HierarchyEvent
2515 * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
2516 * @see #getHierarchyBoundsListeners()
2517 * @since 1.3
2518 */
2519 public synchronized void
2520 removeHierarchyBoundsListener(HierarchyBoundsListener listener)
2521 {
2522 hierarchyBoundsListener =
2523 AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
2524 }
2525
2526 /**
2527 * Returns an array of all specified listeners registered on this component.
2528 *
2529 * @return an array of listeners
2530 * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
2531 * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
2532 * @since 1.4
2533 */
2534 public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
2535 {
2536 return (HierarchyBoundsListener[])
2537 AWTEventMulticaster.getListeners(hierarchyBoundsListener,
2538 HierarchyBoundsListener.class);
2539 }
2540
2541 /**
2542 * Adds the specified listener to this component. This is harmless if the
2543 * listener is null, but if the listener has already been registered, it
2544 * will now be registered twice.
2545 *
2546 * @param listener the new listener to add
2547 * @see KeyEvent
2548 * @see #removeKeyListener(KeyListener)
2549 * @see #getKeyListeners()
2550 * @since 1.1
2551 */
2552 public synchronized void addKeyListener(KeyListener listener)
2553 {
2554 keyListener = AWTEventMulticaster.add(keyListener, listener);
2555 if (keyListener != null)
2556 enableEvents(AWTEvent.KEY_EVENT_MASK);
2557 }
2558
2559 /**
2560 * Removes the specified listener from the component. This is harmless if
2561 * the listener was not previously registered.
2562 *
2563 * @param listener the listener to remove
2564 * @see KeyEvent
2565 * @see #addKeyListener(KeyListener)
2566 * @see #getKeyListeners()
2567 * @since 1.1
2568 */
2569 public synchronized void removeKeyListener(KeyListener listener)
2570 {
2571 keyListener = AWTEventMulticaster.remove(keyListener, listener);
2572 }
2573
2574 /**
2575 * Returns an array of all specified listeners registered on this component.
2576 *
2577 * @return an array of listeners
2578 * @see #addKeyListener(KeyListener)
2579 * @see #removeKeyListener(KeyListener)
2580 * @since 1.4
2581 */
2582 public synchronized KeyListener[] getKeyListeners()
2583 {
2584 return (KeyListener[])
2585 AWTEventMulticaster.getListeners(keyListener, KeyListener.class);
2586 }
2587
2588 /**
2589 * Adds the specified listener to this component. This is harmless if the
2590 * listener is null, but if the listener has already been registered, it
2591 * will now be registered twice.
2592 *
2593 * @param listener the new listener to add
2594 * @see MouseEvent
2595 * @see #removeMouseListener(MouseListener)
2596 * @see #getMouseListeners()
2597 * @since 1.1
2598 */
2599 public synchronized void addMouseListener(MouseListener listener)
2600 {
2601 mouseListener = AWTEventMulticaster.add(mouseListener, listener);
2602 if (mouseListener != null)
2603 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
2604 }
2605
2606 /**
2607 * Removes the specified listener from the component. This is harmless if
2608 * the listener was not previously registered.
2609 *
2610 * @param listener the listener to remove
2611 * @see MouseEvent
2612 * @see #addMouseListener(MouseListener)
2613 * @see #getMouseListeners()
2614 * @since 1.1
2615 */
2616 public synchronized void removeMouseListener(MouseListener listener)
2617 {
2618 mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
2619 }
2620
2621 /**
2622 * Returns an array of all specified listeners registered on this component.
2623 *
2624 * @return an array of listeners
2625 * @see #addMouseListener(MouseListener)
2626 * @see #removeMouseListener(MouseListener)
2627 * @since 1.4
2628 */
2629 public synchronized MouseListener[] getMouseListeners()
2630 {
2631 return (MouseListener[])
2632 AWTEventMulticaster.getListeners(mouseListener, MouseListener.class);
2633 }
2634
2635 /**
2636 * Adds the specified listener to this component. This is harmless if the
2637 * listener is null, but if the listener has already been registered, it
2638 * will now be registered twice.
2639 *
2640 * @param listener the new listener to add
2641 * @see MouseEvent
2642 * @see #removeMouseMotionListener(MouseMotionListener)
2643 * @see #getMouseMotionListeners()
2644 * @since 1.1
2645 */
2646 public synchronized void addMouseMotionListener(MouseMotionListener listener)
2647 {
2648 mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener);
2649 if (mouseMotionListener != null)
2650 enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
2651 }
2652
2653 /**
2654 * Removes the specified listener from the component. This is harmless if
2655 * the listener was not previously registered.
2656 *
2657 * @param listener the listener to remove
2658 * @see MouseEvent
2659 * @see #addMouseMotionListener(MouseMotionListener)
2660 * @see #getMouseMotionListeners()
2661 * @since 1.1
2662 */
2663 public synchronized void removeMouseMotionListener(MouseMotionListener listener)
2664 {
2665 mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
2666 }
2667
2668 /**
2669 * Returns an array of all specified listeners registered on this component.
2670 *
2671 * @return an array of listeners
2672 * @see #addMouseMotionListener(MouseMotionListener)
2673 * @see #removeMouseMotionListener(MouseMotionListener)
2674 * @since 1.4
2675 */
2676 public synchronized MouseMotionListener[] getMouseMotionListeners()
2677 {
2678 return (MouseMotionListener[])
2679 AWTEventMulticaster.getListeners(mouseMotionListener,
2680 MouseMotionListener.class);
2681 }
2682
2683 /**
2684 * Adds the specified listener to this component. This is harmless if the
2685 * listener is null, but if the listener has already been registered, it
2686 * will now be registered twice.
2687 *
2688 * @param listener the new listener to add
2689 * @see MouseEvent
2690 * @see MouseWheelEvent
2691 * @see #removeMouseWheelListener(MouseWheelListener)
2692 * @see #getMouseWheelListeners()
2693 * @since 1.4
2694 */
2695 public synchronized void addMouseWheelListener(MouseWheelListener listener)
2696 {
2697 mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener);
2698 if (mouseWheelListener != null)
2699 enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
2700 }
2701
2702 /**
2703 * Removes the specified listener from the component. This is harmless if
2704 * the listener was not previously registered.
2705 *
2706 * @param listener the listener to remove
2707 * @see MouseEvent
2708 * @see MouseWheelEvent
2709 * @see #addMouseWheelListener(MouseWheelListener)
2710 * @see #getMouseWheelListeners()
2711 * @since 1.4
2712 */
2713 public synchronized void removeMouseWheelListener(MouseWheelListener listener)
2714 {
2715 mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener);
2716 }
2717
2718 /**
2719 * Returns an array of all specified listeners registered on this component.
2720 *
2721 * @return an array of listeners
2722 * @see #addMouseWheelListener(MouseWheelListener)
2723 * @see #removeMouseWheelListener(MouseWheelListener)
2724 * @since 1.4
2725 */
2726 public synchronized MouseWheelListener[] getMouseWheelListeners()
2727 {
2728 return (MouseWheelListener[])
2729 AWTEventMulticaster.getListeners(mouseWheelListener,
2730 MouseWheelListener.class);
2731 }
2732
2733 /**
2734 * Adds the specified listener to this component. This is harmless if the
2735 * listener is null, but if the listener has already been registered, it
2736 * will now be registered twice.
2737 *
2738 * @param listener the new listener to add
2739 * @see InputMethodEvent
2740 * @see #removeInputMethodListener(InputMethodListener)
2741 * @see #getInputMethodListeners()
2742 * @see #getInputMethodRequests()
2743 * @since 1.2
2744 */
2745 public synchronized void addInputMethodListener(InputMethodListener listener)
2746 {
2747 inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener);
2748 if (inputMethodListener != null)
2749 enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);
2750 }
2751
2752 /**
2753 * Removes the specified listener from the component. This is harmless if
2754 * the listener was not previously registered.
2755 *
2756 * @param listener the listener to remove
2757 * @see InputMethodEvent
2758 * @see #addInputMethodListener(InputMethodListener)
2759 * @see #getInputMethodRequests()
2760 * @since 1.2
2761 */
2762 public synchronized void removeInputMethodListener(InputMethodListener listener)
2763 {
2764 inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
2765 }
2766
2767 /**
2768 * Returns an array of all specified listeners registered on this component.
2769 *
2770 * @return an array of listeners
2771 * @see #addInputMethodListener(InputMethodListener)
2772 * @see #removeInputMethodListener(InputMethodListener)
2773 * @since 1.4
2774 */
2775 public synchronized InputMethodListener[] getInputMethodListeners()
2776 {
2777 return (InputMethodListener[])
2778 AWTEventMulticaster.getListeners(inputMethodListener,
2779 InputMethodListener.class);
2780 }
2781
2782 /**
2783 * Returns all registered {@link EventListener}s of the given
2784 * <code>listenerType</code>.
2785 *
2786 * @param listenerType the class of listeners to filter (<code>null</code>
2787 * not permitted).
2788 *
2789 * @return An array of registered listeners.
2790 *
2791 * @throws ClassCastException if <code>listenerType</code> does not implement
2792 * the {@link EventListener} interface.
2793 * @throws NullPointerException if <code>listenerType</code> is
2794 * <code>null</code>.
2795 *
2796 * @see #getComponentListeners()
2797 * @see #getFocusListeners()
2798 * @see #getHierarchyListeners()
2799 * @see #getHierarchyBoundsListeners()
2800 * @see #getKeyListeners()
2801 * @see #getMouseListeners()
2802 * @see #getMouseMotionListeners()
2803 * @see #getMouseWheelListeners()
2804 * @see #getInputMethodListeners()
2805 * @see #getPropertyChangeListeners()
2806 * @since 1.3
2807 */
2808 public EventListener[] getListeners(Class listenerType)
2809 {
2810 if (listenerType == ComponentListener.class)
2811 return getComponentListeners();
2812 if (listenerType == FocusListener.class)
2813 return getFocusListeners();
2814 if (listenerType == HierarchyListener.class)
2815 return getHierarchyListeners();
2816 if (listenerType == HierarchyBoundsListener.class)
2817 return getHierarchyBoundsListeners();
2818 if (listenerType == KeyListener.class)
2819 return getKeyListeners();
2820 if (listenerType == MouseListener.class)
2821 return getMouseListeners();
2822 if (listenerType == MouseMotionListener.class)
2823 return getMouseMotionListeners();
2824 if (listenerType == MouseWheelListener.class)
2825 return getMouseWheelListeners();
2826 if (listenerType == InputMethodListener.class)
2827 return getInputMethodListeners();
2828 if (listenerType == PropertyChangeListener.class)
2829 return getPropertyChangeListeners();
2830 return (EventListener[]) Array.newInstance(listenerType, 0);
2831 }
2832
2833 /**
2834 * Returns the input method request handler, for subclasses which support
2835 * on-the-spot text input. By default, input methods are handled by AWT,
2836 * and this returns null.
2837 *
2838 * @return the input method handler, null by default
2839 * @since 1.2
2840 */
2841 public InputMethodRequests getInputMethodRequests()
2842 {
2843 return null;
2844 }
2845
2846 /**
2847 * Gets the input context of this component, which is inherited from the
2848 * parent unless this is overridden.
2849 *
2850 * @return the text input context
2851 * @since 1.2
2852 */
2853 public InputContext getInputContext()
2854 {
2855 return parent == null ? null : parent.getInputContext();
2856 }
2857
2858 /**
2859 * Enables the specified events. The events to enable are specified
2860 * by OR-ing together the desired masks from <code>AWTEvent</code>.
2861 *
2862 * <p>Events are enabled by default when a listener is attached to the
2863 * component for that event type. This method can be used by subclasses
2864 * to ensure the delivery of a specified event regardless of whether
2865 * or not a listener is attached.
2866 *
2867 * @param eventsToEnable the desired events to enable
2868 * @see #processEvent(AWTEvent)
2869 * @see #disableEvents(long)
2870 * @see AWTEvent
2871 * @since 1.1
2872 */
2873 protected final void enableEvents(long eventsToEnable)
2874 {
2875 eventMask |= eventsToEnable;
2876 // TODO: Unlike Sun's implementation, I think we should try and
2877 // enable/disable events at the peer (gtk/X) level. This will avoid
2878 // clogging the event pipeline with useless mousemove events that
2879 // we arn't interested in, etc. This will involve extending the peer
2880 // interface, but thats okay because the peer interfaces have been
2881 // deprecated for a long time, and no longer feature in the
2882 // API specification at all.
2883 if (isLightweight() && parent != null)
2884 parent.enableEvents(eventsToEnable);
2885 else if (peer != null)
2886 peer.setEventMask(eventMask);
2887 }
2888
2889 /**
2890 * Disables the specified events. The events to disable are specified
2891 * by OR-ing together the desired masks from <code>AWTEvent</code>.
2892 *
2893 * @param eventsToDisable the desired events to disable
2894 * @see #enableEvents(long)
2895 * @since 1.1
2896 */
2897 protected final void disableEvents(long eventsToDisable)
2898 {
2899 eventMask &= ~eventsToDisable;
2900 // forward new event mask to peer?
2901 }
2902
2903 /**
2904 * This is called by the EventQueue if two events with the same event id
2905 * and owner component are queued. Returns a new combined event, or null if
2906 * no combining is done. The coelesced events are currently mouse moves
2907 * (intermediate ones are discarded) and paint events (a merged paint is
2908 * created in place of the two events).
2909 *
2910 * @param existingEvent the event on the queue
2911 * @param newEvent the new event that might be entered on the queue
2912 * @return null if both events are kept, or the replacement coelesced event
2913 */
2914 protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
2915 {
2916 switch (existingEvent.id)
2917 {
2918 case MouseEvent.MOUSE_MOVED:
2919 case MouseEvent.MOUSE_DRAGGED:
2920 // Just drop the old (intermediate) event and return the new one.
2921 return newEvent;
2922 case PaintEvent.PAINT:
2923 case PaintEvent.UPDATE:
2924 return coalescePaintEvents((PaintEvent) existingEvent,
2925 (PaintEvent) newEvent);
2926 default:
2927 return null;
2928 }
2929 }
2930
2931 /**
2932 * Processes the specified event. In this class, this method simply
2933 * calls one of the more specific event handlers.
2934 *
2935 * @param e the event to process
2936 * @throws NullPointerException if e is null
2937 * @see #processComponentEvent(ComponentEvent)
2938 * @see #processFocusEvent(FocusEvent)
2939 * @see #processKeyEvent(KeyEvent)
2940 * @see #processMouseEvent(MouseEvent)
2941 * @see #processMouseMotionEvent(MouseEvent)
2942 * @see #processInputMethodEvent(InputMethodEvent)
2943 * @see #processHierarchyEvent(HierarchyEvent)
2944 * @see #processMouseWheelEvent(MouseWheelEvent)
2945 * @since 1.1
2946 */
2947 protected void processEvent(AWTEvent e)
2948 {
2949 /* Note: the order of these if statements are
2950 important. Subclasses must be checked first. Eg. MouseEvent
2951 must be checked before ComponentEvent, since a MouseEvent
2952 object is also an instance of a ComponentEvent. */
2953
2954 if (e instanceof FocusEvent)
2955 processFocusEvent((FocusEvent) e);
2956 else if (e instanceof MouseWheelEvent)
2957 processMouseWheelEvent((MouseWheelEvent) e);
2958 else if (e instanceof MouseEvent)
2959 {
2960 if (e.id == MouseEvent.MOUSE_MOVED
2961 || e.id == MouseEvent.MOUSE_DRAGGED)
2962 processMouseMotionEvent((MouseEvent) e);
2963 else
2964 processMouseEvent((MouseEvent) e);
2965 }
2966 else if (e instanceof KeyEvent)
2967 processKeyEvent((KeyEvent) e);
2968 else if (e instanceof InputMethodEvent)
2969 processInputMethodEvent((InputMethodEvent) e);
2970 else if (e instanceof ComponentEvent)
2971 processComponentEvent((ComponentEvent) e);
2972 else if (e instanceof HierarchyEvent)
2973 {
2974 if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
2975 processHierarchyEvent((HierarchyEvent) e);
2976 else
2977 processHierarchyBoundsEvent((HierarchyEvent) e);
2978 }
2979 }
2980
2981 /**
2982 * Called when a component event is dispatched and component events are
2983 * enabled. This method passes the event along to any listeners
2984 * that are attached.
2985 *
2986 * @param e the <code>ComponentEvent</code> to process
2987 * @throws NullPointerException if e is null
2988 * @see ComponentListener
2989 * @see #addComponentListener(ComponentListener)
2990 * @see #enableEvents(long)
2991 * @since 1.1
2992 */
2993 protected void processComponentEvent(ComponentEvent e)
2994 {
2995 if (componentListener == null)
2996 return;
2997 switch (e.id)
2998 {
2999 case ComponentEvent.COMPONENT_HIDDEN:
3000 componentListener.componentHidden(e);
3001 break;
3002 case ComponentEvent.COMPONENT_MOVED:
3003 componentListener.componentMoved(e);
3004 break;
3005 case ComponentEvent.COMPONENT_RESIZED:
3006 componentListener.componentResized(e);
3007 break;
3008 case ComponentEvent.COMPONENT_SHOWN:
3009 componentListener.componentShown(e);
3010 break;
3011 }
3012 }
3013
3014 /**
3015 * Called when a focus event is dispatched and component events are
3016 * enabled. This method passes the event along to any listeners
3017 * that are attached.
3018 *
3019 * @param e the <code>FocusEvent</code> to process
3020 * @throws NullPointerException if e is null
3021 * @see FocusListener
3022 * @see #addFocusListener(FocusListener)
3023 * @see #enableEvents(long)
3024 * @since 1.1
3025 */
3026 protected void processFocusEvent(FocusEvent e)
3027 {
3028 if (focusListener == null)
3029 return;
3030
3031 switch (e.id)
3032 {
3033 case FocusEvent.FOCUS_GAINED:
3034 focusListener.focusGained(e);
3035 break;
3036 case FocusEvent.FOCUS_LOST:
3037 focusListener.focusLost(e);
3038 break;
3039 }
3040 }
3041
3042 /**
3043 * Called when a key event is dispatched and component events are
3044 * enabled. This method passes the event along to any listeners
3045 * that are attached.
3046 *
3047 * @param e the <code>KeyEvent</code> to process
3048 * @throws NullPointerException if e is null
3049 * @see KeyListener
3050 * @see #addKeyListener(KeyListener)
3051 * @see #enableEvents(long)
3052 * @since 1.1
3053 */
3054 protected void processKeyEvent(KeyEvent e)
3055 {
3056 if (keyListener == null)
3057 return;
3058 switch (e.id)
3059 {
3060 case KeyEvent.KEY_PRESSED:
3061 keyListener.keyPressed(e);
3062 break;
3063 case KeyEvent.KEY_RELEASED:
3064 keyListener.keyReleased(e);
3065 break;
3066 case KeyEvent.KEY_TYPED:
3067 keyListener.keyTyped(e);
3068 break;
3069 }
3070 }
3071
3072 /**
3073 * Called when a regular mouse event is dispatched and component events are
3074 * enabled. This method passes the event along to any listeners
3075 * that are attached.
3076 *
3077 * @param e the <code>MouseEvent</code> to process
3078 * @throws NullPointerException if e is null
3079 * @see MouseListener
3080 * @see #addMouseListener(MouseListener)
3081 * @see #enableEvents(long)
3082 * @since 1.1
3083 */
3084 protected void processMouseEvent(MouseEvent e)
3085 {
3086 if (mouseListener == null)
3087 return;
3088 switch (e.id)
3089 {
3090 case MouseEvent.MOUSE_CLICKED:
3091 mouseListener.mouseClicked(e);
3092 break;
3093 case MouseEvent.MOUSE_ENTERED:
3094 if( isLightweight() )
3095 setCursor( getCursor() );
3096 mouseListener.mouseEntered(e);
3097 break;
3098 case MouseEvent.MOUSE_EXITED:
3099 mouseListener.mouseExited(e);
3100 break;
3101 case MouseEvent.MOUSE_PRESSED:
3102 mouseListener.mousePressed(e);
3103 break;
3104 case MouseEvent.MOUSE_RELEASED:
3105 mouseListener.mouseReleased(e);
3106 break;
3107 }
3108 }
3109
3110 /**
3111 * Called when a mouse motion event is dispatched and component events are
3112 * enabled. This method passes the event along to any listeners
3113 * that are attached.
3114 *
3115 * @param e the <code>MouseMotionEvent</code> to process
3116 * @throws NullPointerException if e is null
3117 * @see MouseMotionListener
3118 * @see #addMouseMotionListener(MouseMotionListener)
3119 * @see #enableEvents(long)
3120 * @since 1.1
3121 */
3122 protected void processMouseMotionEvent(MouseEvent e)
3123 {
3124 if (mouseMotionListener == null)
3125 return;
3126 switch (e.id)
3127 {
3128 case MouseEvent.MOUSE_DRAGGED:
3129 mouseMotionListener.mouseDragged(e);
3130 break;
3131 case MouseEvent.MOUSE_MOVED:
3132 mouseMotionListener.mouseMoved(e);
3133 break;
3134 }
3135 e.consume();
3136 }
3137
3138 /**
3139 * Called when a mouse wheel event is dispatched and component events are
3140 * enabled. This method passes the event along to any listeners that are
3141 * attached.
3142 *
3143 * @param e the <code>MouseWheelEvent</code> to process
3144 * @throws NullPointerException if e is null
3145 * @see MouseWheelListener
3146 * @see #addMouseWheelListener(MouseWheelListener)
3147 * @see #enableEvents(long)
3148 * @since 1.4
3149 */
3150 protected void processMouseWheelEvent(MouseWheelEvent e)
3151 {
3152 if (mouseWheelListener != null
3153 && e.id == MouseEvent.MOUSE_WHEEL)
3154 {
3155 mouseWheelListener.mouseWheelMoved(e);
3156 e.consume();
3157 }
3158 }
3159
3160 /**
3161 * Called when an input method event is dispatched and component events are
3162 * enabled. This method passes the event along to any listeners that are
3163 * attached.
3164 *
3165 * @param e the <code>InputMethodEvent</code> to process
3166 * @throws NullPointerException if e is null
3167 * @see InputMethodListener
3168 * @see #addInputMethodListener(InputMethodListener)
3169 * @see #enableEvents(long)
3170 * @since 1.2
3171 */
3172 protected void processInputMethodEvent(InputMethodEvent e)
3173 {
3174 if (inputMethodListener == null)
3175 return;
3176 switch (e.id)
3177 {
3178 case InputMethodEvent.CARET_POSITION_CHANGED:
3179 inputMethodListener.caretPositionChanged(e);
3180 break;
3181 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
3182 inputMethodListener.inputMethodTextChanged(e);
3183 break;
3184 }
3185 }
3186
3187 /**
3188 * Called when a hierarchy change event is dispatched and component events
3189 * are enabled. This method passes the event along to any listeners that are
3190 * attached.
3191 *
3192 * @param e the <code>HierarchyEvent</code> to process
3193 * @throws NullPointerException if e is null
3194 * @see HierarchyListener
3195 * @see #addHierarchyListener(HierarchyListener)
3196 * @see #enableEvents(long)
3197 * @since 1.3
3198 */
3199 protected void processHierarchyEvent(HierarchyEvent e)
3200 {
3201 if (hierarchyListener == null)
3202 return;
3203 if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
3204 hierarchyListener.hierarchyChanged(e);
3205 }
3206
3207 /**
3208 * Called when a hierarchy bounds event is dispatched and component events
3209 * are enabled. This method passes the event along to any listeners that are
3210 * attached.
3211 *
3212 * @param e the <code>HierarchyEvent</code> to process
3213 * @throws NullPointerException if e is null
3214 * @see HierarchyBoundsListener
3215 * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
3216 * @see #enableEvents(long)
3217 * @since 1.3
3218 */
3219 protected void processHierarchyBoundsEvent(HierarchyEvent e)
3220 {
3221 if (hierarchyBoundsListener == null)
3222 return;
3223 switch (e.id)
3224 {
3225 case HierarchyEvent.ANCESTOR_MOVED:
3226 hierarchyBoundsListener.ancestorMoved(e);
3227 break;
3228 case HierarchyEvent.ANCESTOR_RESIZED:
3229 hierarchyBoundsListener.ancestorResized(e);
3230 break;
3231 }
3232 }
3233
3234 /**
3235 * AWT 1.0 event handler.
3236 *
3237 * This method calls one of the event-specific handler methods. For
3238 * example for key events, either {@link #keyDown(Event,int)}
3239 * or {@link #keyUp(Event,int)} is called. A derived
3240 * component can override one of these event-specific methods if it
3241 * only needs to handle certain event types. Otherwise it can
3242 * override handleEvent itself and handle any event.
3243 *
3244 * @param evt the event to handle
3245 * @return true if the event was handled, false otherwise
3246 * @deprecated use {@link #processEvent(AWTEvent)} instead
3247 */
3248 public boolean handleEvent (Event evt)
3249 {
3250 switch (evt.id)
3251 {
3252 // Handle key events.
3253 case Event.KEY_ACTION:
3254 case Event.KEY_PRESS:
3255 return keyDown (evt, evt.key);
3256 case Event.KEY_ACTION_RELEASE:
3257 case Event.KEY_RELEASE:
3258 return keyUp (evt, evt.key);
3259
3260 // Handle mouse events.
3261 case Event.MOUSE_DOWN:
3262 return mouseDown (evt, evt.x, evt.y);
3263 case Event.MOUSE_UP:
3264 return mouseUp (evt, evt.x, evt.y);
3265 case Event.MOUSE_MOVE:
3266 return mouseMove (evt, evt.x, evt.y);
3267 case Event.MOUSE_DRAG:
3268 return mouseDrag (evt, evt.x, evt.y);
3269 case Event.MOUSE_ENTER:
3270 return mouseEnter (evt, evt.x, evt.y);
3271 case Event.MOUSE_EXIT:
3272 return mouseExit (evt, evt.x, evt.y);
3273
3274 // Handle focus events.
3275 case Event.GOT_FOCUS:
3276 return gotFocus (evt, evt.arg);
3277 case Event.LOST_FOCUS:
3278 return lostFocus (evt, evt.arg);
3279
3280 // Handle action event.
3281 case Event.ACTION_EVENT:
3282 return action (evt, evt.arg);
3283 }
3284 // Unknown event.
3285 return false;
3286 }
3287
3288 /**
3289 * AWT 1.0 MOUSE_DOWN event handler. This method is meant to be
3290 * overridden by components providing their own MOUSE_DOWN handler.
3291 * The default implementation simply returns false.
3292 *
3293 * @param evt the event to handle
3294 * @param x the x coordinate, ignored
3295 * @param y the y coordinate, ignored
3296 * @return false
3297 * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
3298 */
3299 public boolean mouseDown(Event evt, int x, int y)
3300 {
3301 return false;
3302 }
3303
3304 /**
3305 * AWT 1.0 MOUSE_DRAG event handler. This method is meant to be
3306 * overridden by components providing their own MOUSE_DRAG handler.
3307 * The default implementation simply returns false.
3308 *
3309 * @param evt the event to handle
3310 * @param x the x coordinate, ignored
3311 * @param y the y coordinate, ignored
3312 * @return false
3313 * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
3314 */
3315 public boolean mouseDrag(Event evt, int x, int y)
3316 {
3317 return false;
3318 }
3319
3320 /**
3321 * AWT 1.0 MOUSE_UP event handler. This method is meant to be
3322 * overridden by components providing their own MOUSE_UP handler.
3323 * The default implementation simply returns false.
3324 *
3325 * @param evt the event to handle
3326 * @param x the x coordinate, ignored
3327 * @param y the y coordinate, ignored
3328 * @return false
3329 * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
3330 */
3331 public boolean mouseUp(Event evt, int x, int y)
3332 {
3333 return false;
3334 }
3335
3336 /**
3337 * AWT 1.0 MOUSE_MOVE event handler. This method is meant to be
3338 * overridden by components providing their own MOUSE_MOVE handler.
3339 * The default implementation simply returns false.
3340 *
3341 * @param evt the event to handle
3342 * @param x the x coordinate, ignored
3343 * @param y the y coordinate, ignored
3344 * @return false
3345 * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
3346 */
3347 public boolean mouseMove(Event evt, int x, int y)
3348 {
3349 return false;
3350 }
3351
3352 /**
3353 * AWT 1.0 MOUSE_ENTER event handler. This method is meant to be
3354 * overridden by components providing their own MOUSE_ENTER handler.
3355 * The default implementation simply returns false.
3356 *
3357 * @param evt the event to handle
3358 * @param x the x coordinate, ignored
3359 * @param y the y coordinate, ignored
3360 * @return false
3361 * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
3362 */
3363 public boolean mouseEnter(Event evt, int x, int y)
3364 {
3365 return false;
3366 }
3367
3368 /**
3369 * AWT 1.0 MOUSE_EXIT event handler. This method is meant to be
3370 * overridden by components providing their own MOUSE_EXIT handler.
3371 * The default implementation simply returns false.
3372 *
3373 * @param evt the event to handle
3374 * @param x the x coordinate, ignored
3375 * @param y the y coordinate, ignored
3376 * @return false
3377 * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
3378 */
3379 public boolean mouseExit(Event evt, int x, int y)
3380 {
3381 return false;
3382 }
3383
3384 /**
3385 * AWT 1.0 KEY_PRESS and KEY_ACTION event handler. This method is
3386 * meant to be overridden by components providing their own key
3387 * press handler. The default implementation simply returns false.
3388 *
3389 * @param evt the event to handle
3390 * @param key the key pressed, ignored
3391 * @return false
3392 * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
3393 */
3394 public boolean keyDown(Event evt, int key)
3395 {
3396 return false;
3397 }
3398
3399 /**
3400 * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler. This
3401 * method is meant to be overridden by components providing their
3402 * own key release handler. The default implementation simply
3403 * returns false.
3404 *
3405 * @param evt the event to handle
3406 * @param key the key pressed, ignored
3407 * @return false
3408 * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
3409 */
3410 public boolean keyUp(Event evt, int key)
3411 {
3412 return false;
3413 }
3414
3415 /**
3416 * AWT 1.0 ACTION_EVENT event handler. This method is meant to be
3417 * overridden by components providing their own action event
3418 * handler. The default implementation simply returns false.
3419 *
3420 * @param evt the event to handle
3421 * @param what the object acted on, ignored
3422 * @return false
3423 * @deprecated in classes which support actions, use
3424 * <code>processActionEvent(ActionEvent)</code> instead
3425 */
3426 public boolean action(Event evt, Object what)
3427 {
3428 return false;
3429 }
3430
3431 /**
3432 * Called when the parent of this Component is made visible or when
3433 * the Component is added to an already visible Container and needs
3434 * to be shown. A native peer - if any - is created at this
3435 * time. This method is called automatically by the AWT system and
3436 * should not be called by user level code.
3437 *
3438 * @see #isDisplayable()
3439 * @see #removeNotify()
3440 */
3441 public void addNotify()
3442 {
3443 if (peer == null)
3444 peer = getToolkit().createComponent(this);
3445 else if (parent != null && parent.isLightweight())
3446 new HeavyweightInLightweightListener(parent);
3447 /* Now that all the children has gotten their peers, we should
3448 have the event mask needed for this component and its
3449 lightweight subcomponents. */
3450 peer.setEventMask(eventMask);
3451 /* We do not invalidate here, but rather leave that job up to
3452 the peer. For efficiency, the peer can choose not to
3453 invalidate if it is happy with the current dimensions,
3454 etc. */
3455 }
3456
3457 /**
3458 * Called to inform this component is has been removed from its
3459 * container. Its native peer - if any - is destroyed at this time.
3460 * This method is called automatically by the AWT system and should
3461 * not be called by user level code.
3462 *
3463 * @see #isDisplayable()
3464 * @see #addNotify()
3465 */
3466 public void removeNotify()
3467 {
3468 // We null our peer field before disposing of it, such that if we're
3469 // not the event dispatch thread and the dispatch thread is awoken by
3470 // the dispose call, there will be no race checking the peer's null
3471 // status.
3472
3473 ComponentPeer tmp = peer;
3474 peer = null;
3475 if (tmp != null)
3476 {
3477 tmp.hide();
3478 tmp.dispose();
3479 }
3480 }
3481
3482 /**
3483 * AWT 1.0 GOT_FOCUS event handler. This method is meant to be
3484 * overridden by components providing their own GOT_FOCUS handler.
3485 * The default implementation simply returns false.
3486 *
3487 * @param evt the event to handle
3488 * @param what the Object focused, ignored
3489 * @return false
3490 * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
3491 */
3492 public boolean gotFocus(Event evt, Object what)
3493 {
3494 return false;
3495 }
3496
3497 /**
3498 * AWT 1.0 LOST_FOCUS event handler. This method is meant to be
3499 * overridden by components providing their own LOST_FOCUS handler.
3500 * The default implementation simply returns false.
3501 *
3502 * @param evt the event to handle
3503 * @param what the Object focused, ignored
3504 * @return false
3505 * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
3506 */
3507 public boolean lostFocus(Event evt, Object what)
3508 {
3509 return false;
3510 }
3511
3512 /**
3513 * Tests whether or not this component is in the group that can be
3514 * traversed using the keyboard traversal mechanism (such as the TAB key).
3515 *
3516 * @return true if the component is traversed via the TAB key
3517 * @see #setFocusable(boolean)
3518 * @since 1.1
3519 * @deprecated use {@link #isFocusable()} instead
3520 */
3521 public boolean isFocusTraversable()
3522 {
3523 return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable());
3524 }
3525
3526 /**
3527 * Tests if this component can receive focus.
3528 *
3529 * @return true if this component can receive focus
3530 * @since 1.4
3531 */
3532 public boolean isFocusable()
3533 {
3534 return focusable;
3535 }
3536
3537 /**
3538 * Specify whether this component can receive focus. This method also
3539 * sets the {@link #isFocusTraversableOverridden} field to 1, which
3540 * appears to be the undocumented way {@link
3541 * DefaultFocusTraversalPolicy#accept(Component)} determines whether to
3542 * respect the {@link #isFocusable()} method of the component.
3543 *
3544 * @param focusable the new focusable status
3545 * @since 1.4
3546 */
3547 public void setFocusable(boolean focusable)
3548 {
3549 firePropertyChange("focusable", this.focusable, focusable);
3550 this.focusable = focusable;
3551 this.isFocusTraversableOverridden = 1;
3552 }
3553
3554 /**
3555 * Sets the focus traversal keys for one of the three focus
3556 * traversal directions supported by Components:
3557 * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS},
3558 * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or
3559 * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the
3560 * default values should match the operating system's native
3561 * choices. To disable a given traversal, use
3562 * <code>Collections.EMPTY_SET</code>. The event dispatcher will
3563 * consume PRESSED, RELEASED, and TYPED events for the specified
3564 * key, although focus can only transfer on PRESSED or RELEASED.
3565 *
3566 * <p>The defaults are:
3567 * <table>
3568 * <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
3569 * <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
3570 * <td>Normal forward traversal</td>
3571 * <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr>
3572 * <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
3573 * <td>Normal backward traversal</td>
3574 * <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr>
3575 * <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
3576 * <td>Go up a traversal cycle</td><td>None</td></tr>
3577 * </table>
3578 *
3579 * If keystrokes is null, this component's focus traversal key set
3580 * is inherited from one of its ancestors. If none of its ancestors
3581 * has its own set of focus traversal keys, the focus traversal keys
3582 * are set to the defaults retrieved from the current
3583 * KeyboardFocusManager. If not null, the set must contain only
3584 * AWTKeyStrokes that are not already focus keys and are not
3585 * KEY_TYPED events.
3586 *
3587 * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or
3588 * UP_CYCLE_TRAVERSAL_KEYS
3589 * @param keystrokes a set of keys, or null
3590 * @throws IllegalArgumentException if id or keystrokes is invalid
3591 * @see #getFocusTraversalKeys(int)
3592 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3593 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3594 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3595 * @since 1.4
3596 */
3597 public void setFocusTraversalKeys(int id, Set keystrokes)
3598 {
3599 if (keystrokes == null)
3600 {
3601 Container parent = getParent ();
3602
3603 while (parent != null)
3604 {
3605 if (parent.areFocusTraversalKeysSet (id))
3606 {
3607 keystrokes = parent.getFocusTraversalKeys (id);
3608 break;
3609 }
3610 parent = parent.getParent ();
3611 }
3612
3613 if (keystrokes == null)
3614 keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
3615 getDefaultFocusTraversalKeys (id);
3616 }
3617
3618 Set sa;
3619 Set sb;
3620 String name;
3621 switch (id)
3622 {
3623 case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
3624 sa = getFocusTraversalKeys
3625 (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
3626 sb = getFocusTraversalKeys
3627 (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
3628 name = "forwardFocusTraversalKeys";
3629 break;
3630 case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
3631 sa = getFocusTraversalKeys
3632 (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
3633 sb = getFocusTraversalKeys
3634 (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
3635 name = "backwardFocusTraversalKeys";
3636 break;
3637 case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
3638 sa = getFocusTraversalKeys
3639 (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
3640 sb = getFocusTraversalKeys
3641 (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
3642 name = "upCycleFocusTraversalKeys";
3643 break;
3644 default:
3645 throw new IllegalArgumentException ();
3646 }
3647
3648 int i = keystrokes.size ();
3649 Iterator iter = keystrokes.iterator ();
3650
3651 while (--i >= 0)
3652 {
3653 Object o = iter.next ();
3654 if (!(o instanceof AWTKeyStroke)
3655 || sa.contains (o) || sb.contains (o)
3656 || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
3657 throw new IllegalArgumentException ();
3658 }
3659
3660 if (focusTraversalKeys == null)
3661 focusTraversalKeys = new Set[3];
3662
3663 keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
3664 firePropertyChange (name, focusTraversalKeys[id], keystrokes);
3665
3666 focusTraversalKeys[id] = keystrokes;
3667 }
3668
3669 /**
3670 * Returns the set of keys for a given focus traversal action, as
3671 * defined in <code>setFocusTraversalKeys</code>. If not set, this
3672 * is inherited from the parent component, which may have gotten it
3673 * from the KeyboardFocusManager.
3674 *
3675 * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
3676 * or UP_CYCLE_TRAVERSAL_KEYS
3677 *
3678 * @return set of traversal keys
3679 *
3680 * @throws IllegalArgumentException if id is invalid
3681 *
3682 * @see #setFocusTraversalKeys (int, Set)
3683 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3684 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3685 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3686 *
3687 * @since 1.4
3688 */
3689 public Set getFocusTraversalKeys (int id)
3690 {
3691 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
3692 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
3693 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
3694 throw new IllegalArgumentException();
3695
3696 Set s = null;
3697
3698 if (focusTraversalKeys != null)
3699 s = focusTraversalKeys[id];
3700
3701 if (s == null && parent != null)
3702 s = parent.getFocusTraversalKeys (id);
3703
3704 return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
3705 .getDefaultFocusTraversalKeys(id)) : s;
3706 }
3707
3708 /**
3709 * Tests whether the focus traversal keys for a given action are explicitly
3710 * set or inherited.
3711 *
3712 * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
3713 * or UP_CYCLE_TRAVERSAL_KEYS
3714 * @return true if that set is explicitly specified
3715 * @throws IllegalArgumentException if id is invalid
3716 * @see #getFocusTraversalKeys (int)
3717 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3718 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3719 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3720 * @since 1.4
3721 */
3722 public boolean areFocusTraversalKeysSet (int id)
3723 {
3724 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
3725 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
3726 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
3727 throw new IllegalArgumentException ();
3728
3729 return focusTraversalKeys != null && focusTraversalKeys[id] != null;
3730 }
3731
3732 /**
3733 * Enable or disable focus traversal keys on this Component. If
3734 * they are, then the keyboard focus manager consumes and acts on
3735 * key press and release events that trigger focus traversal, and
3736 * discards the corresponding key typed events. If focus traversal
3737 * keys are disabled, then all key events that would otherwise
3738 * trigger focus traversal are sent to this Component.
3739 *
3740 * @param focusTraversalKeysEnabled the new value of the flag
3741 * @see #getFocusTraversalKeysEnabled ()
3742 * @see #setFocusTraversalKeys (int, Set)
3743 * @see #getFocusTraversalKeys (int)
3744 * @since 1.4
3745 */
3746 public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
3747 {
3748 firePropertyChange ("focusTraversalKeysEnabled",
3749 this.focusTraversalKeysEnabled,
3750 focusTraversalKeysEnabled);
3751 this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
3752 }
3753
3754 /**
3755 * Check whether or not focus traversal keys are enabled on this
3756 * Component. If they are, then the keyboard focus manager consumes
3757 * and acts on key press and release events that trigger focus
3758 * traversal, and discards the corresponding key typed events. If
3759 * focus traversal keys are disabled, then all key events that would
3760 * otherwise trigger focus traversal are sent to this Component.
3761 *
3762 * @return true if focus traversal keys are enabled
3763 * @see #setFocusTraversalKeysEnabled (boolean)
3764 * @see #setFocusTraversalKeys (int, Set)
3765 * @see #getFocusTraversalKeys (int)
3766 * @since 1.4
3767 */
3768 public boolean getFocusTraversalKeysEnabled ()
3769 {
3770 return focusTraversalKeysEnabled;
3771 }
3772
3773 /**
3774 * Request that this Component be given the keyboard input focus and
3775 * that its top-level ancestor become the focused Window.
3776 *
3777 * For the request to be granted, the Component must be focusable,
3778 * displayable and showing and the top-level Window to which it
3779 * belongs must be focusable. If the request is initially denied on
3780 * the basis that the top-level Window is not focusable, the request
3781 * will be remembered and granted when the Window does become
3782 * focused.
3783 *
3784 * Never assume that this Component is the focus owner until it
3785 * receives a FOCUS_GAINED event.
3786 *
3787 * The behaviour of this method is platform-dependent.
3788 * {@link #requestFocusInWindow()} should be used instead.
3789 *
3790 * @see #requestFocusInWindow ()
3791 * @see FocusEvent
3792 * @see #addFocusListener (FocusListener)
3793 * @see #isFocusable ()
3794 * @see #isDisplayable ()
3795 * @see KeyboardFocusManager#clearGlobalFocusOwner ()
3796 */
3797 public void requestFocus ()
3798 {
3799 if (isDisplayable ()
3800 && isShowing ()
3801 && isFocusable ())
3802 {
3803 synchronized (getTreeLock ())
3804 {
3805 // Find this Component's top-level ancestor.
3806 Container parent = (this instanceof Container) ? (Container) this
3807 : getParent();
3808 while (parent != null
3809 && !(parent instanceof Window))
3810 parent = parent.getParent ();
3811
3812 if (parent == null)
3813 return;
3814
3815 Window toplevel = (Window) parent;
3816 if (toplevel.isFocusableWindow ())
3817 {
3818 if (peer != null && !isLightweight())
3819 // This call will cause a FOCUS_GAINED event to be
3820 // posted to the system event queue if the native
3821 // windowing system grants the focus request.
3822 peer.requestFocus ();
3823 else
3824 {
3825 // Either our peer hasn't been created yet or we're a
3826 // lightweight component. In either case we want to
3827 // post a FOCUS_GAINED event.
3828 EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
3829 synchronized (eq)
3830 {
3831 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
3832 Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
3833 if (currentFocusOwner != null)
3834 {
3835 eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
3836 false, this));
3837 eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false,
3838 currentFocusOwner));
3839 }
3840 else
3841 eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false));
3842 }
3843 }
3844 }
3845 else
3846 pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED);
3847 }
3848 }
3849 }
3850
3851 /**
3852 * Request that this Component be given the keyboard input focus and
3853 * that its top-level ancestor become the focused Window.
3854 *
3855 * For the request to be granted, the Component must be focusable,
3856 * displayable and showing and the top-level Window to which it
3857 * belongs must be focusable. If the request is initially denied on
3858 * the basis that the top-level Window is not focusable, the request
3859 * will be remembered and granted when the Window does become
3860 * focused.
3861 *
3862 * Never assume that this Component is the focus owner until it
3863 * receives a FOCUS_GAINED event.
3864 *
3865 * The behaviour of this method is platform-dependent.
3866 * {@link #requestFocusInWindow()} should be used instead.
3867 *
3868 * If the return value is false, the request is guaranteed to fail.
3869 * If the return value is true, the request will succeed unless it
3870 * is vetoed or something in the native windowing system intervenes,
3871 * preventing this Component's top-level ancestor from becoming
3872 * focused. This method is meant to be called by derived
3873 * lightweight Components that want to avoid unnecessary repainting
3874 * when they know a given focus transfer need only be temporary.
3875 *
3876 * @param temporary true if the focus request is temporary
3877 * @return true if the request has a chance of success
3878 * @see #requestFocusInWindow ()
3879 * @see FocusEvent
3880 * @see #addFocusListener (FocusListener)
3881 * @see #isFocusable ()
3882 * @see #isDisplayable ()
3883 * @see KeyboardFocusManager#clearGlobalFocusOwner ()
3884 * @since 1.4
3885 */
3886 protected boolean requestFocus (boolean temporary)
3887 {
3888 if (isDisplayable ()
3889 && isShowing ()
3890 && isFocusable ())
3891 {
3892 synchronized (getTreeLock ())
3893 {
3894 // Find this Component's top-level ancestor.
3895 Container parent = getParent ();
3896
3897 while (parent != null
3898 && !(parent instanceof Window))
3899 parent = parent.getParent ();
3900
3901 Window toplevel = (Window) parent;
3902 if (toplevel.isFocusableWindow ())
3903 {
3904 if (peer != null && !isLightweight())
3905 // This call will cause a FOCUS_GAINED event to be
3906 // posted to the system event queue if the native
3907 // windowing system grants the focus request.
3908 peer.requestFocus ();
3909 else
3910 {
3911 // Either our peer hasn't been created yet or we're a
3912 // lightweight component. In either case we want to
3913 // post a FOCUS_GAINED event.
3914 EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
3915 synchronized (eq)
3916 {
3917 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
3918 Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
3919 if (currentFocusOwner != null)
3920 {
3921 eq.postEvent (new FocusEvent(currentFocusOwner,
3922 FocusEvent.FOCUS_LOST,
3923 temporary, this));
3924 eq.postEvent (new FocusEvent(this,
3925 FocusEvent.FOCUS_GAINED,
3926 temporary,
3927 currentFocusOwner));
3928 }
3929 else
3930 eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
3931 }
3932 }
3933 }
3934 else
3935 // FIXME: need to add a focus listener to our top-level
3936 // ancestor, so that we can post this event when it becomes
3937 // the focused window.
3938 pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary);
3939 }
3940 }
3941 // Always return true.
3942 return true;
3943 }
3944
3945 /**
3946 * Request that this component be given the keyboard input focus, if
3947 * its top-level ancestor is the currently focused Window. A
3948 * <code>FOCUS_GAINED</code> event will be fired if and only if this
3949 * request is successful. To be successful, the component must be
3950 * displayable, showing, and focusable, and its ancestor top-level
3951 * Window must be focused.
3952 *
3953 * If the return value is false, the request is guaranteed to fail.
3954 * If the return value is true, the request will succeed unless it
3955 * is vetoed or something in the native windowing system intervenes,
3956 * preventing this Component's top-level ancestor from becoming
3957 * focused.
3958 *
3959 * @return true if the request has a chance of success
3960 * @see #requestFocus ()
3961 * @see FocusEvent
3962 * @see #addFocusListener (FocusListener)
3963 * @see #isFocusable ()
3964 * @see #isDisplayable ()
3965 * @see KeyboardFocusManager#clearGlobalFocusOwner ()
3966 * @since 1.4
3967 */
3968 public boolean requestFocusInWindow ()
3969 {
3970 return requestFocusInWindow (false);
3971 }
3972
3973 /**
3974 * Request that this component be given the keyboard input focus, if
3975 * its top-level ancestor is the currently focused Window. A
3976 * <code>FOCUS_GAINED</code> event will be fired if and only if this
3977 * request is successful. To be successful, the component must be
3978 * displayable, showing, and focusable, and its ancestor top-level
3979 * Window must be focused.
3980 *
3981 * If the return value is false, the request is guaranteed to fail.
3982 * If the return value is true, the request will succeed unless it
3983 * is vetoed or something in the native windowing system intervenes,
3984 * preventing this Component's top-level ancestor from becoming
3985 * focused. This method is meant to be called by derived
3986 * lightweight Components that want to avoid unnecessary repainting
3987 * when they know a given focus transfer need only be temporary.
3988 *
3989 * @param temporary true if the focus request is temporary
3990 * @return true if the request has a chance of success
3991 * @see #requestFocus ()
3992 * @see FocusEvent
3993 * @see #addFocusListener (FocusListener)
3994 * @see #isFocusable ()
3995 * @see #isDisplayable ()
3996 * @see KeyboardFocusManager#clearGlobalFocusOwner ()
3997 * @since 1.4
3998 */
3999 protected boolean requestFocusInWindow (boolean temporary)
4000 {
4001 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
4002
4003 Window focusedWindow = manager.getFocusedWindow ();
4004
4005 if (isDisplayable ()
4006 && isShowing ()
4007 && isFocusable ())
4008 {
4009 if (focusedWindow != null)
4010 {
4011 synchronized (getTreeLock ())
4012 {
4013 Container parent = getParent ();
4014
4015 while (parent != null
4016 && !(parent instanceof Window))
4017 parent = parent.getParent ();
4018
4019 Window toplevel = (Window) parent;
4020
4021 // Check if top-level ancestor is currently focused window.
4022 if (focusedWindow == toplevel)
4023 {
4024 if (peer != null
4025 && !isLightweight()
4026 && !(this instanceof Window))
4027 // This call will cause a FOCUS_GAINED event to be
4028 // posted to the system event queue if the native
4029 // windowing system grants the focus request.
4030 peer.requestFocus ();
4031 else
4032 {
4033 // Either our peer hasn't been created yet or we're a
4034 // lightweight component. In either case we want to
4035 // post a FOCUS_GAINED event.
4036 EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
4037 synchronized (eq)
4038 {
4039 Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
4040 if (currentFocusOwner != null)
4041 {
4042 eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
4043 temporary, this));
4044 eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary,
4045 currentFocusOwner));
4046 }
4047 else
4048 eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
4049 }
4050 }
4051 }
4052 else
4053 return false;
4054 }
4055 }
4056
4057 return true;
4058 }
4059 return false;
4060 }
4061
4062 /**
4063 * Transfers focus to the next component in the focus traversal
4064 * order, as though this were the current focus owner.
4065 *
4066 * @see #requestFocus()
4067 * @since 1.1
4068 */
4069 public void transferFocus ()
4070 {
4071 nextFocus ();
4072 }
4073
4074 /**
4075 * Returns the root container that owns the focus cycle where this
4076 * component resides. A focus cycle root is in two cycles, one as
4077 * the ancestor, and one as the focusable element; this call always
4078 * returns the ancestor.
4079 *
4080 * @return the ancestor container that owns the focus cycle
4081 * @since 1.4
4082 */
4083 public Container getFocusCycleRootAncestor ()
4084 {
4085 Container parent = getParent ();
4086
4087 while (parent != null && !parent.isFocusCycleRoot())
4088 parent = parent.getParent ();
4089
4090 return parent;
4091 }
4092
4093 /**
4094 * Tests if the container is the ancestor of the focus cycle that
4095 * this component belongs to.
4096 *
4097 * @param c the container to test
4098 * @return true if c is the focus cycle root
4099 * @since 1.4
4100 */
4101 public boolean isFocusCycleRoot (Container c)
4102 {
4103 return c == getFocusCycleRootAncestor ();
4104 }
4105
4106 /**
4107 * AWT 1.0 focus event processor. Transfers focus to the next
4108 * component in the focus traversal order, as though this were the
4109 * current focus owner.
4110 *
4111 * @deprecated use {@link #transferFocus ()} instead
4112 */
4113 public void nextFocus ()
4114 {
4115 // Find the nearest valid (== showing && focusable && enabled) focus
4116 // cycle root ancestor and the focused component in it.
4117 Container focusRoot = getFocusCycleRootAncestor();
4118 Component focusComp = this;
4119 while (focusRoot != null
4120 && ! (focusRoot.isShowing() && focusRoot.isFocusable()
4121 && focusRoot.isEnabled()))
4122 {
4123 focusComp = focusRoot;
4124 focusRoot = focusComp.getFocusCycleRootAncestor();
4125 }
4126
4127 if (focusRoot != null)
4128 {
4129 // First try to get the componentBefore from the policy.
4130 FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
4131 Component nextFocus = policy.getComponentAfter(focusRoot, focusComp);
4132
4133 // If this fails, then ask for the defaultComponent.
4134 if (nextFocus == null)
4135 nextFocus = policy.getDefaultComponent(focusRoot);
4136
4137 // Request focus on this component, if not null.
4138 if (nextFocus != null)
4139 nextFocus.requestFocus();
4140 }
4141 }
4142
4143 /**
4144 * Transfers focus to the previous component in the focus traversal
4145 * order, as though this were the current focus owner.
4146 *
4147 * @see #requestFocus ()
4148 * @since 1.4
4149 */
4150 public void transferFocusBackward ()
4151 {
4152 // Find the nearest valid (== showing && focusable && enabled) focus
4153 // cycle root ancestor and the focused component in it.
4154 Container focusRoot = getFocusCycleRootAncestor();
4155 Component focusComp = this;
4156 while (focusRoot != null
4157 && ! (focusRoot.isShowing() && focusRoot.isFocusable()
4158 && focusRoot.isEnabled()))
4159 {
4160 focusComp = focusRoot;
4161 focusRoot = focusComp.getFocusCycleRootAncestor();
4162 }
4163
4164 if (focusRoot != null)
4165 {
4166 // First try to get the componentBefore from the policy.
4167 FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
4168 Component nextFocus = policy.getComponentBefore(focusRoot, focusComp);
4169
4170 // If this fails, then ask for the defaultComponent.
4171 if (nextFocus == null)
4172 nextFocus = policy.getDefaultComponent(focusRoot);
4173
4174 // Request focus on this component, if not null.
4175 if (nextFocus != null)
4176 nextFocus.requestFocus();
4177 }
4178 }
4179
4180 /**
4181 * Transfers focus to the focus cycle root of this component.
4182 * However, if this is a Window, the default focus owner in the
4183 * window in the current focus cycle is focused instead.
4184 *
4185 * @see #requestFocus()
4186 * @see #isFocusCycleRoot(Container)
4187 * @since 1.4
4188 */
4189 public void transferFocusUpCycle ()
4190 {
4191 // Find the nearest focus cycle root ancestor that is itself
4192 // focusable, showing and enabled.
4193 Container focusCycleRoot = getFocusCycleRootAncestor();
4194 while (focusCycleRoot != null &&
4195 ! (focusCycleRoot.isShowing() && focusCycleRoot.isFocusable()
4196 && focusCycleRoot.isEnabled()))
4197 {
4198 focusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor();
4199 }
4200
4201 KeyboardFocusManager fm =
4202 KeyboardFocusManager.getCurrentKeyboardFocusManager();
4203
4204 if (focusCycleRoot != null)
4205 {
4206 // If we found a focus cycle root, then we make this the new
4207 // focused component, and make it's focus cycle root the new
4208 // global focus cycle root. If the found root has no focus cycle
4209 // root ancestor itself, then the component will be both the focused
4210 // component and the new global focus cycle root.
4211 Container focusCycleAncestor =
4212 focusCycleRoot.getFocusCycleRootAncestor();
4213 Container globalFocusCycleRoot;
4214 if (focusCycleAncestor == null)
4215 globalFocusCycleRoot = focusCycleRoot;
4216 else
4217 globalFocusCycleRoot = focusCycleAncestor;
4218
4219 fm.setGlobalCurrentFocusCycleRoot(globalFocusCycleRoot);
4220 focusCycleRoot.requestFocus();
4221 }
4222 else
4223 {
4224 // If this component has no applicable focus cycle root, we try
4225 // find the nearest window and set this as the new global focus cycle
4226 // root and the default focus component of this window the new focused
4227 // component.
4228 Container cont;
4229 if (this instanceof Container)
4230 cont = (Container) this;
4231 else
4232 cont = getParent();
4233
4234 while (cont != null && !(cont instanceof Window))
4235 cont = cont.getParent();
4236
4237 if (cont != null)
4238 {
4239 FocusTraversalPolicy policy = cont.getFocusTraversalPolicy();
4240 Component focusComp = policy.getDefaultComponent(cont);
4241 if (focusComp != null)
4242 {
4243 fm.setGlobalCurrentFocusCycleRoot(cont);
4244 focusComp.requestFocus();
4245 }
4246 }
4247 }
4248 }
4249
4250 /**
4251 * Tests if this component is the focus owner. Use {@link
4252 * #isFocusOwner ()} instead.
4253 *
4254 * @return true if this component owns focus
4255 * @since 1.2
4256 */
4257 public boolean hasFocus ()
4258 {
4259 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
4260
4261 Component focusOwner = manager.getFocusOwner ();
4262
4263 return this == focusOwner;
4264 }
4265
4266 /**
4267 * Tests if this component is the focus owner.
4268 *
4269 * @return true if this component owns focus
4270 * @since 1.4
4271 */
4272 public boolean isFocusOwner()
4273 {
4274 return hasFocus ();
4275 }
4276
4277 /**
4278 * Adds the specified popup menu to this component.
4279 *
4280 * @param popup the popup menu to be added
4281 *
4282 * @see #remove(MenuComponent)
4283 *
4284 * @since 1.1
4285 */
4286 public synchronized void add(PopupMenu popup)
4287 {
4288 if (popups == null)
4289 popups = new Vector();
4290 popups.add(popup);
4291
4292 if (popup.parent != null)
4293 popup.parent.remove(popup);
4294 popup.parent = this;
4295 if (peer != null)
4296 popup.addNotify();
4297 }
4298
4299 /**
4300 * Removes the specified popup menu from this component.
4301 *
4302 * @param popup the popup menu to remove
4303 * @see #add(PopupMenu)
4304 * @since 1.1
4305 */
4306 public synchronized void remove(MenuComponent popup)
4307 {
4308 if (popups != null)
4309 popups.remove(popup);
4310 }
4311
4312 /**
4313 * Returns a debugging string representing this component. The string may
4314 * be empty but not null.
4315 *
4316 * @return a string representing this component
4317 */
4318 protected String paramString()
4319 {
4320 StringBuffer param = new StringBuffer();
4321 String name = getName();
4322 if (name != null)
4323 param.append(name).append(",");
4324 param.append(x).append(",").append(y).append(",").append(width)
4325 .append("x").append(height);
4326 if (! isValid())
4327 param.append(",invalid");
4328 if (! isVisible())
4329 param.append(",invisible");
4330 if (! isEnabled())
4331 param.append(",disabled");
4332 if (! isOpaque())
4333 param.append(",translucent");
4334 if (isDoubleBuffered())
4335 param.append(",doublebuffered");
4336 if (parent == null)
4337 param.append(",parent=null");
4338 else
4339 param.append(",parent=").append(parent.getName());
4340 return param.toString();
4341 }
4342
4343 /**
4344 * Returns a string representation of this component. This is implemented
4345 * as <code>getClass().getName() + '[' + paramString() + ']'</code>.
4346 *
4347 * @return a string representation of this component
4348 */
4349 public String toString()
4350 {
4351 return getClass().getName() + '[' + paramString() + ']';
4352 }
4353
4354 /**
4355 * Prints a listing of this component to <code>System.out</code>.
4356 *
4357 * @see #list(PrintStream)
4358 */
4359 public void list()
4360 {
4361 list(System.out, 0);
4362 }
4363
4364 /**
4365 * Prints a listing of this component to the specified print stream.
4366 *
4367 * @param out the <code>PrintStream</code> to print to
4368 */
4369 public void list(PrintStream out)
4370 {
4371 list(out, 0);
4372 }
4373
4374 /**
4375 * Prints a listing of this component to the specified print stream,
4376 * starting at the specified indentation point.
4377 *
4378 * @param out the <code>PrintStream</code> to print to
4379 * @param indent the indentation point
4380 */
4381 public void list(PrintStream out, int indent)
4382 {
4383 for (int i = 0; i < indent; ++i)
4384 out.print(' ');
4385 out.println(toString());
4386 }
4387
4388 /**
4389 * Prints a listing of this component to the specified print writer.
4390 *
4391 * @param out the <code>PrintWrinter</code> to print to
4392 * @since 1.1
4393 */
4394 public void list(PrintWriter out)
4395 {
4396 list(out, 0);
4397 }
4398
4399 /**
4400 * Prints a listing of this component to the specified print writer,
4401 * starting at the specified indentation point.
4402 *
4403 * @param out the <code>PrintWriter</code> to print to
4404 * @param indent the indentation point
4405 * @since 1.1
4406 */
4407 public void list(PrintWriter out, int indent)
4408 {
4409 for (int i = 0; i < indent; ++i)
4410 out.print(' ');
4411 out.println(toString());
4412 }
4413
4414 /**
4415 * Adds the specified property listener to this component. This is harmless
4416 * if the listener is null, but if the listener has already been registered,
4417 * it will now be registered twice. The property listener ignores inherited
4418 * properties. Recognized properties include:<br>
4419 * <ul>
4420 * <li>the font (<code>"font"</code>)</li>
4421 * <li>the background color (<code>"background"</code>)</li>
4422 * <li>the foreground color (<code>"foreground"</code>)</li>
4423 * <li>the focusability (<code>"focusable"</code>)</li>
4424 * <li>the focus key traversal enabled state
4425 * (<code>"focusTraversalKeysEnabled"</code>)</li>
4426 * <li>the set of forward traversal keys
4427 * (<code>"forwardFocusTraversalKeys"</code>)</li>
4428 * <li>the set of backward traversal keys
4429 * (<code>"backwardFocusTraversalKeys"</code>)</li>
4430 * <li>the set of up-cycle traversal keys
4431 * (<code>"upCycleFocusTraversalKeys"</code>)</li>
4432 * </ul>
4433 *
4434 * @param listener the new listener to add
4435 * @see #removePropertyChangeListener(PropertyChangeListener)
4436 * @see #getPropertyChangeListeners()
4437 * @see #addPropertyChangeListener(String, PropertyChangeListener)
4438 * @since 1.1
4439 */
4440 public void addPropertyChangeListener(PropertyChangeListener listener)
4441 {
4442 if (changeSupport == null)
4443 changeSupport = new PropertyChangeSupport(this);
4444 changeSupport.addPropertyChangeListener(listener);
4445 }
4446
4447 /**
4448 * Removes the specified property listener from the component. This is
4449 * harmless if the listener was not previously registered.
4450 *
4451 * @param listener the listener to remove
4452 * @see #addPropertyChangeListener(PropertyChangeListener)
4453 * @see #getPropertyChangeListeners()
4454 * @see #removePropertyChangeListener(String, PropertyChangeListener)
4455 * @since 1.1
4456 */
4457 public void removePropertyChangeListener(PropertyChangeListener listener)
4458 {
4459 if (changeSupport != null)
4460 changeSupport.removePropertyChangeListener(listener);
4461 }
4462
4463 /**
4464 * Returns an array of all specified listeners registered on this component.
4465 *
4466 * @return an array of listeners
4467 * @see #addPropertyChangeListener(PropertyChangeListener)
4468 * @see #removePropertyChangeListener(PropertyChangeListener)
4469 * @see #getPropertyChangeListeners(String)
4470 * @since 1.4
4471 */
4472 public PropertyChangeListener[] getPropertyChangeListeners()
4473 {
4474 return changeSupport == null ? new PropertyChangeListener[0]
4475 : changeSupport.getPropertyChangeListeners();
4476 }
4477
4478 /**
4479 * Adds the specified property listener to this component. This is harmless
4480 * if the listener is null, but if the listener has already been registered,
4481 * it will now be registered twice. The property listener ignores inherited
4482 * properties. The listener is keyed to a single property. Recognized
4483 * properties include:<br>
4484 * <ul>
4485 * <li>the font (<code>"font"</code>)</li>
4486 * <li>the background color (<code>"background"</code>)</li>
4487 * <li>the foreground color (<code>"foreground"</code>)</li>
4488 * <li>the focusability (<code>"focusable"</code>)</li>
4489 * <li>the focus key traversal enabled state
4490 * (<code>"focusTraversalKeysEnabled"</code>)</li>
4491 * <li>the set of forward traversal keys
4492 * (<code>"forwardFocusTraversalKeys"</code>)</li>
4493 p * <li>the set of backward traversal keys
4494 * (<code>"backwardFocusTraversalKeys"</code>)</li>
4495 * <li>the set of up-cycle traversal keys
4496 * (<code>"upCycleFocusTraversalKeys"</code>)</li>
4497 * </ul>
4498 *
4499 * @param propertyName the property name to filter on
4500 * @param listener the new listener to add
4501 * @see #removePropertyChangeListener(String, PropertyChangeListener)
4502 * @see #getPropertyChangeListeners(String)
4503 * @see #addPropertyChangeListener(PropertyChangeListener)
4504 * @since 1.1
4505 */
4506 public void addPropertyChangeListener(String propertyName,
4507 PropertyChangeListener listener)
4508 {
4509 if (changeSupport == null)
4510 changeSupport = new PropertyChangeSupport(this);
4511 changeSupport.addPropertyChangeListener(propertyName, listener);
4512 }
4513
4514 /**
4515 * Removes the specified property listener on a particular property from
4516 * the component. This is harmless if the listener was not previously
4517 * registered.
4518 *
4519 * @param propertyName the property name to filter on
4520 * @param listener the listener to remove
4521 * @see #addPropertyChangeListener(String, PropertyChangeListener)
4522 * @see #getPropertyChangeListeners(String)
4523 * @see #removePropertyChangeListener(PropertyChangeListener)
4524 * @since 1.1
4525 */
4526 public void removePropertyChangeListener(String propertyName,
4527 PropertyChangeListener listener)
4528 {
4529 if (changeSupport != null)
4530 changeSupport.removePropertyChangeListener(propertyName, listener);
4531 }
4532
4533 /**
4534 * Returns an array of all specified listeners on the named property that
4535 * are registered on this component.
4536 *
4537 * @return an array of listeners
4538 * @see #addPropertyChangeListener(String, PropertyChangeListener)
4539 * @see #removePropertyChangeListener(String, PropertyChangeListener)
4540 * @see #getPropertyChangeListeners()
4541 * @since 1.4
4542 */
4543 public PropertyChangeListener[] getPropertyChangeListeners(String property)
4544 {
4545 return changeSupport == null ? new PropertyChangeListener[0]
4546 : changeSupport.getPropertyChangeListeners(property);
4547 }
4548
4549 /**
4550 * Report a change in a bound property to any registered property listeners.
4551 *
4552 * @param propertyName the property that changed
4553 * @param oldValue the old property value
4554 * @param newValue the new property value
4555 */
4556 protected void firePropertyChange(String propertyName, Object oldValue,
4557 Object newValue)
4558 {
4559 if (changeSupport != null)
4560 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
4561 }
4562
4563 /**
4564 * Report a change in a bound property to any registered property listeners.
4565 *
4566 * @param propertyName the property that changed
4567 * @param oldValue the old property value
4568 * @param newValue the new property value
4569 */
4570 protected void firePropertyChange(String propertyName, boolean oldValue,
4571 boolean newValue)
4572 {
4573 if (changeSupport != null)
4574 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
4575 }
4576
4577 /**
4578 * Report a change in a bound property to any registered property listeners.
4579 *
4580 * @param propertyName the property that changed
4581 * @param oldValue the old property value
4582 * @param newValue the new property value
4583 */
4584 protected void firePropertyChange(String propertyName, int oldValue,
4585 int newValue)
4586 {
4587 if (changeSupport != null)
4588 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
4589 }
4590
4591 /**
4592 * Report a change in a bound property to any registered property listeners.
4593 *
4594 * @param propertyName the property that changed
4595 * @param oldValue the old property value
4596 * @param newValue the new property value
4597 *
4598 * @since 1.5
4599 */
4600 public void firePropertyChange(String propertyName, byte oldValue,
4601 byte newValue)
4602 {
4603 if (changeSupport != null)
4604 changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
4605 new Byte(newValue));
4606 }
4607
4608 /**
4609 * Report a change in a bound property to any registered property listeners.
4610 *
4611 * @param propertyName the property that changed
4612 * @param oldValue the old property value
4613 * @param newValue the new property value
4614 *
4615 * @since 1.5
4616 */
4617 public void firePropertyChange(String propertyName, char oldValue,
4618 char newValue)
4619 {
4620 if (changeSupport != null)
4621 changeSupport.firePropertyChange(propertyName, new Character(oldValue),
4622 new Character(newValue));
4623 }
4624
4625 /**
4626 * Report a change in a bound property to any registered property listeners.
4627 *
4628 * @param propertyName the property that changed
4629 * @param oldValue the old property value
4630 * @param newValue the new property value
4631 *
4632 * @since 1.5
4633 */
4634 public void firePropertyChange(String propertyName, short oldValue,
4635 short newValue)
4636 {
4637 if (changeSupport != null)
4638 changeSupport.firePropertyChange(propertyName, new Short(oldValue),
4639 new Short(newValue));
4640 }
4641
4642 /**
4643 * Report a change in a bound property to any registered property listeners.
4644 *
4645 * @param propertyName the property that changed
4646 * @param oldValue the old property value
4647 * @param newValue the new property value
4648 *
4649 * @since 1.5
4650 */
4651 public void firePropertyChange(String propertyName, long oldValue,
4652 long newValue)
4653 {
4654 if (changeSupport != null)
4655 changeSupport.firePropertyChange(propertyName, new Long(oldValue),
4656 new Long(newValue));
4657 }
4658
4659 /**
4660 * Report a change in a bound property to any registered property listeners.
4661 *
4662 * @param propertyName the property that changed
4663 * @param oldValue the old property value
4664 * @param newValue the new property value
4665 *
4666 * @since 1.5
4667 */
4668 public void firePropertyChange(String propertyName, float oldValue,
4669 float newValue)
4670 {
4671 if (changeSupport != null)
4672 changeSupport.firePropertyChange(propertyName, new Float(oldValue),
4673 new Float(newValue));
4674 }
4675
4676
4677 /**
4678 * Report a change in a bound property to any registered property listeners.
4679 *
4680 * @param propertyName the property that changed
4681 * @param oldValue the old property value
4682 * @param newValue the new property value
4683 *
4684 * @since 1.5
4685 */
4686 public void firePropertyChange(String propertyName, double oldValue,
4687 double newValue)
4688 {
4689 if (changeSupport != null)
4690 changeSupport.firePropertyChange(propertyName, new Double(oldValue),
4691 new Double(newValue));
4692 }
4693
4694 /**
4695 * Sets the text layout orientation of this component. New components default
4696 * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only
4697 * the current component, while
4698 * {@link #applyComponentOrientation(ComponentOrientation)} affects the
4699 * entire hierarchy.
4700 *
4701 * @param o the new orientation
4702 * @throws NullPointerException if o is null
4703 * @see #getComponentOrientation()
4704 */
4705 public void setComponentOrientation(ComponentOrientation o)
4706 {
4707 if (o == null)
4708 throw new NullPointerException();
4709 ComponentOrientation oldOrientation = orientation;
4710 orientation = o;
4711 firePropertyChange("componentOrientation", oldOrientation, o);
4712 }
4713
4714 /**
4715 * Determines the text layout orientation used by this component.
4716 *
4717 * @return the component orientation
4718 * @see #setComponentOrientation(ComponentOrientation)
4719 */
4720 public ComponentOrientation getComponentOrientation()
4721 {
4722 return orientation;
4723 }
4724
4725 /**
4726 * Sets the text layout orientation of this component. New components default
4727 * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the
4728 * entire hierarchy, while
4729 * {@link #setComponentOrientation(ComponentOrientation)} affects only the
4730 * current component.
4731 *
4732 * @param o the new orientation
4733 * @throws NullPointerException if o is null
4734 * @see #getComponentOrientation()
4735 * @since 1.4
4736 */
4737 public void applyComponentOrientation(ComponentOrientation o)
4738 {
4739 setComponentOrientation(o);
4740 }
4741
4742 /**
4743 * Returns the accessibility framework context of this class. Component is
4744 * not accessible, so the default implementation returns null. Subclasses
4745 * must override this behavior, and return an appropriate subclass of
4746 * {@link AccessibleAWTComponent}.
4747 *
4748 * @return the accessibility context
4749 */
4750 public AccessibleContext getAccessibleContext()
4751 {
4752 return null;
4753 }
4754
4755
4756 // Helper methods; some are package visible for use by subclasses.
4757
4758 /**
4759 * Subclasses should override this to return unique component names like
4760 * "menuitem0".
4761 *
4762 * @return the generated name for this component
4763 */
4764 String generateName()
4765 {
4766 // Component is abstract.
4767 return null;
4768 }
4769
4770 /**
4771 * Sets the peer for this component.
4772 *
4773 * @param peer the new peer
4774 */
4775 final void setPeer(ComponentPeer peer)
4776 {
4777 this.peer = peer;
4778 }
4779
4780 /**
4781 * Implementation method that allows classes such as Canvas and Window to
4782 * override the graphics configuration without violating the published API.
4783 *
4784 * @return the graphics configuration
4785 */
4786 GraphicsConfiguration getGraphicsConfigurationImpl()
4787 {
4788 if (peer != null)
4789 {
4790 GraphicsConfiguration config = peer.getGraphicsConfiguration();
4791 if (config != null)
4792 return config;
4793 }
4794
4795 if (parent != null)
4796 return parent.getGraphicsConfiguration();
4797
4798 return null;
4799 }
4800
4801 /**
4802 * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0
4803 * event ({@link Event}).
4804 *
4805 * @param e an AWT 1.1 event to translate
4806 *
4807 * @return an AWT 1.0 event representing e
4808 */
4809 static Event translateEvent (AWTEvent e)
4810 {
4811 Object target = e.getSource ();
4812 Event translated = null;
4813
4814 if (e instanceof InputEvent)
4815 {
4816 InputEvent ie = (InputEvent) e;
4817 long when = ie.getWhen ();
4818
4819 int oldID = 0;
4820 int id = e.getID ();
4821
4822 int oldMods = 0;
4823 int mods = ie.getModifiersEx ();
4824
4825 if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0)
4826 oldMods |= Event.META_MASK;
4827 else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0)
4828 oldMods |= Event.ALT_MASK;
4829
4830 if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0)
4831 oldMods |= Event.SHIFT_MASK;
4832
4833 if ((mods & InputEvent.CTRL_DOWN_MASK) != 0)
4834 oldMods |= Event.CTRL_MASK;
4835
4836 if ((mods & InputEvent.META_DOWN_MASK) != 0)
4837 oldMods |= Event.META_MASK;
4838
4839 if ((mods & InputEvent.ALT_DOWN_MASK) != 0)
4840 oldMods |= Event.ALT_MASK;
4841
4842 if (e instanceof MouseEvent)
4843 {
4844 if (id == MouseEvent.MOUSE_PRESSED)
4845 oldID = Event.MOUSE_DOWN;
4846 else if (id == MouseEvent.MOUSE_RELEASED)
4847 oldID = Event.MOUSE_UP;
4848 else if (id == MouseEvent.MOUSE_MOVED)
4849 oldID = Event.MOUSE_MOVE;
4850 else if (id == MouseEvent.MOUSE_DRAGGED)
4851 oldID = Event.MOUSE_DRAG;
4852 else if (id == MouseEvent.MOUSE_ENTERED)
4853 oldID = Event.MOUSE_ENTER;
4854 else if (id == MouseEvent.MOUSE_EXITED)
4855 oldID = Event.MOUSE_EXIT;
4856 else
4857 // No analogous AWT 1.0 mouse event.
4858 return null;
4859
4860 MouseEvent me = (MouseEvent) e;
4861
4862 translated = new Event (target, when, oldID,
4863 me.getX (), me.getY (), 0, oldMods);
4864 }
4865 else if (e instanceof KeyEvent)
4866 {
4867 if (id == KeyEvent.KEY_PRESSED)
4868 oldID = Event.KEY_PRESS;
4869 else if (e.getID () == KeyEvent.KEY_RELEASED)
4870 oldID = Event.KEY_RELEASE;
4871 else
4872 // No analogous AWT 1.0 key event.
4873 return null;
4874
4875 int oldKey = 0;
4876 int newKey = ((KeyEvent) e).getKeyCode ();
4877 switch (newKey)
4878 {
4879 case KeyEvent.VK_BACK_SPACE:
4880 oldKey = Event.BACK_SPACE;
4881 break;
4882 case KeyEvent.VK_CAPS_LOCK:
4883 oldKey = Event.CAPS_LOCK;
4884 break;
4885 case KeyEvent.VK_DELETE:
4886 oldKey = Event.DELETE;
4887 break;
4888 case KeyEvent.VK_DOWN:
4889 case KeyEvent.VK_KP_DOWN:
4890 oldKey = Event.DOWN;
4891 break;
4892 case KeyEvent.VK_END:
4893 oldKey = Event.END;
4894 break;
4895 case KeyEvent.VK_ENTER:
4896 oldKey = Event.ENTER;
4897 break;
4898 case KeyEvent.VK_ESCAPE:
4899 oldKey = Event.ESCAPE;
4900 break;
4901 case KeyEvent.VK_F1:
4902 oldKey = Event.F1;
4903 break;
4904 case KeyEvent.VK_F10:
4905 oldKey = Event.F10;
4906 break;
4907 case KeyEvent.VK_F11:
4908 oldKey = Event.F11;
4909 break;
4910 case KeyEvent.VK_F12:
4911 oldKey = Event.F12;
4912 break;
4913 case KeyEvent.VK_F2:
4914 oldKey = Event.F2;
4915 break;
4916 case KeyEvent.VK_F3:
4917 oldKey = Event.F3;
4918 break;
4919 case KeyEvent.VK_F4:
4920 oldKey = Event.F4;
4921 break;
4922 case KeyEvent.VK_F5:
4923 oldKey = Event.F5;
4924 break;
4925 case KeyEvent.VK_F6:
4926 oldKey = Event.F6;
4927 break;
4928 case KeyEvent.VK_F7:
4929 oldKey = Event.F7;
4930 break;
4931 case KeyEvent.VK_F8:
4932 oldKey = Event.F8;
4933 break;
4934 case KeyEvent.VK_F9:
4935 oldKey = Event.F9;
4936 break;
4937 case KeyEvent.VK_HOME:
4938 oldKey = Event.HOME;
4939 break;
4940 case KeyEvent.VK_INSERT:
4941 oldKey = Event.INSERT;
4942 break;
4943 case KeyEvent.VK_LEFT:
4944 case KeyEvent.VK_KP_LEFT:
4945 oldKey = Event.LEFT;
4946 break;
4947 case KeyEvent.VK_NUM_LOCK:
4948 oldKey = Event.NUM_LOCK;
4949 break;
4950 case KeyEvent.VK_PAUSE:
4951 oldKey = Event.PAUSE;
4952 break;
4953 case KeyEvent.VK_PAGE_DOWN:
4954 oldKey = Event.PGDN;
4955 break;
4956 case KeyEvent.VK_PAGE_UP:
4957 oldKey = Event.PGUP;
4958 break;
4959 case KeyEvent.VK_PRINTSCREEN:
4960 oldKey = Event.PRINT_SCREEN;
4961 break;
4962 case KeyEvent.VK_RIGHT:
4963 case KeyEvent.VK_KP_RIGHT:
4964 oldKey = Event.RIGHT;
4965 break;
4966 case KeyEvent.VK_SCROLL_LOCK:
4967 oldKey = Event.SCROLL_LOCK;
4968 break;
4969 case KeyEvent.VK_TAB:
4970 oldKey = Event.TAB;
4971 break;
4972 case KeyEvent.VK_UP:
4973 case KeyEvent.VK_KP_UP:
4974 oldKey = Event.UP;
4975 break;
4976 default:
4977 oldKey = (int) ((KeyEvent) e).getKeyChar();
4978 }
4979
4980 translated = new Event (target, when, oldID,
4981 0, 0, oldKey, oldMods);
4982 }
4983 }
4984 else if (e instanceof AdjustmentEvent)
4985 {
4986 AdjustmentEvent ae = (AdjustmentEvent) e;
4987 int type = ae.getAdjustmentType();
4988 int oldType;
4989 if (type == AdjustmentEvent.BLOCK_DECREMENT)
4990 oldType = Event.SCROLL_PAGE_UP;
4991 else if (type == AdjustmentEvent.BLOCK_INCREMENT)
4992 oldType = Event.SCROLL_PAGE_DOWN;
4993 else if (type == AdjustmentEvent.TRACK)
4994 oldType = Event.SCROLL_ABSOLUTE;
4995 else if (type == AdjustmentEvent.UNIT_DECREMENT)
4996 oldType = Event.SCROLL_LINE_UP;
4997 else if (type == AdjustmentEvent.UNIT_INCREMENT)
4998 oldType = Event.SCROLL_LINE_DOWN;
4999 else
5000 oldType = type;
5001 translated = new Event(target, oldType, new Integer(ae.getValue()));
5002 }
5003 else if (e instanceof ActionEvent)
5004 translated = new Event (target, Event.ACTION_EVENT,
5005 ((ActionEvent) e).getActionCommand ());
5006
5007 return translated;
5008 }
5009
5010 /**
5011 * Implementation of dispatchEvent. Allows trusted package classes
5012 * to dispatch additional events first. This implementation first
5013 * translates <code>e</code> to an AWT 1.0 event and sends the
5014 * result to {@link #postEvent}. If the AWT 1.0 event is not
5015 * handled, and events of type <code>e</code> are enabled for this
5016 * component, e is passed on to {@link #processEvent}.
5017 *
5018 * @param e the event to dispatch
5019 */
5020
5021 void dispatchEventImpl(AWTEvent e)
5022 {
5023 // This boolean tells us not to process focus events when the focus
5024 // opposite component is the same as the focus component.
5025 boolean ignoreFocus =
5026 (e instanceof FocusEvent &&
5027 ((FocusEvent)e).getComponent() == ((FocusEvent)e).getOppositeComponent());
5028
5029 if (eventTypeEnabled (e.id))
5030 {
5031 if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE
5032 && !ignoreFocus)
5033 processEvent(e);
5034
5035 // the trick we use to communicate between dispatch and redispatch
5036 // is to have KeyboardFocusManager.redispatch synchronize on the
5037 // object itself. we then do not redispatch to KeyboardFocusManager
5038 // if we are already holding the lock.
5039 if (! Thread.holdsLock(e))
5040 {
5041 switch (e.id)
5042 {
5043 case WindowEvent.WINDOW_GAINED_FOCUS:
5044 case WindowEvent.WINDOW_LOST_FOCUS:
5045 case KeyEvent.KEY_PRESSED:
5046 case KeyEvent.KEY_RELEASED:
5047 case KeyEvent.KEY_TYPED:
5048 case FocusEvent.FOCUS_GAINED:
5049 case FocusEvent.FOCUS_LOST:
5050 if (KeyboardFocusManager
5051 .getCurrentKeyboardFocusManager()
5052 .dispatchEvent(e))
5053 return;
5054 case MouseEvent.MOUSE_PRESSED:
5055 if (isLightweight() && !e.isConsumed())
5056 requestFocus();
5057 break;
5058 }
5059 }
5060 }
5061
5062 if (peer != null)
5063 peer.handleEvent(e);
5064 }
5065
5066 /**
5067 * Tells whether or not an event type is enabled.
5068 */
5069 boolean eventTypeEnabled (int type)
5070 {
5071 if (type > AWTEvent.RESERVED_ID_MAX)
5072 return true;
5073
5074 switch (type)
5075 {
5076 case HierarchyEvent.HIERARCHY_CHANGED:
5077 return (hierarchyListener != null
5078 || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0);
5079
5080 case HierarchyEvent.ANCESTOR_MOVED:
5081 case HierarchyEvent.ANCESTOR_RESIZED:
5082 return (hierarchyBoundsListener != null
5083 || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0);
5084
5085 case ComponentEvent.COMPONENT_HIDDEN:
5086 case ComponentEvent.COMPONENT_MOVED:
5087 case ComponentEvent.COMPONENT_RESIZED:
5088 case ComponentEvent.COMPONENT_SHOWN:
5089 return (componentListener != null
5090 || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0);
5091
5092 case KeyEvent.KEY_PRESSED:
5093 case KeyEvent.KEY_RELEASED:
5094 case KeyEvent.KEY_TYPED:
5095 return (keyListener != null
5096 || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0);
5097
5098 case MouseEvent.MOUSE_CLICKED:
5099 case MouseEvent.MOUSE_ENTERED:
5100 case MouseEvent.MOUSE_EXITED:
5101 case MouseEvent.MOUSE_PRESSED:
5102 case MouseEvent.MOUSE_RELEASED:
5103 return (mouseListener != null
5104 || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
5105 case MouseEvent.MOUSE_MOVED:
5106 case MouseEvent.MOUSE_DRAGGED:
5107 return (mouseMotionListener != null
5108 || (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
5109 case MouseEvent.MOUSE_WHEEL:
5110 return (mouseWheelListener != null
5111 || (eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0);
5112
5113 case FocusEvent.FOCUS_GAINED:
5114 case FocusEvent.FOCUS_LOST:
5115 return (focusListener != null
5116 || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0);
5117
5118 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
5119 case InputMethodEvent.CARET_POSITION_CHANGED:
5120 return (inputMethodListener != null
5121 || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0);
5122
5123 case PaintEvent.PAINT:
5124 case PaintEvent.UPDATE:
5125 return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0;
5126
5127 default:
5128 return false;
5129 }
5130 }
5131
5132 /**
5133 * Coalesce paint events. Current heuristic is: Merge if the union of
5134 * areas is less than twice that of the sum of the areas. The X server
5135 * tend to create a lot of paint events that are adjacent but not
5136 * overlapping.
5137 *
5138 * <pre>
5139 * +------+
5140 * | +-----+ ...will be merged
5141 * | | |
5142 * | | |
5143 * +------+ |
5144 * +-----+
5145 *
5146 * +---------------+--+
5147 * | | | ...will not be merged
5148 * +---------------+ |
5149 * | |
5150 * | |
5151 * | |
5152 * | |
5153 * | |
5154 * +--+
5155 * </pre>
5156 *
5157 * @param queuedEvent the first paint event
5158 * @param newEvent the second paint event
5159 * @return the combined paint event, or null
5160 */
5161 private PaintEvent coalescePaintEvents(PaintEvent queuedEvent,
5162 PaintEvent newEvent)
5163 {
5164 Rectangle r1 = queuedEvent.getUpdateRect();
5165 Rectangle r2 = newEvent.getUpdateRect();
5166 Rectangle union = r1.union(r2);
5167 newEvent.setUpdateRect(union);
5168 return newEvent;
5169 }
5170
5171 /**
5172 * This method is used to implement transferFocus(). CHILD is the child
5173 * making the request. This is overridden by Container; when called for an
5174 * ordinary component there is no child and so we always return null.
5175 *
5176 * FIXME: is this still needed, in light of focus traversal policies?
5177 *
5178 * @param child the component making the request
5179 * @return the next component to focus on
5180 */
5181 Component findNextFocusComponent(Component child)
5182 {
5183 return null;
5184 }
5185
5186 /**
5187 * Deserializes this component. This regenerates all serializable listeners
5188 * which were registered originally.
5189 *
5190 * @param s the stream to read from
5191 * @throws ClassNotFoundException if deserialization fails
5192 * @throws IOException if the stream fails
5193 */
5194 private void readObject(ObjectInputStream s)
5195 throws ClassNotFoundException, IOException
5196 {
5197 s.defaultReadObject();
5198 String key = (String) s.readObject();
5199 while (key != null)
5200 {
5201 Object listener = s.readObject();
5202 if ("componentL".equals(key))
5203 addComponentListener((ComponentListener) listener);
5204 else if ("focusL".equals(key))
5205 addFocusListener((FocusListener) listener);
5206 else if ("keyL".equals(key))
5207 addKeyListener((KeyListener) listener);
5208 else if ("mouseL".equals(key))
5209 addMouseListener((MouseListener) listener);
5210 else if ("mouseMotionL".equals(key))
5211 addMouseMotionListener((MouseMotionListener) listener);
5212 else if ("inputMethodL".equals(key))
5213 addInputMethodListener((InputMethodListener) listener);
5214 else if ("hierarchyL".equals(key))
5215 addHierarchyListener((HierarchyListener) listener);
5216 else if ("hierarchyBoundsL".equals(key))
5217 addHierarchyBoundsListener((HierarchyBoundsListener) listener);
5218 else if ("mouseWheelL".equals(key))
5219 addMouseWheelListener((MouseWheelListener) listener);
5220 key = (String) s.readObject();
5221 }
5222 }
5223
5224 /**
5225 * Serializes this component. This ignores all listeners which do not
5226 * implement Serializable, but includes those that do.
5227 *
5228 * @param s the stream to write to
5229 * @throws IOException if the stream fails
5230 */
5231 private void writeObject(ObjectOutputStream s) throws IOException
5232 {
5233 s.defaultWriteObject();
5234 AWTEventMulticaster.save(s, "componentL", componentListener);
5235 AWTEventMulticaster.save(s, "focusL", focusListener);
5236 AWTEventMulticaster.save(s, "keyL", keyListener);
5237 AWTEventMulticaster.save(s, "mouseL", mouseListener);
5238 AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener);
5239 AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener);
5240 AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener);
5241 AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener);
5242 AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener);
5243 s.writeObject(null);
5244 }
5245
5246
5247 // Nested classes.
5248
5249 /**
5250 * This class fixes the bounds for a Heavyweight component that
5251 * is placed inside a Lightweight container. When the lightweight is
5252 * moved or resized, setBounds for the lightweight peer does nothing.
5253 * Therefore, it was never moved on the screen. This class is
5254 * attached to the lightweight, and it adjusts the position and size
5255 * of the peer when notified.
5256 * This is the same for show and hide.
5257 */
5258 class HeavyweightInLightweightListener
5259 implements ComponentListener
5260 {
5261
5262 /**
5263 * Constructor. Adds component listener to lightweight parent.
5264 *
5265 * @param parent - the lightweight container.
5266 */
5267 public HeavyweightInLightweightListener(Container parent)
5268 {
5269 parent.addComponentListener(this);
5270 }
5271
5272 /**
5273 * This method is called when the component is resized.
5274 *
5275 * @param event the <code>ComponentEvent</code> indicating the resize
5276 */
5277 public void componentResized(ComponentEvent event)
5278 {
5279 // Nothing to do here, componentMoved will be called.
5280 }
5281
5282 /**
5283 * This method is called when the component is moved.
5284 *
5285 * @param event the <code>ComponentEvent</code> indicating the move
5286 */
5287 public void componentMoved(ComponentEvent event)
5288 {
5289 if (peer != null)
5290 peer.setBounds(x, y, width, height);
5291 }
5292
5293 /**
5294 * This method is called when the component is made visible.
5295 *
5296 * @param event the <code>ComponentEvent</code> indicating the visibility
5297 */
5298 public void componentShown(ComponentEvent event)
5299 {
5300 if (isShowing())
5301 peer.show();
5302 }
5303
5304 /**
5305 * This method is called when the component is hidden.
5306 *
5307 * @param event the <code>ComponentEvent</code> indicating the visibility
5308 */
5309 public void componentHidden(ComponentEvent event)
5310 {
5311 if (!isShowing())
5312 peer.hide();
5313 }
5314 }
5315
5316 /**
5317 * This class provides accessibility support for subclasses of container.
5318 *
5319 * @author Eric Blake (ebb9@email.byu.edu)
5320 * @since 1.3
5321 * @status updated to 1.4
5322 */
5323 protected abstract class AccessibleAWTComponent extends AccessibleContext
5324 implements Serializable, AccessibleComponent
5325 {
5326 /**
5327 * Compatible with JDK 1.3+.
5328 */
5329 private static final long serialVersionUID = 642321655757800191L;
5330
5331 /**
5332 * Converts show/hide events to PropertyChange events, and is registered
5333 * as a component listener on this component.
5334 *
5335 * @serial the component handler
5336 */
5337 protected ComponentListener accessibleAWTComponentHandler
5338 = new AccessibleAWTComponentHandler();
5339
5340 /**
5341 * Converts focus events to PropertyChange events, and is registered
5342 * as a focus listener on this component.
5343 *
5344 * @serial the focus handler
5345 */
5346 protected FocusListener accessibleAWTFocusHandler
5347 = new AccessibleAWTFocusHandler();
5348
5349 /**
5350 * The default constructor.
5351 */
5352 protected AccessibleAWTComponent()
5353 {
5354 Component.this.addComponentListener(accessibleAWTComponentHandler);
5355 Component.this.addFocusListener(accessibleAWTFocusHandler);
5356 }
5357
5358 /**
5359 * Adds a global property change listener to the accessible component.
5360 *
5361 * @param l the listener to add
5362 * @see #ACCESSIBLE_NAME_PROPERTY
5363 * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
5364 * @see #ACCESSIBLE_STATE_PROPERTY
5365 * @see #ACCESSIBLE_VALUE_PROPERTY
5366 * @see #ACCESSIBLE_SELECTION_PROPERTY
5367 * @see #ACCESSIBLE_TEXT_PROPERTY
5368 * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
5369 */
5370 public void addPropertyChangeListener(PropertyChangeListener l)
5371 {
5372 Component.this.addPropertyChangeListener(l);
5373 super.addPropertyChangeListener(l);
5374 }
5375
5376 /**
5377 * Removes a global property change listener from this accessible
5378 * component.
5379 *
5380 * @param l the listener to remove
5381 */
5382 public void removePropertyChangeListener(PropertyChangeListener l)
5383 {
5384 Component.this.removePropertyChangeListener(l);
5385 super.removePropertyChangeListener(l);
5386 }
5387
5388 /**
5389 * Returns the accessible name of this component. It is almost always
5390 * wrong to return getName(), since it is not localized. In fact, for
5391 * things like buttons, this should be the text of the button, not the
5392 * name of the object. The tooltip text might also be appropriate.
5393 *
5394 * @return the name
5395 * @see #setAccessibleName(String)
5396 */
5397 public String getAccessibleName()
5398 {
5399 return accessibleName;
5400 }
5401
5402 /**
5403 * Returns a brief description of this accessible context. This should
5404 * be localized.
5405 *
5406 * @return a description of this component
5407 * @see #setAccessibleDescription(String)
5408 */
5409 public String getAccessibleDescription()
5410 {
5411 return accessibleDescription;
5412 }
5413
5414 /**
5415 * Returns the role of this component.
5416 *
5417 * @return the accessible role
5418 */
5419 public AccessibleRole getAccessibleRole()
5420 {
5421 return AccessibleRole.AWT_COMPONENT;
5422 }
5423
5424 /**
5425 * Returns a state set describing this component's state.
5426 *
5427 * @return a new state set
5428 * @see AccessibleState
5429 */
5430 public AccessibleStateSet getAccessibleStateSet()
5431 {
5432 AccessibleStateSet s = new AccessibleStateSet();
5433 if (Component.this.isEnabled())
5434 s.add(AccessibleState.ENABLED);
5435 if (isFocusable())
5436 s.add(AccessibleState.FOCUSABLE);
5437 if (isFocusOwner())
5438 s.add(AccessibleState.FOCUSED);
5439 // Note: While the java.awt.Component has an 'opaque' property, it
5440 // seems that it is not added to the accessible state set here, even
5441 // if this property is true. However, it is handled for
5442 // javax.swing.JComponent, so we add it there.
5443 if (Component.this.isShowing())
5444 s.add(AccessibleState.SHOWING);
5445 if (Component.this.isVisible())
5446 s.add(AccessibleState.VISIBLE);
5447 return s;
5448 }
5449
5450 /**
5451 * Returns the parent of this component, if it is accessible.
5452 *
5453 * @return the accessible parent
5454 */
5455 public Accessible getAccessibleParent()
5456 {
5457 if (accessibleParent == null)
5458 {
5459 Container parent = getParent();
5460 accessibleParent = parent instanceof Accessible
5461 ? (Accessible) parent : null;
5462 }
5463 return accessibleParent;
5464 }
5465
5466 /**
5467 * Returns the index of this component in its accessible parent.
5468 *
5469 * @return the index, or -1 if the parent is not accessible
5470 * @see #getAccessibleParent()
5471 */
5472 public int getAccessibleIndexInParent()
5473 {
5474 if (getAccessibleParent() == null)
5475 return -1;
5476 AccessibleContext context
5477 = ((Component) accessibleParent).getAccessibleContext();
5478 if (context == null)
5479 return -1;
5480 for (int i = context.getAccessibleChildrenCount(); --i >= 0; )
5481 if (context.getAccessibleChild(i) == Component.this)
5482 return i;
5483 return -1;
5484 }
5485
5486 /**
5487 * Returns the number of children of this component which implement
5488 * Accessible. Subclasses must override this if they can have children.
5489 *
5490 * @return the number of accessible children, default 0
5491 */
5492 public int getAccessibleChildrenCount()
5493 {
5494 return 0;
5495 }
5496
5497 /**
5498 * Returns the ith accessible child. Subclasses must override this if
5499 * they can have children.
5500 *
5501 * @return the ith accessible child, or null
5502 * @see #getAccessibleChildrenCount()
5503 */
5504 public Accessible getAccessibleChild(int i)
5505 {
5506 return null;
5507 }
5508
5509 /**
5510 * Returns the locale of this component.
5511 *
5512 * @return the locale
5513 * @throws IllegalComponentStateException if the locale is unknown
5514 */
5515 public Locale getLocale()
5516 {
5517 return Component.this.getLocale();
5518 }
5519
5520 /**
5521 * Returns this, since it is an accessible component.
5522 *
5523 * @return the accessible component
5524 */
5525 public AccessibleComponent getAccessibleComponent()
5526 {
5527 return this;
5528 }
5529
5530 /**
5531 * Gets the background color.
5532 *
5533 * @return the background color
5534 * @see #setBackground(Color)
5535 */
5536 public Color getBackground()
5537 {
5538 return Component.this.getBackground();
5539 }
5540
5541 /**
5542 * Sets the background color.
5543 *
5544 * @param c the background color
5545 * @see #getBackground()
5546 * @see #isOpaque()
5547 */
5548 public void setBackground(Color c)
5549 {
5550 Component.this.setBackground(c);
5551 }
5552
5553 /**
5554 * Gets the foreground color.
5555 *
5556 * @return the foreground color
5557 * @see #setForeground(Color)
5558 */
5559 public Color getForeground()
5560 {
5561 return Component.this.getForeground();
5562 }
5563
5564 /**
5565 * Sets the foreground color.
5566 *
5567 * @param c the foreground color
5568 * @see #getForeground()
5569 */
5570 public void setForeground(Color c)
5571 {
5572 Component.this.setForeground(c);
5573 }
5574
5575 /**
5576 * Gets the cursor.
5577 *
5578 * @return the cursor
5579 * @see #setCursor(Cursor)
5580 */
5581 public Cursor getCursor()
5582 {
5583 return Component.this.getCursor();
5584 }
5585
5586 /**
5587 * Sets the cursor.
5588 *
5589 * @param cursor the cursor
5590 * @see #getCursor()
5591 */
5592 public void setCursor(Cursor cursor)
5593 {
5594 Component.this.setCursor(cursor);
5595 }
5596
5597 /**
5598 * Gets the font.
5599 *
5600 * @return the font
5601 * @see #setFont(Font)
5602 */
5603 public Font getFont()
5604 {
5605 return Component.this.getFont();
5606 }
5607
5608 /**
5609 * Sets the font.
5610 *
5611 * @param f the font
5612 * @see #getFont()
5613 */
5614 public void setFont(Font f)
5615 {
5616 Component.this.setFont(f);
5617 }
5618
5619 /**
5620 * Gets the font metrics for a font.
5621 *
5622 * @param f the font to look up
5623 * @return its metrics
5624 * @throws NullPointerException if f is null
5625 * @see #getFont()
5626 */
5627 public FontMetrics getFontMetrics(Font f)
5628 {
5629 return Component.this.getFontMetrics(f);
5630 }
5631
5632 /**
5633 * Tests if the component is enabled.
5634 *
5635 * @return true if the component is enabled
5636 * @see #setEnabled(boolean)
5637 * @see #getAccessibleStateSet()
5638 * @see AccessibleState#ENABLED
5639 */
5640 public boolean isEnabled()
5641 {
5642 return Component.this.isEnabled();
5643 }
5644
5645 /**
5646 * Set whether the component is enabled.
5647 *
5648 * @param b the new enabled status
5649 * @see #isEnabled()
5650 */
5651 public void setEnabled(boolean b)
5652 {
5653 Component.this.setEnabled(b);
5654 }
5655
5656 /**
5657 * Test whether the component is visible (not necesarily showing).
5658 *
5659 * @return true if it is visible
5660 * @see #setVisible(boolean)
5661 * @see #getAccessibleStateSet()
5662 * @see AccessibleState#VISIBLE
5663 */
5664 public boolean isVisible()
5665 {
5666 return Component.this.isVisible();
5667 }
5668
5669 /**
5670 * Sets the visibility of this component.
5671 *
5672 * @param b the desired visibility
5673 * @see #isVisible()
5674 */
5675 public void setVisible(boolean b)
5676 {
5677 Component.this.setVisible(b);
5678 }
5679
5680 /**
5681 * Tests if the component is showing.
5682 *
5683 * @return true if this is showing
5684 */
5685 public boolean isShowing()
5686 {
5687 return Component.this.isShowing();
5688 }
5689
5690 /**
5691 * Tests if the point is contained in this component.
5692 *
5693 * @param p the point to check
5694 * @return true if it is contained
5695 * @throws NullPointerException if p is null
5696 */
5697 public boolean contains(Point p)
5698 {
5699 return Component.this.contains(p.x, p.y);
5700 }
5701
5702 /**
5703 * Returns the location of this object on the screen, or null if it is
5704 * not showing.
5705 *
5706 * @return the location relative to screen coordinates, if showing
5707 * @see #getBounds()
5708 * @see #getLocation()
5709 */
5710 public Point getLocationOnScreen()
5711 {
5712 return Component.this.isShowing() ? Component.this.getLocationOnScreen()
5713 : null;
5714 }
5715
5716 /**
5717 * Returns the location of this object relative to its parent's coordinate
5718 * system, or null if it is not showing.
5719 *
5720 * @return the location
5721 * @see #getBounds()
5722 * @see #getLocationOnScreen()
5723 */
5724 public Point getLocation()
5725 {
5726 return Component.this.getLocation();
5727 }
5728
5729 /**
5730 * Sets the location of this relative to its parent's coordinate system.
5731 *
5732 * @param p the location
5733 * @throws NullPointerException if p is null
5734 * @see #getLocation()
5735 */
5736 public void setLocation(Point p)
5737 {
5738 Component.this.setLocation(p.x, p.y);
5739 }
5740
5741 /**
5742 * Gets the bounds of this component, or null if it is not on screen.
5743 *
5744 * @return the bounds
5745 * @see #contains(Point)
5746 * @see #setBounds(Rectangle)
5747 */
5748 public Rectangle getBounds()
5749 {
5750 return Component.this.getBounds();
5751 }
5752
5753 /**
5754 * Sets the bounds of this component.
5755 *
5756 * @param r the bounds
5757 * @throws NullPointerException if r is null
5758 * @see #getBounds()
5759 */
5760 public void setBounds(Rectangle r)
5761 {
5762 Component.this.setBounds(r.x, r.y, r.width, r.height);
5763 }
5764
5765 /**
5766 * Gets the size of this component, or null if it is not showing.
5767 *
5768 * @return the size
5769 * @see #setSize(Dimension)
5770 */
5771 public Dimension getSize()
5772 {
5773 return Component.this.getSize();
5774 }
5775
5776 /**
5777 * Sets the size of this component.
5778 *
5779 * @param d the size
5780 * @throws NullPointerException if d is null
5781 * @see #getSize()
5782 */
5783 public void setSize(Dimension d)
5784 {
5785 Component.this.setSize(d.width, d.height);
5786 }
5787
5788 /**
5789 * Returns the Accessible child at a point relative to the coordinate
5790 * system of this component, if one exists, or null. Since components
5791 * have no children, subclasses must override this to get anything besides
5792 * null.
5793 *
5794 * @param p the point to check
5795 * @return the accessible child at that point
5796 * @throws NullPointerException if p is null
5797 */
5798 public Accessible getAccessibleAt(Point p)
5799 {
5800 return null;
5801 }
5802
5803 /**
5804 * Tests whether this component can accept focus.
5805 *
5806 * @return true if this is focus traversable
5807 * @see #getAccessibleStateSet ()
5808 * @see AccessibleState#FOCUSABLE
5809 * @see AccessibleState#FOCUSED
5810 */
5811 public boolean isFocusTraversable ()
5812 {
5813 return Component.this.isFocusTraversable ();
5814 }
5815
5816 /**
5817 * Requests focus for this component.
5818 *
5819 * @see #isFocusTraversable ()
5820 */
5821 public void requestFocus ()
5822 {
5823 Component.this.requestFocus ();
5824 }
5825
5826 /**
5827 * Adds a focus listener.
5828 *
5829 * @param l the listener to add
5830 */
5831 public void addFocusListener(FocusListener l)
5832 {
5833 Component.this.addFocusListener(l);
5834 }
5835
5836 /**
5837 * Removes a focus listener.
5838 *
5839 * @param l the listener to remove
5840 */
5841 public void removeFocusListener(FocusListener l)
5842 {
5843 Component.this.removeFocusListener(l);
5844 }
5845
5846 /**
5847 * Converts component changes into property changes.
5848 *
5849 * @author Eric Blake (ebb9@email.byu.edu)
5850 * @since 1.3
5851 * @status updated to 1.4
5852 */
5853 protected class AccessibleAWTComponentHandler implements ComponentListener
5854 {
5855 /**
5856 * Default constructor.
5857 */
5858 protected AccessibleAWTComponentHandler()
5859 {
5860 // Nothing to do here.
5861 }
5862
5863 /**
5864 * Convert a component hidden to a property change.
5865 *
5866 * @param e the event to convert
5867 */
5868 public void componentHidden(ComponentEvent e)
5869 {
5870 AccessibleAWTComponent.this.firePropertyChange
5871 (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null);
5872 }
5873
5874 /**
5875 * Convert a component shown to a property change.
5876 *
5877 * @param e the event to convert
5878 */
5879 public void componentShown(ComponentEvent e)
5880 {
5881 AccessibleAWTComponent.this.firePropertyChange
5882 (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE);
5883 }
5884
5885 /**
5886 * Moving a component does not affect properties.
5887 *
5888 * @param e ignored
5889 */
5890 public void componentMoved(ComponentEvent e)
5891 {
5892 // Nothing to do here.
5893 }
5894
5895 /**
5896 * Resizing a component does not affect properties.
5897 *
5898 * @param e ignored
5899 */
5900 public void componentResized(ComponentEvent e)
5901 {
5902 // Nothing to do here.
5903 }
5904 } // class AccessibleAWTComponentHandler
5905
5906 /**
5907 * Converts focus changes into property changes.
5908 *
5909 * @author Eric Blake (ebb9@email.byu.edu)
5910 * @since 1.3
5911 * @status updated to 1.4
5912 */
5913 protected class AccessibleAWTFocusHandler implements FocusListener
5914 {
5915 /**
5916 * Default constructor.
5917 */
5918 protected AccessibleAWTFocusHandler()
5919 {
5920 // Nothing to do here.
5921 }
5922
5923 /**
5924 * Convert a focus gained to a property change.
5925 *
5926 * @param e the event to convert
5927 */
5928 public void focusGained(FocusEvent e)
5929 {
5930 AccessibleAWTComponent.this.firePropertyChange
5931 (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED);
5932 }
5933
5934 /**
5935 * Convert a focus lost to a property change.
5936 *
5937 * @param e the event to convert
5938 */
5939 public void focusLost(FocusEvent e)
5940 {
5941 AccessibleAWTComponent.this.firePropertyChange
5942 (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null);
5943 }
5944 } // class AccessibleAWTComponentHandler
5945 } // class AccessibleAWTComponent
5946
5947 /**
5948 * This class provides support for blitting offscreen surfaces to a
5949 * component.
5950 *
5951 * @see BufferStrategy
5952 *
5953 * @since 1.4
5954 */
5955 protected class BltBufferStrategy extends BufferStrategy
5956 {
5957 /**
5958 * The capabilities of the image buffer.
5959 */
5960 protected BufferCapabilities caps;
5961
5962 /**
5963 * The back buffers used in this strategy.
5964 */
5965 protected VolatileImage[] backBuffers;
5966
5967 /**
5968 * Whether or not the image buffer resources are allocated and
5969 * ready to be drawn into.
5970 */
5971 protected boolean validatedContents;
5972
5973 /**
5974 * The width of the back buffers.
5975 */
5976 protected int width;
5977
5978 /**
5979 * The height of the back buffers.
5980 */
5981 protected int height;
5982
5983 /**
5984 * The front buffer.
5985 */
5986 private VolatileImage frontBuffer;
5987
5988 /**
5989 * Creates a blitting buffer strategy.
5990 *
5991 * @param numBuffers the number of buffers, including the front
5992 * buffer
5993 * @param caps the capabilities of this strategy
5994 */
5995 protected BltBufferStrategy(int numBuffers, BufferCapabilities caps)
5996 {
5997 this.caps = caps;
5998 createBackBuffers(numBuffers - 1);
5999 width = getWidth();
6000 height = getHeight();
6001 }
6002
6003 /**
6004 * Initializes the backBuffers field with an array of numBuffers
6005 * VolatileImages.
6006 *
6007 * @param numBuffers the number of backbuffers to create
6008 */
6009 protected void createBackBuffers(int numBuffers)
6010 {
6011 GraphicsConfiguration c =
6012 GraphicsEnvironment.getLocalGraphicsEnvironment()
6013 .getDefaultScreenDevice().getDefaultConfiguration();
6014
6015 backBuffers = new VolatileImage[numBuffers];
6016
6017 for (int i = 0; i < numBuffers; i++)
6018 backBuffers[i] = c.createCompatibleVolatileImage(width, height);
6019 }
6020
6021 /**
6022 * Retrieves the capabilities of this buffer strategy.
6023 *
6024 * @return the capabilities of this buffer strategy
6025 */
6026 public BufferCapabilities getCapabilities()
6027 {
6028 return caps;
6029 }
6030
6031 /**
6032 * Retrieves a graphics object that can be used to draw into this
6033 * strategy's image buffer.
6034 *
6035 * @return a graphics object
6036 */
6037 public Graphics getDrawGraphics()
6038 {
6039 // Return the backmost buffer's graphics.
6040 return backBuffers[0].getGraphics();
6041 }
6042
6043 /**
6044 * Bring the contents of the back buffer to the front buffer.
6045 */
6046 public void show()
6047 {
6048 GraphicsConfiguration c =
6049 GraphicsEnvironment.getLocalGraphicsEnvironment()
6050 .getDefaultScreenDevice().getDefaultConfiguration();
6051
6052 // draw the front buffer.
6053 getGraphics().drawImage(backBuffers[backBuffers.length - 1],
6054 width, height, null);
6055
6056 BufferCapabilities.FlipContents f = getCapabilities().getFlipContents();
6057
6058 // blit the back buffers.
6059 for (int i = backBuffers.length - 1; i > 0 ; i--)
6060 backBuffers[i] = backBuffers[i - 1];
6061
6062 // create new backmost buffer.
6063 if (f == BufferCapabilities.FlipContents.UNDEFINED)
6064 backBuffers[0] = c.createCompatibleVolatileImage(width, height);
6065
6066 // create new backmost buffer and clear it to the background
6067 // color.
6068 if (f == BufferCapabilities.FlipContents.BACKGROUND)
6069 {
6070 backBuffers[0] = c.createCompatibleVolatileImage(width, height);
6071 backBuffers[0].getGraphics().clearRect(0, 0, width, height);
6072 }
6073
6074 // FIXME: set the backmost buffer to the prior contents of the
6075 // front buffer. How do we retrieve the contents of the front
6076 // buffer?
6077 //
6078 // if (f == BufferCapabilities.FlipContents.PRIOR)
6079
6080 // set the backmost buffer to a copy of the new front buffer.
6081 if (f == BufferCapabilities.FlipContents.COPIED)
6082 backBuffers[0] = backBuffers[backBuffers.length - 1];
6083 }
6084
6085 /**
6086 * Re-create the image buffer resources if they've been lost.
6087 */
6088 protected void revalidate()
6089 {
6090 GraphicsConfiguration c =
6091 GraphicsEnvironment.getLocalGraphicsEnvironment()
6092 .getDefaultScreenDevice().getDefaultConfiguration();
6093
6094 for (int i = 0; i < backBuffers.length; i++)
6095 {
6096 int result = backBuffers[i].validate(c);
6097 if (result == VolatileImage.IMAGE_INCOMPATIBLE)
6098 backBuffers[i] = c.createCompatibleVolatileImage(width, height);
6099 }
6100 validatedContents = true;
6101 }
6102
6103 /**
6104 * Returns whether or not the image buffer resources have been
6105 * lost.
6106 *
6107 * @return true if the resources have been lost, false otherwise
6108 */
6109 public boolean contentsLost()
6110 {
6111 for (int i = 0; i < backBuffers.length; i++)
6112 {
6113 if (backBuffers[i].contentsLost())
6114 {
6115 validatedContents = false;
6116 return true;
6117 }
6118 }
6119 // we know that the buffer resources are valid now because we
6120 // just checked them
6121 validatedContents = true;
6122 return false;
6123 }
6124
6125 /**
6126 * Returns whether or not the image buffer resources have been
6127 * restored.
6128 *
6129 * @return true if the resources have been restored, false
6130 * otherwise
6131 */
6132 public boolean contentsRestored()
6133 {
6134 GraphicsConfiguration c =
6135 GraphicsEnvironment.getLocalGraphicsEnvironment()
6136 .getDefaultScreenDevice().getDefaultConfiguration();
6137
6138 boolean imageRestored = false;
6139
6140 for (int i = 0; i < backBuffers.length; i++)
6141 {
6142 int result = backBuffers[i].validate(c);
6143 if (result == VolatileImage.IMAGE_RESTORED)
6144 imageRestored = true;
6145 else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
6146 return false;
6147 }
6148 // we know that the buffer resources are valid now because we
6149 // just checked them
6150 validatedContents = true;
6151 return imageRestored;
6152 }
6153 }
6154
6155 /**
6156 * This class provides support for flipping component buffers. It
6157 * can only be used on Canvases and Windows.
6158 *
6159 * @since 1.4
6160 */
6161 protected class FlipBufferStrategy extends BufferStrategy
6162 {
6163 /**
6164 * The number of buffers.
6165 */
6166 protected int numBuffers;
6167
6168 /**
6169 * The capabilities of this buffering strategy.
6170 */
6171 protected BufferCapabilities caps;
6172
6173 /**
6174 * An Image reference to the drawing buffer.
6175 */
6176 protected Image drawBuffer;
6177
6178 /**
6179 * A VolatileImage reference to the drawing buffer.
6180 */
6181 protected VolatileImage drawVBuffer;
6182
6183 /**
6184 * Whether or not the image buffer resources are allocated and
6185 * ready to be drawn into.
6186 */
6187 protected boolean validatedContents;
6188
6189 /**
6190 * The width of the back buffer.
6191 */
6192 private int width;
6193
6194 /**
6195 * The height of the back buffer.
6196 */
6197 private int height;
6198
6199 /**
6200 * Creates a flipping buffer strategy. The only supported
6201 * strategy for FlipBufferStrategy itself is a double-buffer page
6202 * flipping strategy. It forms the basis for more complex derived
6203 * strategies.
6204 *
6205 * @param numBuffers the number of buffers
6206 * @param caps the capabilities of this buffering strategy
6207 *
6208 * @throws AWTException if the requested
6209 * number-of-buffers/capabilities combination is not supported
6210 */
6211 protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
6212 throws AWTException
6213 {
6214 this.caps = caps;
6215 width = getWidth();
6216 height = getHeight();
6217
6218 if (numBuffers > 1)
6219 createBuffers(numBuffers, caps);
6220 else
6221 {
6222 drawVBuffer = peer.createVolatileImage(width, height);
6223 drawBuffer = drawVBuffer;
6224 }
6225 }
6226
6227 /**
6228 * Creates a multi-buffer flipping strategy. The number of
6229 * buffers must be greater than one and the buffer capabilities
6230 * must specify page flipping.
6231 *
6232 * @param numBuffers the number of flipping buffers; must be
6233 * greater than one
6234 * @param caps the buffering capabilities; caps.isPageFlipping()
6235 * must return true
6236 *
6237 * @throws IllegalArgumentException if numBuffers is not greater
6238 * than one or if the page flipping capability is not requested
6239 *
6240 * @throws AWTException if the requested flipping strategy is not
6241 * supported
6242 */
6243 protected void createBuffers(int numBuffers, BufferCapabilities caps)
6244 throws AWTException
6245 {
6246 if (numBuffers <= 1)
6247 throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
6248 + " numBuffers must be greater than"
6249 + " one.");
6250
6251 if (!caps.isPageFlipping())
6252 throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
6253 + " flipping must be a specified"
6254 + " capability.");
6255
6256 peer.createBuffers(numBuffers, caps);
6257 }
6258
6259 /**
6260 * Return a direct reference to the back buffer image.
6261 *
6262 * @return a direct reference to the back buffer image.
6263 */
6264 protected Image getBackBuffer()
6265 {
6266 return peer.getBackBuffer();
6267 }
6268
6269 /**
6270 * Perform a flip operation to transfer the contents of the back
6271 * buffer to the front buffer.
6272 */
6273 protected void flip(BufferCapabilities.FlipContents flipAction)
6274 {
6275 peer.flip(flipAction);
6276 }
6277
6278 /**
6279 * Release the back buffer's resources.
6280 */
6281 protected void destroyBuffers()
6282 {
6283 peer.destroyBuffers();
6284 }
6285
6286 /**
6287 * Retrieves the capabilities of this buffer strategy.
6288 *
6289 * @return the capabilities of this buffer strategy
6290 */
6291 public BufferCapabilities getCapabilities()
6292 {
6293 return caps;
6294 }
6295
6296 /**
6297 * Retrieves a graphics object that can be used to draw into this
6298 * strategy's image buffer.
6299 *
6300 * @return a graphics object
6301 */
6302 public Graphics getDrawGraphics()
6303 {
6304 return drawVBuffer.getGraphics();
6305 }
6306
6307 /**
6308 * Re-create the image buffer resources if they've been lost.
6309 */
6310 protected void revalidate()
6311 {
6312 GraphicsConfiguration c =
6313 GraphicsEnvironment.getLocalGraphicsEnvironment()
6314 .getDefaultScreenDevice().getDefaultConfiguration();
6315
6316 if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE)
6317 drawVBuffer = peer.createVolatileImage(width, height);
6318 validatedContents = true;
6319 }
6320
6321 /**
6322 * Returns whether or not the image buffer resources have been
6323 * lost.
6324 *
6325 * @return true if the resources have been lost, false otherwise
6326 */
6327 public boolean contentsLost()
6328 {
6329 if (drawVBuffer.contentsLost())
6330 {
6331 validatedContents = false;
6332 return true;
6333 }
6334 // we know that the buffer resources are valid now because we
6335 // just checked them
6336 validatedContents = true;
6337 return false;
6338 }
6339
6340 /**
6341 * Returns whether or not the image buffer resources have been
6342 * restored.
6343 *
6344 * @return true if the resources have been restored, false
6345 * otherwise
6346 */
6347 public boolean contentsRestored()
6348 {
6349 GraphicsConfiguration c =
6350 GraphicsEnvironment.getLocalGraphicsEnvironment()
6351 .getDefaultScreenDevice().getDefaultConfiguration();
6352
6353 int result = drawVBuffer.validate(c);
6354
6355 boolean imageRestored = false;
6356
6357 if (result == VolatileImage.IMAGE_RESTORED)
6358 imageRestored = true;
6359 else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
6360 return false;
6361
6362 // we know that the buffer resources are valid now because we
6363 // just checked them
6364 validatedContents = true;
6365 return imageRestored;
6366 }
6367
6368 /**
6369 * Bring the contents of the back buffer to the front buffer.
6370 */
6371 public void show()
6372 {
6373 flip(caps.getFlipContents());
6374 }
6375 }
6376 }