OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [JComponent.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* JComponent.java -- Every component in swing inherits from this class.
2
   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing;
40
 
41
import java.applet.Applet;
42
import java.awt.AWTEvent;
43
import java.awt.Color;
44
import java.awt.Component;
45
import java.awt.Container;
46
import java.awt.Dimension;
47
import java.awt.EventQueue;
48
import java.awt.FlowLayout;
49
import java.awt.FocusTraversalPolicy;
50
import java.awt.Font;
51
import java.awt.Graphics;
52
import java.awt.Graphics2D;
53
import java.awt.Image;
54
import java.awt.Insets;
55
import java.awt.Point;
56
import java.awt.Rectangle;
57
import java.awt.Shape;
58
import java.awt.Window;
59
import java.awt.dnd.DropTarget;
60
import java.awt.event.ActionEvent;
61
import java.awt.event.ActionListener;
62
import java.awt.event.ContainerEvent;
63
import java.awt.event.ContainerListener;
64
import java.awt.event.FocusEvent;
65
import java.awt.event.FocusListener;
66
import java.awt.event.KeyEvent;
67
import java.awt.event.MouseEvent;
68
import java.awt.geom.Rectangle2D;
69
import java.awt.peer.LightweightPeer;
70
import java.beans.PropertyChangeEvent;
71
import java.beans.PropertyChangeListener;
72
import java.beans.PropertyVetoException;
73
import java.beans.VetoableChangeListener;
74
import java.io.Serializable;
75
import java.util.EventListener;
76
import java.util.Hashtable;
77
import java.util.Locale;
78
import java.util.Set;
79
 
80
import javax.accessibility.Accessible;
81
import javax.accessibility.AccessibleContext;
82
import javax.accessibility.AccessibleExtendedComponent;
83
import javax.accessibility.AccessibleKeyBinding;
84
import javax.accessibility.AccessibleRole;
85
import javax.accessibility.AccessibleStateSet;
86
import javax.swing.border.Border;
87
import javax.swing.border.CompoundBorder;
88
import javax.swing.border.TitledBorder;
89
import javax.swing.event.AncestorEvent;
90
import javax.swing.event.AncestorListener;
91
import javax.swing.event.EventListenerList;
92
import javax.swing.event.SwingPropertyChangeSupport;
93
import javax.swing.plaf.ComponentUI;
94
 
95
/**
96
 * The base class of all Swing components.
97
 * It contains generic methods to manage events, properties and sizes. Actual
98
 * drawing of the component is channeled to a look-and-feel class that is
99
 * implemented elsewhere.
100
 *
101
 * @author Ronald Veldema (rveldema&064;cs.vu.nl)
102
 * @author Graydon Hoare (graydon&064;redhat.com)
103
 */
104
public abstract class JComponent extends Container implements Serializable
105
{
106
  private static final long serialVersionUID = -7908749299918704233L;
107
 
108
  /**
109
   * Accessibility support is currently missing.
110
   */
111
  protected AccessibleContext accessibleContext;
112
 
113
  /**
114
   * Basic accessibility support for <code>JComponent</code> derived
115
   * widgets.
116
   */
117
  public abstract class AccessibleJComponent
118
    extends AccessibleAWTContainer
119
    implements AccessibleExtendedComponent
120
  {
121
    /**
122
     * Accessibility support for <code>JComponent</code>'s focus handler.
123
     */
124
    protected class AccessibleFocusHandler
125
      implements FocusListener
126
    {
127
      protected AccessibleFocusHandler()
128
      {
129
        // TODO: Implement this properly.
130
      }
131
      public void focusGained(FocusEvent event)
132
      {
133
        // TODO: Implement this properly.
134
      }
135
      public void focusLost(FocusEvent valevent)
136
      {
137
        // TODO: Implement this properly.
138
      }
139
    }
140
 
141
    /**
142
     * Accessibility support for <code>JComponent</code>'s container handler.
143
     */
144
    protected class AccessibleContainerHandler
145
      implements ContainerListener
146
    {
147
      protected AccessibleContainerHandler()
148
      {
149
        // TODO: Implement this properly.
150
      }
151
      public void componentAdded(ContainerEvent event)
152
      {
153
        // TODO: Implement this properly.
154
      }
155
      public void componentRemoved(ContainerEvent valevent)
156
      {
157
        // TODO: Implement this properly.
158
      }
159
    }
160
 
161
    private static final long serialVersionUID = -7047089700479897799L;
162
 
163
    protected ContainerListener accessibleContainerHandler;
164
    protected FocusListener accessibleFocusHandler;
165
 
166
    /**
167
     * Manages the property change listeners;
168
     */
169
    private SwingPropertyChangeSupport changeSupport;
170
 
171
    protected AccessibleJComponent()
172
    {
173
      changeSupport = new SwingPropertyChangeSupport(this);
174
    }
175
 
176
    /**
177
     * Adds a property change listener to the list of registered listeners.
178
     *
179
     * @param listener the listener to add
180
     */
181
    public void addPropertyChangeListener(PropertyChangeListener listener)
182
    {
183
      changeSupport.addPropertyChangeListener(listener);
184
    }
185
 
186
    /**
187
     * Removes a propery change listener from the list of registered listeners.
188
     *
189
     * @param listener the listener to remove
190
     */
191
    public void removePropertyChangeListener(PropertyChangeListener listener)
192
    {
193
      changeSupport.removePropertyChangeListener(listener);
194
    }
195
 
196
    /**
197
     * Returns the number of accessible children of this object.
198
     *
199
     * @return  the number of accessible children of this object
200
     */
201
    public int getAccessibleChildrenCount()
202
    {
203
      int count = 0;
204
      Component[] children = getComponents();
205
      for (int i = 0; i < children.length; ++i)
206
        {
207
          if (children[i] instanceof Accessible)
208
            count++;
209
        }
210
      return count;
211
    }
212
 
213
    /**
214
     * Returns the accessible child component at index <code>i</code>.
215
     *
216
     * @param i the index of the accessible child to return
217
     *
218
     * @return the accessible child component at index <code>i</code>
219
     */
220
    public Accessible getAccessibleChild(int i)
221
    {
222
      int index = 0;
223
      Component[] children = getComponents();
224
      Accessible found = null;
225
      for (int j = 0; index != i; j++)
226
        {
227
          if (children[j] instanceof Accessible)
228
            index++;
229
          if (index == i)
230
            found = (Accessible) children[index];
231
        }
232
      // TODO: Figure out what to do when i is not a valid index.
233
      return found;
234
    }
235
 
236
    /**
237
     * Returns the accessible state set of this component.
238
     *
239
     * @return the accessible state set of this component
240
     */
241
    public AccessibleStateSet getAccessibleStateSet()
242
    {
243
      // FIXME: Figure out which states should be set here, and which are
244
      // inherited from the super class.
245
      return super.getAccessibleStateSet();
246
    }
247
 
248
    /**
249
     * Returns the localized name for this object. Generally this should
250
     * almost never return {@link Component#getName()} since that is not
251
     * a localized name. If the object is some kind of text component (like
252
     * a menu item), then the value of the object may be returned. Also, if
253
     * the object has a tooltip, the value of the tooltip may also be
254
     * appropriate.
255
     *
256
     * @return the localized name for this object or <code>null</code> if this
257
     *         object has no name
258
     */
259
    public String getAccessibleName()
260
    {
261
      // TODO: Figure out what exactly to return here. It's possible that this
262
      // method simply should return null.
263
      return null;
264
    }
265
 
266
    /**
267
     * Returns the localized description of this object.
268
     *
269
     * @return the localized description of this object or <code>null</code>
270
     *         if this object has no description
271
     */
272
    public String getAccessibleDescription()
273
    {
274
      // TODO: Figure out what exactly to return here. It's possible that this
275
      // method simply should return null.
276
      return null;
277
    }
278
 
279
    /**
280
     * Returns the accessible role of this component.
281
     *
282
     * @return the accessible role of this component
283
     *
284
     * @see AccessibleRole
285
     */
286
    public AccessibleRole getAccessibleRole()
287
    {
288
      // TODO: Check if this is correct.
289
      return AccessibleRole.SWING_COMPONENT;
290
    }
291
 
292
    /**
293
     * Recursivly searches a border hierarchy (starting at <code>border) for
294
     * a titled border and returns the title if one is found, <code>null</code>
295
     * otherwise.
296
     *
297
     * @param border the border to start search from
298
     *
299
     * @return the border title of a possibly found titled border
300
     */
301
    protected String getBorderTitle(Border border)
302
    {
303
      String title = null;
304
      if (border instanceof CompoundBorder)
305
        {
306
          CompoundBorder compound = (CompoundBorder) border;
307
          Border inner = compound.getInsideBorder();
308
          title = getBorderTitle(inner);
309
          if (title == null)
310
            {
311
              Border outer = compound.getOutsideBorder();
312
              title = getBorderTitle(outer);
313
            }
314
        }
315
      else if (border instanceof TitledBorder)
316
        {
317
          TitledBorder titled = (TitledBorder) border;
318
          title = titled.getTitle();
319
        }
320
      return title;
321
    }
322
 
323
    /**
324
     * Returns the tooltip text for this accessible component.
325
     *
326
     * @return the tooltip text for this accessible component
327
     */
328
    public String getToolTipText()
329
    {
330
      return JComponent.this.getToolTipText();
331
    }
332
 
333
    /**
334
     * Returns the title of the border of this accessible component if
335
     * this component has a titled border, otherwise returns <code>null</code>.
336
     *
337
     * @return the title of the border of this accessible component if
338
     *         this component has a titled border, otherwise returns
339
     *         <code>null</code>
340
     */
341
    public String getTitledBorderText()
342
    {
343
      return getBorderTitle(getBorder());
344
    }
345
 
346
    /**
347
     * Returns the keybindings associated with this accessible component or
348
     * <code>null</code> if the component does not support key bindings.
349
     *
350
     * @return the keybindings associated with this accessible component
351
     */
352
    public AccessibleKeyBinding getAccessibleKeyBinding()
353
    {
354
      // TODO: Implement this properly.
355
      return null;
356
    }
357
  }
358
 
359
  /**
360
   * An explicit value for the component's preferred size; if not set by a
361
   * user, this is calculated on the fly by delegating to the {@link
362
   * ComponentUI#getPreferredSize} method on the {@link #ui} property.
363
   */
364
  Dimension preferredSize;
365
 
366
  /**
367
   * An explicit value for the component's minimum size; if not set by a
368
   * user, this is calculated on the fly by delegating to the {@link
369
   * ComponentUI#getMinimumSize} method on the {@link #ui} property.
370
   */
371
  Dimension minimumSize;
372
 
373
  /**
374
   * An explicit value for the component's maximum size; if not set by a
375
   * user, this is calculated on the fly by delegating to the {@link
376
   * ComponentUI#getMaximumSize} method on the {@link #ui} property.
377
   */
378
  Dimension maximumSize;
379
 
380
  /**
381
   * A value between 0.0 and 1.0 indicating the preferred horizontal
382
   * alignment of the component, relative to its siblings. The values
383
   * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
384
   * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
385
   * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
386
   * managers use this property.
387
   *
388
   * @see #getAlignmentX
389
   * @see #setAlignmentX
390
   * @see javax.swing.OverlayLayout
391
   * @see javax.swing.BoxLayout
392
   */
393
  float alignmentX = -1.0F;
394
 
395
  /**
396
   * A value between 0.0 and 1.0 indicating the preferred vertical
397
   * alignment of the component, relative to its siblings. The values
398
   * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
399
   * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
400
   * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
401
   * managers use this property.
402
   *
403
   * @see #getAlignmentY
404
   * @see #setAlignmentY
405
   * @see javax.swing.OverlayLayout
406
   * @see javax.swing.BoxLayout
407
   */
408
  float alignmentY = -1.0F;
409
 
410
  /**
411
   * The border painted around this component.
412
   *
413
   * @see #paintBorder
414
   */
415
  Border border;
416
 
417
  /**
418
   * The text to show in the tooltip associated with this component.
419
   *
420
   * @see #setToolTipText
421
   * @see #getToolTipText()
422
   */
423
   String toolTipText;
424
 
425
  /**
426
   * <p>Whether to double buffer this component when painting. This flag
427
   * should generally be <code>true</code>, to ensure good painting
428
   * performance.</p>
429
   *
430
   * <p>All children of a double buffered component are painted into the
431
   * double buffer automatically, so only the top widget in a window needs
432
   * to be double buffered.</p>
433
   *
434
   * @see #setDoubleBuffered
435
   * @see #isDoubleBuffered
436
   * @see #paint
437
   */
438
  boolean doubleBuffered = true;
439
 
440
  /**
441
   * A set of flags indicating which debugging graphics facilities should
442
   * be enabled on this component. The values should be a combination of
443
   * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
444
   * {@link DebugGraphics#FLASH_OPTION}, or {@link
445
   * DebugGraphics#BUFFERED_OPTION}.
446
   *
447
   * @see #setDebugGraphicsOptions
448
   * @see #getDebugGraphicsOptions
449
   * @see DebugGraphics
450
   * @see #getComponentGraphics
451
   */
452
  int debugGraphicsOptions;
453
 
454
  /**
455
   * <p>This property controls two independent behaviors simultaneously.</p>
456
   *
457
   * <p>First, it controls whether to fill the background of this widget
458
   * when painting its body. This affects calls to {@link
459
   * JComponent#paintComponent}, which in turn calls {@link
460
   * ComponentUI#update} on the component's {@link #ui} property. If the
461
   * component is opaque during this call, the background will be filled
462
   * before calling {@link ComponentUI#paint}. This happens merely as a
463
   * convenience; you may fill the component's background yourself too,
464
   * but there is no need to do so if you will be filling with the same
465
   * color.</p>
466
   *
467
   * <p>Second, it the opaque property informs swing's repaint system
468
   * whether it will be necessary to paint the components "underneath" this
469
   * component, in Z-order. If the component is opaque, it is considered to
470
   * completely occlude components "underneath" it, so they will not be
471
   * repainted along with the opaque component.</p>
472
   *
473
   * <p>The default value for this property is <code>false</code>, but most
474
   * components will want to set it to <code>true</code> when installing UI
475
   * defaults in {@link ComponentUI#installUI}.</p>
476
   *
477
   * @see #setOpaque
478
   * @see #isOpaque
479
   * @see #paintComponent
480
   */
481
  boolean opaque = false;
482
 
483
  /**
484
   * The user interface delegate for this component. Event delivery and
485
   * repainting of the component are usually delegated to this object.
486
   *
487
   * @see #setUI
488
   * @see #getUIClassID
489
   * @see #updateUI
490
   */
491
  protected ComponentUI ui;
492
 
493
  /**
494
   * A hint to the focus system that this component should or should not
495
   * get focus. If this is <code>false</code>, swing will not try to
496
   * request focus on this component; if <code>true</code>, swing might
497
   * try to request focus, but the request might fail. Thus it is only
498
   * a hint guiding swing's behavior.
499
   *
500
   * @see #requestFocus()
501
   * @see #isRequestFocusEnabled
502
   * @see #setRequestFocusEnabled
503
   */
504
  boolean requestFocusEnabled;
505
 
506
  /**
507
   * Flag indicating behavior of this component when the mouse is dragged
508
   * outside the component and the mouse <em>stops moving</em>. If
509
   * <code>true</code>, synthetic mouse events will be delivered on regular
510
   * timed intervals, continuing off in the direction the mouse exited the
511
   * component, until the mouse is released or re-enters the component.
512
   *
513
   * @see #setAutoscrolls
514
   * @see #getAutoscrolls
515
   */
516
  boolean autoscrolls = false;
517
 
518
  /**
519
   * Indicates whether the current paint call is already double buffered or
520
   * not.
521
   */
522
  static boolean isPaintingDoubleBuffered = false;
523
 
524
  /**
525
   * Listeners for events other than {@link PropertyChangeEvent} are
526
   * handled by this listener list. PropertyChangeEvents are handled in
527
   * {@link #changeSupport}.
528
   */
529
  protected EventListenerList listenerList = new EventListenerList();
530
 
531
  /**
532
   * Support for {@link PropertyChangeEvent} events. This is constructed
533
   * lazily when the component gets its first {@link
534
   * PropertyChangeListener} subscription; until then it's an empty slot.
535
   */
536
  private SwingPropertyChangeSupport changeSupport;
537
 
538
 
539
  /**
540
   * Storage for "client properties", which are key/value pairs associated
541
   * with this component by a "client", such as a user application or a
542
   * layout manager. This is lazily constructed when the component gets its
543
   * first client property.
544
   */
545
  private Hashtable clientProperties;
546
 
547
  private InputMap inputMap_whenFocused;
548
  private InputMap inputMap_whenAncestorOfFocused;
549
  private ComponentInputMap inputMap_whenInFocusedWindow;
550
  private ActionMap actionMap;
551
  /** @since 1.3 */
552
  private boolean verifyInputWhenFocusTarget;
553
  private InputVerifier inputVerifier;
554
 
555
  private TransferHandler transferHandler;
556
 
557
  /**
558
   * Indicates if this component is currently painting a tile or not.
559
   */
560
  private boolean paintingTile;
561
 
562
  /**
563
   * A cached Rectangle object to be reused. Be careful when you use that,
564
   * so that it doesn't get modified in another context within the same
565
   * method call chain.
566
   */
567
  private static transient Rectangle rectCache;
568
 
569
  /**
570
   * The default locale of the component.
571
   *
572
   * @see #getDefaultLocale
573
   * @see #setDefaultLocale
574
   */
575
  private static Locale defaultLocale;
576
 
577
  public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
578
 
579
  /**
580
   * Constant used to indicate that no condition has been assigned to a
581
   * particular action.
582
   *
583
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
584
   */
585
  public static final int UNDEFINED_CONDITION = -1;
586
 
587
  /**
588
   * Constant used to indicate that an action should be performed only when
589
   * the component has focus.
590
   *
591
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
592
   */
593
  public static final int WHEN_FOCUSED = 0;
594
 
595
  /**
596
   * Constant used to indicate that an action should be performed only when
597
   * the component is an ancestor of the component which has focus.
598
   *
599
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
600
   */
601
  public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
602
 
603
  /**
604
   * Constant used to indicate that an action should be performed only when
605
   * the component is in the window which has focus.
606
   *
607
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
608
   */
609
  public static final int WHEN_IN_FOCUSED_WINDOW = 2;
610
 
611
  /**
612
   * Indicates if this component is completely dirty or not. This is used
613
   * by the RepaintManager's
614
   * {@link RepaintManager#isCompletelyDirty(JComponent)} method.
615
   */
616
  boolean isCompletelyDirty = false;
617
 
618
  /**
619
   * Creates a new <code>JComponent</code> instance.
620
   */
621
  public JComponent()
622
  {
623
    super();
624
    super.setLayout(new FlowLayout());
625
    setDropTarget(new DropTarget());
626
    defaultLocale = Locale.getDefault();
627
    debugGraphicsOptions = DebugGraphics.NONE_OPTION;
628
    setRequestFocusEnabled(true);
629
  }
630
 
631
  /**
632
   * Helper to lazily construct and return the client properties table.
633
   *
634
   * @return The current client properties table
635
   *
636
   * @see #clientProperties
637
   * @see #getClientProperty
638
   * @see #putClientProperty
639
   */
640
  private Hashtable getClientProperties()
641
  {
642
    if (clientProperties == null)
643
      clientProperties = new Hashtable();
644
    return clientProperties;
645
  }
646
 
647
  /**
648
   * Get a client property associated with this component and a particular
649
   * key.
650
   *
651
   * @param key The key with which to look up the client property
652
   *
653
   * @return A client property associated with this object and key
654
   *
655
   * @see #clientProperties
656
   * @see #getClientProperties
657
   * @see #putClientProperty
658
   */
659
  public final Object getClientProperty(Object key)
660
  {
661
    return getClientProperties().get(key);
662
  }
663
 
664
  /**
665
   * Add a client property <code>value</code> to this component, associated
666
   * with <code>key</code>. If there is an existing client property
667
   * associated with <code>key</code>, it will be replaced.  A
668
   * {@link PropertyChangeEvent} is sent to registered listeners (with the
669
   * name of the property being <code>key.toString()</code>).
670
   *
671
   * @param key The key of the client property association to add
672
   * @param value The value of the client property association to add
673
   *
674
   * @see #clientProperties
675
   * @see #getClientProperties
676
   * @see #getClientProperty
677
   */
678
  public final void putClientProperty(Object key, Object value)
679
  {
680
    Hashtable t = getClientProperties();
681
    Object old = t.get(key);
682
    if (value != null)
683
      t.put(key, value);
684
    else
685
      t.remove(key);
686
    firePropertyChange(key.toString(), old, value);
687
  }
688
 
689
  /**
690
   * Unregister an <code>AncestorListener</code>.
691
   *
692
   * @param listener The listener to unregister
693
   *
694
   * @see #addAncestorListener
695
   */
696
  public void removeAncestorListener(AncestorListener listener)
697
  {
698
    listenerList.remove(AncestorListener.class, listener);
699
  }
700
 
701
  /**
702
   * Unregister a <code>PropertyChangeListener</code>.
703
   *
704
   * @param listener The listener to register
705
   *
706
   * @see #addPropertyChangeListener(PropertyChangeListener)
707
   * @see #changeSupport
708
   */
709
  public void removePropertyChangeListener(PropertyChangeListener listener)
710
  {
711
    if (changeSupport != null)
712
      changeSupport.removePropertyChangeListener(listener);
713
  }
714
 
715
  /**
716
   * Unregister a <code>PropertyChangeListener</code>.
717
   *
718
   * @param propertyName The property name to unregister the listener from
719
   * @param listener The listener to unregister
720
   *
721
   * @see #addPropertyChangeListener(String, PropertyChangeListener)
722
   * @see #changeSupport
723
   */
724
  public void removePropertyChangeListener(String propertyName,
725
                                           PropertyChangeListener listener)
726
  {
727
    if (changeSupport != null)
728
      changeSupport.removePropertyChangeListener(propertyName, listener);
729
  }
730
 
731
  /**
732
   * Unregister a <code>VetoableChangeChangeListener</code>.
733
   *
734
   * @param listener The listener to unregister
735
   *
736
   * @see #addVetoableChangeListener
737
   */
738
  public void removeVetoableChangeListener(VetoableChangeListener listener)
739
  {
740
    listenerList.remove(VetoableChangeListener.class, listener);
741
  }
742
 
743
  /**
744
   * Register an <code>AncestorListener</code>.
745
   *
746
   * @param listener The listener to register
747
   *
748
   * @see #removeVetoableChangeListener
749
   */
750
  public void addAncestorListener(AncestorListener listener)
751
  {
752
    listenerList.add(AncestorListener.class, listener);
753
  }
754
 
755
  /**
756
   * Register a <code>PropertyChangeListener</code>. This listener will
757
   * receive any PropertyChangeEvent, regardless of property name. To
758
   * listen to a specific property name, use {@link
759
   * #addPropertyChangeListener(String,PropertyChangeListener)} instead.
760
   *
761
   * @param listener The listener to register
762
   *
763
   * @see #removePropertyChangeListener(PropertyChangeListener)
764
   * @see #changeSupport
765
   */
766
  public void addPropertyChangeListener(PropertyChangeListener listener)
767
  {
768
    if (changeSupport == null)
769
      changeSupport = new SwingPropertyChangeSupport(this);
770
    changeSupport.addPropertyChangeListener(listener);
771
  }
772
 
773
  /**
774
   * Register a <code>PropertyChangeListener</code> for a specific, named
775
   * property. To listen to all property changes, regardless of name, use
776
   * {@link #addPropertyChangeListener(PropertyChangeListener)} instead.
777
   *
778
   * @param propertyName The property name to listen to
779
   * @param listener The listener to register
780
   *
781
   * @see #removePropertyChangeListener(String, PropertyChangeListener)
782
   * @see #changeSupport
783
   */
784
  public void addPropertyChangeListener(String propertyName,
785
                                        PropertyChangeListener listener)
786
  {
787
    listenerList.add(PropertyChangeListener.class, listener);
788
  }
789
 
790
  /**
791
   * Register a <code>VetoableChangeListener</code>.
792
   *
793
   * @param listener The listener to register
794
   *
795
   * @see #removeVetoableChangeListener
796
   * @see #listenerList
797
   */
798
  public void addVetoableChangeListener(VetoableChangeListener listener)
799
  {
800
    listenerList.add(VetoableChangeListener.class, listener);
801
  }
802
 
803
  /**
804
   * Return all registered listeners of a particular type.
805
   *
806
   * @param listenerType The type of listener to return
807
   *
808
   * @return All listeners in the {@link #listenerList} which
809
   * are of the specified type
810
   *
811
   * @see #listenerList
812
   */
813
  public EventListener[] getListeners(Class listenerType)
814
  {
815
    return listenerList.getListeners(listenerType);
816
  }
817
 
818
  /**
819
   * Return all registered <code>AncestorListener</code> objects.
820
   *
821
   * @return The set of <code>AncestorListener</code> objects in {@link
822
   * #listenerList}
823
   */
824
  public AncestorListener[] getAncestorListeners()
825
  {
826
    return (AncestorListener[]) getListeners(AncestorListener.class);
827
  }
828
 
829
  /**
830
   * Return all registered <code>VetoableChangeListener</code> objects.
831
   *
832
   * @return The set of <code>VetoableChangeListener</code> objects in {@link
833
   * #listenerList}
834
   */
835
  public VetoableChangeListener[] getVetoableChangeListeners()
836
  {
837
    return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class);
838
  }
839
 
840
  /**
841
   * Return all <code>PropertyChangeListener</code> objects registered to listen
842
   * for a particular property.
843
   *
844
   * @param property The property to return the listeners of
845
   *
846
   * @return The set of <code>PropertyChangeListener</code> objects in
847
   *     {@link #changeSupport} registered to listen on the specified property
848
   */
849
  public PropertyChangeListener[] getPropertyChangeListeners(String property)
850
  {
851
    return changeSupport == null ? new PropertyChangeListener[0]
852
                          : changeSupport.getPropertyChangeListeners(property);
853
  }
854
 
855
  /**
856
   * A variant of {@link #firePropertyChange(String,Object,Object)}
857
   * for properties with <code>boolean</code> values.
858
   */
859
  public void firePropertyChange(String propertyName, boolean oldValue,
860
                                 boolean newValue)
861
  {
862
    if (changeSupport != null)
863
      changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue),
864
                                       Boolean.valueOf(newValue));
865
  }
866
 
867
  /**
868
   * A variant of {@link #firePropertyChange(String,Object,Object)}
869
   * for properties with <code>byte</code> values.
870
   */
871
  public void firePropertyChange(String propertyName, byte oldValue,
872
                                 byte newValue)
873
  {
874
    if (changeSupport != null)
875
      changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
876
                                       new Byte(newValue));
877
  }
878
 
879
  /**
880
   * A variant of {@link #firePropertyChange(String,Object,Object)}
881
   * for properties with <code>char</code> values.
882
   */
883
  public void firePropertyChange(String propertyName, char oldValue,
884
                                 char newValue)
885
  {
886
    if (changeSupport != null)
887
      changeSupport.firePropertyChange(propertyName, new Character(oldValue),
888
                                       new Character(newValue));
889
  }
890
 
891
  /**
892
   * A variant of {@link #firePropertyChange(String,Object,Object)}
893
   * for properties with <code>double</code> values.
894
   */
895
  public void firePropertyChange(String propertyName, double oldValue,
896
                                 double newValue)
897
  {
898
    if (changeSupport != null)
899
      changeSupport.firePropertyChange(propertyName, new Double(oldValue),
900
                                       new Double(newValue));
901
  }
902
 
903
  /**
904
   * A variant of {@link #firePropertyChange(String,Object,Object)}
905
   * for properties with <code>float</code> values.
906
   */
907
  public void firePropertyChange(String propertyName, float oldValue,
908
                                 float newValue)
909
  {
910
    if (changeSupport != null)
911
      changeSupport.firePropertyChange(propertyName, new Float(oldValue),
912
                                       new Float(newValue));
913
  }
914
 
915
  /**
916
   * A variant of {@link #firePropertyChange(String,Object,Object)}
917
   * for properties with <code>int</code> values.
918
   */
919
  public void firePropertyChange(String propertyName, int oldValue,
920
                                 int newValue)
921
  {
922
    if (changeSupport != null)
923
      changeSupport.firePropertyChange(propertyName, new Integer(oldValue),
924
                                       new Integer(newValue));
925
  }
926
 
927
  /**
928
   * A variant of {@link #firePropertyChange(String,Object,Object)}
929
   * for properties with <code>long</code> values.
930
   */
931
  public void firePropertyChange(String propertyName, long oldValue,
932
                                 long newValue)
933
  {
934
    if (changeSupport != null)
935
      changeSupport.firePropertyChange(propertyName, new Long(oldValue),
936
                                       new Long(newValue));
937
  }
938
 
939
  /**
940
   * Call {@link PropertyChangeListener#propertyChange} on all listeners
941
   * registered to listen to a given property. Any method which changes
942
   * the specified property of this component should call this method.
943
   *
944
   * @param propertyName The property which changed
945
   * @param oldValue The old value of the property
946
   * @param newValue The new value of the property
947
   *
948
   * @see #changeSupport
949
   * @see #addPropertyChangeListener(PropertyChangeListener)
950
   * @see #removePropertyChangeListener(PropertyChangeListener)
951
   */
952
  protected void firePropertyChange(String propertyName, Object oldValue,
953
                                    Object newValue)
954
  {
955
    if (changeSupport != null)
956
      changeSupport.firePropertyChange(propertyName, oldValue, newValue);
957
  }
958
 
959
  /**
960
   * A variant of {@link #firePropertyChange(String,Object,Object)}
961
   * for properties with <code>short</code> values.
962
   */
963
  public void firePropertyChange(String propertyName, short oldValue,
964
                                 short newValue)
965
  {
966
    if (changeSupport != null)
967
      changeSupport.firePropertyChange(propertyName, new Short(oldValue),
968
                                       new Short(newValue));
969
  }
970
 
971
  /**
972
   * Call {@link VetoableChangeListener#vetoableChange} on all listeners
973
   * registered to listen to a given property. Any method which changes
974
   * the specified property of this component should call this method.
975
   *
976
   * @param propertyName The property which changed
977
   * @param oldValue The old value of the property
978
   * @param newValue The new value of the property
979
   *
980
   * @throws PropertyVetoException if the change was vetoed by a listener
981
   *
982
   * @see #addVetoableChangeListener
983
   * @see #removeVetoableChangeListener
984
   */
985
  protected void fireVetoableChange(String propertyName, Object oldValue,
986
                                    Object newValue)
987
    throws PropertyVetoException
988
  {
989
    VetoableChangeListener[] listeners = getVetoableChangeListeners();
990
 
991
    PropertyChangeEvent evt =
992
      new PropertyChangeEvent(this, propertyName, oldValue, newValue);
993
 
994
    for (int i = 0; i < listeners.length; i++)
995
      listeners[i].vetoableChange(evt);
996
  }
997
 
998
  /**
999
   * Get the value of the accessibleContext property for this component.
1000
   *
1001
   * @return the current value of the property
1002
   */
1003
  public AccessibleContext getAccessibleContext()
1004
  {
1005
    return null;
1006
  }
1007
 
1008
  /**
1009
   * Get the value of the {@link #alignmentX} property.
1010
   *
1011
   * @return The current value of the property.
1012
   *
1013
   * @see #setAlignmentX
1014
   * @see #alignmentY
1015
   */
1016
  public float getAlignmentX()
1017
  {
1018
    float ret = alignmentX;
1019
    if (alignmentX < 0)
1020
      // alignment has not been set explicitly.
1021
      ret = super.getAlignmentX();
1022
 
1023
    return ret;
1024
  }
1025
 
1026
  /**
1027
   * Get the value of the {@link #alignmentY} property.
1028
   *
1029
   * @return The current value of the property.
1030
   *
1031
   * @see #setAlignmentY
1032
   * @see #alignmentX
1033
   */
1034
  public float getAlignmentY()
1035
  {
1036
    float ret = alignmentY;
1037
    if (alignmentY < 0)
1038
      // alignment has not been set explicitly.
1039
      ret = super.getAlignmentY();
1040
 
1041
    return ret;
1042
  }
1043
 
1044
  /**
1045
   * Get the current value of the {@link #autoscrolls} property.
1046
   *
1047
   * @return The current value of the property
1048
   */
1049
  public boolean getAutoscrolls()
1050
  {
1051
    return autoscrolls;
1052
  }
1053
 
1054
  /**
1055
   * Set the value of the {@link #border} property.
1056
   *
1057
   * @param newBorder The new value of the property
1058
   *
1059
   * @see #getBorder
1060
   */
1061
  public void setBorder(Border newBorder)
1062
  {
1063
    Border oldBorder = getBorder();
1064
    if (oldBorder == newBorder)
1065
      return;
1066
 
1067
    border = newBorder;
1068
    firePropertyChange("border", oldBorder, newBorder);
1069
    repaint();
1070
  }
1071
 
1072
  /**
1073
   * Get the value of the {@link #border} property.
1074
   *
1075
   * @return The property's current value
1076
   *
1077
   * @see #setBorder
1078
   */
1079
  public Border getBorder()
1080
  {
1081
    return border;
1082
  }
1083
 
1084
  /**
1085
   * Get the component's current bounding box. If a rectangle is provided,
1086
   * use this as the return value (adjusting its fields in place);
1087
   * otherwise (of <code>null</code> is provided) return a new {@link
1088
   * Rectangle}.
1089
   *
1090
   * @param rv Optional return value to use
1091
   *
1092
   * @return A rectangle bounding the component
1093
   */
1094
  public Rectangle getBounds(Rectangle rv)
1095
  {
1096
    if (rv == null)
1097
      return new Rectangle(getX(), getY(), getWidth(), getHeight());
1098
    else
1099
      {
1100
        rv.setBounds(getX(), getY(), getWidth(), getHeight());
1101
        return rv;
1102
      }
1103
  }
1104
 
1105
  /**
1106
   * Prepares a graphics context for painting this object. If {@link
1107
   * #debugGraphicsOptions} is not equal to {@link
1108
   * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
1109
   * wrapping the parameter. Otherwise configure the parameter with this
1110
   * component's foreground color and font.
1111
   *
1112
   * @param g The graphics context to wrap or configure
1113
   *
1114
   * @return A graphics context to paint this object with
1115
   *
1116
   * @see #debugGraphicsOptions
1117
   * @see #paint
1118
   */
1119
  protected Graphics getComponentGraphics(Graphics g)
1120
  {
1121
    Graphics g2 = g;
1122
    int options = getDebugGraphicsOptions();
1123
    if (options != DebugGraphics.NONE_OPTION)
1124
      {
1125
        if (!(g2 instanceof DebugGraphics))
1126
          g2 = new DebugGraphics(g);
1127
        DebugGraphics dg = (DebugGraphics) g2;
1128
        dg.setDebugOptions(dg.getDebugOptions() | options);
1129
      }
1130
    g2.setFont(this.getFont());
1131
    g2.setColor(this.getForeground());
1132
    return g2;
1133
  }
1134
 
1135
  /**
1136
   * Get the value of the {@link #debugGraphicsOptions} property.
1137
   *
1138
   * @return The current value of the property.
1139
   *
1140
   * @see #setDebugGraphicsOptions
1141
   * @see #debugGraphicsOptions
1142
   */
1143
  public int getDebugGraphicsOptions()
1144
  {
1145
    String option = System.getProperty("gnu.javax.swing.DebugGraphics");
1146
    int options = debugGraphicsOptions;
1147
    if (option != null && option.length() != 0)
1148
      {
1149
        if (options < 0)
1150
          options = 0;
1151
 
1152
        if (option.equals("LOG"))
1153
          options |= DebugGraphics.LOG_OPTION;
1154
        else if (option.equals("FLASH"))
1155
          options |= DebugGraphics.FLASH_OPTION;
1156
      }
1157
    return options;
1158
  }
1159
 
1160
  /**
1161
   * Get the component's insets, which are calculated from
1162
   * the {@link #border} property. If the border is <code>null</code>,
1163
   * calls {@link Container#getInsets}.
1164
   *
1165
   * @return The component's current insets
1166
   */
1167
  public Insets getInsets()
1168
  {
1169
    if (border == null)
1170
      return super.getInsets();
1171
    return getBorder().getBorderInsets(this);
1172
  }
1173
 
1174
  /**
1175
   * Get the component's insets, which are calculated from the {@link
1176
   * #border} property. If the border is <code>null</code>, calls {@link
1177
   * Container#getInsets}. The passed-in {@link Insets} value will be
1178
   * used as the return value, if possible.
1179
   *
1180
   * @param insets Return value object to reuse, if possible
1181
   *
1182
   * @return The component's current insets
1183
   */
1184
  public Insets getInsets(Insets insets)
1185
  {
1186
    Insets t = getInsets();
1187
 
1188
    if (insets == null)
1189
      return t;
1190
 
1191
    insets.left = t.left;
1192
    insets.right = t.right;
1193
    insets.top = t.top;
1194
    insets.bottom = t.bottom;
1195
    return insets;
1196
  }
1197
 
1198
  /**
1199
   * Get the component's location. The passed-in {@link Point} value
1200
   * will be used as the return value, if possible.
1201
   *
1202
   * @param rv Return value object to reuse, if possible
1203
   *
1204
   * @return The component's current location
1205
   */
1206
  public Point getLocation(Point rv)
1207
  {
1208
    if (rv == null)
1209
      return new Point(getX(), getY());
1210
 
1211
    rv.setLocation(getX(), getY());
1212
    return rv;
1213
  }
1214
 
1215
  /**
1216
   * Get the component's maximum size. If the {@link #maximumSize} property
1217
   * has been explicitly set, it is returned. If the {@link #maximumSize}
1218
   * property has not been set but the {@link #ui} property has been, the
1219
   * result of {@link ComponentUI#getMaximumSize} is returned. If neither
1220
   * property has been set, the result of {@link Container#getMaximumSize}
1221
   * is returned.
1222
   *
1223
   * @return The maximum size of the component
1224
   *
1225
   * @see #maximumSize
1226
   * @see #setMaximumSize
1227
   */
1228
  public Dimension getMaximumSize()
1229
  {
1230
    if (maximumSize != null)
1231
      return maximumSize;
1232
 
1233
    if (ui != null)
1234
      {
1235
        Dimension s = ui.getMaximumSize(this);
1236
        if (s != null)
1237
          return s;
1238
      }
1239
 
1240
    Dimension p = super.getMaximumSize();
1241
    return p;
1242
  }
1243
 
1244
  /**
1245
   * Get the component's minimum size. If the {@link #minimumSize} property
1246
   * has been explicitly set, it is returned. If the {@link #minimumSize}
1247
   * property has not been set but the {@link #ui} property has been, the
1248
   * result of {@link ComponentUI#getMinimumSize} is returned. If neither
1249
   * property has been set, the result of {@link Container#getMinimumSize}
1250
   * is returned.
1251
   *
1252
   * @return The minimum size of the component
1253
   *
1254
   * @see #minimumSize
1255
   * @see #setMinimumSize
1256
   */
1257
  public Dimension getMinimumSize()
1258
  {
1259
    if (minimumSize != null)
1260
      return minimumSize;
1261
 
1262
    if (ui != null)
1263
      {
1264
        Dimension s = ui.getMinimumSize(this);
1265
        if (s != null)
1266
          return s;
1267
      }
1268
 
1269
    Dimension p = super.getMinimumSize();
1270
    return p;
1271
  }
1272
 
1273
  /**
1274
   * Get the component's preferred size. If the {@link #preferredSize}
1275
   * property has been explicitly set, it is returned. If the {@link
1276
   * #preferredSize} property has not been set but the {@link #ui} property
1277
   * has been, the result of {@link ComponentUI#getPreferredSize} is
1278
   * returned. If neither property has been set, the result of {@link
1279
   * Container#getPreferredSize} is returned.
1280
   *
1281
   * @return The preferred size of the component
1282
   *
1283
   * @see #preferredSize
1284
   * @see #setPreferredSize
1285
   */
1286
  public Dimension getPreferredSize()
1287
  {
1288
    Dimension prefSize = null;
1289
    if (preferredSize != null)
1290
      prefSize = preferredSize;
1291
 
1292
    else if (ui != null)
1293
      {
1294
        Dimension s = ui.getPreferredSize(this);
1295
        if (s != null)
1296
          prefSize = s;
1297
      }
1298
 
1299
    if (prefSize == null)
1300
      prefSize = super.getPreferredSize();
1301
    // make sure that prefSize is not smaller than minSize
1302
    if (minimumSize != null && prefSize != null
1303
        && (minimumSize.width > prefSize.width
1304
            || minimumSize.height > prefSize.height))
1305
        prefSize = new Dimension(Math.max(minimumSize.width, prefSize.width),
1306
                                 Math.max(minimumSize.height, prefSize.height));
1307
    return prefSize;
1308
  }
1309
 
1310
  /**
1311
   * Checks if a maximum size was explicitely set on the component.
1312
   *
1313
   * @return <code>true</code> if a maximum size was set,
1314
   * <code>false</code> otherwise
1315
   *
1316
   * @since 1.3
1317
   */
1318
  public boolean isMaximumSizeSet()
1319
  {
1320
    return maximumSize != null;
1321
  }
1322
 
1323
  /**
1324
   * Checks if a minimum size was explicitely set on the component.
1325
   *
1326
   * @return <code>true</code> if a minimum size was set,
1327
   * <code>false</code> otherwise
1328
   *
1329
   * @since 1.3
1330
   */
1331
  public boolean isMinimumSizeSet()
1332
  {
1333
    return minimumSize != null;
1334
  }
1335
 
1336
  /**
1337
   * Checks if a preferred size was explicitely set on the component.
1338
   *
1339
   * @return <code>true</code> if a preferred size was set,
1340
   * <code>false</code> otherwise
1341
   *
1342
   * @since 1.3
1343
   */
1344
  public boolean isPreferredSizeSet()
1345
  {
1346
    return preferredSize != null;
1347
  }
1348
 
1349
  /**
1350
   * Return the value of the <code>nextFocusableComponent</code> property.
1351
   *
1352
   * @return The current value of the property, or <code>null</code>
1353
   * if none has been set.
1354
   *
1355
   * @deprecated See {@link java.awt.FocusTraversalPolicy}
1356
   */
1357
  public Component getNextFocusableComponent()
1358
  {
1359
    return null;
1360
  }
1361
 
1362
  /**
1363
   * Return the set of {@link KeyStroke} objects which are registered
1364
   * to initiate actions on this component.
1365
   *
1366
   * @return An array of the registered keystrokes
1367
   */
1368
  public KeyStroke[] getRegisteredKeyStrokes()
1369
  {
1370
    return null;
1371
  }
1372
 
1373
  /**
1374
   * Returns the first ancestor of this component which is a {@link JRootPane}.
1375
   * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1376
   *
1377
   * @return An ancestral JRootPane, or <code>null</code> if none exists.
1378
   */
1379
  public JRootPane getRootPane()
1380
  {
1381
    JRootPane p = SwingUtilities.getRootPane(this);
1382
    return p;
1383
  }
1384
 
1385
  /**
1386
   * Get the component's size. The passed-in {@link Dimension} value
1387
   * will be used as the return value, if possible.
1388
   *
1389
   * @param rv Return value object to reuse, if possible
1390
   *
1391
   * @return The component's current size
1392
   */
1393
  public Dimension getSize(Dimension rv)
1394
  {
1395
    if (rv == null)
1396
      return new Dimension(getWidth(), getHeight());
1397
    else
1398
      {
1399
        rv.setSize(getWidth(), getHeight());
1400
        return rv;
1401
      }
1402
  }
1403
 
1404
  /**
1405
   * Return the <code>toolTip</code> property of this component, creating it and
1406
   * setting it if it is currently <code>null</code>. This method can be
1407
   * overridden in subclasses which wish to control the exact form of
1408
   * tooltip created.
1409
   *
1410
   * @return The current toolTip
1411
   */
1412
  public JToolTip createToolTip()
1413
  {
1414
    JToolTip toolTip = new JToolTip();
1415
    toolTip.setComponent(this);
1416
    toolTip.setTipText(toolTipText);
1417
 
1418
    return toolTip;
1419
  }
1420
 
1421
  /**
1422
   * Return the location at which the {@link #toolTipText} property should be
1423
   * displayed, when triggered by a particular mouse event.
1424
   *
1425
   * @param event The event the tooltip is being presented in response to
1426
   *
1427
   * @return The point at which to display a tooltip, or <code>null</code>
1428
   *     if swing is to choose a default location.
1429
   */
1430
  public Point getToolTipLocation(MouseEvent event)
1431
  {
1432
    return null;
1433
  }
1434
 
1435
  /**
1436
   * Set the value of the {@link #toolTipText} property.
1437
   *
1438
   * @param text The new property value
1439
   *
1440
   * @see #getToolTipText()
1441
   */
1442
  public void setToolTipText(String text)
1443
  {
1444
    if (text == null)
1445
    {
1446
      ToolTipManager.sharedInstance().unregisterComponent(this);
1447
      toolTipText = null;
1448
      return;
1449
    }
1450
 
1451
    // XXX: The tip text doesn't get updated unless you set it to null
1452
    // and then to something not-null. This is consistent with the behaviour
1453
    // of Sun's ToolTipManager.
1454
 
1455
    String oldText = toolTipText;
1456
    toolTipText = text;
1457
 
1458
    if (oldText == null)
1459
      ToolTipManager.sharedInstance().registerComponent(this);
1460
  }
1461
 
1462
  /**
1463
   * Get the value of the {@link #toolTipText} property.
1464
   *
1465
   * @return The current property value
1466
   *
1467
   * @see #setToolTipText
1468
   */
1469
  public String getToolTipText()
1470
  {
1471
    return toolTipText;
1472
  }
1473
 
1474
  /**
1475
   * Get the value of the {@link #toolTipText} property, in response to a
1476
   * particular mouse event.
1477
   *
1478
   * @param event The mouse event which triggered the tooltip
1479
   *
1480
   * @return The current property value
1481
   *
1482
   * @see #setToolTipText
1483
   */
1484
  public String getToolTipText(MouseEvent event)
1485
  {
1486
    return getToolTipText();
1487
  }
1488
 
1489
  /**
1490
   * Return the top level ancestral container (usually a {@link
1491
   * java.awt.Window} or {@link java.applet.Applet}) which this component is
1492
   * contained within, or <code>null</code> if no ancestors exist.
1493
   *
1494
   * @return The top level container, if it exists
1495
   */
1496
  public Container getTopLevelAncestor()
1497
  {
1498
    Container c = getParent();
1499
    for (Container peek = c; peek != null; peek = peek.getParent())
1500
      c = peek;
1501
    return c;
1502
  }
1503
 
1504
  /**
1505
   * Compute the component's visible rectangle, which is defined
1506
   * recursively as either the component's bounds, if it has no parent, or
1507
   * the intersection of the component's bounds with the visible rectangle
1508
   * of its parent.
1509
   *
1510
   * @param rect The return value slot to place the visible rectangle in
1511
   */
1512
  public void computeVisibleRect(Rectangle rect)
1513
  {
1514
    Component c = getParent();
1515
    if (c != null && c instanceof JComponent)
1516
      {
1517
        ((JComponent) c).computeVisibleRect(rect);
1518
        rect.translate(-getX(), -getY());
1519
        Rectangle2D.intersect(rect,
1520
                              new Rectangle(0, 0, getWidth(), getHeight()),
1521
                              rect);
1522
      }
1523
    else
1524
      rect.setRect(0, 0, getWidth(), getHeight());
1525
  }
1526
 
1527
  /**
1528
   * Return the component's visible rectangle in a new {@link Rectangle},
1529
   * rather than via a return slot.
1530
   *
1531
   * @return The component's visible rectangle
1532
   *
1533
   * @see #computeVisibleRect(Rectangle)
1534
   */
1535
  public Rectangle getVisibleRect()
1536
  {
1537
    Rectangle r = new Rectangle();
1538
    computeVisibleRect(r);
1539
    return r;
1540
  }
1541
 
1542
  /**
1543
   * <p>Requests that this component receive input focus, giving window
1544
   * focus to the top level ancestor of this component. Only works on
1545
   * displayable, focusable, visible components.</p>
1546
   *
1547
   * <p>This method should not be called by clients; it is intended for
1548
   * focus implementations. Use {@link Component#requestFocus()} instead.</p>
1549
   *
1550
   * @see Component#requestFocus()
1551
   */
1552
  public void grabFocus()
1553
  {
1554
    // TODO: Implement this properly.
1555
  }
1556
 
1557
  /**
1558
   * Get the value of the {@link #doubleBuffered} property.
1559
   *
1560
   * @return The property's current value
1561
   */
1562
  public boolean isDoubleBuffered()
1563
  {
1564
    return doubleBuffered;
1565
  }
1566
 
1567
  /**
1568
   * Return <code>true</code> if the provided component has no native peer;
1569
   * in other words, if it is a "lightweight component".
1570
   *
1571
   * @param c The component to test for lightweight-ness
1572
   *
1573
   * @return Whether or not the component is lightweight
1574
   */
1575
  public static boolean isLightweightComponent(Component c)
1576
  {
1577
    return c.getPeer() instanceof LightweightPeer;
1578
  }
1579
 
1580
  /**
1581
   * Return <code>true</code> if you wish this component to manage its own
1582
   * focus. In particular: if you want this component to be sent
1583
   * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1584
   * have its children considered as focus transfer targets. If
1585
   * <code>true</code>, focus traversal around this component changes to
1586
   * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1587
   *
1588
   * @return <code>true</code> if you want this component to manage its own
1589
   *     focus, otherwise (by default) <code>false</code>
1590
   *
1591
   * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
1592
   *     {@link Container#setFocusCycleRoot(boolean)} instead
1593
   */
1594
  public boolean isManagingFocus()
1595
  {
1596
    return false;
1597
  }
1598
 
1599
  /**
1600
   * Return the current value of the {@link #opaque} property.
1601
   *
1602
   * @return The current property value
1603
   */
1604
  public boolean isOpaque()
1605
  {
1606
    return opaque;
1607
  }
1608
 
1609
  /**
1610
   * Return <code>true</code> if the component can guarantee that none of its
1611
   * children will overlap in Z-order. This is a hint to the painting system.
1612
   * The default is to return <code>true</code>, but some components such as
1613
   * {@link JLayeredPane} should override this to return <code>false</code>.
1614
   *
1615
   * @return Whether the component tiles its children
1616
   */
1617
  public boolean isOptimizedDrawingEnabled()
1618
  {
1619
    return true;
1620
  }
1621
 
1622
  /**
1623
   * Return <code>true</code> if this component is currently painting a tile,
1624
   * this means that paint() is called again on another child component. This
1625
   * method returns <code>false</code> if this component does not paint a tile
1626
   * or if the last tile is currently painted.
1627
   *
1628
   * @return whether the component is painting a tile
1629
   */
1630
  public boolean isPaintingTile()
1631
  {
1632
    return paintingTile;
1633
  }
1634
 
1635
  /**
1636
   * Get the value of the {@link #requestFocusEnabled} property.
1637
   *
1638
   * @return The current value of the property
1639
   */
1640
  public boolean isRequestFocusEnabled()
1641
  {
1642
    return requestFocusEnabled;
1643
  }
1644
 
1645
  /**
1646
   * Return <code>true</code> if this component is a validation root; this
1647
   * will cause calls to {@link #invalidate()} in this component's children
1648
   * to be "captured" at this component, and not propagate to its parents.
1649
   * For most components this should return <code>false</code>, but some
1650
   * components such as {@link JViewport} will want to return
1651
   * <code>true</code>.
1652
   *
1653
   * @return Whether this component is a validation root
1654
   */
1655
  public boolean isValidateRoot()
1656
  {
1657
    return false;
1658
  }
1659
 
1660
  /**
1661
   * <p>Paint the component. This is a delicate process, and should only be
1662
   * called from the repaint thread, under control of the {@link
1663
   * RepaintManager}. Client code should usually call {@link #repaint()} to
1664
   * trigger painting.</p>
1665
   *
1666
   * <p>The body of the <code>paint</code> call involves calling {@link
1667
   * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1668
   * order. If you want to customize painting behavior, you should override
1669
   * one of these methods rather than <code>paint</code>.</p>
1670
   *
1671
   * <p>For more details on the painting sequence, see <a
1672
   * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
1673
   * this article</a>.</p>
1674
   *
1675
   * @param g The graphics context to paint with
1676
   *
1677
   * @see #paintImmediately(Rectangle)
1678
   */
1679
  public void paint(Graphics g)
1680
  {
1681
    RepaintManager rm = RepaintManager.currentManager(this);
1682
    // We do a little stunt act here to switch on double buffering if it's
1683
    // not already on. If we are not already doublebuffered, then we jump
1684
    // into the method paintDoubleBuffered, which turns on the double buffer
1685
    // and then calls paint(g) again. In the second call we go into the else
1686
    // branch of this if statement and actually paint things to the double
1687
    // buffer. When this method completes, the call stack unwinds back to
1688
    // paintDoubleBuffered, where the buffer contents is finally drawn to the
1689
    // screen.
1690
    if (!isPaintingDoubleBuffered && isDoubleBuffered()
1691
        && rm.isDoubleBufferingEnabled())
1692
      paintDoubleBuffered(g);
1693
    else
1694
      {
1695
        if (g.getClip() == null)
1696
          g.setClip(0, 0, getWidth(), getHeight());
1697
        Graphics g2 = getComponentGraphics(g);
1698
        paintComponent(g2);
1699
        paintBorder(g2);
1700
        paintChildren(g2);
1701
        Rectangle clip = g2.getClipBounds();
1702
        if (clip.x == 0 && clip.y == 0 && clip.width == getWidth()
1703
            && clip.height == getHeight())
1704
          RepaintManager.currentManager(this).markCompletelyClean(this);
1705
      }
1706
  }
1707
 
1708
  /**
1709
   * Paint the component's border. This usually means calling {@link
1710
   * Border#paintBorder} on the {@link #border} property, if it is
1711
   * non-<code>null</code>. You may override this if you wish to customize
1712
   * border painting behavior. The border is painted after the component's
1713
   * body, but before the component's children.
1714
   *
1715
   * @param g The graphics context with which to paint the border
1716
   *
1717
   * @see #paint
1718
   * @see #paintChildren
1719
   * @see #paintComponent
1720
   */
1721
  protected void paintBorder(Graphics g)
1722
  {
1723
    if (getBorder() != null)
1724
      getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
1725
  }
1726
 
1727
  /**
1728
   * Paint the component's children. This usually means calling {@link
1729
   * Container#paint}, which recursively calls {@link #paint} on any of the
1730
   * component's children, with appropriate changes to coordinate space and
1731
   * clipping region. You may override this if you wish to customize
1732
   * children painting behavior. The children are painted after the
1733
   * component's body and border.
1734
   *
1735
   * @param g The graphics context with which to paint the children
1736
   *
1737
   * @see #paint
1738
   * @see #paintBorder
1739
   * @see #paintComponent
1740
   */
1741
  protected void paintChildren(Graphics g)
1742
  {
1743
    Shape originalClip = g.getClip();
1744
    Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
1745
    g.clipRect(inner.x, inner.y, inner.width, inner.height);
1746
    Component[] children = getComponents();
1747
 
1748
    // Find the bottommost component that needs to be painted. This is a
1749
    // component that completely covers the current clip and is opaque. In
1750
    // this case we don't need to paint the components below it.
1751
    int startIndex = children.length - 1;
1752
    // No need to check for overlapping components when this component is
1753
    // optimizedDrawingEnabled (== it tiles its children).
1754
    if (! isOptimizedDrawingEnabled())
1755
      {
1756
        Rectangle clip = g.getClipBounds();
1757
        for (int i = 0; i < children.length; i++)
1758
          {
1759
            Rectangle childBounds = children[i].getBounds();
1760
            if (children[i].isOpaque()
1761
                && SwingUtilities.isRectangleContainingRectangle(childBounds,
1762
                                                            g.getClipBounds()))
1763
              {
1764
                startIndex = i;
1765
                break;
1766
              }
1767
          }
1768
      }
1769
    // paintingTile becomes true just before we start painting the component's
1770
    // children.
1771
    paintingTile = true;
1772
    for (int i = startIndex; i >= 0; --i)
1773
      {
1774
        // paintingTile must be set to false before we begin to start painting
1775
        // the last tile.
1776
        if (i == 0)
1777
          paintingTile = false;
1778
 
1779
        if (!children[i].isVisible())
1780
          continue;
1781
 
1782
        Rectangle bounds = children[i].getBounds(rectCache);
1783
        Rectangle oldClip = g.getClipBounds();
1784
        if (oldClip == null)
1785
          oldClip = bounds;
1786
 
1787
        if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height))
1788
          continue;
1789
 
1790
        boolean translated = false;
1791
        try
1792
          {
1793
            g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height);
1794
            g.translate(bounds.x, bounds.y);
1795
            translated = true;
1796
            children[i].paint(g);
1797
          }
1798
        finally
1799
          {
1800
            if (translated)
1801
              g.translate(-bounds.x, -bounds.y);
1802
            g.setClip(oldClip);
1803
          }
1804
      }
1805
    g.setClip(originalClip);
1806
  }
1807
 
1808
  /**
1809
   * Paint the component's body. This usually means calling {@link
1810
   * ComponentUI#update} on the {@link #ui} property of the component, if
1811
   * it is non-<code>null</code>. You may override this if you wish to
1812
   * customize the component's body-painting behavior. The component's body
1813
   * is painted first, before the border and children.
1814
   *
1815
   * @param g The graphics context with which to paint the body
1816
   *
1817
   * @see #paint
1818
   * @see #paintBorder
1819
   * @see #paintChildren
1820
   */
1821
  protected void paintComponent(Graphics g)
1822
  {
1823
    if (ui != null)
1824
      {
1825
        Graphics g2 = g;
1826
        if (!(g instanceof Graphics2D))
1827
          g2 = g.create();
1828
        ui.update(g2, this);
1829
        if (!(g instanceof Graphics2D))
1830
          g2.dispose();
1831
      }
1832
  }
1833
 
1834
  /**
1835
   * A variant of {@link #paintImmediately(Rectangle)} which takes
1836
   * integer parameters.
1837
   *
1838
   * @param x The left x coordinate of the dirty region
1839
   * @param y The top y coordinate of the dirty region
1840
   * @param w The width of the dirty region
1841
   * @param h The height of the dirty region
1842
   */
1843
  public void paintImmediately(int x, int y, int w, int h)
1844
  {
1845
    paintImmediately(new Rectangle(x, y, w, h));
1846
  }
1847
 
1848
  /**
1849
   * Transform the provided dirty rectangle for this component into the
1850
   * appropriate ancestral {@link JRootPane} and call {@link #paint} on
1851
   * that root pane. This method is called from the {@link RepaintManager}
1852
   * and should always be called within the painting thread.
1853
   *
1854
   * <p>This method will acquire a double buffer from the {@link
1855
   * RepaintManager} if the component's {@link #doubleBuffered} property is
1856
   * <code>true</code> and the <code>paint</code> call is the
1857
   * <em>first</em> recursive <code>paint</code> call inside swing.</p>
1858
   *
1859
   * <p>The method will also modify the provided {@link Graphics} context
1860
   * via the {@link #getComponentGraphics} method. If you want to customize
1861
   * the graphics object used for painting, you should override that method
1862
   * rather than <code>paint</code>.</p>
1863
   *
1864
   * @param r The dirty rectangle to paint
1865
   */
1866
  public void paintImmediately(Rectangle r)
1867
  {
1868
    // Try to find a root pane for this component.
1869
    //Component root = findPaintRoot(r);
1870
    Component root = findPaintRoot(r);
1871
    // If no paint root is found, then this component is completely overlapped
1872
    // by another component and we don't need repainting.
1873
    if (root == null)
1874
      return;
1875
    if (root == null || !root.isShowing())
1876
      return;
1877
 
1878
    Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root);
1879
    if (root instanceof JComponent)
1880
      ((JComponent) root).paintImmediately2(rootClip);
1881
    else
1882
      root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height);
1883
  }
1884
 
1885
  /**
1886
   * Performs the actual work of paintImmediatly on the repaint root.
1887
   *
1888
   * @param r the area to be repainted
1889
   */
1890
  void paintImmediately2(Rectangle r)
1891
  {
1892
    RepaintManager rm = RepaintManager.currentManager(this);
1893
    Graphics g = getGraphics();
1894
    g.setClip(r.x, r.y, r.width, r.height);
1895
    if (rm.isDoubleBufferingEnabled() && isDoubleBuffered())
1896
      paintDoubleBuffered(g);
1897
    else
1898
      paintSimple(g);
1899
    g.dispose();
1900
  }
1901
 
1902
  /**
1903
   * Performs double buffered repainting.
1904
   *
1905
   * @param g the graphics context to paint to
1906
   */
1907
  void paintDoubleBuffered(Graphics g)
1908
  {
1909
 
1910
    Rectangle r = g.getClipBounds();
1911
    if (r == null)
1912
      r = new Rectangle(0, 0, getWidth(), getHeight());
1913
    RepaintManager rm = RepaintManager.currentManager(this);
1914
 
1915
    // Paint on the offscreen buffer.
1916
    Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
1917
    Graphics g2 = buffer.getGraphics();
1918
    g2 = getComponentGraphics(g2);
1919
    g2.setClip(r.x, r.y, r.width, r.height);
1920
    isPaintingDoubleBuffered = true;
1921
    try
1922
      {
1923
        paint(g2);
1924
      }
1925
    finally
1926
      {
1927
        isPaintingDoubleBuffered = false;
1928
        g2.dispose();
1929
      }
1930
 
1931
    // Paint the buffer contents on screen.
1932
    g.drawImage(buffer, 0, 0, this);
1933
  }
1934
 
1935
  /**
1936
   * Performs normal painting without double buffering.
1937
   *
1938
   * @param g the graphics context to use
1939
   */
1940
  void paintSimple(Graphics g)
1941
  {
1942
    Graphics g2 = getComponentGraphics(g);
1943
    paint(g2);
1944
  }
1945
 
1946
  /**
1947
   * Return a string representation for this component, for use in
1948
   * debugging.
1949
   *
1950
   * @return A string describing this component.
1951
   */
1952
  protected String paramString()
1953
  {
1954
    StringBuffer sb = new StringBuffer();
1955
    sb.append(super.paramString());
1956
    sb.append(",alignmentX=").append(getAlignmentX());
1957
    sb.append(",alignmentY=").append(getAlignmentY());
1958
    sb.append(",border=");
1959
    if (getBorder() != null)
1960
      sb.append(getBorder());
1961
    sb.append(",maximumSize=");
1962
    if (getMaximumSize() != null)
1963
      sb.append(getMaximumSize());
1964
    sb.append(",minimumSize=");
1965
    if (getMinimumSize() != null)
1966
      sb.append(getMinimumSize());
1967
    sb.append(",preferredSize=");
1968
    if (getPreferredSize() != null)
1969
      sb.append(getPreferredSize());
1970
    return sb.toString();
1971
  }
1972
 
1973
  /**
1974
   * A variant of {@link
1975
   * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
1976
   * provides <code>null</code> for the command name.
1977
   */
1978
  public void registerKeyboardAction(ActionListener act,
1979
                                     KeyStroke stroke,
1980
                                     int cond)
1981
  {
1982
    registerKeyboardAction(act, null, stroke, cond);
1983
  }
1984
 
1985
  /*
1986
   * There is some charmingly undocumented behavior sun seems to be using
1987
   * to simulate the old register/unregister keyboard binding API. It's not
1988
   * clear to me why this matters, but we shall endeavour to follow suit.
1989
   *
1990
   * Two main thing seem to be happening when you do registerKeyboardAction():
1991
   *
1992
   *  - no actionMap() entry gets created, just an entry in inputMap()
1993
   *
1994
   *  - the inputMap() entry is a proxy class which invokes the the
1995
   *  binding's actionListener as a target, and which clobbers the command
1996
   *  name sent in the ActionEvent, providing the binding command name
1997
   *  instead.
1998
   *
1999
   * This much you can work out just by asking the input and action maps
2000
   * what they contain after making bindings, and watching the event which
2001
   * gets delivered to the recipient. Beyond that, it seems to be a
2002
   * sun-private solution so I will only immitate it as much as it matters
2003
   * to external observers.
2004
   */
2005
  private static class ActionListenerProxy
2006
    extends AbstractAction
2007
  {
2008
    ActionListener target;
2009
    String bindingCommandName;
2010
 
2011
    public ActionListenerProxy(ActionListener li,
2012
                               String cmd)
2013
    {
2014
      target = li;
2015
      bindingCommandName = cmd;
2016
    }
2017
 
2018
    public void actionPerformed(ActionEvent e)
2019
    {
2020
      ActionEvent derivedEvent = new ActionEvent(e.getSource(),
2021
                                                 e.getID(),
2022
                                                 bindingCommandName,
2023
                                                 e.getModifiers());
2024
      target.actionPerformed(derivedEvent);
2025
    }
2026
  }
2027
 
2028
 
2029
  /**
2030
   * An obsolete method to register a keyboard action on this component.
2031
   * You should use <code>getInputMap</code> and <code>getActionMap</code>
2032
   * to fetch mapping tables from keystrokes to commands, and commands to
2033
   * actions, respectively, and modify those mappings directly.
2034
   *
2035
   * @param act The action to be registered
2036
   * @param cmd The command to deliver in the delivered {@link
2037
   *     java.awt.event.ActionEvent}
2038
   * @param stroke The keystroke to register on
2039
   * @param cond One of the values {@link #UNDEFINED_CONDITION},
2040
   *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
2041
   *     {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
2042
   *     be met for the action to be fired
2043
   *
2044
   * @see #unregisterKeyboardAction
2045
   * @see #getConditionForKeyStroke
2046
   * @see #resetKeyboardActions
2047
   */
2048
  public void registerKeyboardAction(ActionListener act,
2049
                                     String cmd,
2050
                                     KeyStroke stroke,
2051
                                     int cond)
2052
  {
2053
    getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd));
2054
  }
2055
 
2056
  public final void setInputMap(int condition, InputMap map)
2057
  {
2058
    enableEvents(AWTEvent.KEY_EVENT_MASK);
2059
    switch (condition)
2060
      {
2061
      case WHEN_FOCUSED:
2062
        inputMap_whenFocused = map;
2063
        break;
2064
 
2065
      case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2066
        inputMap_whenAncestorOfFocused = map;
2067
        break;
2068
 
2069
      case WHEN_IN_FOCUSED_WINDOW:
2070
        if (map != null && !(map instanceof ComponentInputMap))
2071
            throw new
2072
              IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " +
2073
                                       "InputMap must be a ComponentInputMap");
2074
        inputMap_whenInFocusedWindow = (ComponentInputMap)map;
2075
        break;
2076
 
2077
      case UNDEFINED_CONDITION:
2078
      default:
2079
        throw new IllegalArgumentException();
2080
      }
2081
  }
2082
 
2083
  public final InputMap getInputMap(int condition)
2084
  {
2085
    enableEvents(AWTEvent.KEY_EVENT_MASK);
2086
    switch (condition)
2087
      {
2088
      case WHEN_FOCUSED:
2089
        if (inputMap_whenFocused == null)
2090
          inputMap_whenFocused = new InputMap();
2091
        return inputMap_whenFocused;
2092
 
2093
      case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2094
        if (inputMap_whenAncestorOfFocused == null)
2095
          inputMap_whenAncestorOfFocused = new InputMap();
2096
        return inputMap_whenAncestorOfFocused;
2097
 
2098
      case WHEN_IN_FOCUSED_WINDOW:
2099
        if (inputMap_whenInFocusedWindow == null)
2100
          inputMap_whenInFocusedWindow = new ComponentInputMap(this);
2101
        return inputMap_whenInFocusedWindow;
2102
 
2103
      case UNDEFINED_CONDITION:
2104
      default:
2105
        return null;
2106
      }
2107
  }
2108
 
2109
  public final InputMap getInputMap()
2110
  {
2111
    return getInputMap(WHEN_FOCUSED);
2112
  }
2113
 
2114
  public final ActionMap getActionMap()
2115
  {
2116
    if (actionMap == null)
2117
      actionMap = new ActionMap();
2118
    return actionMap;
2119
  }
2120
 
2121
  public final void setActionMap(ActionMap map)
2122
  {
2123
    actionMap = map;
2124
  }
2125
 
2126
  /**
2127
   * Return the condition that determines whether a registered action
2128
   * occurs in response to the specified keystroke.
2129
   *
2130
   * @param ks The keystroke to return the condition of
2131
   *
2132
   * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
2133
   *     #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
2134
   *     #WHEN_IN_FOCUSED_WINDOW}
2135
   *
2136
   * @deprecated As of 1.3 KeyStrokes can be registered with multiple
2137
   *     simultaneous conditions.
2138
   *
2139
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2140
   * @see #unregisterKeyboardAction
2141
   * @see #resetKeyboardActions
2142
   */
2143
  public int getConditionForKeyStroke(KeyStroke ks)
2144
  {
2145
    if (inputMap_whenFocused != null
2146
        && inputMap_whenFocused.get(ks) != null)
2147
      return WHEN_FOCUSED;
2148
    else if (inputMap_whenAncestorOfFocused != null
2149
             && inputMap_whenAncestorOfFocused.get(ks) != null)
2150
      return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
2151
    else if (inputMap_whenInFocusedWindow != null
2152
             && inputMap_whenInFocusedWindow.get(ks) != null)
2153
      return WHEN_IN_FOCUSED_WINDOW;
2154
    else
2155
      return UNDEFINED_CONDITION;
2156
  }
2157
 
2158
  /**
2159
   * Get the ActionListener (typically an {@link Action} object) which is
2160
   * associated with a particular keystroke.
2161
   *
2162
   * @param ks The keystroke to retrieve the action of
2163
   *
2164
   * @return The action associated with the specified keystroke
2165
   *
2166
   * @deprecated Use {@link #getActionMap()}
2167
   */
2168
  public ActionListener getActionForKeyStroke(KeyStroke ks)
2169
  {
2170
    Object cmd = getInputMap().get(ks);
2171
    if (cmd != null)
2172
      {
2173
        if (cmd instanceof ActionListenerProxy)
2174
          return (ActionListenerProxy) cmd;
2175
        else if (cmd instanceof String)
2176
          return getActionMap().get(cmd);
2177
      }
2178
    return null;
2179
  }
2180
 
2181
  /**
2182
   * A hook for subclasses which want to customize event processing.
2183
   */
2184
  protected void processComponentKeyEvent(KeyEvent e)
2185
  {
2186
    // This method does nothing, it is meant to be overridden by subclasses.
2187
  }
2188
 
2189
  /**
2190
   * Override the default key dispatch system from Component to hook into
2191
   * the swing {@link InputMap} / {@link ActionMap} system.
2192
   *
2193
   * See <a
2194
   * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
2195
   * this report</a> for more details, it's somewhat complex.
2196
   */
2197
  protected void processKeyEvent(KeyEvent e)
2198
  {
2199
    // let the AWT event processing send KeyEvents to registered listeners
2200
    super.processKeyEvent(e);
2201
    processComponentKeyEvent(e);
2202
 
2203
    if (e.isConsumed())
2204
      return;
2205
 
2206
    // Input maps are checked in this order:
2207
    // 1. The focused component's WHEN_FOCUSED map is checked.
2208
    // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
2209
    // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
2210
    //    component's parent, then its parent's parent, and so on.
2211
    //    Note: Input maps for disabled components are skipped.
2212
    // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
2213
    //    the focused window are searched.
2214
 
2215
    KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
2216
    boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
2217
 
2218
    if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
2219
      {
2220
        // This is step 1 from above comment.
2221
        e.consume();
2222
        return;
2223
      }
2224
    else if (processKeyBinding
2225
             (keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2226
      {
2227
        // This is step 2 from above comment.
2228
        e.consume();
2229
        return;
2230
      }
2231
 
2232
    // This is step 3 from above comment.
2233
    Container current = getParent();
2234
    while (current != null)
2235
      {
2236
        // If current is a JComponent, see if it handles the event in its
2237
        // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
2238
        if ((current instanceof JComponent) &&
2239
            ((JComponent)current).processKeyBinding
2240
            (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2241
          {
2242
            e.consume();
2243
            return;
2244
          }
2245
 
2246
        // Stop when we've tried a top-level container and it didn't handle it
2247
        if (current instanceof Window || current instanceof Applet)
2248
          break;
2249
 
2250
        // Move up the hierarchy
2251
        current = current.getParent();
2252
      }
2253
 
2254
    // Current being null means the JComponent does not currently have a
2255
    // top-level ancestor, in which case we don't need to check 
2256
    // WHEN_IN_FOCUSED_WINDOW bindings.
2257
    if (current == null || e.isConsumed())
2258
      return;
2259
 
2260
    // This is step 4 from above comment.  KeyboardManager maintains mappings
2261
    // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to 
2262
    // traverse the containment hierarchy each time.
2263
    if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
2264
      e.consume();
2265
  }
2266
 
2267
  protected boolean processKeyBinding(KeyStroke ks,
2268
                                      KeyEvent e,
2269
                                      int condition,
2270
                                      boolean pressed)
2271
  {
2272
    if (isEnabled())
2273
      {
2274
        Action act = null;
2275
        InputMap map = getInputMap(condition);
2276
        if (map != null)
2277
          {
2278
            Object cmd = map.get(ks);
2279
            if (cmd != null)
2280
              {
2281
                if (cmd instanceof ActionListenerProxy)
2282
                  act = (Action) cmd;
2283
                else
2284
                  act = (Action) getActionMap().get(cmd);
2285
              }
2286
          }
2287
        if (act != null && act.isEnabled())
2288
          return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers());
2289
      }
2290
    return false;
2291
  }
2292
 
2293
  /**
2294
   * Remove a keyboard action registry.
2295
   *
2296
   * @param aKeyStroke The keystroke to unregister
2297
   *
2298
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2299
   * @see #getConditionForKeyStroke
2300
   * @see #resetKeyboardActions
2301
   */
2302
  public void unregisterKeyboardAction(KeyStroke aKeyStroke)
2303
  {
2304
    // FIXME: Must be implemented.
2305
  }
2306
 
2307
 
2308
  /**
2309
   * Reset all keyboard action registries.
2310
   *
2311
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2312
   * @see #unregisterKeyboardAction
2313
   * @see #getConditionForKeyStroke
2314
   */
2315
  public void resetKeyboardActions()
2316
  {
2317
    if (inputMap_whenFocused != null)
2318
      inputMap_whenFocused.clear();
2319
    if (inputMap_whenAncestorOfFocused != null)
2320
      inputMap_whenAncestorOfFocused.clear();
2321
    if (inputMap_whenInFocusedWindow != null)
2322
      inputMap_whenInFocusedWindow.clear();
2323
    if (actionMap != null)
2324
      actionMap.clear();
2325
  }
2326
 
2327
  /**
2328
   * Mark the described region of this component as dirty in the current
2329
   * {@link RepaintManager}. This will queue an asynchronous repaint using
2330
   * the system painting thread in the near future.
2331
   *
2332
   * @param tm ignored
2333
   * @param x coordinate of the region to mark as dirty
2334
   * @param y coordinate of the region to mark as dirty
2335
   * @param width dimension of the region to mark as dirty
2336
   * @param height dimension of the region to mark as dirty
2337
   */
2338
  public void repaint(long tm, int x, int y, int width, int height)
2339
  {
2340
    Rectangle dirty = new Rectangle(x, y, width, height);
2341
    Rectangle vis = getVisibleRect();
2342
    dirty = dirty.intersection(vis);
2343
    RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y,
2344
                                                       dirty.width,
2345
                                                       dirty.height);
2346
  }
2347
 
2348
  /**
2349
   * Mark the described region of this component as dirty in the current
2350
   * {@link RepaintManager}. This will queue an asynchronous repaint using
2351
   * the system painting thread in the near future.
2352
   *
2353
   * @param r The rectangle to mark as dirty
2354
   */
2355
  public void repaint(Rectangle r)
2356
  {
2357
    repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(),
2358
            (int) r.getHeight());
2359
  }
2360
 
2361
  /**
2362
   * Request focus on the default component of this component's {@link
2363
   * FocusTraversalPolicy}.
2364
   *
2365
   * @return The result of {@link #requestFocus()}
2366
   *
2367
   * @deprecated Use {@link #requestFocus()} on the default component provided
2368
   *     from the {@link FocusTraversalPolicy} instead.
2369
   */
2370
  public boolean requestDefaultFocus()
2371
  {
2372
    return false;
2373
  }
2374
 
2375
  /**
2376
   * Queue a an invalidation and revalidation of this component, using
2377
   * {@link RepaintManager#addInvalidComponent}.
2378
   */
2379
  public void revalidate()
2380
  {
2381
    if (! EventQueue.isDispatchThread())
2382
      SwingUtilities.invokeLater(new Runnable()
2383
        {
2384
          public void run()
2385
          {
2386
            revalidate();
2387
          }
2388
        });
2389
    else
2390
      {
2391
        invalidate();
2392
        RepaintManager.currentManager(this).addInvalidComponent(this);
2393
      }
2394
  }
2395
 
2396
  /**
2397
   * Calls <code>scrollRectToVisible</code> on the component's parent.
2398
   * Components which can service this call should override.
2399
   *
2400
   * @param r The rectangle to make visible
2401
   */
2402
  public void scrollRectToVisible(Rectangle r)
2403
  {
2404
    Component p = getParent();
2405
    if (p instanceof JComponent)
2406
      ((JComponent) p).scrollRectToVisible(r);
2407
  }
2408
 
2409
  /**
2410
   * Set the value of the {@link #alignmentX} property.
2411
   *
2412
   * @param a The new value of the property
2413
   */
2414
  public void setAlignmentX(float a)
2415
  {
2416
    if (a < 0.0F)
2417
      alignmentX = 0.0F;
2418
    else if (a > 1.0)
2419
      alignmentX = 1.0F;
2420
    else
2421
      alignmentX = a;
2422
  }
2423
 
2424
  /**
2425
   * Set the value of the {@link #alignmentY} property.
2426
   *
2427
   * @param a The new value of the property
2428
   */
2429
  public void setAlignmentY(float a)
2430
  {
2431
    if (a < 0.0F)
2432
      alignmentY = 0.0F;
2433
    else if (a > 1.0)
2434
      alignmentY = 1.0F;
2435
    else
2436
      alignmentY = a;
2437
  }
2438
 
2439
  /**
2440
   * Set the value of the {@link #autoscrolls} property.
2441
   *
2442
   * @param a The new value of the property
2443
   */
2444
  public void setAutoscrolls(boolean a)
2445
  {
2446
    autoscrolls = a;
2447
  }
2448
 
2449
  /**
2450
   * Set the value of the {@link #debugGraphicsOptions} property.
2451
   *
2452
   * @param debugOptions The new value of the property
2453
   */
2454
  public void setDebugGraphicsOptions(int debugOptions)
2455
  {
2456
    debugGraphicsOptions = debugOptions;
2457
  }
2458
 
2459
  /**
2460
   * Set the value of the {@link #doubleBuffered} property.
2461
   *
2462
   * @param db The new value of the property
2463
   */
2464
  public void setDoubleBuffered(boolean db)
2465
  {
2466
    doubleBuffered = db;
2467
  }
2468
 
2469
  /**
2470
   * Set the value of the <code>enabled</code> property.
2471
   *
2472
   * @param enable The new value of the property
2473
   */
2474
  public void setEnabled(boolean enable)
2475
  {
2476
    if (enable == isEnabled())
2477
      return;
2478
    super.setEnabled(enable);
2479
    firePropertyChange("enabled", !enable, enable);
2480
    repaint();
2481
  }
2482
 
2483
  /**
2484
   * Set the value of the <code>font</code> property.
2485
   *
2486
   * @param f The new value of the property
2487
   */
2488
  public void setFont(Font f)
2489
  {
2490
    if (f == getFont())
2491
      return;
2492
    super.setFont(f);
2493
    revalidate();
2494
    repaint();
2495
  }
2496
 
2497
  /**
2498
   * Set the value of the <code>background</code> property.
2499
   *
2500
   * @param bg The new value of the property
2501
   */
2502
  public void setBackground(Color bg)
2503
  {
2504
    if (bg == getBackground())
2505
      return;
2506
    super.setBackground(bg);
2507
    repaint();
2508
  }
2509
 
2510
  /**
2511
   * Set the value of the <code>foreground</code> property.
2512
   *
2513
   * @param fg The new value of the property
2514
   */
2515
  public void setForeground(Color fg)
2516
  {
2517
    if (fg == getForeground())
2518
      return;
2519
    super.setForeground(fg);
2520
    repaint();
2521
  }
2522
 
2523
  /**
2524
   * Set the value of the {@link #maximumSize} property. The passed value is
2525
   * copied, the later direct changes on the argument have no effect on the
2526
   * property value.
2527
   *
2528
   * @param max The new value of the property
2529
   */
2530
  public void setMaximumSize(Dimension max)
2531
  {
2532
    Dimension oldMaximumSize = maximumSize;
2533
    maximumSize = new Dimension(max);
2534
    firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
2535
  }
2536
 
2537
  /**
2538
   * Set the value of the {@link #minimumSize} property. The passed value is
2539
   * copied, the later direct changes on the argument have no effect on the
2540
   * property value.
2541
   *
2542
   * @param min The new value of the property
2543
   */
2544
  public void setMinimumSize(Dimension min)
2545
  {
2546
    Dimension oldMinimumSize = minimumSize;
2547
    minimumSize = new Dimension(min);
2548
    firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
2549
  }
2550
 
2551
  /**
2552
   * Set the value of the {@link #preferredSize} property. The passed value is
2553
   * copied, the later direct changes on the argument have no effect on the
2554
   * property value.
2555
   *
2556
   * @param pref The new value of the property
2557
   */
2558
  public void setPreferredSize(Dimension pref)
2559
  {
2560
    Dimension oldPreferredSize = preferredSize;
2561
    preferredSize = new Dimension(pref);
2562
    firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
2563
  }
2564
 
2565
  /**
2566
   * Set the specified component to be the next component in the
2567
   * focus cycle, overriding the {@link FocusTraversalPolicy} for
2568
   * this component.
2569
   *
2570
   * @param aComponent The component to set as the next focusable
2571
   *
2572
   * @deprecated Use FocusTraversalPolicy instead
2573
   */
2574
  public void setNextFocusableComponent(Component aComponent)
2575
  {
2576
    // TODO: Implement this properly.
2577
  }
2578
 
2579
  /**
2580
   * Set the value of the {@link #requestFocusEnabled} property.
2581
   *
2582
   * @param e The new value of the property
2583
   */
2584
  public void setRequestFocusEnabled(boolean e)
2585
  {
2586
    requestFocusEnabled = e;
2587
  }
2588
 
2589
  /**
2590
   * Get the value of the {@link #transferHandler} property.
2591
   *
2592
   * @return The current value of the property
2593
   *
2594
   * @see #setTransferHandler
2595
   */
2596
 
2597
  public TransferHandler getTransferHandler()
2598
  {
2599
    return transferHandler;
2600
  }
2601
 
2602
  /**
2603
   * Set the value of the {@link #transferHandler} property.
2604
   *
2605
   * @param newHandler The new value of the property
2606
   *
2607
   * @see #getTransferHandler
2608
   */
2609
 
2610
  public void setTransferHandler(TransferHandler newHandler)
2611
  {
2612
    if (transferHandler == newHandler)
2613
      return;
2614
 
2615
    TransferHandler oldHandler = transferHandler;
2616
    transferHandler = newHandler;
2617
    firePropertyChange("transferHandler", oldHandler, newHandler);
2618
  }
2619
 
2620
  /**
2621
   * Set the value of the {@link #opaque} property.
2622
   *
2623
   * @param isOpaque The new value of the property
2624
   *
2625
   * @see ComponentUI#update
2626
   */
2627
  public void setOpaque(boolean isOpaque)
2628
  {
2629
    boolean oldOpaque = opaque;
2630
    opaque = isOpaque;
2631
    firePropertyChange("opaque", oldOpaque, opaque);
2632
  }
2633
 
2634
  /**
2635
   * Set the value of the visible property.
2636
   *
2637
   * If the value is changed, then the AncestorListeners of this component
2638
   * and all its children (recursivly) are notified.
2639
   *
2640
   * @param v The new value of the property
2641
   */
2642
  public void setVisible(boolean v)
2643
  {
2644
    // No need to do anything if the actual value doesn't change.
2645
    if (isVisible() == v)
2646
      return;
2647
 
2648
    super.setVisible(v);
2649
 
2650
    // Notify AncestorListeners.
2651
    if (v == true)
2652
      fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2653
    else
2654
      fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2655
 
2656
    Container parent = getParent();
2657
    if (parent != null)
2658
      parent.repaint(getX(), getY(), getWidth(), getHeight());
2659
    revalidate();
2660
  }
2661
 
2662
  /**
2663
   * Call {@link #paint}.
2664
   *
2665
   * @param g The graphics context to paint into
2666
   */
2667
  public void update(Graphics g)
2668
  {
2669
    paint(g);
2670
  }
2671
 
2672
  /**
2673
   * Get the value of the UIClassID property. This property should be a key
2674
   * in the {@link UIDefaults} table managed by {@link UIManager}, the
2675
   * value of which is the name of a class to load for the component's
2676
   * {@link #ui} property.
2677
   *
2678
   * @return A "symbolic" name which will map to a class to use for the
2679
   * component's UI, such as <code>"ComponentUI"</code>
2680
   *
2681
   * @see #setUI
2682
   * @see #updateUI
2683
   */
2684
  public String getUIClassID()
2685
  {
2686
    return "ComponentUI";
2687
  }
2688
 
2689
  /**
2690
   * Install a new UI delegate as the component's {@link #ui} property. In
2691
   * the process, this will call {@link ComponentUI#uninstallUI} on any
2692
   * existing value for the {@link #ui} property, and {@link
2693
   * ComponentUI#installUI} on the new UI delegate.
2694
   *
2695
   * @param newUI The new UI delegate to install
2696
   *
2697
   * @see #updateUI
2698
   * @see #getUIClassID
2699
   */
2700
  protected void setUI(ComponentUI newUI)
2701
  {
2702
    if (ui != null)
2703
      ui.uninstallUI(this);
2704
 
2705
    ComponentUI oldUI = ui;
2706
    ui = newUI;
2707
 
2708
    if (ui != null)
2709
      ui.installUI(this);
2710
 
2711
    firePropertyChange("UI", oldUI, newUI);
2712
    revalidate();
2713
    repaint();
2714
  }
2715
 
2716
  /**
2717
   * This method should be overridden in subclasses. In JComponent, the
2718
   * method does nothing. In subclasses, it should a UI delegate
2719
   * (corresponding to the symbolic name returned from {@link
2720
   * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
2721
   * with the new delegate.
2722
   */
2723
  public void updateUI()
2724
  {
2725
    System.out.println("update UI not overwritten in class: " + this);
2726
  }
2727
 
2728
  public static Locale getDefaultLocale()
2729
  {
2730
    return defaultLocale;
2731
  }
2732
 
2733
  public static void setDefaultLocale(Locale l)
2734
  {
2735
    defaultLocale = l;
2736
  }
2737
 
2738
  /**
2739
   * Returns the currently set input verifier for this component.
2740
   *
2741
   * @return the input verifier, or <code>null</code> if none
2742
   */
2743
  public InputVerifier getInputVerifier()
2744
  {
2745
    return inputVerifier;
2746
  }
2747
 
2748
  /**
2749
   * Sets the input verifier to use by this component.
2750
   *
2751
   * @param verifier the input verifier, or <code>null</code>
2752
   */
2753
  public void setInputVerifier(InputVerifier verifier)
2754
  {
2755
    InputVerifier oldVerifier = inputVerifier;
2756
    inputVerifier = verifier;
2757
    firePropertyChange("inputVerifier", oldVerifier, verifier);
2758
  }
2759
 
2760
  /**
2761
   * @since 1.3
2762
   */
2763
  public boolean getVerifyInputWhenFocusTarget()
2764
  {
2765
    return verifyInputWhenFocusTarget;
2766
  }
2767
 
2768
  /**
2769
   * @since 1.3
2770
   */
2771
  public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget)
2772
  {
2773
    if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget)
2774
      return;
2775
 
2776
    this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
2777
    firePropertyChange("verifyInputWhenFocusTarget",
2778
                       ! verifyInputWhenFocusTarget,
2779
                       verifyInputWhenFocusTarget);
2780
  }
2781
 
2782
  /**
2783
   * Requests that this component gets the input focus if the
2784
   * requestFocusEnabled property is set to <code>true</code>.
2785
   * This also means that this component's top-level window becomes
2786
   * the focused window, if that is not already the case.
2787
   *
2788
   * The preconditions that have to be met to become a focus owner is that
2789
   * the component must be displayable, visible and focusable.
2790
   *
2791
   * Note that this signals only a request for becoming focused. There are
2792
   * situations in which it is not possible to get the focus. So developers
2793
   * should not assume that the component has the focus until it receives
2794
   * a {@link java.awt.event.FocusEvent} with a value of
2795
   * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2796
   *
2797
   * @see Component#requestFocus()
2798
   */
2799
  public void requestFocus()
2800
  {
2801
    if (isRequestFocusEnabled())
2802
      super.requestFocus();
2803
  }
2804
 
2805
  /**
2806
   * This method is overridden to make it public so that it can be used
2807
   * by look and feel implementations.
2808
   *
2809
   * You should not use this method directly. Instead you are strongly
2810
   * encouraged to call {@link #requestFocus()} or
2811
   * {@link #requestFocusInWindow()} instead.
2812
   *
2813
   * @param temporary if the focus change is temporary
2814
   *
2815
   * @return <code>false</code> if the focus change request will definitly
2816
   *     fail, <code>true</code> if it will likely succeed
2817
   *
2818
   * @see Component#requestFocus(boolean)
2819
   *
2820
   * @since 1.4
2821
   */
2822
  public boolean requestFocus(boolean temporary)
2823
  {
2824
    return super.requestFocus(temporary);
2825
  }
2826
 
2827
  /**
2828
   * Requests that this component gets the input focus if the top level
2829
   * window that contains this component has the focus and the
2830
   * requestFocusEnabled property is set to <code>true</code>.
2831
   *
2832
   * The preconditions that have to be met to become a focus owner is that
2833
   * the component must be displayable, visible and focusable.
2834
   *
2835
   * Note that this signals only a request for becoming focused. There are
2836
   * situations in which it is not possible to get the focus. So developers
2837
   * should not assume that the component has the focus until it receives
2838
   * a {@link java.awt.event.FocusEvent} with a value of
2839
   * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2840
   *
2841
   * @return <code>false</code> if the focus change request will definitly
2842
   *     fail, <code>true</code> if it will likely succeed
2843
   *
2844
   * @see Component#requestFocusInWindow()
2845
   */
2846
  public boolean requestFocusInWindow()
2847
  {
2848
    if (isRequestFocusEnabled())
2849
      return super.requestFocusInWindow();
2850
    else
2851
      return false;
2852
  }
2853
 
2854
  /**
2855
   * This method is overridden to make it public so that it can be used
2856
   * by look and feel implementations.
2857
   *
2858
   * You should not use this method directly. Instead you are strongly
2859
   * encouraged to call {@link #requestFocus()} or
2860
   * {@link #requestFocusInWindow()} instead.
2861
   *
2862
   * @param temporary if the focus change is temporary
2863
   *
2864
   * @return <code>false</code> if the focus change request will definitly
2865
   *     fail, <code>true</code> if it will likely succeed
2866
   *
2867
   * @see Component#requestFocus(boolean)
2868
   *
2869
   * @since 1.4
2870
   */
2871
  public boolean requestFocusInWindow(boolean temporary)
2872
  {
2873
    return super.requestFocusInWindow(temporary);
2874
  }
2875
 
2876
  /**
2877
   * Receives notification if this component is added to a parent component.
2878
   *
2879
   * Notification is sent to all registered AncestorListeners about the
2880
   * new parent.
2881
   *
2882
   * This method sets up ActionListeners for all registered KeyStrokes of
2883
   * this component in the chain of parent components.
2884
   *
2885
   * A PropertyChange event is fired to indicate that the ancestor property
2886
   * has changed.
2887
   *
2888
   * This method is used internally and should not be used in applications.
2889
   */
2890
  public void addNotify()
2891
  {
2892
    // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
2893
    // Note that here we unregister all bindings associated with
2894
    // this component and then re-register them.  This may be more than
2895
    // necessary if the top-level ancestor hasn't changed.  Should
2896
    // maybe improve this.
2897
    KeyboardManager km = KeyboardManager.getManager();
2898
    km.clearBindingsForComp(this);
2899
    km.registerEntireMap((ComponentInputMap)
2900
                         this.getInputMap(WHEN_IN_FOCUSED_WINDOW));
2901
    super.addNotify();
2902
 
2903
    // Notify AncestorListeners.
2904
    fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2905
 
2906
    // fire property change event for 'ancestor'
2907
    firePropertyChange("ancestor", null, getParent());
2908
  }
2909
 
2910
  /**
2911
   * Receives notification that this component no longer has a parent.
2912
   *
2913
   * This method sends an AncestorEvent to all registered AncestorListeners,
2914
   * notifying them that the parent is gone.
2915
   *
2916
   * The keybord actions of this component are removed from the parent and
2917
   * its ancestors.
2918
   *
2919
   * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
2920
   * has changed.
2921
   *
2922
   * This method is called before the component is actually removed from
2923
   * its parent, so the parent is still visible through
2924
   * {@link Component#getParent}.
2925
   */
2926
  public void removeNotify()
2927
  {
2928
    super.removeNotify();
2929
 
2930
    KeyboardManager.getManager().clearBindingsForComp(this);
2931
 
2932
    // Notify ancestor listeners.
2933
    fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2934
 
2935
    // fire property change event for 'ancestor'
2936
    firePropertyChange("ancestor", getParent(), null);
2937
  }
2938
 
2939
  /**
2940
   * Returns <code>true</code> if the coordinates (x, y) lie within
2941
   * the bounds of this component and <code>false</code> otherwise.
2942
   * x and y are relative to the coordinate space of the component.
2943
   *
2944
   * @param x the X coordinate of the point to check
2945
   * @param y the Y coordinate of the point to check
2946
   *
2947
   * @return <code>true</code> if the specified point lies within the bounds
2948
   *     of this component, <code>false</code> otherwise
2949
   */
2950
  public boolean contains(int x, int y)
2951
  {
2952
    if (ui == null)
2953
      return super.contains(x, y);
2954
    else
2955
      return ui.contains(this, x, y);
2956
  }
2957
 
2958
  /**
2959
   * Disables this component.
2960
   *
2961
   * @deprecated replaced by {@link #setEnabled(boolean)}
2962
   */
2963
  public void disable()
2964
  {
2965
    super.disable();
2966
  }
2967
 
2968
  /**
2969
   * Enables this component.
2970
   *
2971
   * @deprecated replaced by {@link #setEnabled(boolean)}
2972
   */
2973
  public void enable()
2974
  {
2975
    super.enable();
2976
  }
2977
 
2978
  /**
2979
   * Returns the Graphics context for this component. This can be used
2980
   * to draw on a component.
2981
   *
2982
   * @return the Graphics context for this component
2983
   */
2984
  public Graphics getGraphics()
2985
  {
2986
    return super.getGraphics();
2987
  }
2988
 
2989
  /**
2990
   * Returns the X coordinate of the upper left corner of this component.
2991
   * Prefer this method over {@link #getBounds} or {@link #getLocation}
2992
   * because it does not cause any heap allocation.
2993
   *
2994
   * @return the X coordinate of the upper left corner of the component
2995
   */
2996
  public int getX()
2997
  {
2998
    return super.getX();
2999
  }
3000
 
3001
  /**
3002
   * Returns the Y coordinate of the upper left corner of this component.
3003
   * Prefer this method over {@link #getBounds} or {@link #getLocation}
3004
   * because it does not cause any heap allocation.
3005
   *
3006
   * @return the Y coordinate of the upper left corner of the component
3007
   */
3008
  public int getY()
3009
  {
3010
    return super.getY();
3011
  }
3012
 
3013
  /**
3014
   * Returns the height of this component. Prefer this method over
3015
   * {@link #getBounds} or {@link #getSize} because it does not cause
3016
   * any heap allocation.
3017
   *
3018
   * @return the height of the component
3019
   */
3020
  public int getHeight()
3021
  {
3022
    return super.getHeight();
3023
  }
3024
 
3025
  /**
3026
   * Returns the width of this component. Prefer this method over
3027
   * {@link #getBounds} or {@link #getSize} because it does not cause
3028
   * any heap allocation.
3029
   *
3030
   * @return the width of the component
3031
   */
3032
  public int getWidth()
3033
  {
3034
    return super.getWidth();
3035
  }
3036
 
3037
  /**
3038
   * Return all <code>PropertyChangeListener</code> objects registered.
3039
   *
3040
   * @return The set of <code>PropertyChangeListener</code> objects
3041
   */
3042
  public PropertyChangeListener[] getPropertyChangeListeners()
3043
  {
3044
    if (changeSupport == null)
3045
      return new PropertyChangeListener[0];
3046
    else
3047
      return changeSupport.getPropertyChangeListeners();
3048
  }
3049
 
3050
  /**
3051
   * Prints this component to the given Graphics context. A call to this
3052
   * method results in calls to the methods {@link #printComponent},
3053
   * {@link #printBorder} and {@link #printChildren} in this order.
3054
   *
3055
   * Double buffering is temporarily turned off so the painting goes directly
3056
   * to the supplied Graphics context.
3057
   *
3058
   * @param g the Graphics context to print onto
3059
   */
3060
  public void print(Graphics g)
3061
  {
3062
    boolean doubleBufferState = isDoubleBuffered();
3063
    setDoubleBuffered(false);
3064
    printComponent(g);
3065
    printBorder(g);
3066
    printChildren(g);
3067
    setDoubleBuffered(doubleBufferState);
3068
  }
3069
 
3070
  /**
3071
   * Prints this component to the given Graphics context. This invokes
3072
   * {@link #print}.
3073
   *
3074
   * @param g the Graphics context to print onto
3075
   */
3076
  public void printAll(Graphics g)
3077
  {
3078
    print(g);
3079
  }
3080
 
3081
  /**
3082
   * Prints this component to the specified Graphics context. The default
3083
   * behaviour is to invoke {@link #paintComponent}. Override this
3084
   * if you want special behaviour for printing.
3085
   *
3086
   * @param g the Graphics context to print onto
3087
   *
3088
   * @since 1.3
3089
   */
3090
  public void printComponent(Graphics g)
3091
  {
3092
    paintComponent(g);
3093
  }
3094
 
3095
  /**
3096
   * Print this component's children to the specified Graphics context.
3097
   * The default behaviour is to invoke {@link #paintChildren}. Override this
3098
   * if you want special behaviour for printing.
3099
   *
3100
   * @param g the Graphics context to print onto
3101
   *
3102
   * @since 1.3
3103
   */
3104
  public void printChildren(Graphics g)
3105
  {
3106
    paintChildren(g);
3107
  }
3108
 
3109
  /**
3110
   * Print this component's border to the specified Graphics context.
3111
   * The default behaviour is to invoke {@link #paintBorder}. Override this
3112
   * if you want special behaviour for printing.
3113
   *
3114
   * @param g the Graphics context to print onto
3115
   *
3116
   * @since 1.3
3117
   */
3118
  public void printBorder(Graphics g)
3119
  {
3120
    paintBorder(g);
3121
  }
3122
 
3123
  /**
3124
   * Processes mouse motion event, like dragging and moving.
3125
   *
3126
   * @param ev the MouseEvent describing the mouse motion
3127
   */
3128
  protected void processMouseMotionEvent(MouseEvent ev)
3129
  {
3130
    super.processMouseMotionEvent(ev);
3131
  }
3132
 
3133
  /**
3134
   * Moves and resizes the component.
3135
   *
3136
   * @param x the new horizontal location
3137
   * @param y the new vertial location
3138
   * @param w the new width
3139
   * @param h the new height
3140
   */
3141
  public void reshape(int x, int y, int w, int h)
3142
  {
3143
    int oldX = getX();
3144
    int oldY = getY();
3145
    super.reshape(x, y, w, h);
3146
    // Notify AncestorListeners.
3147
    if (oldX != getX() || oldY != getY())
3148
      fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
3149
  }
3150
 
3151
  /**
3152
   * Fires an AncestorEvent to this component's and all of its child
3153
   * component's AncestorListeners.
3154
   *
3155
   * @param ancestor the component that triggered the event
3156
   * @param id the kind of ancestor event that should be fired
3157
   */
3158
  void fireAncestorEvent(JComponent ancestor, int id)
3159
  {
3160
    // Fire event for registered ancestor listeners of this component.
3161
    AncestorListener[] listeners = getAncestorListeners();
3162
    if (listeners.length > 0)
3163
      {
3164
        AncestorEvent ev = new AncestorEvent(this, id,
3165
                                             ancestor, ancestor.getParent());
3166
        for (int i = 0; i < listeners.length; i++)
3167
          {
3168
            switch (id)
3169
              {
3170
              case AncestorEvent.ANCESTOR_MOVED:
3171
                listeners[i].ancestorMoved(ev);
3172
                break;
3173
              case AncestorEvent.ANCESTOR_ADDED:
3174
                listeners[i].ancestorAdded(ev);
3175
                break;
3176
              case AncestorEvent.ANCESTOR_REMOVED:
3177
                listeners[i].ancestorRemoved(ev);
3178
                break;
3179
              }
3180
          }
3181
      }
3182
    // Dispatch event to all children.
3183
    Component[] children = getComponents();
3184
    for (int i = 0; i < children.length; i++)
3185
      {
3186
        if (!(children[i] instanceof JComponent))
3187
          continue;
3188
        JComponent jc = (JComponent) children[i];
3189
        jc.fireAncestorEvent(ancestor, id);
3190
      }
3191
  }
3192
 
3193
  /**
3194
   * Finds a suitable paint root for painting this component. This method first
3195
   * checks if this component is overlapped using
3196
   * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
3197
   * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
3198
   * component for this paint root. If no paint is necessary, then we return
3199
   * <code>null</code>.
3200
   *
3201
   * @param c the clip of this component
3202
   *
3203
   * @return the paint root or <code>null</code> if no painting is necessary
3204
   */
3205
  private Component findPaintRoot(Rectangle c)
3206
  {
3207
    Component p = findOverlapFreeParent(c);
3208
    if (p == null)
3209
      return null;
3210
    Component root = findOpaqueParent(p);
3211
    return root;
3212
  }
3213
 
3214
  /**
3215
   * Scans the containment hierarchy upwards for components that overlap the
3216
   * this component in the specified clip. This method returns
3217
   * <code>this</code>, if no component overlaps this component. It returns
3218
   * <code>null</code> if another component completely covers this component
3219
   * in the specified clip (no repaint necessary). If another component partly
3220
   * overlaps this component in the specified clip, then the parent of this
3221
   * component is returned (this is the component that must be used as repaint
3222
   * root). For efficient lookup, the method
3223
   * {@link #isOptimizedDrawingEnabled()} is used.
3224
   *
3225
   * @param clip the clip of this component
3226
   *
3227
   * @return the paint root, or <code>null</code> if no paint is necessary
3228
   */
3229
  private Component findOverlapFreeParent(Rectangle clip)
3230
  {
3231
    Rectangle currentClip = clip;
3232
    Component found = this;
3233
    Container parent = this;
3234
    while (parent != null && !(parent instanceof Window))
3235
      {
3236
        Container newParent = parent.getParent();
3237
        if (newParent == null)
3238
          break;
3239
        // If the parent is optimizedDrawingEnabled, then its children are
3240
        // tiled and cannot have an overlapping child. Go directly to next
3241
        // parent.
3242
        if (newParent instanceof JComponent
3243
            && ((JComponent) newParent).isOptimizedDrawingEnabled())
3244
          {
3245
            parent = newParent;
3246
            continue;
3247
          }
3248
 
3249
        // First we must check if the new parent itself somehow clips the
3250
        // target rectangle. This can happen in JViewports.
3251
        Rectangle parRect = new Rectangle(0, 0, newParent.getWidth(),
3252
                                          newParent.getHeight());
3253
        Rectangle target = SwingUtilities.convertRectangle(found,
3254
                                                           currentClip,
3255
                                                           newParent);
3256
        if (target.contains(parRect) || target.intersects(parRect))
3257
          {
3258
            found = newParent;
3259
            currentClip = target;
3260
            parent = newParent;
3261
            continue;
3262
          }
3263
 
3264
        // Otherwise we must check if one of the children of this parent
3265
        // overlaps with the current component.
3266
        Component[] children = newParent.getComponents();
3267
        // This flag is used to skip components that are 'below' the component
3268
        // in question.
3269
        boolean skip = true;
3270
        for (int i = children.length - 1; i >= 0; i--)
3271
          {
3272
            if (children[i] == parent)
3273
              skip = false;
3274
            if (skip)
3275
              continue;
3276
            Component c = children[i];
3277
            Rectangle compBounds = c.getBounds();
3278
            // If the component completely overlaps the clip in question, we
3279
            // don't need to repaint. Return null.
3280
            if (compBounds.contains(target))
3281
              return null;
3282
            if (compBounds.intersects(target))
3283
              {
3284
                // We found a parent whose children overlap with our current
3285
                // component. Make this the current component.
3286
                found = newParent;
3287
                currentClip = target;
3288
                break;
3289
              }
3290
          }
3291
        parent = newParent;
3292
      }
3293
    return found;
3294
  }
3295
 
3296
  /**
3297
   * Finds the nearest component to <code>c</code> (upwards in the containment
3298
   * hierarchy), that is opaque. If <code>c</code> itself is opaque,
3299
   * this returns <code>c</code> itself.
3300
   *
3301
   * @param c the start component for the search
3302
   * @return the nearest component to <code>c</code> (upwards in the containment
3303
   *         hierarchy), that is opaque; If <code>c</code> itself is opaque,
3304
   *         this returns <code>c</code> itself
3305
   */
3306
  private Component findOpaqueParent(Component c)
3307
  {
3308
    Component found = c;
3309
    while (true)
3310
      {
3311
        if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
3312
          break;
3313
        else if (!(found instanceof JComponent))
3314
          break;
3315
        Container p = found.getParent();
3316
        if (p == null)
3317
          break;
3318
        else
3319
          found = p;
3320
      }
3321
    return found;
3322
  }
3323
 
3324
  /**
3325
   * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
3326
   * is changed.
3327
   *
3328
   * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
3329
   *        map
3330
   */
3331
  void updateComponentInputMap(ComponentInputMap changed)
3332
  {
3333
    // Since you can change a component's input map via
3334
    // setInputMap, we have to check if <code>changed</code>
3335
    // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
3336
    InputMap curr = getInputMap(WHEN_IN_FOCUSED_WINDOW);
3337
    while (curr != null && curr != changed)
3338
      curr = curr.getParent();
3339
 
3340
    // If curr is null then changed is not in the hierarchy
3341
    if (curr == null)
3342
      return;
3343
 
3344
    // Now we have to update the keyboard manager's hashtable
3345
    KeyboardManager km = KeyboardManager.getManager();
3346
 
3347
    // This is a poor strategy, should be improved.  We currently 
3348
    // delete all the old bindings for the component and then register
3349
    // the current bindings.
3350
    km.clearBindingsForComp(changed.getComponent());
3351
    km.registerEntireMap((ComponentInputMap)
3352
                         getInputMap(WHEN_IN_FOCUSED_WINDOW));
3353
  }
3354
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.