aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/awt/KeyboardFocusManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/awt/KeyboardFocusManager.java')
-rw-r--r--libjava/java/awt/KeyboardFocusManager.java556
1 files changed, 556 insertions, 0 deletions
diff --git a/libjava/java/awt/KeyboardFocusManager.java b/libjava/java/awt/KeyboardFocusManager.java
new file mode 100644
index 0000000..2680894
--- /dev/null
+++ b/libjava/java/awt/KeyboardFocusManager.java
@@ -0,0 +1,556 @@
+/* KeyboardFocusManager.java -- manage component focusing via the keyboard
+ Copyright (C) 2002 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.awt;
+
+import java.awt.event.KeyEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @since 1.4
+ * @status partially updated to 1.4, needs documentation.
+ */
+public abstract class KeyboardFocusManager
+ implements KeyEventDispatcher, KeyEventPostProcessor
+{
+ public static final int FORWARD_TRAVERSAL_KEYS = 0;
+ public static final int BACKWARD_TRAVERSAL_KEYS = 1;
+ public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
+ public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
+
+ private static final Set DEFAULT_FORWARD_KEYS;
+ private static final Set DEFAULT_BACKWARD_KEYS;
+ static
+ {
+ Set s = new HashSet();
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.CTRL_DOWN_MASK));
+ DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
+ s = new HashSet();
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK));
+ s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
+ KeyEvent.SHIFT_DOWN_MASK
+ | KeyEvent.CTRL_DOWN_MASK));
+ DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
+ }
+
+ private static KeyboardFocusManager current
+ = new DefaultKeyboardFocusManager();
+
+ // XXX Not implemented correctly. I think a good implementation here may
+ // be to have permanentFocusOwner be null, and fall back to focusOwner,
+ // unless a temporary focus change is in effect.
+ private static Component focusOwner;
+ private static Component permanentFocusOwner;
+
+ private static Window focusedWindow;
+ private static Window activeWindow;
+ private static Container focusCycleRoot;
+
+ private FocusTraversalPolicy defaultPolicy;
+ private Set[] defaultFocusKeys = new Set[] {
+ DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
+ Collections.EMPTY_SET, Collections.EMPTY_SET
+ };
+
+ private final PropertyChangeSupport propertyChangeSupport
+ = new PropertyChangeSupport(this);
+ private final VetoableChangeSupport vetoableChangeSupport
+ = new VetoableChangeSupport(this);
+ private final ArrayList keyEventDispatchers = new ArrayList();
+ private final ArrayList keyEventPostProcessors = new ArrayList();
+
+
+ public KeyboardFocusManager()
+ {
+ }
+
+ public static KeyboardFocusManager getCurrentKeyboardFocusManager()
+ {
+ // XXX Need a way to divide this into contexts.
+ return current;
+ }
+
+ public static void setCurrentKeyboardFocusManager(KeyboardFocusManager m)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AWTPermission("replaceKeyboardFocusManager"));
+ // XXX Need a way to divide this into contexts.
+ current = m == null ? new DefaultKeyboardFocusManager() : m;
+ }
+
+ public Component getFocusOwner()
+ {
+ // XXX Need an easy way to test if this thread is in the context of the
+ // global focus owner, to avoid creating the exception in the first place.
+ try
+ {
+ return getGlobalFocusOwner();
+ }
+ catch (SecurityException e)
+ {
+ return null;
+ }
+ }
+
+ protected Component getGlobalFocusOwner()
+ {
+ // XXX Need a way to test if this thread is in the context of the focus
+ // owner, and throw a SecurityException if that is the case.
+ // XXX Implement.
+ return focusOwner;
+ }
+
+ protected void setGlobalFocusOwner(Component owner)
+ {
+ // XXX Should this send focus events to the components involved?
+ if (owner == null || owner.focusable)
+ {
+ firePropertyChange("focusOwner", focusOwner, owner);
+ try
+ {
+ fireVetoableChange("focusOwner", focusOwner, owner);
+ focusOwner = owner;
+ }
+ catch (PropertyVetoException e)
+ {
+ }
+ }
+ }
+
+ public void clearGlobalFocusOwner()
+ {
+ // XXX Is this enough?
+ setGlobalFocusOwner(null);
+ }
+
+ public Component getPermanentFocusOwner()
+ {
+ // XXX Need an easy way to test if this thread is in the context of the
+ // global focus owner, to avoid creating the exception in the first place.
+ try
+ {
+ return getGlobalPermanentFocusOwner();
+ }
+ catch (SecurityException e)
+ {
+ return null;
+ }
+ }
+
+ protected Component getGlobalPermanentFocusOwner()
+ {
+ // XXX Need a way to test if this thread is in the context of the focus
+ // owner, and throw a SecurityException if that is the case.
+ // XXX Implement.
+ return permanentFocusOwner == null ? focusOwner : permanentFocusOwner;
+ }
+
+ protected void setGlobalPermanentFocusOwner(Component focusOwner)
+ {
+ // XXX Should this send focus events to the components involved?
+ if (focusOwner == null || focusOwner.focusable)
+ {
+ firePropertyChange("permanentFocusOwner", permanentFocusOwner,
+ focusOwner);
+ try
+ {
+ fireVetoableChange("permanentFocusOwner", permanentFocusOwner,
+ focusOwner);
+ permanentFocusOwner = focusOwner;
+ }
+ catch (PropertyVetoException e)
+ {
+ }
+ }
+ }
+
+ public Window getFocusedWindow()
+ {
+ // XXX Need an easy way to test if this thread is in the context of the
+ // global focus owner, to avoid creating the exception in the first place.
+ try
+ {
+ return getGlobalFocusedWindow();
+ }
+ catch (SecurityException e)
+ {
+ return null;
+ }
+ }
+
+ protected Window getGlobalFocusedWindow()
+ {
+ // XXX Need a way to test if this thread is in the context of the focus
+ // owner, and throw a SecurityException if that is the case.
+ // XXX Implement.
+ return focusedWindow;
+ }
+
+ protected void setGlobalFocusedWindow(Window window)
+ {
+ // XXX Should this send focus events to the windows involved?
+ if (window == null || window.focusable)
+ {
+ firePropertyChange("focusedWindow", focusedWindow, window);
+ try
+ {
+ fireVetoableChange("focusedWindow", focusedWindow, window);
+ focusedWindow = window;
+ }
+ catch (PropertyVetoException e)
+ {
+ }
+ }
+ }
+
+ public Window getActiveWindow()
+ {
+ // XXX Need an easy way to test if this thread is in the context of the
+ // global focus owner, to avoid creating the exception in the first place.
+ try
+ {
+ return getGlobalActiveWindow();
+ }
+ catch (SecurityException e)
+ {
+ return null;
+ }
+ }
+
+ protected Window getGlobalActiveWindow()
+ {
+ // XXX Need a way to test if this thread is in the context of the focus
+ // owner, and throw a SecurityException if that is the case.
+ // XXX Implement.
+ return activeWindow;
+ }
+
+ protected void setGlobalActiveWindow(Window window)
+ {
+ // XXX Should this send focus events to the windows involved?
+ firePropertyChange("activeWindow", activeWindow, window);
+ try
+ {
+ fireVetoableChange("activeWindow", activeWindow, window);
+ activeWindow = window;
+ }
+ catch (PropertyVetoException e)
+ {
+ }
+ }
+
+ public FocusTraversalPolicy getDefaultFocusTraversalPolicy()
+ {
+ if (defaultPolicy == null)
+ defaultPolicy = new DefaultFocusTraversalPolicy();
+ return defaultPolicy;
+ }
+
+ public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy policy)
+ {
+ if (policy == null)
+ throw new IllegalArgumentException();
+ firePropertyChange("defaultFocusTraversalPolicy", defaultPolicy, policy);
+ defaultPolicy = policy;
+ }
+
+ public void setDefaultFocusTraversalKeys(int id, Set keystrokes)
+ {
+ if (keystrokes == null)
+ throw new IllegalArgumentException();
+ Set sa;
+ Set sb;
+ Set sc;
+ String type;
+ switch (id)
+ {
+ case FORWARD_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "forwardDefaultFocusTraversalKeys";
+ break;
+ case BACKWARD_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "backwardDefaultFocusTraversalKeys";
+ break;
+ case UP_CYCLE_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
+ type = "upCycleDefaultFocusTraversalKeys";
+ break;
+ case DOWN_CYCLE_TRAVERSAL_KEYS:
+ sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
+ sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
+ sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
+ type = "downCycleDefaultFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ int i = keystrokes.size();
+ Iterator iter = keystrokes.iterator();
+ while (--i >= 0)
+ {
+ Object o = iter.next();
+ if (! (o instanceof AWTKeyStroke)
+ || sa.contains(o) || sb.contains(o) || sc.contains(o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException();
+ }
+ keystrokes = Collections.unmodifiableSet(new HashSet(keystrokes));
+ firePropertyChange(type, defaultFocusKeys[id], keystrokes);
+ defaultFocusKeys[id] = keystrokes;
+ }
+
+ public Set getDefaultFocusTraversalKeys(int id)
+ {
+ if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException();
+ return defaultFocusKeys[id];
+ }
+
+ public Container getCurrentFocusCycleRoot()
+ {
+ // XXX Need an easy way to test if this thread is in the context of the
+ // global focus owner, to avoid creating the exception in the first place.
+ try
+ {
+ return getGlobalCurrentFocusCycleRoot();
+ }
+ catch (SecurityException e)
+ {
+ return null;
+ }
+ }
+
+ protected Container getGlobalCurrentFocusCycleRoot()
+ {
+ // XXX Need a way to test if this thread is in the context of the focus
+ // owner, and throw a SecurityException if that is the case.
+ // XXX Implement.
+ return focusCycleRoot;
+ }
+
+ protected void setGlobalCurrentFocusCycleRoot(Container cycleRoot)
+ {
+ firePropertyChange("currentFocusCycleRoot", focusCycleRoot, cycleRoot);
+ focusCycleRoot = cycleRoot;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.addPropertyChangeListener(l);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.removePropertyChangeListener(l);
+ }
+
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return propertyChangeSupport.getPropertyChangeListeners();
+ }
+
+ public void addPropertyChangeListener(String name, PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.addPropertyChangeListener(name, l);
+ }
+
+ public void removePropertyChangeListener(String name,
+ PropertyChangeListener l)
+ {
+ if (l != null)
+ propertyChangeSupport.removePropertyChangeListener(name, l);
+ }
+
+ public PropertyChangeListener[] getPropertyChangeListeners(String name)
+ {
+ return propertyChangeSupport.getPropertyChangeListeners(name);
+ }
+
+ protected void firePropertyChange(String name, Object o, Object n)
+ {
+ propertyChangeSupport.firePropertyChange(name, o, n);
+ }
+
+ public void addVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.addVetoableChangeListener(l);
+ }
+
+ public void removeVetoableChangeListener(VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.removeVetoableChangeListener(l);
+ }
+
+ public VetoableChangeListener[] getVetoableChangeListeners()
+ {
+ return vetoableChangeSupport.getVetoableChangeListeners();
+ }
+
+ public void addVetoableChangeListener(String name, VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.addVetoableChangeListener(name, l);
+ }
+
+ public void removeVetoableChangeListener(String name,
+ VetoableChangeListener l)
+ {
+ if (l != null)
+ vetoableChangeSupport.removeVetoableChangeListener(name, l);
+ }
+
+ public VetoableChangeListener[] getVetoableChangeListeners(String name)
+ {
+ return vetoableChangeSupport.getVetoableChangeListeners(name);
+ }
+
+ protected void fireVetoableChange(String name, Object o, Object n)
+ throws PropertyVetoException
+ {
+ vetoableChangeSupport.fireVetoableChange(name, o, n);
+ }
+
+ public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
+ {
+ if (dispatcher != null)
+ keyEventDispatchers.add(dispatcher);
+ }
+
+ public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
+ {
+ keyEventDispatchers.remove(dispatcher);
+ }
+
+ protected List getKeyEventDispatchers()
+ {
+ return (List) keyEventDispatchers.clone();
+ }
+
+ public void addKeyEventPostProcessor(KeyEventPostProcessor postProcessor)
+ {
+ if (postProcessor != null)
+ keyEventPostProcessors.add(postProcessor);
+ }
+
+ public void removeKeyEventPostProcessor(KeyEventPostProcessor postProcessor)
+ {
+ keyEventPostProcessors.remove(postProcessor);
+ }
+
+ protected List getKeyEventPostProcessors()
+ {
+ return (List) keyEventPostProcessors.clone();
+ }
+
+ public abstract boolean dispatchEvent(AWTEvent e);
+
+ public final void redispatchEvent(Component target, AWTEvent e)
+ {
+ throw new Error("not implemented");
+ }
+
+ public abstract boolean dispatchKeyEvent(KeyEvent e);
+
+ public abstract boolean postProcessKeyEvent(KeyEvent e);
+
+ public abstract void processKeyEvent(Component focused, KeyEvent e);
+
+ protected abstract void enqueueKeyEvents(long after, Component untilFocused);
+
+ protected abstract void dequeueKeyEvents(long after, Component untilFocused);
+
+ protected abstract void discardKeyEvents(Component comp);
+
+ public abstract void focusNextComponent(Component comp);
+
+ public abstract void focusPreviousComponent(Component comp);
+
+ public abstract void upFocusCycle(Component comp);
+
+ public abstract void downFocusCycle(Container cont);
+
+ public final void focusNextComponent()
+ {
+ focusNextComponent(focusOwner);
+ }
+
+ public final void focusPreviousComponent()
+ {
+ focusPreviousComponent(focusOwner);
+ }
+
+ public final void upFocusCycle()
+ {
+ upFocusCycle(focusOwner);
+ }
+
+ public final void downFocusCycle()
+ {
+ if (focusOwner instanceof Container
+ && ((Container) focusOwner).isFocusCycleRoot())
+ downFocusCycle((Container) focusOwner);
+ }
+} // class KeyboardFocusManager