source: trunk/gcc/libjava/java/awt/KeyboardFocusManager.java

Last change on this file was 1389, checked in by bird, 21 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.6 KB
Line 
1/* KeyboardFocusManager.java -- manage component focusing via the keyboard
2 Copyright (C) 2002 Free Software Foundation
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38
39package java.awt;
40
41import java.awt.event.KeyEvent;
42import java.beans.PropertyChangeListener;
43import java.beans.PropertyChangeSupport;
44import java.beans.PropertyVetoException;
45import java.beans.VetoableChangeListener;
46import java.beans.VetoableChangeSupport;
47import java.util.ArrayList;
48import java.util.Collections;
49import java.util.HashSet;
50import java.util.Iterator;
51import java.util.List;
52import java.util.Set;
53
54/**
55 *
56 * @author Eric Blake <ebb9@email.byu.edu>
57 * @since 1.4
58 * @status partially updated to 1.4, needs documentation.
59 */
60public abstract class KeyboardFocusManager
61 implements KeyEventDispatcher, KeyEventPostProcessor
62{
63 public static final int FORWARD_TRAVERSAL_KEYS = 0;
64 public static final int BACKWARD_TRAVERSAL_KEYS = 1;
65 public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
66 public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
67
68 private static final Set DEFAULT_FORWARD_KEYS;
69 private static final Set DEFAULT_BACKWARD_KEYS;
70 static
71 {
72 Set s = new HashSet();
73 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
74 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
75 KeyEvent.CTRL_DOWN_MASK));
76 DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
77 s = new HashSet();
78 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
79 KeyEvent.SHIFT_DOWN_MASK));
80 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
81 KeyEvent.SHIFT_DOWN_MASK
82 | KeyEvent.CTRL_DOWN_MASK));
83 DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
84 }
85
86 private static KeyboardFocusManager current
87 = new DefaultKeyboardFocusManager();
88
89 // XXX Not implemented correctly. I think a good implementation here may
90 // be to have permanentFocusOwner be null, and fall back to focusOwner,
91 // unless a temporary focus change is in effect.
92 private static Component focusOwner;
93 private static Component permanentFocusOwner;
94
95 private static Window focusedWindow;
96 private static Window activeWindow;
97 private static Container focusCycleRoot;
98
99 private FocusTraversalPolicy defaultPolicy;
100 private Set[] defaultFocusKeys = new Set[] {
101 DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
102 Collections.EMPTY_SET, Collections.EMPTY_SET
103 };
104
105 private final PropertyChangeSupport propertyChangeSupport
106 = new PropertyChangeSupport(this);
107 private final VetoableChangeSupport vetoableChangeSupport
108 = new VetoableChangeSupport(this);
109 private final ArrayList keyEventDispatchers = new ArrayList();
110 private final ArrayList keyEventPostProcessors = new ArrayList();
111
112
113
114 public KeyboardFocusManager()
115 {
116 }
117
118 public static KeyboardFocusManager getCurrentKeyboardFocusManager()
119 {
120 // XXX Need a way to divide this into contexts.
121 return current;
122 }
123
124 public static void setCurrentKeyboardFocusManager(KeyboardFocusManager m)
125 {
126 SecurityManager sm = System.getSecurityManager();
127 if (sm != null)
128 sm.checkPermission(new AWTPermission("replaceKeyboardFocusManager"));
129 // XXX Need a way to divide this into contexts.
130 current = m == null ? new DefaultKeyboardFocusManager() : m;
131 }
132
133 public Component getFocusOwner()
134 {
135 // XXX Need an easy way to test if this thread is in the context of the
136 // global focus owner, to avoid creating the exception in the first place.
137 try
138 {
139 return getGlobalFocusOwner();
140 }
141 catch (SecurityException e)
142 {
143 return null;
144 }
145 }
146
147 protected Component getGlobalFocusOwner()
148 {
149 // XXX Need a way to test if this thread is in the context of the focus
150 // owner, and throw a SecurityException if that is the case.
151 // XXX Implement.
152 return focusOwner;
153 }
154
155 protected void setGlobalFocusOwner(Component owner)
156 {
157 // XXX Should this send focus events to the components involved?
158 if (owner == null || owner.focusable)
159 {
160 firePropertyChange("focusOwner", focusOwner, owner);
161 try
162 {
163 fireVetoableChange("focusOwner", focusOwner, owner);
164 focusOwner = owner;
165 }
166 catch (PropertyVetoException e)
167 {
168 }
169 }
170 }
171
172 public void clearGlobalFocusOwner()
173 {
174 // XXX Is this enough?
175 setGlobalFocusOwner(null);
176 }
177
178 public Component getPermanentFocusOwner()
179 {
180 // XXX Need an easy way to test if this thread is in the context of the
181 // global focus owner, to avoid creating the exception in the first place.
182 try
183 {
184 return getGlobalPermanentFocusOwner();
185 }
186 catch (SecurityException e)
187 {
188 return null;
189 }
190 }
191
192 protected Component getGlobalPermanentFocusOwner()
193 {
194 // XXX Need a way to test if this thread is in the context of the focus
195 // owner, and throw a SecurityException if that is the case.
196 // XXX Implement.
197 return permanentFocusOwner == null ? focusOwner : permanentFocusOwner;
198 }
199
200 protected void setGlobalPermanentFocusOwner(Component focusOwner)
201 {
202 // XXX Should this send focus events to the components involved?
203 if (focusOwner == null || focusOwner.focusable)
204 {
205 firePropertyChange("permanentFocusOwner", permanentFocusOwner,
206 focusOwner);
207 try
208 {
209 fireVetoableChange("permanentFocusOwner", permanentFocusOwner,
210 focusOwner);
211 permanentFocusOwner = focusOwner;
212 }
213 catch (PropertyVetoException e)
214 {
215 }
216 }
217 }
218
219 public Window getFocusedWindow()
220 {
221 // XXX Need an easy way to test if this thread is in the context of the
222 // global focus owner, to avoid creating the exception in the first place.
223 try
224 {
225 return getGlobalFocusedWindow();
226 }
227 catch (SecurityException e)
228 {
229 return null;
230 }
231 }
232
233 protected Window getGlobalFocusedWindow()
234 {
235 // XXX Need a way to test if this thread is in the context of the focus
236 // owner, and throw a SecurityException if that is the case.
237 // XXX Implement.
238 return focusedWindow;
239 }
240
241 protected void setGlobalFocusedWindow(Window window)
242 {
243 // XXX Should this send focus events to the windows involved?
244 if (window == null || window.focusable)
245 {
246 firePropertyChange("focusedWindow", focusedWindow, window);
247 try
248 {
249 fireVetoableChange("focusedWindow", focusedWindow, window);
250 focusedWindow = window;
251 }
252 catch (PropertyVetoException e)
253 {
254 }
255 }
256 }
257
258 public Window getActiveWindow()
259 {
260 // XXX Need an easy way to test if this thread is in the context of the
261 // global focus owner, to avoid creating the exception in the first place.
262 try
263 {
264 return getGlobalActiveWindow();
265 }
266 catch (SecurityException e)
267 {
268 return null;
269 }
270 }
271
272 protected Window getGlobalActiveWindow()
273 {
274 // XXX Need a way to test if this thread is in the context of the focus
275 // owner, and throw a SecurityException if that is the case.
276 // XXX Implement.
277 return activeWindow;
278 }
279
280 protected void setGlobalActiveWindow(Window window)
281 {
282 // XXX Should this send focus events to the windows involved?
283 firePropertyChange("activeWindow", activeWindow, window);
284 try
285 {
286 fireVetoableChange("activeWindow", activeWindow, window);
287 activeWindow = window;
288 }
289 catch (PropertyVetoException e)
290 {
291 }
292 }
293
294 public FocusTraversalPolicy getDefaultFocusTraversalPolicy()
295 {
296 if (defaultPolicy == null)
297 defaultPolicy = new DefaultFocusTraversalPolicy();
298 return defaultPolicy;
299 }
300
301 public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy policy)
302 {
303 if (policy == null)
304 throw new IllegalArgumentException();
305 firePropertyChange("defaultFocusTraversalPolicy", defaultPolicy, policy);
306 defaultPolicy = policy;
307 }
308
309 public void setDefaultFocusTraversalKeys(int id, Set keystrokes)
310 {
311 if (keystrokes == null)
312 throw new IllegalArgumentException();
313 Set sa;
314 Set sb;
315 Set sc;
316 String type;
317 switch (id)
318 {
319 case FORWARD_TRAVERSAL_KEYS:
320 sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
321 sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
322 sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
323 type = "forwardDefaultFocusTraversalKeys";
324 break;
325 case BACKWARD_TRAVERSAL_KEYS:
326 sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
327 sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
328 sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
329 type = "backwardDefaultFocusTraversalKeys";
330 break;
331 case UP_CYCLE_TRAVERSAL_KEYS:
332 sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
333 sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
334 sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
335 type = "upCycleDefaultFocusTraversalKeys";
336 break;
337 case DOWN_CYCLE_TRAVERSAL_KEYS:
338 sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
339 sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
340 sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
341 type = "downCycleDefaultFocusTraversalKeys";
342 break;
343 default:
344 throw new IllegalArgumentException();
345 }
346 int i = keystrokes.size();
347 Iterator iter = keystrokes.iterator();
348 while (--i >= 0)
349 {
350 Object o = iter.next();
351 if (! (o instanceof AWTKeyStroke)
352 || sa.contains(o) || sb.contains(o) || sc.contains(o)
353 || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
354 throw new IllegalArgumentException();
355 }
356 keystrokes = Collections.unmodifiableSet(new HashSet(keystrokes));
357 firePropertyChange(type, defaultFocusKeys[id], keystrokes);
358 defaultFocusKeys[id] = keystrokes;
359 }
360
361 public Set getDefaultFocusTraversalKeys(int id)
362 {
363 if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
364 throw new IllegalArgumentException();
365 return defaultFocusKeys[id];
366 }
367
368 public Container getCurrentFocusCycleRoot()
369 {
370 // XXX Need an easy way to test if this thread is in the context of the
371 // global focus owner, to avoid creating the exception in the first place.
372 try
373 {
374 return getGlobalCurrentFocusCycleRoot();
375 }
376 catch (SecurityException e)
377 {
378 return null;
379 }
380 }
381
382 protected Container getGlobalCurrentFocusCycleRoot()
383 {
384 // XXX Need a way to test if this thread is in the context of the focus
385 // owner, and throw a SecurityException if that is the case.
386 // XXX Implement.
387 return focusCycleRoot;
388 }
389
390 protected void setGlobalCurrentFocusCycleRoot(Container cycleRoot)
391 {
392 firePropertyChange("currentFocusCycleRoot", focusCycleRoot, cycleRoot);
393 focusCycleRoot = cycleRoot;
394 }
395
396 public void addPropertyChangeListener(PropertyChangeListener l)
397 {
398 if (l != null)
399 propertyChangeSupport.addPropertyChangeListener(l);
400 }
401
402 public void removePropertyChangeListener(PropertyChangeListener l)
403 {
404 if (l != null)
405 propertyChangeSupport.removePropertyChangeListener(l);
406 }
407
408 public PropertyChangeListener[] getPropertyChangeListeners()
409 {
410 return propertyChangeSupport.getPropertyChangeListeners();
411 }
412
413 public void addPropertyChangeListener(String name, PropertyChangeListener l)
414 {
415 if (l != null)
416 propertyChangeSupport.addPropertyChangeListener(name, l);
417 }
418
419 public void removePropertyChangeListener(String name,
420 PropertyChangeListener l)
421 {
422 if (l != null)
423 propertyChangeSupport.removePropertyChangeListener(name, l);
424 }
425
426 public PropertyChangeListener[] getPropertyChangeListeners(String name)
427 {
428 return propertyChangeSupport.getPropertyChangeListeners(name);
429 }
430
431 protected void firePropertyChange(String name, Object o, Object n)
432 {
433 propertyChangeSupport.firePropertyChange(name, o, n);
434 }
435
436 public void addVetoableChangeListener(VetoableChangeListener l)
437 {
438 if (l != null)
439 vetoableChangeSupport.addVetoableChangeListener(l);
440 }
441
442 public void removeVetoableChangeListener(VetoableChangeListener l)
443 {
444 if (l != null)
445 vetoableChangeSupport.removeVetoableChangeListener(l);
446 }
447
448 public VetoableChangeListener[] getVetoableChangeListeners()
449 {
450 return vetoableChangeSupport.getVetoableChangeListeners();
451 }
452
453 public void addVetoableChangeListener(String name, VetoableChangeListener l)
454 {
455 if (l != null)
456 vetoableChangeSupport.addVetoableChangeListener(name, l);
457 }
458
459 public void removeVetoableChangeListener(String name,
460 VetoableChangeListener l)
461 {
462 if (l != null)
463 vetoableChangeSupport.removeVetoableChangeListener(name, l);
464 }
465
466 public VetoableChangeListener[] getVetoableChangeListeners(String name)
467 {
468 return vetoableChangeSupport.getVetoableChangeListeners(name);
469 }
470
471 protected void fireVetoableChange(String name, Object o, Object n)
472 throws PropertyVetoException
473 {
474 vetoableChangeSupport.fireVetoableChange(name, o, n);
475 }
476
477 public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
478 {
479 if (dispatcher != null)
480 keyEventDispatchers.add(dispatcher);
481 }
482
483 public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
484 {
485 keyEventDispatchers.remove(dispatcher);
486 }
487
488 protected List getKeyEventDispatchers()
489 {
490 return (List) keyEventDispatchers.clone();
491 }
492
493 public void addKeyEventPostProcessor(KeyEventPostProcessor postProcessor)
494 {
495 if (postProcessor != null)
496 keyEventPostProcessors.add(postProcessor);
497 }
498
499 public void removeKeyEventPostProcessor(KeyEventPostProcessor postProcessor)
500 {
501 keyEventPostProcessors.remove(postProcessor);
502 }
503
504 protected List getKeyEventPostProcessors()
505 {
506 return (List) keyEventPostProcessors.clone();
507 }
508
509 public abstract boolean dispatchEvent(AWTEvent e);
510
511 public final void redispatchEvent(Component target, AWTEvent e)
512 {
513 throw new Error("not implemented");
514 }
515
516 public abstract boolean dispatchKeyEvent(KeyEvent e);
517
518 public abstract boolean postProcessKeyEvent(KeyEvent e);
519
520 public abstract void processKeyEvent(Component focused, KeyEvent e);
521
522 protected abstract void enqueueKeyEvents(long after, Component untilFocused);
523
524 protected abstract void dequeueKeyEvents(long after, Component untilFocused);
525
526 protected abstract void discardKeyEvents(Component comp);
527
528 public abstract void focusNextComponent(Component comp);
529
530 public abstract void focusPreviousComponent(Component comp);
531
532 public abstract void upFocusCycle(Component comp);
533
534 public abstract void downFocusCycle(Container cont);
535
536 public final void focusNextComponent()
537 {
538 focusNextComponent(focusOwner);
539 }
540
541 public final void focusPreviousComponent()
542 {
543 focusPreviousComponent(focusOwner);
544 }
545
546 public final void upFocusCycle()
547 {
548 upFocusCycle(focusOwner);
549 }
550
551 public final void downFocusCycle()
552 {
553 if (focusOwner instanceof Container
554 && ((Container) focusOwner).isFocusCycleRoot())
555 downFocusCycle((Container) focusOwner);
556 }
557} // class KeyboardFocusManager
Note: See TracBrowser for help on using the repository browser.