KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > misc > AcceleratorHook


1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.misc;
12
13 import org.eclipse.jface.action.*;
14 import org.eclipse.swt.SWT;
15 import org.eclipse.swt.widgets.*;
16 import java.util.*;
17
18 /**
19  * A strategy for hooking accelerators on a control.
20  * <p>
21  * In SWT an accelerator which is defined in a shell menu is global. If
22  * enabled, it will always be executed regardless of the current focus control or its
23  * abilities. This creates a problem where the focus control has an equivalent
24  * key sequence. For example, if <code>Ctrl+C</code> is defined as the accelerator
25  * for <code>Copy</code> at the shell level it will override the same key sequence
26  * in a text widget within the shell, thus breaking the text widget.
27  * </p><p>
28  * To avoid this problem an <code>AcceleratorHook</code> may be used to define
29  * the accelerators locally on each control rather than globally on the shell.
30  * The accelerators defined in an <code>AcceleratorHook</code> are only operational
31  * when the control has focus.
32  * </p><p>
33  * To use this class, instantiate an instance for a particular control and register
34  * each action which has an accelerator. If the accelerator is pressed the action will
35  * be invoked.
36  * </p><p>
37  * This class may be instantiated; it is not intended to be subclassed.
38  * </p>
39  */

40 public class AcceleratorHook implements Listener {
41     private ArrayList actionList;
42     
43     private class ActionItem {
44         public ActionItem(int accel, IAction act) {
45             accelerator = accel;
46             action = act;
47         }
48         public int accelerator;
49         public IAction action;
50     }
51
52     private class FakeAction extends Action {
53         public FakeAction(String JavaDoc name) {
54             super(name);
55         }
56         public void run() {
57         }
58     }
59 /**
60  * AcceleratorHook constructor comment.
61  */

62 public AcceleratorHook(Control ctrl) {
63     actionList = new ArrayList(5);
64     ctrl.addListener(SWT.KeyDown, this);
65     ctrl.addListener(SWT.KeyUp, this);
66 }
67 /**
68  * Adds an action to the control. If the action accelerator is pressed
69  * the action will be run.
70  * <p>
71  * The accelerator for the action is derived from the action.
72  * </p>
73  *
74  * @param action an action with unique accelerator
75  */

76 public void add(IAction action) {
77     if (action.getAccelerator() == 0)
78         return;
79     actionList.add(new ActionItem(action.getAccelerator(), action));
80 }
81 /**
82  * Adds an action to the control with a particular accelerator.
83  * If the accelerator is pressed the action will be run.
84  * <p>
85  * The accelerator for the action is derived from <code>strAccel</code>
86  * string. The content of this string must conform to the standard JFace
87  * conventions for accelerator declaration. For more information see
88  * the <code>org.eclipse.jface.action.Action</code> class.
89  * </p>
90  *
91  * @param action an action
92  * @param strAccel the action accelerator
93  * @see org.eclipse.jface.action.Action
94  */

95 public void add(IAction action, String JavaDoc strAccel) {
96     Action fakeAction = new FakeAction("Fake\t"+strAccel);//$NON-NLS-1$
97
if (fakeAction.getAccelerator() == 0)
98         return;
99     actionList.add(new ActionItem(fakeAction.getAccelerator(), action));
100 }
101 /**
102  * Returns the first item which represents the action.
103  *
104  * @returns the first item to match, or <code>null</code>.
105  */

106 private ActionItem findItem(IAction action) {
107     Iterator iter = actionList.iterator();
108     while (iter.hasNext()) {
109         ActionItem item = (ActionItem)iter.next();
110         if (item.action == action)
111             return item;
112     }
113     return null;
114 }
115 /**
116  * Returns the first item with an accelerator which maches
117  * the key event.
118  *
119  * @returns the first item to match, or <code>null</code>.
120  */

121 private ActionItem findItem(Event e) {
122     // Map event to accel.
123
int accel = getAccel(e);
124     if (accel == 0)
125         return null;
126     
127     // Map accelerator to item.
128
Iterator iter = actionList.iterator();
129     while (iter.hasNext()) {
130         ActionItem item = (ActionItem)iter.next();
131         // System.out.println("Accel = " + Integer.toString(item.accelerator, 16));
132
if (item.accelerator == accel)
133             return item;
134     }
135     return null;
136 }
137 /**
138  * Convert a key event to an accelerator.
139  *
140  * @param e the key event
141  * @return the int accelerator value
142  */

143 private int getAccel(Event e) {
144     // Debug.
145
/*
146     System.out.println("KeyEvent");
147     System.out.println("\tChar = " + Integer.toString((int)e.character, 16));
148     System.out.println("\tKeyCode = " + Integer.toString(e.keyCode, 16));
149     System.out.println("\tState Mask = " + Integer.toString(e.stateMask, 16));
150     */

151     
152     // Real work.
153
int key = (int)Character.toUpperCase(e.character);
154     int mods = 0;
155     if ((e.stateMask & SWT.ALT) > 0)
156         mods |= SWT.ALT;
157     if ((e.stateMask & SWT.SHIFT) > 0)
158         mods |= SWT.SHIFT;
159     if ((e.stateMask & SWT.CTRL) > 0) {
160         mods |= SWT.CTRL;
161         key = key + 'A' - 1; // Convert unicode to char.
162
}
163     int accel = key | mods | e.keyCode;
164
165     // Debug
166
/*
167     System.out.println("Accel = " + Integer.toString(accel, 16));
168     */

169     return accel;
170 }
171
172 /**
173  * Notifies that a key has been pressed on the system keyboard.
174  * <p>
175  * This method is a callback from the target control for this hook.
176  * Other clients are not expected to call this method.
177  * </p>
178  *
179  * @param e an event containing information about the key press
180  */

181 public void handleEvent(Event event) {
182     ActionItem item = findItem(event);
183     if (item != null)
184         item.action.runWithEvent(event);
185 }
186
187 /**
188  * Removes an action from the hook. Does nothing if the action is
189  * not found.
190  *
191  * @param action an action
192  */

193 public void remove(IAction action) {
194     ActionItem item = findItem(action);
195     if (item != null)
196         actionList.remove(item);
197 }
198 }
199
Popular Tags