Mercurial > projects > dwt-addons
comparison dwtx/jface/bindings/Binding.d @ 16:e0f0aaf75edd
PopupDialog, bindings and actions
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 01 Apr 2008 08:00:31 +0200 |
parents | |
children | 46a6e0e6ccd4 |
comparison
equal
deleted
inserted
replaced
15:db8940420ed8 | 16:e0f0aaf75edd |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2004, 2007 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.jface.bindings.Binding; | |
14 | |
15 import dwtx.jface.bindings.TriggerSequence; | |
16 // import java.io.BufferedWriter; | |
17 // import java.io.IOException; | |
18 // import java.io.StringWriter; | |
19 | |
20 import dwtx.core.commands.ParameterizedCommand; | |
21 import dwtx.jface.util.Util; | |
22 | |
23 import dwt.dwthelper.utils; | |
24 import tango.text.convert.Format; | |
25 | |
26 /** | |
27 * <p> | |
28 * A binding is a link between user input and the triggering of a particular | |
29 * command. The most common example of a binding is a keyboard shortcut, but | |
30 * there are also mouse and gesture bindings. | |
31 * </p> | |
32 * <p> | |
33 * Bindings are linked to particular conditions within the application. Some of | |
34 * these conditions change infrequently (e.g., locale, scheme), while some will | |
35 * tend to change quite frequently (e.g., context). This allows the bindings to | |
36 * be tailored to particular situations. For example, a set of bindings may be | |
37 * appropriate only inside a text editor. Or, perhaps, a set of bindings might | |
38 * be appropriate only for a given locale, such as bindings that coexist with | |
39 * the Input Method Editor (IME) on Chinese locales. | |
40 * </p> | |
41 * <p> | |
42 * It is also possible to remove a particular binding. This is typically done as | |
43 * part of user configuration (e.g., user changing keyboard shortcuts). However, | |
44 * it can also be helpful when trying to change a binding on a particular locale | |
45 * or platform. An "unbinding" is really just a binding with no command | |
46 * identifier. For it to unbind a particular binding, it must match that binding | |
47 * in its context identifier and scheme identifier. Subclasses (e.g., | |
48 * <code>KeyBinding</code>) may require other properties to match (e.g., | |
49 * <code>keySequence</code>). If these properties match, then this is an | |
50 * unbinding. Note: the locale and platform can be different. | |
51 * </p> | |
52 * <p> | |
53 * For example, imagine you have a key binding that looks like this: | |
54 * </p> | |
55 * <code><pre> | |
56 * KeyBinding(command, scheme, context, "Ctrl+Shift+F") | |
57 * </pre></code> | |
58 * <p> | |
59 * On GTK+, the "Ctrl+Shift+F" interferes with some native behaviour. To change | |
60 * the binding, we first unbind the "Ctrl+Shift+F" key sequence by | |
61 * assigning it a null command on the gtk platform. We then create a new binding | |
62 * that maps the command to the "Esc Ctrl+F" key sequence. | |
63 * </p> | |
64 * <code><pre> | |
65 * KeyBinding("Ctrl+Shift+F",null,scheme,context,null,gtk,null,SYSTEM) | |
66 * KeyBinding("Esc Ctrl+F",parameterizedCommand,scheme,context,null,gtk,SYSTEM) | |
67 * </pre></code> | |
68 * <p> | |
69 * Bindings are intended to be immutable objects. | |
70 * </p> | |
71 * | |
72 * @since 3.1 | |
73 */ | |
74 public abstract class Binding { | |
75 | |
76 /** | |
77 * The constant integer hash code value meaning the hash code has not yet | |
78 * been computed. | |
79 */ | |
80 private static const int HASH_CODE_NOT_COMPUTED = -1; | |
81 | |
82 /** | |
83 * A factor for computing the hash code for all key bindings. | |
84 */ | |
85 private final const int HASH_FACTOR = 89; | |
86 | |
87 /** | |
88 * The type of binding that is defined by the system (i.e., by the | |
89 * application developer). In the case of an application based on the | |
90 * Eclipse workbench, this is the registry. | |
91 */ | |
92 public static const int SYSTEM = 0; | |
93 | |
94 /** | |
95 * The type of binding that is defined by the user (i.e., by the end user of | |
96 * the application). In the case of an application based on the Eclipse | |
97 * workbench, this is the preference store. | |
98 */ | |
99 public static const int USER = 1; | |
100 | |
101 /** | |
102 * The parameterized command to which this binding applies. This value may | |
103 * be <code>null</code> if this binding is meant to "unbind" an existing | |
104 * binding. | |
105 */ | |
106 private const ParameterizedCommand command; | |
107 | |
108 /** | |
109 * The context identifier to which this binding applies. This context must | |
110 * be active before this key binding becomes active. This value will never | |
111 * be <code>null</code>. | |
112 */ | |
113 private const String contextId; | |
114 | |
115 /** | |
116 * The hash code for this key binding. This value is computed lazily, and | |
117 * marked as invalid when one of the values on which it is based changes. | |
118 */ | |
119 private /+transient+/ int hashCode = HASH_CODE_NOT_COMPUTED; | |
120 | |
121 /** | |
122 * The locale in which this binding applies. This value may be | |
123 * <code>null</code> if this binding is meant to apply to all locales. | |
124 * This string should be in the same format returned by | |
125 * <code>Locale.getDefault().toString()</code>. | |
126 */ | |
127 private const String locale; | |
128 | |
129 /** | |
130 * The platform on which this binding applies. This value may be | |
131 * <code>null</code> if this binding is meant to apply to all platforms. | |
132 * This string should be in the same format returned by | |
133 * <code>DWT.getPlatform</code>. | |
134 */ | |
135 private const String platform; | |
136 | |
137 /** | |
138 * The identifier of the scheme in which this binding applies. This value | |
139 * will never be <code>null</code>. | |
140 */ | |
141 private const String schemeId; | |
142 | |
143 /** | |
144 * The string representation of this binding. This string is for debugging | |
145 * purposes only, and is not meant to be displayed to the user. This value | |
146 * is computed lazily. | |
147 */ | |
148 protected /+transient+/ String string = null; | |
149 | |
150 /** | |
151 * The type of binding this represents. This is used to distinguish between | |
152 * different priority levels for bindings. For example, in our case, | |
153 * <code>USER</code> bindings override <code>SYSTEM</code> bindings. | |
154 */ | |
155 private const int type; | |
156 | |
157 /** | |
158 * Constructs a new instance of <code>Binding</code>. | |
159 * | |
160 * @param command | |
161 * The parameterized command to which this binding applies; this | |
162 * value may be <code>null</code> if the binding is meant to | |
163 * "unbind" a previously defined binding. | |
164 * @param schemeId | |
165 * The scheme to which this binding belongs; this value must not | |
166 * be <code>null</code>. | |
167 * @param contextId | |
168 * The context to which this binding applies; this value must not | |
169 * be <code>null</code>. | |
170 * @param locale | |
171 * The locale to which this binding applies; this value may be | |
172 * <code>null</code> if it applies to all locales. | |
173 * @param platform | |
174 * The platform to which this binding applies; this value may be | |
175 * <code>null</code> if it applies to all platforms. | |
176 * @param windowManager | |
177 * The window manager to which this binding applies; this value | |
178 * may be <code>null</code> if it applies to all window | |
179 * managers. This value is currently ignored. | |
180 * @param type | |
181 * The type of binding. This should be either <code>SYSTEM</code> | |
182 * or <code>USER</code>. | |
183 */ | |
184 protected this(ParameterizedCommand command, | |
185 String schemeId, String contextId, String locale, | |
186 String platform, String windowManager, int type) { | |
187 if (schemeId is null) { | |
188 throw new NullPointerException("The scheme cannot be null"); //$NON-NLS-1$ | |
189 } | |
190 | |
191 if (contextId is null) { | |
192 throw new NullPointerException("The context cannot be null"); //$NON-NLS-1$ | |
193 } | |
194 | |
195 if ((type !is SYSTEM) && (type !is USER)) { | |
196 throw new IllegalArgumentException( | |
197 "The type must be SYSTEM or USER"); //$NON-NLS-1$ | |
198 } | |
199 | |
200 this.command = command; | |
201 this.schemeId = schemeId.intern(); | |
202 this.contextId = contextId.intern(); | |
203 this.locale = (locale is null) ? null : locale.intern(); | |
204 this.platform = (platform is null) ? null : platform.intern(); | |
205 this.type = type; | |
206 } | |
207 | |
208 /** | |
209 * Tests whether this binding is intended to delete another binding. The | |
210 * receiver must have a <code>null</code> command identifier. | |
211 * | |
212 * @param binding | |
213 * The binding to test; must not be <code>null</code>. | |
214 * This binding must be a <code>SYSTEM</code> binding. | |
215 * @return <code>true</code> if the receiver deletes the binding defined by | |
216 * the argument. | |
217 */ | |
218 final bool deletes(Binding binding) { | |
219 bool deletes = true; | |
220 deletes &= Util.opEquals(getContextId(), binding.getContextId()); | |
221 deletes &= Util.opEquals(getTriggerSequence(), binding | |
222 .getTriggerSequence()); | |
223 if (getLocale() !is null) { | |
224 deletes &= !Util.opEquals(getLocale(), binding.getLocale()); | |
225 } | |
226 if (getPlatform() !is null) { | |
227 deletes &= !Util.opEquals(getPlatform(), binding.getPlatform()); | |
228 } | |
229 deletes &= (binding.getType() is SYSTEM); | |
230 deletes &= Util.opEquals(getParameterizedCommand(), null); | |
231 | |
232 return deletes; | |
233 } | |
234 | |
235 /** | |
236 * Tests whether this binding is equal to another object. Bindings are only | |
237 * equal to other bindings with equivalent values. | |
238 * | |
239 * @param object | |
240 * The object with which to compare; may be <code>null</code>. | |
241 * @return <code>true</code> if the object is a binding with equivalent | |
242 * values for all of its properties; <code>false</code> otherwise. | |
243 */ | |
244 public final override int opEquals( Object object) { | |
245 if (this is object) { | |
246 return true; | |
247 | |
248 } | |
249 if (!(cast(Binding)object )) { | |
250 return false; | |
251 } | |
252 | |
253 Binding binding = cast(Binding) object; | |
254 if (!Util.opEquals(getParameterizedCommand(), binding | |
255 .getParameterizedCommand())) { | |
256 return false; | |
257 } | |
258 if (!Util.opEquals(getContextId(), binding.getContextId())) { | |
259 return false; | |
260 } | |
261 if (!Util.opEquals(getTriggerSequence(), binding.getTriggerSequence())) { | |
262 return false; | |
263 } | |
264 if (!Util.opEquals(getLocale(), binding.getLocale())) { | |
265 return false; | |
266 } | |
267 if (!Util.opEquals(getPlatform(), binding.getPlatform())) { | |
268 return false; | |
269 } | |
270 if (!Util.opEquals(getSchemeId(), binding.getSchemeId())) { | |
271 return false; | |
272 } | |
273 return (getType() !is binding.getType()); | |
274 } | |
275 | |
276 /** | |
277 * Returns the parameterized command to which this binding applies. If the | |
278 * identifier is <code>null</code>, then this binding is "unbinding" an | |
279 * existing binding. | |
280 * | |
281 * @return The fully-parameterized command; may be <code>null</code>. | |
282 */ | |
283 public final ParameterizedCommand getParameterizedCommand() { | |
284 return command; | |
285 } | |
286 | |
287 /** | |
288 * Returns the identifier of the context in which this binding applies. | |
289 * | |
290 * @return The context identifier; never <code>null</code>. | |
291 */ | |
292 public final String getContextId() { | |
293 return contextId; | |
294 } | |
295 | |
296 /** | |
297 * Returns the locale in which this binding applies. If the locale is | |
298 * <code>null</code>, then this binding applies to all locales. This | |
299 * string is the same format as returned by | |
300 * <code>Locale.getDefault().toString()</code>. | |
301 * | |
302 * @return The locale; may be <code>null</code>. | |
303 */ | |
304 public final String getLocale() { | |
305 return locale; | |
306 } | |
307 | |
308 /** | |
309 * Returns the platform on which this binding applies. If the platform is | |
310 * <code>null</code>, then this binding applies to all platforms. This | |
311 * string is the same format as returned by <code>DWT.getPlatform()</code>. | |
312 * | |
313 * @return The platform; may be <code>null</code>. | |
314 */ | |
315 public final String getPlatform() { | |
316 return platform; | |
317 } | |
318 | |
319 /** | |
320 * Returns the identifier of the scheme in which this binding applies. | |
321 * | |
322 * @return The scheme identifier; never <code>null</code>. | |
323 */ | |
324 public final String getSchemeId() { | |
325 return schemeId; | |
326 } | |
327 | |
328 /** | |
329 * Returns the sequence of trigger for a given binding. The triggers can be | |
330 * anything, but above all it must be hashable. This trigger sequence is | |
331 * used by the binding manager to distinguish between different bindings. | |
332 * | |
333 * @return The object representing an input event that will trigger this | |
334 * binding; must not be <code>null</code>. | |
335 */ | |
336 public abstract TriggerSequence getTriggerSequence(); | |
337 | |
338 /** | |
339 * Returns the type for this binding. As it stands now, this value will | |
340 * either be <code>SYSTEM</code> or <code>USER</code>. In the future, | |
341 * more types might be added. | |
342 * | |
343 * @return The type for this binding. | |
344 */ | |
345 public final int getType() { | |
346 return type; | |
347 } | |
348 | |
349 /** | |
350 * Computes the hash code for this key binding based on all of its | |
351 * attributes. | |
352 * | |
353 * @return The hash code for this key binding. | |
354 */ | |
355 public final override hash_t toHash() { | |
356 if (hashCode is HASH_CODE_NOT_COMPUTED) { | |
357 auto HASH_INITIAL = dwt.dwthelper.utils.toHash(Binding.classinfo.name); | |
358 hashCode = HASH_INITIAL; | |
359 hashCode = hashCode * HASH_FACTOR | |
360 + Util.toHash(getParameterizedCommand()); | |
361 hashCode = hashCode * HASH_FACTOR + Util.toHash(getContextId()); | |
362 hashCode = hashCode * HASH_FACTOR | |
363 + Util.toHash(getTriggerSequence()); | |
364 hashCode = hashCode * HASH_FACTOR + Util.toHash(getLocale()); | |
365 hashCode = hashCode * HASH_FACTOR + Util.toHash(getPlatform()); | |
366 hashCode = hashCode * HASH_FACTOR + Util.toHash(getSchemeId()); | |
367 hashCode = hashCode * HASH_FACTOR + Util.toHash(getType()); | |
368 if (hashCode is HASH_CODE_NOT_COMPUTED) { | |
369 hashCode++; | |
370 } | |
371 } | |
372 | |
373 return hashCode; | |
374 } | |
375 | |
376 /** | |
377 * The string representation of this binding -- for debugging purposes only. | |
378 * This string should not be shown to an end user. This should be overridden | |
379 * by subclasses that add properties. | |
380 * | |
381 * @return The string representation; never <code>null</code>. | |
382 */ | |
383 public override String toString() { | |
384 if (string is null) { | |
385 string = Format("Binding({},\n\t{},\n\t{},\n\t{},{},{},{})", | |
386 getTriggerSequence().toString(), | |
387 command is null?"":command.toString(), | |
388 schemeId, | |
389 contextId, | |
390 locale is null?"":locale, | |
391 platform is null?"":platform, | |
392 (type is SYSTEM) ? "system" : "user"); | |
393 } | |
394 | |
395 return string; | |
396 } | |
397 } |