Mercurial > projects > dwt-addons
comparison dwtx/jface/bindings/CachedBindingSet.d @ 16:e0f0aaf75edd
PopupDialog, bindings and actions
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 01 Apr 2008 08:00:31 +0200 |
parents | |
children | 04b47443bb01 |
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.CachedBindingSet; | |
14 | |
15 import dwtx.jface.bindings.TriggerSequence; | |
16 import dwtx.jface.bindings.Binding; | |
17 | |
18 import tango.util.collection.model.Map; | |
19 | |
20 import dwtx.jface.util.Util; | |
21 | |
22 import dwt.dwthelper.utils; | |
23 | |
24 /** | |
25 * <p> | |
26 * A resolution of bindings for a given state. To see if we already have a | |
27 * cached binding set, just create one of these binding sets and then look it up | |
28 * in a map. If it is not already there, then add it and set the cached binding | |
29 * resolution. | |
30 * </p> | |
31 * | |
32 * @since 3.1 | |
33 */ | |
34 final class CachedBindingSet { | |
35 | |
36 /** | |
37 * A factor for computing the hash code for all cached binding sets. | |
38 */ | |
39 private const static int HASH_FACTOR = 89; | |
40 | |
41 /** | |
42 * <p> | |
43 * A representation of the tree of active contexts at the time this cached | |
44 * binding set was computed. It is a map of context id (<code>String</code>) | |
45 * to context id (<code>String</code>). Each key represents one of the | |
46 * active contexts or one of its ancestors, while each value represents its | |
47 * parent. This is a way of perserving information about what the hierarchy | |
48 * looked like. | |
49 * </p> | |
50 * <p> | |
51 * This value will be <code>null</code> if the contexts were disregarded | |
52 * in the computation. It may also be empty. All of the keys are guaranteed | |
53 * to be non- <code>null</code>, but the values can be <code>null</code> | |
54 * (i.e., no parent). | |
55 * </p> | |
56 */ | |
57 private const Map!(Object,Object) activeContextTree; | |
58 | |
59 /** | |
60 * The map representing the resolved state of the bindings. This is a map of | |
61 * a trigger (<code>TriggerSequence</code>) to binding (<code>Binding</code>). | |
62 * This value may be <code>null</code> if it has not yet been initialized. | |
63 */ | |
64 private Map!(Object,Object) bindingsByTrigger = null; | |
65 | |
66 /** | |
67 * A map of triggers to collections of bindings. If this binding set | |
68 * contains conflicts, they are logged here. | |
69 * | |
70 * @since 3.3 | |
71 */ | |
72 private Map!(Object,Object) conflictsByTrigger = null; | |
73 | |
74 /** | |
75 * The hash code for this object. This value is computed lazily, and marked | |
76 * as invalid when one of the values on which it is based changes. | |
77 */ | |
78 private /+transient+/ int hashCode; | |
79 | |
80 /** | |
81 * Whether <code>hashCode</code> still contains a valid value. | |
82 */ | |
83 private /+transient+/ bool hashCodeComputed = false; | |
84 | |
85 /** | |
86 * <p> | |
87 * The list of locales that were active at the time this binding set was | |
88 * computed. This list starts with the most specific representation of the | |
89 * locale, and moves to more general representations. For example, this | |
90 * array might look like ["en_US", "en", "", null]. | |
91 * </p> | |
92 * <p> | |
93 * This value will never be <code>null</code>, and it will never be | |
94 * empty. It must contain at least one element, but its elements can be | |
95 * <code>null</code>. | |
96 * </p> | |
97 */ | |
98 private const String[] locales; | |
99 | |
100 /** | |
101 * <p> | |
102 * The list of platforms that were active at the time this binding set was | |
103 * computed. This list starts with the most specific representation of the | |
104 * platform, and moves to more general representations. For example, this | |
105 * array might look like ["gtk", "", null]. | |
106 * </p> | |
107 * <p> | |
108 * This value will never be <code>null</code>, and it will never be | |
109 * empty. It must contain at least one element, but its elements can be | |
110 * <code>null</code>. | |
111 * </p> | |
112 */ | |
113 private const String[] platforms; | |
114 | |
115 /** | |
116 * A map of prefixes (<code>TriggerSequence</code>) to a map of | |
117 * available completions (possibly <code>null</code>, which means there | |
118 * is an exact match). The available completions is a map of trigger (<code>TriggerSequence</code>) | |
119 * to command identifier (<code>String</code>). This value is | |
120 * <code>null</code> if it has not yet been initialized. | |
121 */ | |
122 private Map!(Object,Object) prefixTable = null; | |
123 | |
124 /** | |
125 * <p> | |
126 * The list of schemes that were active at the time this binding set was | |
127 * computed. This list starts with the active scheme, and then continues | |
128 * with all of its ancestors -- in order. For example, this might look like | |
129 * ["emacs", "default"]. | |
130 * </p> | |
131 * <p> | |
132 * This value will never be <code>null</code>, and it will never be | |
133 * empty. It must contain at least one element. Its elements cannot be | |
134 * <code>null</code>. | |
135 * </p> | |
136 */ | |
137 private const String[] schemeIds; | |
138 | |
139 /** | |
140 * The map representing the resolved state of the bindings. This is a map of | |
141 * a command id (<code>String</code>) to triggers (<code>Collection</code> | |
142 * of <code>TriggerSequence</code>). This value may be <code>null</code> | |
143 * if it has not yet been initialized. | |
144 */ | |
145 private Map!(Object,Object) triggersByCommandId = null; | |
146 | |
147 /** | |
148 * Constructs a new instance of <code>CachedBindingSet</code>. | |
149 * | |
150 * @param activeContextTree | |
151 * The set of context identifiers that were active when this | |
152 * binding set was calculated; may be empty. If it is | |
153 * <code>null</code>, then the contexts were disregarded in | |
154 * the computation. This is a map of context id ( | |
155 * <code>String</code>) to parent context id ( | |
156 * <code>String</code>). This is a way of caching the look of | |
157 * the context tree at the time the binding set was computed. | |
158 * @param locales | |
159 * The locales that were active when this binding set was | |
160 * calculated. The first element is the currently active locale, | |
161 * and it is followed by increasingly more general locales. This | |
162 * must not be <code>null</code> and must contain at least one | |
163 * element. The elements can be <code>null</code>, though. | |
164 * @param platforms | |
165 * The platform that were active when this binding set was | |
166 * calculated. The first element is the currently active | |
167 * platform, and it is followed by increasingly more general | |
168 * platforms. This must not be <code>null</code> and must | |
169 * contain at least one element. The elements can be | |
170 * <code>null</code>, though. | |
171 * @param schemeIds | |
172 * The scheme that was active when this binding set was | |
173 * calculated, followed by its ancestors. This may be | |
174 * <code>null</code or empty. The | |
175 * elements cannot be <code>null</code>. | |
176 */ | |
177 this(Map!(Object,Object) activeContextTree, String[] locales, | |
178 String[] platforms, String[] schemeIds) { | |
179 if (locales is null) { | |
180 throw new NullPointerException("The locales cannot be null."); //$NON-NLS-1$ | |
181 } | |
182 | |
183 if (locales.length is 0) { | |
184 throw new NullPointerException("The locales cannot be empty."); //$NON-NLS-1$ | |
185 } | |
186 | |
187 if (platforms is null) { | |
188 throw new NullPointerException("The platforms cannot be null."); //$NON-NLS-1$ | |
189 } | |
190 | |
191 if (platforms.length is 0) { | |
192 throw new NullPointerException("The platforms cannot be empty."); //$NON-NLS-1$ | |
193 } | |
194 | |
195 this.activeContextTree = activeContextTree; | |
196 this.locales = locales; | |
197 this.platforms = platforms; | |
198 this.schemeIds = schemeIds; | |
199 } | |
200 | |
201 /** | |
202 * Compares this binding set with another object. The objects will be equal | |
203 * if they are both instance of <code>CachedBindingSet</code> and have | |
204 * equivalent values for all of their properties. | |
205 * | |
206 * @param object | |
207 * The object with which to compare; may be <code>null</code>. | |
208 * @return <code>true</code> if they are both instances of | |
209 * <code>CachedBindingSet</code> and have the same values for all | |
210 * of their properties; <code>false</code> otherwise. | |
211 */ | |
212 public final override int opEquals(Object object) { | |
213 if (!(cast(CachedBindingSet)object )) { | |
214 return false; | |
215 } | |
216 | |
217 CachedBindingSet other = cast(CachedBindingSet) object; | |
218 | |
219 if (!Util.opEquals(cast(Object)activeContextTree, cast(Object)other.activeContextTree)) { | |
220 return false; | |
221 } | |
222 if (!Util.opEquals(locales, other.locales)) { | |
223 return false; | |
224 } | |
225 if (!Util.opEquals(platforms, other.platforms)) { | |
226 return false; | |
227 } | |
228 return Util.opEquals(schemeIds, other.schemeIds); | |
229 } | |
230 | |
231 /** | |
232 * Returns the map of command identifiers indexed by trigger sequence. | |
233 * | |
234 * @return A map of triggers (<code>TriggerSequence</code>) to bindings (<code>Binding</code>). | |
235 * This value may be <code>null</code> if this was not yet | |
236 * initialized. | |
237 */ | |
238 final Map!(Object,Object) getBindingsByTrigger() { | |
239 return bindingsByTrigger; | |
240 } | |
241 | |
242 /** | |
243 * Returns a map of conflicts for this set of contexts. | |
244 * | |
245 * @return A map of trigger to a collection of Bindings. May be | |
246 * <code>null</code>. | |
247 * @since 3.3 | |
248 */ | |
249 final Map!(Object,Object) getConflictsByTrigger() { | |
250 return conflictsByTrigger; | |
251 } | |
252 | |
253 /** | |
254 * Returns the map of prefixes to a map of trigger sequence to command | |
255 * identifiers. | |
256 * | |
257 * @return A map of prefixes (<code>TriggerSequence</code>) to a map of | |
258 * available completions (possibly <code>null</code>, which means | |
259 * there is an exact match). The available completions is a map of | |
260 * trigger (<code>TriggerSequence</code>) to command identifier (<code>String</code>). | |
261 * This value may be <code>null</code> if it has not yet been | |
262 * initialized. | |
263 */ | |
264 final Map!(Object,Object) getPrefixTable() { | |
265 return prefixTable; | |
266 } | |
267 | |
268 /** | |
269 * Returns the map of triggers indexed by command identifiers. | |
270 * | |
271 * @return A map of command identifiers (<code>String</code>) to | |
272 * triggers (<code>Collection</code> of | |
273 * <code>TriggerSequence</code>). This value may be | |
274 * <code>null</code> if this was not yet initialized. | |
275 */ | |
276 final Map!(Object,Object) getTriggersByCommandId() { | |
277 return triggersByCommandId; | |
278 } | |
279 | |
280 /** | |
281 * Computes the hash code for this cached binding set. The hash code is | |
282 * based only on the immutable values. This allows the set to be created and | |
283 * checked for in a hashed collection <em>before</em> doing any | |
284 * computation. | |
285 * | |
286 * @return The hash code for this cached binding set. | |
287 */ | |
288 public final override hash_t toHash() { | |
289 if (!hashCodeComputed) { | |
290 | |
291 auto HASH_INITIAL = dwt.dwthelper.utils.toHash(CachedBindingSet.classinfo.name ); | |
292 hashCode = HASH_INITIAL; | |
293 hashCode = hashCode * HASH_FACTOR | |
294 + Util.toHash(cast(Object)activeContextTree); | |
295 hashCode = hashCode * HASH_FACTOR + Util.toHash(locales); | |
296 hashCode = hashCode * HASH_FACTOR + Util.toHash(platforms); | |
297 hashCode = hashCode * HASH_FACTOR + Util.toHash(schemeIds); | |
298 hashCodeComputed = true; | |
299 } | |
300 | |
301 return hashCode; | |
302 } | |
303 | |
304 /** | |
305 * Sets the map of command identifiers indexed by trigger. | |
306 * | |
307 * @param commandIdsByTrigger | |
308 * The map to set; must not be <code>null</code>. This is a | |
309 * map of triggers (<code>TriggerSequence</code>) to binding (<code>Binding</code>). | |
310 */ | |
311 final void setBindingsByTrigger(Map!(Object,Object) commandIdsByTrigger) { | |
312 if (commandIdsByTrigger is null) { | |
313 throw new NullPointerException( | |
314 "Cannot set a null binding resolution"); //$NON-NLS-1$ | |
315 } | |
316 | |
317 this.bindingsByTrigger = commandIdsByTrigger; | |
318 } | |
319 | |
320 /** | |
321 * Sets the map of conflicting bindings by trigger. | |
322 * | |
323 * @param conflicts | |
324 * The map to set; must not be <code>null</code>. | |
325 * @since 3.3 | |
326 */ | |
327 final void setConflictsByTrigger(Map!(Object,Object) conflicts) { | |
328 if (conflicts is null) { | |
329 throw new NullPointerException( | |
330 "Cannot set a null binding conflicts"); //$NON-NLS-1$ | |
331 } | |
332 conflictsByTrigger = conflicts; | |
333 } | |
334 | |
335 /** | |
336 * Sets the map of prefixes to a map of trigger sequence to command | |
337 * identifiers. | |
338 * | |
339 * @param prefixTable | |
340 * A map of prefixes (<code>TriggerSequence</code>) to a map | |
341 * of available completions (possibly <code>null</code>, which | |
342 * means there is an exact match). The available completions is a | |
343 * map of trigger (<code>TriggerSequence</code>) to command | |
344 * identifier (<code>String</code>). Must not be | |
345 * <code>null</code>. | |
346 */ | |
347 final void setPrefixTable(Map!(Object,Object) prefixTable) { | |
348 if (prefixTable is null) { | |
349 throw new NullPointerException("Cannot set a null prefix table"); //$NON-NLS-1$ | |
350 } | |
351 | |
352 this.prefixTable = prefixTable; | |
353 } | |
354 | |
355 /** | |
356 * Sets the map of triggers indexed by command identifiers. | |
357 * | |
358 * @param triggersByCommandId | |
359 * The map to set; must not be <code>null</code>. This is a | |
360 * map of command identifiers (<code>String</code>) to | |
361 * triggers (<code>Collection</code> of | |
362 * <code>TriggerSequence</code>). | |
363 */ | |
364 final void setTriggersByCommandId(Map!(Object,Object) triggersByCommandId) { | |
365 if (triggersByCommandId is null) { | |
366 throw new NullPointerException( | |
367 "Cannot set a null binding resolution"); //$NON-NLS-1$ | |
368 } | |
369 | |
370 this.triggersByCommandId = triggersByCommandId; | |
371 } | |
372 } |