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