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