Source for java.awt.KeyboardFocusManager

   1: /* 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: }