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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [awt/] [KeyboardFocusManager.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* KeyboardFocusManager.java -- manage component focusing via the keyboard
2
   Copyright (C) 2002, 2004  Free Software Foundation
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 java.awt;
40
 
41
import java.applet.Applet;
42
import java.awt.FocusTraversalPolicy;
43
import java.awt.event.FocusEvent;
44
import java.awt.event.KeyEvent;
45
import java.awt.event.WindowEvent;
46
import java.beans.PropertyChangeListener;
47
import java.beans.PropertyChangeSupport;
48
import java.beans.PropertyVetoException;
49
import java.beans.VetoableChangeListener;
50
import java.beans.VetoableChangeSupport;
51
import java.util.ArrayList;
52
import java.util.Collection;
53
import java.util.Collections;
54
import java.util.HashMap;
55
import java.util.HashSet;
56
import java.util.Iterator;
57
import java.util.List;
58
import java.util.Map;
59
import java.util.Set;
60
 
61
/**
62
 * The <code>KeyboardFocusManager</code> handles the focusing of
63
 * windows for receiving keyboard events.  The manager handles
64
 * the dispatch of all <code>FocusEvent</code>s and
65
 * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s
66
 * relating to the focused window.  Users can use the manager
67
 * to ascertain the current focus owner and fire events.
68
 * <br />
69
 * <br />
70
 * The focus owner is the <code>Component</code> that receives
71
 * key events.  The focus owner is either the currently focused
72
 * window or a component within this window.
73
 * <br />
74
 * <br />
75
 * The underlying native windowing system may denote the active
76
 * window or its children with special decorations (e.g. a highlighted
77
 * title bar).  The active window is always either a <code>Frame</code>
78
 * or <code>Dialog</code>, and is either the currently focused
79
 * window or its owner.
80
 * <br />
81
 * <br />
82
 * Applets may be partitioned into different applet contexts, according
83
 * to their code base.  In this case, each context has its own
84
 * <code>KeyboardFocusManager</code>, as opposed to the global
85
 * manager maintained by applets which share the same context.
86
 * Each context is insulated from the others, and they don't interact.
87
 * The resulting behaviour, as with context division, depends on the browser
88
 * supporting the applets.  Regardless, there can only ever be
89
 * one focused window, one active window and one focus owner
90
 * per <code>ClassLoader</code>.
91
 * <br />
92
 * <br />
93
 * To support this separation of focus managers, the manager instances
94
 * and the internal state information is grouped by the
95
 * <code>ThreadGroup</code> to which it pertains.  With respect to
96
 * applets, each code base has its own <code>ThreadGroup</code>, so the
97
 * isolation of each context is enforced within the manager.
98
 * <br />
99
 * <br />
100
 * By default, the manager defines TAB and Ctrl+TAB as the
101
 * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB
102
 * as the backward focus traversal keys.  No up or down cycle
103
 * traversal keys are defined by default.  Traversal takes effect
104
 * on the firing of a relevant <code>KEY_PRESSED</code> event.
105
 * However, all other key events related to the use of the
106
 * defined focus traversal key sequence are consumed and not
107
 * dispatched.
108
 * <br />
109
 * <br />
110
 * These default traversal keys come into effect on all windows
111
 * for which no alternative set of keys is defined.  This also
112
 * applies recursively to any child components of such a window,
113
 * which define no traversal keys of their own.
114
 *
115
 * @author Eric Blake (ebb9@email.byu.edu)
116
 * @author Thomas Fitzsimmons (fitzsim@redhat.com)
117
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
118
 * @since 1.4
119
 */
120
public abstract class KeyboardFocusManager
121
  implements KeyEventDispatcher, KeyEventPostProcessor
122
{
123
  /** Identifies {@link AWTKeyStroke}s that move the focus forward in
124
      the focus cycle. */
125
  public static final int FORWARD_TRAVERSAL_KEYS = 0;
126
 
127
  /** Identifies {@link AWTKeyStroke}s that move the focus backward in
128
      the focus cycle. */
129
  public static final int BACKWARD_TRAVERSAL_KEYS = 1;
130
 
131
  /** Identifies {@link AWTKeyStroke}s that move the focus up to the
132
      parent focus cycle root. */
133
  public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
134
 
135
  /** Identifies {@link AWTKeyStroke}s that move the focus down to the
136
      child focus cycle root. */
137
  public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
138
 
139
  /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
140
      the next focusable Component in the focus cycle. */
141
  private static final Set DEFAULT_FORWARD_KEYS;
142
 
143
  /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
144
      the previous focusable Component in the focus cycle. */
145
  private static final Set DEFAULT_BACKWARD_KEYS;
146
 
147
  /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS
148
      {@link java.util.Set}s. */
149
  static
150
  {
151
    Set s = new HashSet();
152
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
153
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
154
                                       KeyEvent.CTRL_DOWN_MASK));
155
    DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
156
    s = new HashSet();
157
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
158
                                       KeyEvent.SHIFT_DOWN_MASK));
159
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
160
                                       KeyEvent.SHIFT_DOWN_MASK
161
                                       | KeyEvent.CTRL_DOWN_MASK));
162
    DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
163
  }
164
 
165
  /** The global object {@link java.util.Map}s. */
166
 
167
  /** For security reasons, {@link java.applet.Applet}s in different
168
      codebases must be insulated from one another.  Since {@link
169
      KeyboardFocusManager}s have the ability to return {@link
170
      Component}s from a given {@link java.applet.Applet}, each
171
      codebase must have an independent {@link KeyboardFocusManager}.
172
      Since each codebase has its own {@link ThreadGroup} in which its
173
      {@link Applet}s run, it makes sense to partition {@link
174
      KeyboardFocusManager}s according to {@link
175
      java.lang.ThreadGroup}.  Thus, currentKeyboardFocusManagers is a
176
      {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */
177
  private static Map currentKeyboardFocusManagers = new HashMap ();
178
 
179
  /** {@link java.applet.Applet}s in one codebase must not be allowed
180
      to access {@link Component}s in {@link java.applet.Applet}s in
181
      other codebases.  To enforce this restriction, we key the
182
      following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which
183
      are per-codebase).  For example, if {@link
184
      java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner},
185
      passing {@link Component} C, currentFocusOwners[A] is assigned
186
      C, and all other currentFocusOwners values are nullified.  Then
187
      if {@link java.lang.ThreadGroup} A subsequently calls {@link
188
      #getGlobalFocusOwner}, it will return currentFocusOwners[A],
189
      that is, {@link Component} C.  If another {@link
190
      java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it
191
      will return currentFocusOwners[K], that is, null.
192
 
193
      Since this is a static field, we ensure that there is only one
194
      focused {@link Component} per class loader. */
195
  private static Map currentFocusOwners = new HashMap ();
196
 
197
  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
198
      that stores the {@link Component} that owns the permanent
199
      keyboard focus. @see currentFocusOwners */
200
  private static Map currentPermanentFocusOwners = new HashMap ();
201
 
202
  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
203
      that stores the focused {@link Window}. @see
204
      currentFocusOwners */
205
  private static Map currentFocusedWindows = new HashMap ();
206
 
207
  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
208
      that stores the active {@link Window}. @see
209
      currentFocusOwners */
210
  private static Map currentActiveWindows = new HashMap ();
211
 
212
  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
213
      that stores the focus cycle root {@link Container}. @see
214
      currentFocusOwners */
215
  private static Map currentFocusCycleRoots = new HashMap ();
216
 
217
  /** The default {@link FocusTraversalPolicy} that focus-managing
218
      {@link Container}s will use to define their initial focus
219
      traversal policy. */
220
  private FocusTraversalPolicy defaultPolicy;
221
 
222
  /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link
223
      #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and
224
      {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link
225
      java.util.Set}s. */
226
  private Set[] defaultFocusKeys = new Set[]
227
  {
228
    DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
229
    Collections.EMPTY_SET, Collections.EMPTY_SET
230
  };
231
 
232
  /**
233
   * A utility class to support the handling of events relating to property changes.
234
   */
235
  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);
236
 
237
  /**
238
   * A utility class to support the handling of events relating to vetoable changes.
239
   */
240
  private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this);
241
 
242
  /** A list of {@link KeyEventDispatcher}s that process {@link
243
      KeyEvent}s before they are processed the default keyboard focus
244
      manager. */
245
  private final ArrayList keyEventDispatchers = new ArrayList();
246
 
247
  /** A list of {@link KeyEventPostProcessor}s that process unconsumed
248
      {@link KeyEvent}s. */
249
  private final ArrayList keyEventPostProcessors = new ArrayList();
250
 
251
  /**
252
   * Construct a KeyboardFocusManager.
253
   */
254
  public KeyboardFocusManager ()
255
  {
256
  }
257
 
258
  /**
259
   * Retrieve the keyboard focus manager associated with the {@link
260
   * java.lang.ThreadGroup} to which the calling thread belongs.
261
   *
262
   * @return the keyboard focus manager associated with the current
263
   * thread group
264
   */
265
  public static KeyboardFocusManager getCurrentKeyboardFocusManager ()
266
  {
267
    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
268
 
269
    if (currentKeyboardFocusManagers.get (currentGroup) == null)
270
      setCurrentKeyboardFocusManager (null);
271
 
272
    return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
273
  }
274
 
275
  /**
276
   * Set the keyboard focus manager associated with the {@link
277
   * java.lang.ThreadGroup} to which the calling thread belongs.
278
   *
279
   * @param m the keyboard focus manager for the current thread group
280
   */
281
  public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m)
282
  {
283
    SecurityManager sm = System.getSecurityManager ();
284
    if (sm != null)
285
      sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));
286
 
287
    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
288
    KeyboardFocusManager manager;
289
 
290
    if (m == null)
291
      manager = new DefaultKeyboardFocusManager();
292
    else
293
      manager = m;
294
 
295
    currentKeyboardFocusManagers.put (currentGroup, manager);
296
  }
297
 
298
  /**
299
   * Retrieve the {@link Component} that has the keyboard focus, or
300
   * null if the focus owner was not set by a thread in the current
301
   * {@link java.lang.ThreadGroup}.
302
   *
303
   * @return the keyboard focus owner or null
304
   */
305
  public Component getFocusOwner ()
306
  {
307
    Component owner = (Component) getObject (currentFocusOwners);
308
    if (owner == null)
309
      owner = (Component) getObject (currentPermanentFocusOwners);
310
    return owner;
311
  }
312
 
313
  /**
314
   * Retrieve the {@link Component} that has the keyboard focus,
315
   * regardless of whether or not it was set by a thread in the
316
   * current {@link java.lang.ThreadGroup}.  If there is no temporary
317
   * focus owner in effect then this method will return the same value
318
   * as {@link #getGlobalPermanentFocusOwner}.
319
   *
320
   * @return the keyboard focus owner
321
   * @throws SecurityException if this is not the keyboard focus
322
   * manager associated with the current {@link java.lang.ThreadGroup}
323
   */
324
  protected Component getGlobalFocusOwner ()
325
  {
326
    // Check if there is a temporary focus owner.
327
    Component focusOwner = (Component) getGlobalObject (currentFocusOwners);
328
 
329
    return (focusOwner == null) ? getGlobalPermanentFocusOwner () : focusOwner;
330
  }
331
 
332
  /**
333
   * Set the {@link Component} that will be returned by {@link
334
   * #getFocusOwner} (when it is called from the current {@link
335
   * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}.  This
336
   * method does not actually transfer the keyboard focus.
337
   *
338
   * @param owner the Component to return from getFocusOwner and
339
   * getGlobalFocusOwner
340
   *
341
   * @see Component#requestFocus()
342
   * @see Component#requestFocusInWindow()
343
   */
344
  protected void setGlobalFocusOwner (Component owner)
345
  {
346
    if (owner == null || owner.focusable)
347
      setGlobalObject (currentFocusOwners, owner, "focusOwner");
348
  }
349
 
350
  /**
351
   * Clear the global focus owner and deliver a FOCUS_LOST event to
352
   * the previously-focused {@link Component}.  Until another {@link
353
   * Component} becomes the keyboard focus owner, key events will be
354
   * discarded by top-level windows.
355
   */
356
  public void clearGlobalFocusOwner ()
357
  {
358
    synchronized (currentFocusOwners)
359
      {
360
        Component focusOwner = getGlobalFocusOwner ();
361
        Component permanentFocusOwner = getGlobalPermanentFocusOwner ();
362
 
363
        setGlobalFocusOwner (null);
364
        setGlobalPermanentFocusOwner (null);
365
 
366
        // Inform the old focus owner that it has lost permanent
367
        // focus.
368
        if (focusOwner != null)
369
          {
370
            // We can't cache the event queue, because of
371
            // bootstrapping issues.  We need to set the default
372
            // KeyboardFocusManager in EventQueue before the event
373
            // queue is started.
374
            EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
375
            if (focusOwner != permanentFocusOwner)
376
              q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true));
377
            else
378
              q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false));
379
          }
380
 
381
        if (focusOwner != permanentFocusOwner)
382
          {
383
            EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
384
            q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
385
          }
386
      }
387
  }
388
 
389
  /**
390
   * Retrieve the {@link Component} that has the permanent keyboard
391
   * focus, or null if the focus owner was not set by a thread in the
392
   * current {@link java.lang.ThreadGroup}.
393
   *
394
   * @return the keyboard focus owner or null
395
   */
396
  public Component getPermanentFocusOwner ()
397
  {
398
    return (Component) getObject (currentPermanentFocusOwners);
399
  }
400
 
401
  /**
402
   * Retrieve the {@link Component} that has the permanent keyboard
403
   * focus, regardless of whether or not it was set by a thread in the
404
   * current {@link java.lang.ThreadGroup}.
405
   *
406
   * @return the keyboard focus owner
407
   * @throws SecurityException if this is not the keyboard focus
408
   * manager associated with the current {@link java.lang.ThreadGroup}
409
   */
410
  protected Component getGlobalPermanentFocusOwner ()
411
  {
412
    return (Component) getGlobalObject (currentPermanentFocusOwners);
413
  }
414
 
415
  /**
416
   * Set the {@link Component} that will be returned by {@link
417
   * #getPermanentFocusOwner} (when it is called from the current
418
   * {@link java.lang.ThreadGroup}) and {@link
419
   * #getGlobalPermanentFocusOwner}.  This method does not actually
420
   * transfer the keyboard focus.
421
   *
422
   * @param focusOwner the Component to return from
423
   * getPermanentFocusOwner and getGlobalPermanentFocusOwner
424
   *
425
   * @see Component#requestFocus()
426
   * @see Component#requestFocusInWindow()
427
   */
428
  protected void setGlobalPermanentFocusOwner (Component focusOwner)
429
  {
430
    if (focusOwner == null || focusOwner.focusable)
431
      setGlobalObject (currentPermanentFocusOwners, focusOwner,
432
                       "permanentFocusOwner");
433
  }
434
 
435
  /**
436
   * Retrieve the {@link Window} that is or contains the keyboard
437
   * focus owner, or null if the focused window was not set by a
438
   * thread in the current {@link java.lang.ThreadGroup}.
439
   *
440
   * @return the focused window or null
441
   */
442
  public Window getFocusedWindow ()
443
  {
444
    return (Window) getObject (currentFocusedWindows);
445
  }
446
 
447
  /**
448
   * Retrieve the {@link Window} that is or contains the focus owner,
449
   * regardless of whether or not the {@link Window} was set focused
450
   * by a thread in the current {@link java.lang.ThreadGroup}.
451
   *
452
   * @return the focused window
453
   * @throws SecurityException if this is not the keyboard focus
454
   * manager associated with the current {@link java.lang.ThreadGroup}
455
   */
456
  protected Window getGlobalFocusedWindow ()
457
  {
458
    return (Window) getGlobalObject (currentFocusedWindows);
459
  }
460
 
461
  /**
462
   * Set the {@link Window} that will be returned by {@link
463
   * #getFocusedWindow} (when it is called from the current {@link
464
   * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}.
465
   * This method does not actually cause <code>window</code> to become
466
   * the focused {@link Window}.
467
   *
468
   * @param window the Window to return from getFocusedWindow and
469
   * getGlobalFocusedWindow
470
   */
471
  protected void setGlobalFocusedWindow (Window window)
472
  {
473
    if (window == null || window.focusable)
474
      setGlobalObject (currentFocusedWindows, window, "focusedWindow");
475
  }
476
 
477
  /**
478
   * Retrieve the active {@link Window}, or null if the active window
479
   * was not set by a thread in the current {@link
480
   * java.lang.ThreadGroup}.
481
   *
482
   * @return the active window or null
483
   */
484
  public Window getActiveWindow()
485
  {
486
    return (Window) getObject (currentActiveWindows);
487
  }
488
 
489
  /**
490
   * Retrieve the active {@link Window}, regardless of whether or not
491
   * the {@link Window} was made active by a thread in the current
492
   * {@link java.lang.ThreadGroup}.
493
   *
494
   * @return the active window
495
   * @throws SecurityException if this is not the keyboard focus
496
   * manager associated with the current {@link java.lang.ThreadGroup}
497
   */
498
  protected Window getGlobalActiveWindow()
499
  {
500
    return (Window) getGlobalObject (currentActiveWindows);
501
  }
502
 
503
  /**
504
   * Set the {@link Window} that will be returned by {@link
505
   * #getActiveWindow} (when it is called from the current {@link
506
   * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}.  This
507
   * method does not actually cause <code>window</code> to be made
508
   * active.
509
   *
510
   * @param window the Window to return from getActiveWindow and
511
   * getGlobalActiveWindow
512
   */
513
  protected void setGlobalActiveWindow(Window window)
514
  {
515
    setGlobalObject (currentActiveWindows, window, "activeWindow");
516
  }
517
 
518
  /**
519
   * Retrieve the default {@link FocusTraversalPolicy}.
520
   * Focus-managing {@link Container}s use the returned object to
521
   * define their initial focus traversal policy.
522
   *
523
   * @return a non-null default FocusTraversalPolicy object
524
   */
525
  public FocusTraversalPolicy getDefaultFocusTraversalPolicy ()
526
  {
527
    if (defaultPolicy == null)
528
      defaultPolicy = new DefaultFocusTraversalPolicy ();
529
    return defaultPolicy;
530
  }
531
 
532
  /**
533
   * Set the {@link FocusTraversalPolicy} returned by {@link
534
   * #getDefaultFocusTraversalPolicy}.  Focus-managing {@link
535
   * Container}s created after this call will use policy as their
536
   * initial focus traversal policy.  Existing {@link Container}s'
537
   * focus traversal policies will not be affected by calls to this
538
   * method.
539
   *
540
   * @param policy the FocusTraversalPolicy that will be returned by
541
   * subsequent calls to getDefaultFocusTraversalPolicy
542
   * @throws IllegalArgumentException if policy is null
543
   */
544
  public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy)
545
  {
546
    if (policy == null)
547
      throw new IllegalArgumentException ();
548
    firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
549
    defaultPolicy = policy;
550
  }
551
 
552
  /**
553
   * Set the default {@link java.util.Set} of focus traversal keys for
554
   * one of the focus traversal directions.
555
   *
556
   * @param id focus traversal direction identifier
557
   * @param keystrokes set of AWTKeyStrokes
558
   *
559
   * @see #FORWARD_TRAVERSAL_KEYS
560
   * @see #BACKWARD_TRAVERSAL_KEYS
561
   * @see #UP_CYCLE_TRAVERSAL_KEYS
562
   * @see #DOWN_CYCLE_TRAVERSAL_KEYS
563
   */
564
  public void setDefaultFocusTraversalKeys (int id, Set keystrokes)
565
  {
566
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
567
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
568
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
569
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
570
      throw new IllegalArgumentException ();
571
 
572
    if (keystrokes == null)
573
      throw new IllegalArgumentException ();
574
 
575
    Set sa;
576
    Set sb;
577
    Set sc;
578
    String type;
579
    switch (id)
580
      {
581
      case FORWARD_TRAVERSAL_KEYS:
582
        sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
583
        sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
584
        sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
585
        type = "forwardDefaultFocusTraversalKeys";
586
        break;
587
      case BACKWARD_TRAVERSAL_KEYS:
588
        sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
589
        sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
590
        sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
591
        type = "backwardDefaultFocusTraversalKeys";
592
        break;
593
      case UP_CYCLE_TRAVERSAL_KEYS:
594
        sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
595
        sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
596
        sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
597
        type = "upCycleDefaultFocusTraversalKeys";
598
        break;
599
      case DOWN_CYCLE_TRAVERSAL_KEYS:
600
        sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
601
        sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
602
        sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
603
        type = "downCycleDefaultFocusTraversalKeys";
604
        break;
605
      default:
606
        throw new IllegalArgumentException ();
607
      }
608
    int i = keystrokes.size ();
609
    Iterator iter = keystrokes.iterator ();
610
    while (--i >= 0)
611
      {
612
        Object o = iter.next ();
613
        if (!(o instanceof AWTKeyStroke)
614
            || sa.contains (o) || sb.contains (o) || sc.contains (o)
615
            || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
616
          throw new IllegalArgumentException ();
617
      }
618
    keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
619
    firePropertyChange (type, defaultFocusKeys[id], keystrokes);
620
    defaultFocusKeys[id] = keystrokes;
621
  }
622
 
623
  /**
624
   * Retrieve the default {@link java.util.Set} of focus traversal
625
   * keys for one of the focus traversal directions.
626
   *
627
   * @param id focus traversal direction identifier
628
   *
629
   * @return the default set of AWTKeyStrokes
630
   *
631
   * @see #FORWARD_TRAVERSAL_KEYS
632
   * @see #BACKWARD_TRAVERSAL_KEYS
633
   * @see #UP_CYCLE_TRAVERSAL_KEYS
634
   * @see #DOWN_CYCLE_TRAVERSAL_KEYS
635
   */
636
  public Set getDefaultFocusTraversalKeys (int id)
637
  {
638
    if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
639
      throw new IllegalArgumentException ();
640
    return defaultFocusKeys[id];
641
  }
642
 
643
  /**
644
   * Retrieve the current focus cycle root, or null if the focus owner
645
   * was not set by a thread in the current {@link
646
   * java.lang.ThreadGroup}.
647
   *
648
   * @return the current focus cycle root or null
649
   */
650
  public Container getCurrentFocusCycleRoot ()
651
  {
652
    return (Container) getObject (currentFocusCycleRoots);
653
  }
654
 
655
  /**
656
   * Retrieve the current focus cycle root, regardless of whether or
657
   * not it was made set by a thread in the current {@link
658
   * java.lang.ThreadGroup}.
659
   *
660
   * @return the current focus cycle root
661
   * @throws SecurityException if this is not the keyboard focus
662
   * manager associated with the current {@link java.lang.ThreadGroup}
663
   */
664
  protected Container getGlobalCurrentFocusCycleRoot ()
665
  {
666
    return (Container) getGlobalObject (currentFocusCycleRoots);
667
  }
668
 
669
  /**
670
   * Set the {@link Container} that will be returned by {@link
671
   * #getCurrentFocusCycleRoot} (when it is called from the current
672
   * {@link java.lang.ThreadGroup}) and {@link
673
   * #getGlobalCurrentFocusCycleRoot}.  This method does not actually
674
   * make <code>cycleRoot</code> the current focus cycle root.
675
   *
676
   * @param cycleRoot the focus cycle root to return from
677
   * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
678
   */
679
  public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
680
  {
681
    setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
682
  }
683
 
684
  /**
685
   * Registers the supplied property change listener for receiving
686
   * events caused by the following property changes:
687
   *
688
   * <ul>
689
   * <li>the current focus owner ("focusOwner")</li>
690
   * <li>the permanent focus owner ("permanentFocusOwner")</li>
691
   * <li>the focused window ("focusedWindow")</li>
692
   * <li>the active window ("activeWindow")</li>
693
   * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
694
   * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
695
   * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
696
   * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
697
   * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
698
   * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
699
   * </ul>
700
   *
701
   * If the supplied listener is null, nothing occurs.
702
   *
703
   * @param l the new listener to register.
704
   * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
705
   */
706
  public void addPropertyChangeListener(PropertyChangeListener l)
707
  {
708
    if (l != null)
709
      propertyChangeSupport.addPropertyChangeListener(l);
710
  }
711
 
712
  /**
713
   * Removes the supplied property change listener from the list
714
   * of registered listeners.  If the supplied listener is null,
715
   * nothing occurs.
716
   *
717
   * @param l the listener to remove.
718
   */
719
  public void removePropertyChangeListener(PropertyChangeListener l)
720
  {
721
    if (l != null)
722
      propertyChangeSupport.removePropertyChangeListener(l);
723
  }
724
 
725
  /**
726
   * Returns the currently registered property change listeners
727
   * in array form.  The returned array is empty if no listeners are
728
   * currently registered.
729
   *
730
   * @return an array of registered property change listeners.
731
   */
732
  public PropertyChangeListener[] getPropertyChangeListeners()
733
  {
734
    return propertyChangeSupport.getPropertyChangeListeners();
735
  }
736
 
737
  /**
738
   * Registers a property change listener for receiving events relating
739
   * to a change to a specified property.  The supplied property name can be
740
   * either user-defined or one from the following list of properties
741
   * relevant to this class:
742
   *
743
   * <ul>
744
   * <li>the current focus owner ("focusOwner")</li>
745
   * <li>the permanent focus owner ("permanentFocusOwner")</li>
746
   * <li>the focused window ("focusedWindow")</li>
747
   * <li>the active window ("activeWindow")</li>
748
   * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
749
   * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
750
   * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
751
   * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
752
   * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
753
   * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
754
   * </ul>
755
   *
756
   * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
757
   *
758
   * @param name the name of the property to handle change events for.
759
   * @param l the listener to register for changes to the specified property.
760
   * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
761
   */
762
  public void addPropertyChangeListener(String name, PropertyChangeListener l)
763
  {
764
    if (l != null)
765
      propertyChangeSupport.addPropertyChangeListener(name, l);
766
  }
767
 
768
  /**
769
   * Removes the supplied property change listener registered for the
770
   * specified property from the list of registered listeners.  If the
771
   * supplied listener is null, nothing occurs.
772
   *
773
   * @param name the name of the property the listener is
774
   *        monitoring changes to.
775
   * @param l the listener to remove.
776
   */
777
  public void removePropertyChangeListener(String name,
778
                                           PropertyChangeListener l)
779
  {
780
    if (l != null)
781
      propertyChangeSupport.removePropertyChangeListener(name, l);
782
  }
783
 
784
  /**
785
   * Returns the currently registered property change listeners
786
   * in array form, which listen for changes to the supplied property.
787
   * The returned array is empty, if no listeners are currently registered
788
   * for events pertaining to the supplied property.
789
   *
790
   * @param name The property the returned listeners monitor for changes.
791
   * @return an array of registered property change listeners which
792
   *         listen for changes to the supplied property.
793
   */
794
  public PropertyChangeListener[] getPropertyChangeListeners(String name)
795
  {
796
    return propertyChangeSupport.getPropertyChangeListeners(name);
797
  }
798
 
799
  /**
800
   * Fires a property change event as a response to a change to
801
   * to the specified property.  The event is only fired if a
802
   * change has actually occurred (i.e. o and n are different).
803
   *
804
   * @param name The name of the property to which a change occurred.
805
   * @param o The old value of the property.
806
   * @param n The new value of the property.
807
   */
808
  protected void firePropertyChange(String name, Object o, Object n)
809
  {
810
    propertyChangeSupport.firePropertyChange(name, o, n);
811
  }
812
 
813
  /**
814
   * Registers a vetoable property change listener for receiving events
815
   * relating to the following properties:
816
   *
817
   * <ul>
818
   * <li>the current focus owner ("focusOwner")</li>
819
   * <li>the permanent focus owner ("permanentFocusOwner")</li>
820
   * <li>the focused window ("focusedWindow")</li>
821
   * <li>the active window ("activeWindow")</li>
822
   * </ul>
823
   *
824
   * Nothing occurs if a null listener is supplied.
825
   *
826
   * @param l the listener to register.
827
   * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
828
   */
829
  public void addVetoableChangeListener(VetoableChangeListener l)
830
  {
831
    if (l != null)
832
      vetoableChangeSupport.addVetoableChangeListener(l);
833
  }
834
 
835
  /**
836
   * Removes the supplied vetoable property change listener from
837
   * the list of registered listeners.  If the supplied listener
838
   * is null, nothing occurs.
839
   *
840
   * @param l the listener to remove.
841
   */
842
  public void removeVetoableChangeListener(VetoableChangeListener l)
843
  {
844
    if (l != null)
845
      vetoableChangeSupport.removeVetoableChangeListener(l);
846
  }
847
 
848
  /**
849
   * Returns the currently registered vetoable property change listeners
850
   * in array form.  The returned array is empty if no listeners are
851
   * currently registered.
852
   *
853
   * @return an array of registered vetoable property change listeners.
854
   * @since 1.4
855
   */
856
  public VetoableChangeListener[] getVetoableChangeListeners()
857
  {
858
    return vetoableChangeSupport.getVetoableChangeListeners();
859
  }
860
 
861
  /**
862
   * Registers a vetoable property change listener for receiving events relating
863
   * to a vetoable change to a specified property.  The supplied property name can be
864
   * either user-defined or one from the following list of properties
865
   * relevant to this class:
866
   *
867
   * <ul>
868
   * <li>the current focus owner ("focusOwner")</li>
869
   * <li>the permanent focus owner ("permanentFocusOwner")</li>
870
   * <li>the focused window ("focusedWindow")</li>
871
   * <li>the active window ("activeWindow")</li>
872
   * </ul>
873
   *
874
   * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
875
   *
876
   * @param name the name of the property to handle change events for.
877
   * @param l the listener to register for changes to the specified property.
878
   * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
879
   */
880
  public void addVetoableChangeListener(String name, VetoableChangeListener l)
881
  {
882
    if (l != null)
883
      vetoableChangeSupport.addVetoableChangeListener(name, l);
884
  }
885
 
886
  /**
887
   * Removes the supplied vetoable property change listener registered
888
   * for the specified property from the list of registered listeners.
889
   * If the supplied listener is null, nothing occurs.
890
   *
891
   * @param name the name of the vetoable property the listener is
892
   *        monitoring changes to.
893
   * @param l the listener to remove.
894
   */
895
  public void removeVetoableChangeListener(String name,
896
                                           VetoableChangeListener l)
897
  {
898
    if (l != null)
899
      vetoableChangeSupport.removeVetoableChangeListener(name, l);
900
  }
901
 
902
  /**
903
   * Returns the currently registered vetoable property change listeners
904
   * in array form, which listen for changes to the supplied property.
905
   * The returned array is empty, if no listeners are currently registered
906
   * for events pertaining to the supplied property.
907
   *
908
   * @param name The property the returned listeners monitor for changes.
909
   * @return an array of registered property change listeners which
910
   *         listen for changes to the supplied property.
911
   * @since 1.4
912
   */
913
  public VetoableChangeListener[] getVetoableChangeListeners(String name)
914
  {
915
    return vetoableChangeSupport.getVetoableChangeListeners(name);
916
  }
917
 
918
  /**
919
   * Fires a property change event as a response to a vetoable change to
920
   * to the specified property.  The event is only fired if a
921
   * change has actually occurred (i.e. o and n are different).
922
   * In the event that the property change is vetoed, the following
923
   * occurs:
924
   *
925
   * <ol>
926
   * <li>
927
   * This method throws a <code>PropertyVetoException</code> to
928
   * the proposed change.
929
   * </li>
930
   * <li>
931
   * A new event is fired to reverse the previous change.
932
   * </li>
933
   * <li>
934
   * This method again throws a <code>PropertyVetoException</code>
935
   * in response to the reversion.
936
   * </li>
937
   * </ol>
938
   *
939
   * @param name The name of the property to which a change occurred.
940
   * @param o The old value of the property.
941
   * @param n The new value of the property.
942
   * @throws PropertyVetoException if one of the listeners vetos
943
   *         the change by throwing this exception.
944
   */
945
  protected void fireVetoableChange(String name, Object o, Object n)
946
    throws PropertyVetoException
947
  {
948
    vetoableChangeSupport.fireVetoableChange(name, o, n);
949
  }
950
 
951
  /**
952
   * Adds a key event dispatcher to the list of registered dispatchers.
953
   * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
954
   * method is called in the order that they were added, prior to the manager
955
   * dispatching the event itself.  Notifications halt when one of the
956
   * dispatchers returns true.
957
   * <br />
958
   * <br />
959
   * The same dispatcher can exist multiple times within the list
960
   * of registered dispatchers, and there is no limit on the length
961
   * of this list.  A null dispatcher is simply ignored.
962
   *
963
   * @param dispatcher The dispatcher to register.
964
   */
965
  public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
966
  {
967
    if (dispatcher != null)
968
      keyEventDispatchers.add(dispatcher);
969
  }
970
 
971
  /**
972
   * Removes the specified key event dispatcher from the list of
973
   * registered dispatchers.  The manager always dispatches events,
974
   * regardless of its existence within the list.  The manager
975
   * can be added and removed from the list, as with any other
976
   * dispatcher, but this does not affect its ability to dispatch
977
   * key events.  Non-existent and null dispatchers are simply ignored
978
   * by this method.
979
   *
980
   * @param dispatcher The dispatcher to remove.
981
   */
982
  public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
983
  {
984
    keyEventDispatchers.remove(dispatcher);
985
  }
986
 
987
  /**
988
   * Returns the currently registered key event dispatchers in <code>List</code>
989
   * form.  At present, this only includes dispatchers explicitly registered
990
   * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
991
   * is subject to change and should not be depended on.  The manager itself
992
   * may be a member of the list, but only if explicitly registered.  If no
993
   * dispatchers have been registered, the list will be empty.
994
   *
995
   * @return A list of explicitly registered key event dispatchers.
996
   * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
997
   */
998
  protected List getKeyEventDispatchers ()
999
  {
1000
    return (List) keyEventDispatchers.clone ();
1001
  }
1002
 
1003
  /**
1004
   * Adds a key event post processor to the list of registered post processors.
1005
   * Post processors work in the same way as key event dispatchers, except
1006
   * that they are invoked after the manager has dispatched the key event,
1007
   * and not prior to this.  Each post processor's <code>postProcessKeyEvent</code>
1008
   * method is called to see if any post processing needs to be performed.  THe
1009
   * processors are called in the order in which they were added to the list,
1010
   * and notifications continue until one returns true.  As with key event
1011
   * dispatchers, the manager is implicitly called following this process,
1012
   * regardless of whether or not it is present within the list.
1013
   * <br />
1014
   * <br />
1015
   * The same post processor can exist multiple times within the list
1016
   * of registered post processors, and there is no limit on the length
1017
   * of this list.  A null post processor is simply ignored.
1018
   *
1019
   * @param postProcessor the post processor to register.
1020
   * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
1021
   */
1022
  public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1023
  {
1024
    if (postProcessor != null)
1025
      keyEventPostProcessors.add (postProcessor);
1026
  }
1027
 
1028
  /**
1029
   * Removes the specified key event post processor from the list of
1030
   * registered post processors.  The manager always post processes events,
1031
   * regardless of its existence within the list.  The manager
1032
   * can be added and removed from the list, as with any other
1033
   * post processor, but this does not affect its ability to post process
1034
   * key events.  Non-existent and null post processors are simply ignored
1035
   * by this method.
1036
   *
1037
   * @param postProcessor the post processor to remove.
1038
   */
1039
  public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1040
  {
1041
    keyEventPostProcessors.remove (postProcessor);
1042
  }
1043
 
1044
  /**
1045
   * Returns the currently registered key event post processors in <code>List</code>
1046
   * form.  At present, this only includes post processors explicitly registered
1047
   * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
1048
   * is subject to change and should not be depended on.  The manager itself
1049
   * may be a member of the list, but only if explicitly registered.  If no
1050
   * post processors have been registered, the list will be empty.
1051
   *
1052
   * @return A list of explicitly registered key event post processors.
1053
   * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
1054
   */
1055
  protected List getKeyEventPostProcessors ()
1056
  {
1057
    return (List) keyEventPostProcessors.clone ();
1058
  }
1059
 
1060
  /**
1061
   * The AWT event dispatcher uses this method to request that the manager
1062
   * handle a particular event.  If the manager fails or refuses to
1063
   * dispatch the supplied event (this method returns false), the
1064
   * AWT event dispatcher will try to dispatch the event itself.
1065
   * <br />
1066
   * <br />
1067
   * The manager is expected to handle all <code>FocusEvent</code>s
1068
   * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
1069
   * relating to the focus.  Dispatch is done with regard to the
1070
   * the focus owner and the currently focused and active windows.
1071
   * In handling the event, the source of the event may be overridden.
1072
   * <br />
1073
   * <br />
1074
   * The actual dispatching is performed by calling
1075
   * <code>redispatchEvent()</code>.  This avoids the infinite recursion
1076
   * of dispatch requests which may occur if this method is called on
1077
   * the target component.
1078
   *
1079
   * @param e the event to dispatch.
1080
   * @return true if the event was dispatched.
1081
   * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
1082
   * @see KeyEvent
1083
   * @see FocusEvent
1084
   * @see WindowEvent
1085
   */
1086
  public abstract boolean dispatchEvent (AWTEvent e);
1087
 
1088
  /**
1089
   * Handles redispatching of an event so that recursion of
1090
   * dispatch requests does not occur.  Event dispatch methods
1091
   * within this manager (<code>dispatchEvent()</code>) and
1092
   * the key event dispatchers should use this method to handle
1093
   * dispatching rather than the dispatch method of the target
1094
   * component.
1095
   * <br />
1096
   * <br />
1097
   * <strong>
1098
   * This method is not intended for general consumption, and is
1099
   * only for the use of the aforementioned classes.
1100
   * </strong>
1101
   *
1102
   * @param target the target component to which the event is
1103
   *        dispatched.
1104
   * @param e the event to dispatch.
1105
   */
1106
  public final void redispatchEvent (Component target, AWTEvent e)
1107
  {
1108
    synchronized (e)
1109
      {
1110
        e.setSource (target);
1111
        target.dispatchEvent (e);
1112
      }
1113
  }
1114
 
1115
  /**
1116
   * Attempts to dispatch key events for which no key event dispatcher
1117
   * has so far succeeded.  This method is usually called by
1118
   * <code>dispatchEvent()</code> following the sending of the key
1119
   * event to any registered key event dispatchers.  If the key
1120
   * event reaches this stage, none of the dispatchers returned
1121
   * true.  This is, of course, always the case if there are no
1122
   * registered dispatchers.
1123
   * <br />
1124
   * <br />
1125
   * If this method also fails to handle the key event, then
1126
   * false is returned to the caller.  In the case of
1127
   * <code>dispatchEvent()</code>, the calling method may try
1128
   * to handle the event itself or simply forward on the
1129
   * false result to its caller.  When the event is dispatched
1130
   * by this method, a true result is propogated through the
1131
   * calling methods.
1132
   *
1133
   * @param e the key event to dispatch.
1134
   * @return true if the event was dispatched successfully.
1135
   */
1136
  public abstract boolean dispatchKeyEvent (KeyEvent e);
1137
 
1138
  /**
1139
   * Handles the post processing of key events.  By default,
1140
   * this method will map unhandled key events to appropriate
1141
   * <code>MenuShortcut</code>s.  The event is consumed
1142
   * in the process and the shortcut is activated.  This
1143
   * method is usually called by <code>dispatchKeyEvent</code>.
1144
   *
1145
   * @param e the key event to post process.
1146
   * @return true by default, as the event was handled.
1147
   */
1148
  public abstract boolean postProcessKeyEvent (KeyEvent e);
1149
 
1150
  /**
1151
   * Handles focus traversal operations for key events which
1152
   * represent focus traversal keys in relation to the supplied
1153
   * component.  The supplied component is assumed to have the
1154
   * focus, whether it does so or not, and the operation is
1155
   * carried out as appropriate, with this in mind.
1156
   *
1157
   * @param focused the component on which to perform focus traversal,
1158
   *        on the assumption that this component has the focus.
1159
   * @param e the possible focus traversal key event.
1160
   */
1161
  public abstract void processKeyEvent (Component focused, KeyEvent e);
1162
 
1163
  /**
1164
   * Delays all key events following the specified timestamp until the
1165
   * supplied component has focus.  The AWT calls this method when it is
1166
   * determined that a focus change may occur within the native windowing
1167
   * system.  Any key events which occur following the time specified by
1168
   * after are delayed until a <code>FOCUS_GAINED</code> event is received
1169
   * for the untilFocused component.  The manager is responsible for ensuring
1170
   * this takes place.
1171
   *
1172
   * @param after the timestamp beyond which all key events are delayed until
1173
   *        the supplied component gains focus.
1174
   * @param untilFocused the component to wait on gaining focus.
1175
   */
1176
  protected abstract void enqueueKeyEvents (long after, Component untilFocused);
1177
 
1178
  /**
1179
   * Removes the key event block specified by the supplied timestamp and component.
1180
   * All delayed key events are released for normal dispatching following its
1181
   * removal and subsequent key events that would have been blocked are now
1182
   * immediately dispatched.  If the specified timestamp is below 0, then
1183
   * the request with the oldest timestamp is removed.
1184
   *
1185
   * @param after the timestamp of the key event block to be removed, or a
1186
   *        value smaller than 0 if the oldest is to be removed.
1187
   * @param untilFocused the component of the key event block to be removed.
1188
   */
1189
  protected abstract void dequeueKeyEvents (long after, Component untilFocused);
1190
 
1191
  /**
1192
   * Discards all key event blocks relating to focus requirements for
1193
   * the supplied component, regardless of timestamp.
1194
   *
1195
   * @param comp the component of the key event block(s) to be removed.
1196
   */
1197
  protected abstract void discardKeyEvents (Component comp);
1198
 
1199
  /**
1200
   * Moves the current focus to the next component following
1201
   * comp, based on the current focus traversal policy.  By
1202
   * default, only visible, displayable, accepted components
1203
   * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
1204
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1205
   * <code>Window</code>s and lightweight components are judged
1206
   * to be unacceptable by default.  See the
1207
   * <code>DefaultFocusTraversalPolicy</code> for more details.
1208
   *
1209
   * @param comp the component prior to the one which will
1210
   *        become the focus, following execution of this method.
1211
   * @see DefaultFocusTraversalPolicy
1212
   */
1213
  public abstract void focusNextComponent(Component comp);
1214
 
1215
  /**
1216
   * Moves the current focus to the previous component, prior to
1217
   * comp, based on the current focus traversal policy.  By
1218
   * default, only visible, displayable, accepted components
1219
   * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
1220
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1221
   * <code>Window</code>s and lightweight components are judged
1222
   * to be unacceptable by default.  See the
1223
   * <code>DefaultFocusTraversalPolicy</code> for more details.
1224
   *
1225
   * @param comp the component following the one which will
1226
   *        become the focus, following execution of this method.
1227
   * @see DefaultFocusTraversalPolicy
1228
   */
1229
  public abstract void focusPreviousComponent(Component comp);
1230
 
1231
  /**
1232
   * Moves the current focus upwards by one focus cycle.
1233
   * Both the current focus owner and current focus cycle root
1234
   * become the focus cycle root of the supplied component.
1235
   * However, in the case of a <code>Window</code>, the default
1236
   * focus component becomes the focus owner and the focus cycle
1237
   * root is not changed.
1238
   *
1239
   * @param comp the component used as part of the focus traversal.
1240
   */
1241
  public abstract void upFocusCycle(Component comp);
1242
 
1243
  /**
1244
   * Moves the current focus downwards by one focus cycle.
1245
   * If the supplied container is a focus cycle root, then this
1246
   * becomes the current focus cycle root and the focus goes
1247
   * to the default component of the specified container.
1248
   * Nothing happens for non-focus cycle root containers.
1249
   *
1250
   * @param cont the container used as part of the focus traversal.
1251
   */
1252
  public abstract void downFocusCycle(Container cont);
1253
 
1254
  /**
1255
   * Moves the current focus to the next component, based on the
1256
   * current focus traversal policy.  By default, only visible,
1257
   * displayable, accepted component can receive focus.
1258
   * <code>Canvas</code>es, <code>Panel</code>s,
1259
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1260
   * <code>Window</code>s and lightweight components are judged
1261
   * to be unacceptable by default.  See the
1262
   * <code>DefaultFocusTraversalPolicy</code> for more details.
1263
   *
1264
   * @see DefaultFocusTraversalPolicy
1265
   */
1266
  public final void focusNextComponent()
1267
  {
1268
    focusNextComponent (null);
1269
  }
1270
 
1271
  /**
1272
   * Moves the current focus to the previous component, based on the
1273
   * current focus traversal policy.  By default, only visible,
1274
   * displayable, accepted component can receive focus.
1275
   * <code>Canvas</code>es, <code>Panel</code>s,
1276
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1277
   * <code>Window</code>s and lightweight components are judged
1278
   * to be unacceptable by default.  See the
1279
   * <code>DefaultFocusTraversalPolicy</code> for more details.
1280
   *
1281
   * @see DefaultFocusTraversalPolicy
1282
   */
1283
  public final void focusPreviousComponent()
1284
  {
1285
    focusPreviousComponent (null);
1286
  }
1287
 
1288
  /**
1289
   * Moves the current focus upwards by one focus cycle,
1290
   * so that the new focus owner is the focus cycle root
1291
   * of the current owner.  The current focus cycle root then
1292
   * becomes the focus cycle root of the new focus owner.
1293
   * However, in the case of the focus cycle root of the
1294
   * current focus owner being a <code>Window</code>, the default
1295
   * component of this window becomes the focus owner and the
1296
   * focus cycle root is not changed.
1297
   */
1298
  public final void upFocusCycle()
1299
  {
1300
    upFocusCycle (null);
1301
  }
1302
 
1303
  /**
1304
   * Moves the current focus downwards by one focus cycle,
1305
   * iff the current focus cycle root is a <code>Container</code>.
1306
   * Usually, the new focus owner is set to the default component
1307
   * of the container and the current focus cycle root is set
1308
   * to the current focus owner.  Nothing occurs if the current
1309
   * focus cycle root is not a container.
1310
   */
1311
  public final void downFocusCycle()
1312
  {
1313
    Component focusOwner = getGlobalFocusOwner ();
1314
    if (focusOwner instanceof Container
1315
        && ((Container) focusOwner).isFocusCycleRoot ())
1316
      downFocusCycle ((Container) focusOwner);
1317
  }
1318
 
1319
  /**
1320
   * Retrieve an object from one of the global object {@link
1321
   * java.util.Map}s, if the object was set by the a thread in the
1322
   * current {@link java.lang.ThreadGroup}.  Otherwise, return null.
1323
   *
1324
   * @param globalMap one of the global object Maps
1325
   *
1326
   * @return a global object set by the current ThreadGroup, or null
1327
   *
1328
   * @see #getFocusOwner()
1329
   * @see #getPermanentFocusOwner()
1330
   * @see #getFocusedWindow()
1331
   * @see #getActiveWindow()
1332
   * @see #getCurrentFocusCycleRoot()
1333
   */
1334
  private Object getObject (Map globalMap)
1335
  {
1336
    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1337
    return globalMap.get (currentGroup);
1338
  }
1339
 
1340
  /**
1341
   * Retrieve an object from one of the global object {@link
1342
   * java.util.Map}s, regardless of whether or not the object was set
1343
   * by a thread in the current {@link java.lang.ThreadGroup}.
1344
   *
1345
   * @param globalMap one of the global object Maps
1346
   *
1347
   * @return a global object set by the current ThreadGroup, or null
1348
   *
1349
   * @throws SecurityException if this is not the keyboard focus
1350
   * manager associated with the current {@link java.lang.ThreadGroup}
1351
   *
1352
   * @see #getGlobalFocusOwner()
1353
   * @see #getGlobalPermanentFocusOwner()
1354
   * @see #getGlobalFocusedWindow()
1355
   * @see #getGlobalActiveWindow()
1356
   * @see #getGlobalCurrentFocusCycleRoot()
1357
   */
1358
  private Object getGlobalObject (Map globalMap)
1359
  {
1360
    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1361
    KeyboardFocusManager managerForCallingThread
1362
      = (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
1363
 
1364
    if (this != managerForCallingThread)
1365
      throw new SecurityException ("Attempted to retrieve an object from a "
1366
                                   + "keyboard focus manager that isn't "
1367
                                   + "associated with the current thread group.");
1368
 
1369
    synchronized (globalMap)
1370
      {
1371
        Collection globalObjects = globalMap.values ();
1372
        Iterator i = globalObjects.iterator ();
1373
        Component globalObject;
1374
 
1375
        while (i.hasNext ())
1376
          {
1377
            globalObject = (Component) i.next ();
1378
            if (globalObject != null)
1379
              return globalObject;
1380
          }
1381
      }
1382
 
1383
    // No Object was found.
1384
    return null;
1385
  }
1386
 
1387
  /**
1388
   * Set an object in one of the global object {@link java.util.Map}s,
1389
   * that will be returned by subsequent calls to getGlobalObject on
1390
   * the same {@link java.util.Map}.
1391
   *
1392
   * @param globalMap one of the global object Maps
1393
   * @param newObject the object to set
1394
   * @param property the property that will change
1395
   *
1396
   * @see #setGlobalFocusOwner(Component)
1397
   * @see #setGlobalPermanentFocusOwner(Component)
1398
   * @see #setGlobalFocusedWindow(Window)
1399
   * @see #setGlobalActiveWindow(Window)
1400
   * @see #setGlobalCurrentFocusCycleRoot(Container)
1401
   */
1402
  private void setGlobalObject (Map globalMap,
1403
                                Object newObject,
1404
                                String property)
1405
  {
1406
    synchronized (globalMap)
1407
      {
1408
        // Save old object.
1409
        Object oldObject = getGlobalObject (globalMap);
1410
 
1411
        // Nullify old object.
1412
        Collection threadGroups = globalMap.keySet ();
1413
        Iterator i = threadGroups.iterator ();
1414
        while (i.hasNext ())
1415
          {
1416
            ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
1417
            if (globalMap.get (oldThreadGroup) != null)
1418
              {
1419
                globalMap.put (oldThreadGroup, null);
1420
                // There should only be one object set at a time, so
1421
                // we can short circuit.
1422
                break;
1423
              }
1424
          }
1425
 
1426
        ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1427
        firePropertyChange (property, oldObject, newObject);
1428
        try
1429
          {
1430
            fireVetoableChange (property, oldObject, newObject);
1431
            // Set new object.
1432
            globalMap.put (currentGroup, newObject);
1433
          }
1434
        catch (PropertyVetoException e)
1435
          {
1436
          }
1437
      }
1438
  }
1439
}

powered by: WebSVN 2.1.0

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