Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 482a77e1123cc458099bb13beb5d28bfd6786ea8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.keys;

import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.eclipse.ui.internal.util.Util;

/**
 * <p>
 * A <code>KeyStroke</code> is defined as an optional set of modifier keys
 * followed optionally by a natural key. A <code>KeyStroke</code> is said to be
 * complete if it contains a natural key. A natural key is any Unicode character
 * (e.g., "backspace", etc.), any character belonging to a natural language
 * (e.g., "A", "1", "[", etc.), or any special control character specific to
 * computers (e.g., "F10", "PageUp", etc.).
 * </p>
 * <p>
 * All <code>KeyStroke</code> objects have a formal string representation
 * available via the <code>toString()</code> method. There are a number of
 * methods to get instances of <code>KeyStroke</code> objects, including one
 * which can parse this formal string representation.
 * </p>
 * <p>
 * All <code>KeyStroke</code> objects, via the <code>format()</code> method,
 * provide a version of their formal string representation translated by
 * platform and locale, suitable for display to a user.
 * </p>
 * <p>
 * <code>KeyStroke</code> objects are immutable. Clients are not permitted to
 * extend this class.
 * </p>
 *
 * @deprecated Please use org.eclipse.jface.bindings.keys.KeyStroke
 * @since 3.0
 * @see org.eclipse.ui.keys.ModifierKey
 * @see org.eclipse.ui.keys.NaturalKey
 */
@Deprecated
public final class KeyStroke implements Comparable {

	/**
	 * The delimiter between multiple keys in a single key strokes -- expressed in
	 * the formal key stroke grammar. This is not to be displayed to the user. It is
	 * only intended as an internal representation.
	 */
	public static final String KEY_DELIMITER = "\u002B"; //$NON-NLS-1$

	/**
	 * An internal constant used only in this object's hash code algorithm.
	 */
	private static final int HASH_FACTOR = 89;

	/**
	 * An internal constant used only in this object's hash code algorithm.
	 */
	private static final int HASH_INITIAL = KeyStroke.class.getName().hashCode();

	/**
	 * The set of delimiters for <code>Key</code> objects allowed during parsing of
	 * the formal string representation.
	 */
	public static final String KEY_DELIMITERS = KEY_DELIMITER;

	/**
	 * Gets an instance of <code>KeyStroke</code> given a single modifier key and a
	 * natural key.
	 *
	 * @param modifierKey a modifier key. Must not be <code>null</code>.
	 * @param naturalKey  the natural key. May be <code>null</code>.
	 * @return a key stroke. Guaranteed not to be <code>null</code>.
	 */
	public static KeyStroke getInstance(ModifierKey modifierKey, NaturalKey naturalKey) {
		if (modifierKey == null) {
			throw new NullPointerException();
		}

		return new KeyStroke(new TreeSet(Collections.singletonList(modifierKey)), naturalKey);
	}

	/**
	 * Gets an instance of <code>KeyStroke</code> given an array of modifier keys
	 * and a natural key.
	 *
	 * @param modifierKeys the array of modifier keys. This array may be empty, but
	 *                     it must not be <code>null</code>. If this array is not
	 *                     empty, it must not contain <code>null</code> elements.
	 * @param naturalKey   the natural key. May be <code>null</code>.
	 * @return a key stroke. Guaranteed not to be <code>null</code>.
	 */
	public static KeyStroke getInstance(ModifierKey[] modifierKeys, NaturalKey naturalKey) {
		Util.assertInstance(modifierKeys, ModifierKey.class);
		return new KeyStroke(new TreeSet(Arrays.asList(modifierKeys)), naturalKey);
	}

	/**
	 * Gets an instance of <code>KeyStroke</code> given a natural key.
	 *
	 * @param naturalKey the natural key. May be <code>null</code>.
	 * @return a key stroke. This key stroke will have no modifier keys. Guaranteed
	 *         not to be <code>null</code>.
	 */
	public static KeyStroke getInstance(NaturalKey naturalKey) {
		return new KeyStroke(Util.EMPTY_SORTED_SET, naturalKey);
	}

	/**
	 * Gets an instance of <code>KeyStroke</code> given a set of modifier keys and a
	 * natural key.
	 *
	 * @param modifierKeys the set of modifier keys. This set may be empty, but it
	 *                     must not be <code>null</code>. If this set is not empty,
	 *                     it must only contain instances of
	 *                     <code>ModifierKey</code>.
	 * @param naturalKey   the natural key. May be <code>null</code>.
	 * @return a key stroke. Guaranteed not to be <code>null</code>.
	 */
	public static KeyStroke getInstance(SortedSet modifierKeys, NaturalKey naturalKey) {
		return new KeyStroke(modifierKeys, naturalKey);
	}

	/**
	 * Gets an instance of <code>KeyStroke</code> by parsing a given a formal string
	 * representation.
	 *
	 * @param string the formal string representation to parse.
	 * @return a key stroke. Guaranteed not to be <code>null</code>.
	 * @throws ParseException if the given formal string representation could not be
	 *                        parsed to a valid key stroke.
	 */
	public static KeyStroke getInstance(String string) throws ParseException {
		if (string == null) {
			throw new NullPointerException();
		}

		SortedSet modifierKeys = new TreeSet();
		NaturalKey naturalKey = null;
		StringTokenizer stringTokenizer = new StringTokenizer(string, KEY_DELIMITERS, true);
		int i = 0;

		while (stringTokenizer.hasMoreTokens()) {
			String token = stringTokenizer.nextToken();

			if (i % 2 == 0) {
				if (stringTokenizer.hasMoreTokens()) {
					token = token.toUpperCase(Locale.ENGLISH);
					ModifierKey modifierKey = (ModifierKey) ModifierKey.modifierKeysByName.get(token);

					if (modifierKey == null || !modifierKeys.add(modifierKey)) {
						throw new ParseException(
								"Cannot create key stroke with duplicate or non-existent modifier key: " //$NON-NLS-1$
										+ token);
					}
				} else if (token.length() == 1) {
					naturalKey = CharacterKey.getInstance(token.charAt(0));
					break;
				} else {
					token = token.toUpperCase(Locale.ENGLISH);
					naturalKey = (NaturalKey) CharacterKey.characterKeysByName.get(token);

					if (naturalKey == null) {
						naturalKey = (NaturalKey) SpecialKey.specialKeysByName.get(token);
					}

					if (naturalKey == null) {
						throw new ParseException("Cannot create key stroke with invalid natural key: " //$NON-NLS-1$
								+ token);
					}
				}
			}

			i++;
		}

		try {
			return new KeyStroke(modifierKeys, naturalKey);
		} catch (Throwable t) {
			throw new ParseException("Cannot create key stroke with " //$NON-NLS-1$
					+ modifierKeys + " and " + naturalKey); //$NON-NLS-1$
		}
	}

	/**
	 * The cached hash code for this object. Because <code>KeyStroke</code> objects
	 * are immutable, their hash codes need only to be computed once. After the
	 * first call to <code>hashCode()</code>, the computed value is cached here for
	 * all subsequent calls.
	 */
	private transient int hashCode;

	/**
	 * A flag to determine if the <code>hashCode</code> field has already been
	 * computed.
	 */
	private transient boolean hashCodeComputed;

	/**
	 * The set of modifier keys for this key stroke.
	 */
	private SortedSet modifierKeys;

	/**
	 * The set of modifier keys for this key stroke in the form of an array. Used
	 * internally by <code>int compareTo(Object)</code>.
	 */
	private transient ModifierKey[] modifierKeysAsArray;

	/**
	 * The natural key for this key stroke.
	 */
	private NaturalKey naturalKey;

	/**
	 * Constructs an instance of <code>KeyStroke</code> given a set of modifier keys
	 * and a natural key.
	 *
	 * @param modifierKeys the set of modifier keys. This set may be empty, but it
	 *                     must not be <code>null</code>. If this set is not empty,
	 *                     it must only contain instances of
	 *                     <code>ModifierKey</code>.
	 * @param naturalKey   the natural key. May be <code>null</code>.
	 */
	private KeyStroke(SortedSet modifierKeys, NaturalKey naturalKey) {
		this.modifierKeys = Util.safeCopy(modifierKeys, ModifierKey.class);
		this.naturalKey = naturalKey;
		this.modifierKeysAsArray = (ModifierKey[]) this.modifierKeys.toArray(new ModifierKey[this.modifierKeys.size()]);
	}

	/**
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Object object) {
		KeyStroke castedObject = (KeyStroke) object;
		int compareTo = Util.compare(modifierKeysAsArray, castedObject.modifierKeysAsArray);

		if (compareTo == 0) {
			compareTo = Util.compare(naturalKey, castedObject.naturalKey);
		}

		return compareTo;
	}

	@Override
	public boolean equals(Object object) {
		if (!(object instanceof KeyStroke)) {
			return false;
		}

		KeyStroke castedObject = (KeyStroke) object;

		if (!modifierKeys.equals(castedObject.modifierKeys)) {
			return false;
		}
		return Util.equals(naturalKey, castedObject.naturalKey);
	}

	/**
	 * Formats this key stroke into the current default look.
	 *
	 * @return A string representation for this key stroke using the default look;
	 *         never <code>null</code>.
	 */
	public String format() {
		return KeyFormatterFactory.getDefault().format(this);
	}

	/**
	 * Returns the set of modifier keys for this key stroke.
	 *
	 * @return the set of modifier keys. This set may be empty, but is guaranteed
	 *         not to be <code>null</code>. If this set is not empty, it is
	 *         guaranteed to only contain instances of <code>ModifierKey</code>.
	 */
	public Set getModifierKeys() {
		return Collections.unmodifiableSet(modifierKeys);
	}

	/**
	 * Returns the natural key for this key stroke.
	 *
	 * @return the natural key. May be <code>null</code>.
	 */
	public NaturalKey getNaturalKey() {
		return naturalKey;
	}

	@Override
	public int hashCode() {
		if (!hashCodeComputed) {
			hashCode = HASH_INITIAL;
			hashCode = hashCode * HASH_FACTOR + modifierKeys.hashCode();
			hashCode = hashCode * HASH_FACTOR + Util.hashCode(naturalKey);
			hashCodeComputed = true;
		}

		return hashCode;
	}

	/**
	 * Returns whether or not this key stroke is complete. Key strokes are complete
	 * iff they have a natural key which is not <code>null</code>.
	 *
	 * @return <code>true</code>, iff the key stroke is complete.
	 */
	public boolean isComplete() {
		return naturalKey != null;
	}

	/**
	 * Returns the formal string representation for this key stroke.
	 *
	 * @return The formal string representation for this key stroke. Guaranteed not
	 *         to be <code>null</code>.
	 */
	@Override
	public String toString() {
		return KeyFormatterFactory.getFormalKeyFormatter().format(this);
	}
}

Back to the top