KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > Settings


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor;
21
22 import java.util.Map JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.logging.Level JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import org.openide.util.RequestProcessor;
31
32 /**
33 * Configurable settings that editor uses. All the methods are static
34 * The editor is configurable mainly by using the following static
35 * method in Settings class:
36 *
37 * org.netbeans.editor.Settings.setValue(Class kitClass, String settingName, Object newValue);
38 *
39 * kitClass - this is the class of the editor kit for which the setting is changed.
40 * The current hierarchy of editor kits starts
41 * with the <tt>org.netbeans.editor.BaseKit</tt> kit, the begining of the whole
42 * kit hierarchy. There should be a different editor kit for each mime-type.
43 *
44 * When the particular setting is not set foar a given kit, then the superclass of
45 * the given kit class is retrieved and the search for the setting value is performed.
46 * Example: If the java document calls Settings.getValue() to retrieve the value
47 * for TAB_SIZE setting and it passes JavaKit.class as the kitClass
48 * parameter and the setting has no value on this level, then the super class
49 * of the JavaKit is retrieved (by using Class.getSuperclass() call) which is BaseKit
50 * in this case and the search for the value of TAB_SIZE setting
51 * is performed again. It is finished by reaching the null value for the kitClass.
52 * The null value can be also used as the kitClass parameter value.
53 * In a more general look not only the kit-class hierarchy could be used
54 * in <tt>Settings</tt>. Any class inheritance hierarchy could be used here
55 * having the null as the common root.
56 *
57 * This way the inheritance of the setting values is guaranteed. By changing
58 * the setting value on the BaseKit level (or even on the null level),
59 * all the kit classes that don't
60 * override the particular setting are affected.
61 *
62 * settingName - name of the setting to change. The base setting names
63 * are defined as public String constants in <tt>SettingsNames</tt> class.
64 * The additional packages that extend the basic editor functionality
65 * can define additional setting names.
66 *
67 * newValue - new value for the setting. It must be always an object even
68 * if the setting is logicaly the basic datatype such as int (java.lang.Integer
69 * would be used in this case). A particular class types that can be used for
70 * the value of the settings are documented for each setting.
71 *
72 * WARNING! Please read carefully the description for each option you're
73 * going to change as you can make the editor stop working if you'll
74 * change the setting in a wrong way.
75 *
76 * @author Miloslav Metelka
77 * @version 1.00
78 */

79
80 public class Settings {
81
82     private static final Logger JavaDoc LOG = Logger.getLogger(Settings.class.getName());
83     
84     /** Core level used by the settings initializers. This is the level used
85     * for the base and ext editor packages initializers only.
86     */

87     public static final int CORE_LEVEL = 0;
88
89     /** System level used by the settings initializers. This is the (default)
90     * first level.
91     * It should be used by all the modules that install the new kits
92     * into the editor.
93     */

94     public static final int SYSTEM_LEVEL = 1;
95
96     /** Extension level used by the settings initializers. This is the second
97     * level. It should be used by all the modules that want to extend
98     * or modify the settings but they don't install their own kits.
99     * The example can be a module extending the popup menu of an existing
100     * kit.
101     */

102     public static final int EXTENSION_LEVEL = 2;
103
104     /** Option level used by the settings initializers. This is the third
105     * level. It should be used by the visual options created by the IDE.
106     */

107     public static final int OPTION_LEVEL = 3;
108
109     /** User level used by the settings initializers. This is the fourth level.
110     * All the initializers with this level will be called AFTER
111     * all the initializers at the system level. All the user custom
112     * initializers should be added at this level to guarantee
113     * they will overwrite the settings added by the system.
114     */

115     public static final int USER_LEVEL = 4;
116
117     /** List of Initializers */
118     private static final ArrayList JavaDoc initializerLists = new ArrayList JavaDoc();
119     private static long initializerListsVersion = 0;
120     private static List JavaDoc [] listsOfInitializers = null;
121     private static long listsOfInitializersVersion = -1;
122
123     /** Current initializer sorter. */
124     private static InitializerSorter currentInitializerSorter;
125
126     /** List of Filters */
127     private static final Filter [] NULL_FILTERS = new Filter[0];
128     private static final String JavaDoc FILTERS_LOCK = new String JavaDoc("Settings.FILTERS_LOCK"); //NOI18N
129
private static volatile Filter [] filters = NULL_FILTERS;
130
131     /** [kit-class, map-of-settings] pairs */
132     private static final Map JavaDoc kit2Maps = new HashMap JavaDoc();
133
134     /** Support for firing change events */
135     private static final WeakEventListenerList listenerList = new WeakEventListenerList();
136
137     /** Internal map instance signing that initializer returned null
138     * map for particular kit. To sign this fact and not query initializer
139     * again, this simple map is used.
140     */

141     private static final Map JavaDoc NULL_MAP = new HashMap JavaDoc(1);
142
143     private static volatile boolean firingEnabled = true;
144
145     /** Save repetitive creation of the empty maps using this variable.
146      * [kit-class, map-of-settings] pairs
147      */

148     private static final HashMap JavaDoc emptyMaps = new HashMap JavaDoc();
149
150     private static final RequestProcessor PROCESSOR = new RequestProcessor("org.netbeans.editor.Settings.PROCESSOR"); //NOI18N
151
private static final RequestProcessor.Task RESET_TASK = PROCESSOR.create(new Runnable JavaDoc() {
152         public void run() {
153             synchronized (Settings.class) {
154                 kit2Maps.clear();
155             }
156             fireSettingsChange(null, null, null, null);
157         }
158     });
159     
160     private Settings() {
161         // no instances allowed
162
}
163
164     /** Add the initializer at the system level and perform reset. */
165     public static void addInitializer(Initializer i) {
166         addInitializer(i, SYSTEM_LEVEL);
167         reset();
168     }
169
170     /** Add initializer instance to the list of current initializers.
171     * You can call reset() after adding the initializer to make sure
172     * it will update the current settings with its values.
173     * However all the changes
174     * that were made explicitly by calling setValue() will be lost
175     * in this case.
176     *
177     * @param i initializer to add to the current list of initializers
178     * @param level initializer level. It defines in which order
179     * the initializers will be called. There are currently three levels
180     * <tt>CORE_LEVEL</tt>, <tt>SYSTEM_LEVEL</tt> and <tt>USER_LEVEL</tt>.
181     * It's guaranteed that initializers with the particular level
182     * will be called in the order shown above.
183     * The order of the initializers at the same
184     * level is given by the order of their addition.
185     */

186     public static void addInitializer(Initializer i, int level) {
187         synchronized (initializerLists) {
188             int size = initializerLists.size();
189             for (int j = size; j <= level; j++) {
190                 initializerLists.add(new ArrayList JavaDoc());
191             }
192             ((List JavaDoc)initializerLists.get(level)).add(i);
193
194             // Sort the initializers if there's a valid sorter
195
if (currentInitializerSorter != null) {
196                 currentInitializerSorter.sort(initializerLists);
197             }
198
199             initializerListsVersion++;
200         }
201     }
202
203     /** Remove the initializer of the given name from all the levels
204     * where it occurs.
205     * @param name name of the initializer sorter to remove.
206     */

207     public static void removeInitializer(String JavaDoc name) {
208         synchronized (initializerLists) {
209             Iterator JavaDoc itit = initializerLists.iterator();
210             while (itit.hasNext()) {
211                 Iterator JavaDoc it = ((List JavaDoc)itit.next()).iterator();
212                 while (it.hasNext()) {
213                     if (name.equals(((Initializer)it.next()).getName())) {
214                         it.remove();
215                     }
216                 }
217             }
218
219             // Sort the initializers if there's a valid sorter
220
if (currentInitializerSorter != null) {
221                 currentInitializerSorter.sort(initializerLists);
222             }
223             
224             initializerListsVersion++;
225         }
226     }
227
228     /** Get the current initializer sorter. */
229     public static InitializerSorter getInitializerSorter() {
230         synchronized (initializerLists) {
231             return currentInitializerSorter;
232         }
233     }
234
235     /** Set the current initializer sorter. */
236     public static void setInitializerSorter(InitializerSorter initializerSorter) {
237         synchronized (initializerLists) {
238             currentInitializerSorter = initializerSorter;
239         }
240     }
241
242     private static List JavaDoc [] getListsOfInitializers() {
243         synchronized (initializerLists) {
244             if (listsOfInitializersVersion != initializerListsVersion) {
245                 List JavaDoc [] lists = (List JavaDoc []) initializerLists.toArray(new List JavaDoc[initializerLists.size()]);
246
247                 // copy & immutize
248
for (int i = 0; i < lists.length; i++) {
249                     lists[i] = Collections.unmodifiableList(new ArrayList JavaDoc(lists[i]));
250                 }
251                 
252                 listsOfInitializers = lists;
253                 listsOfInitializersVersion = initializerListsVersion;
254             }
255             
256             return listsOfInitializers;
257         }
258     }
259     
260     /** Add filter instance to the list of current filters.
261     * If there are already existing editor components,
262     * and you want to apply the changes that this filter makes
263     * to these existing
264     * components, you can call reset(). However all the changes
265     * that were made explicitly by calling setValue() will be lost
266     * in this case.
267     *
268     * @param f filter to add to the list of the filters
269     */

270     public static void addFilter(Filter f) {
271         synchronized (FILTERS_LOCK) {
272             if (filters.length == 0) {
273                 filters = new Filter [] { f };
274             } else {
275                 Filter [] tmp = new Filter [filters.length + 1];
276                 System.arraycopy(filters, 0, tmp, 0, filters.length);
277                 tmp[filters.length] = f;
278                 
279                 filters = tmp;
280             }
281         }
282     }
283
284     public static void removeFilter(Filter f) {
285         synchronized (FILTERS_LOCK) {
286             if (filters.length == 0) {
287                 return;
288             } else if (filters.length == 1 && filters[0] == f) {
289                 filters = NULL_FILTERS;
290             } else {
291                 int idx = -1;
292                 for (int i = 0; i < filters.length; i++) {
293                     if (filters[i] == f) {
294                         idx = i;
295                         break;
296                     }
297                 }
298
299                 if (idx != -1) {
300                     Filter [] tmp = new Filter [filters.length - 1];
301                     System.arraycopy(filters, 0, tmp, 0, idx);
302                     if (idx < tmp.length) {
303                         System.arraycopy(filters, idx + 1, tmp, idx, tmp.length - idx);
304                     }
305                     
306                     filters = tmp;
307                 }
308             }
309         }
310     }
311
312     /** Get the value and evaluate the evaluators. */
313     public static Object JavaDoc getValue(Class JavaDoc kitClass, String JavaDoc settingName) {
314         return getValue(kitClass, settingName, true);
315     }
316
317     /** Get the property by searching the given kit class settings and if not
318     * found then the settings for super class and so on.
319     * @param kitClass editor kit class for which the value of setting should
320     * be retrieved. The null can be used as the root of the whole hierarchy.
321     * @param settingName name of the setting for which the value should
322     * be retrieved
323     * @return the value of the setting
324     */

325     public static synchronized Object JavaDoc getValue(Class JavaDoc kitClass, String JavaDoc settingName,
326             boolean evaluateEvaluators) {
327         Object JavaDoc value = null;
328         Class JavaDoc kc = kitClass;
329         while (true) {
330             Map JavaDoc map = getKitMap(kc, false);
331             if (map != null) {
332                 value = map.get(settingName);
333                 if (evaluateEvaluators && value instanceof Evaluator) {
334                     value = ((Evaluator)value).getValue(kitClass, settingName);
335                 }
336                 if (value != null) {
337                     break;
338                 }
339             }
340             if (kc == null) {
341                 break;
342             }
343             kc = kc.getSuperclass();
344         }
345
346         // filter the value if necessary
347
Filter [] currentFilters = filters;
348         for (int i = 0; i < currentFilters.length; i++) {
349             value = currentFilters[i].filterValue(kitClass, settingName, value);
350         }
351
352         return value;
353     }
354
355     /** Get the value hierarchy and evaluate the evaluators */
356     public static KitAndValue[] getValueHierarchy(Class JavaDoc kitClass,
357             String JavaDoc settingName) {
358         return getValueHierarchy(kitClass, settingName, true);
359     }
360
361     /** Get array of KitAndValue objects sorted from the given kit class to its
362     * deepest superclass and the last member can be filled whether there
363     * is global setting (kit class of that member would be null).
364     * This method is useful for objects like keymaps that
365     * need to create all the parent keymaps to work properly.
366     * The method can either evaluate evaluators or leave them untouched
367     * which can become handy in some cases.
368     * @param kitClass editor kit class for which the value of setting should
369     * be retrieved. The null can be used as the root of the whole hierarchy.
370     * @param settingName name of the setting for which the value should
371     * be retrieved
372     * @param evaluateEvaluators whether the evaluators should be evaluated or not
373     * @return the array containing KitAndValue instances describing the particular
374     * setting's value on the specific kit level.
375     */

376     public static synchronized KitAndValue[] getValueHierarchy(Class JavaDoc kitClass,
377             String JavaDoc settingName, boolean evaluateEvaluators) {
378         ArrayList JavaDoc kavList = new ArrayList JavaDoc();
379         Class JavaDoc kc = kitClass;
380         while (true) {
381             Map JavaDoc map = getKitMap(kc, false);
382             if (map != null) {
383                 Object JavaDoc value = map.get(settingName);
384                 if (evaluateEvaluators && value instanceof Evaluator) {
385                     value = ((Evaluator)value).getValue(kitClass, settingName);
386                 }
387                 if (value != null) {
388                     kavList.add(new KitAndValue(kc, value));
389                 }
390             }
391             if (kc == null) {
392                 break;
393             }
394             kc = kc.getSuperclass();
395         }
396         KitAndValue[] kavArray = (KitAndValue[])kavList.toArray(
397                                      new KitAndValue[kavList.size()]);
398
399         // filter the value if necessary
400
Filter [] currentFilters = filters;
401         for (int i = 0; i < currentFilters.length; i++) {
402             kavArray = currentFilters[i].filterValueHierarchy(kitClass, settingName, kavArray);
403         }
404
405         return kavArray;
406     }
407
408     /** Set the new value for property on kit level. The old and new values
409     * are compared and if they are equal the setting is not changed and
410     * nothing is fired.
411     *
412     * @param kitClass editor kit class for which the value of setting should
413     * be set. The null can be used as the root of the whole hierarchy.
414     * @param settingName the string used for searching the value
415     * @param newValue new value to set for the property; the value can
416     * be null to clear the value for the specified kit
417     */

418     public static void setValue(Class JavaDoc kitClass, String JavaDoc settingName, Object JavaDoc newValue) {
419         Object JavaDoc oldValue;
420         
421         synchronized (Settings.class) {
422             Map JavaDoc map = getKitMap(kitClass, true);
423             oldValue = map.get(settingName);
424             if (oldValue == null && newValue == null
425                     || (oldValue != null && oldValue.equals(newValue))
426                ) {
427                 return; // no change
428
}
429             if (newValue != null) {
430                 map.put(settingName, newValue);
431             } else {
432                 map.remove(settingName);
433             }
434         }
435         
436         fireSettingsChange(kitClass, settingName, oldValue, newValue);
437     }
438
439     /** Don't change the value of the setting, but fire change
440     * event. This is useful when there's internal change in the value object
441     * of some setting.
442     */

443     public static void touchValue(Class JavaDoc kitClass, String JavaDoc settingName) {
444         fireSettingsChange(kitClass, settingName, null, null); // kit class currently not used
445
}
446
447     /** Set the value for the current kit and propagate it to all
448     * the children of the given kit by removing
449     * the possible values for the setting from the children kit setting maps.
450     * Note: This call only affects the settings for the kit classes for which
451     * the kit setting map with the setting values currently exists, i.e. when
452     * there was at least one getValue() or setValue() call performed for any
453     * setting on that particular kit class level. Other kit classes maps
454     * will be initialized by the particular initializer(s) as soon as
455     * the first getValue() or setValue() will be performed for them.
456     * However that future process will not be affected by the current
457     * propagateValue() call.
458     * This method is useful for the visual options that always set
459     * the value on all the kit levels without regard whether it's necessary or not.
460     * If the value is then changed for the base kit, it's not propagated
461     * naturally as there's a special setting
462     * This method enables
463     *
464     * The current implementation always fires the change regardless whether
465     * there was real change in setting value or not.
466     * @param kitClass editor kit class for which the value of setting should
467     * be set. The null can be used as the root of the whole hierarchy.
468     * @param settingName the string used for searching the value
469     * @param newValue new value to set for the property; the value can
470     * be null to clear the value for the specified kit
471     */

472     public static void propagateValue(Class JavaDoc kitClass, String JavaDoc settingName, Object JavaDoc newValue) {
473         synchronized (Settings.class) {
474             Map JavaDoc map = getKitMap(kitClass, true);
475             if (newValue != null) {
476                 map.put(settingName, newValue);
477             } else {
478                 map.remove(settingName);
479             }
480             // resolve kits
481
Iterator JavaDoc it = kit2Maps.entrySet().iterator();
482             while(it.hasNext()) {
483                 Map.Entry JavaDoc me = (Map.Entry JavaDoc)it.next();
484                 Class JavaDoc kc = (Class JavaDoc)me.getKey();
485                 if (kitClass != kc && (kitClass == null || kitClass.isAssignableFrom(kc))) {
486                     ((Map JavaDoc)me.getValue()).remove(settingName);
487                 }
488             }
489         }
490         
491         fireSettingsChange(null, settingName, null, null);
492     }
493
494     /** Run the given runnable. All the changes in the settings are not fired until
495     * the whole runnable completes. Nesting of <tt>update()</tt> call is allowed.
496     * Only one firing is performed after the whole runnable completes
497     * using the 'null triple'.
498     */

499     public static void update(Runnable JavaDoc r) {
500         boolean fire = false;
501         
502         synchronized (Settings.class) {
503             boolean turnedOff = firingEnabled;
504             firingEnabled = false;
505             try {
506                 r.run();
507             } finally {
508                 if (turnedOff) {
509                     firingEnabled = true;
510                     fire = true;
511                 }
512             }
513         }
514         
515         if (fire) {
516             fireSettingsChange(null, null, null, null);
517         }
518     }
519
520     /** Reset all the settings and fire the change of the settings
521     * so that all the listeners will be notified and will reload
522     * the settings.
523     * The settings that were changed using setValue() and propagateValue()
524     * are lost. Initializers will be asked for the settings values when
525     * necessary.
526     */

527     public static void reset() {
528         RESET_TASK.schedule(1);
529     }
530
531     /** Debug the current initializers */
532     public static String JavaDoc initializersToString() {
533         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
534         List JavaDoc [] lists = getListsOfInitializers();
535         for (int i = 0; i < lists.length; i++) {
536             // debug the level
537
switch (i) {
538             case CORE_LEVEL:
539                 sb.append("CORE_LEVEL"); // NOI18N
540
break;
541
542             case SYSTEM_LEVEL:
543                 sb.append("SYSTEM_LEVEL"); // NOI18N
544
break;
545
546             case EXTENSION_LEVEL:
547                 sb.append("EXTENSION_LEVEL"); // NOI18N
548
break;
549                 
550             case OPTION_LEVEL:
551                 sb.append("OPTION_LEVEL"); // NOI18N
552
break;
553
554             case USER_LEVEL:
555                 sb.append("USER_LEVEL"); // NOI18N
556
break;
557
558             default:
559                 sb.append("level " + i); // NOI18N
560
break;
561             }
562             sb.append(":\n"); // NOI18N
563

564             // debug the initializers
565
sb.append(EditorDebug.debugList((List JavaDoc)lists[i]));
566             sb.append('\n'); //NOI18N
567
}
568
569         return sb.toString();
570     }
571
572     /** Add weak listener to listen to change of any property. The caller must
573     * hold the listener object in some instance variable to prevent it
574     * from being garbage collected.
575     */

576     public static void addSettingsChangeListener(SettingsChangeListener l) {
577         listenerList.add(SettingsChangeListener.class, l);
578     }
579
580     /** Remove listener for changes in properties */
581     public static void removeSettingsChangeListener(SettingsChangeListener l) {
582         listenerList.remove(SettingsChangeListener.class, l);
583     }
584
585     private static void fireSettingsChange(Class JavaDoc kitClass, String JavaDoc settingName,
586                                            Object JavaDoc oldValue, Object JavaDoc newValue) {
587         if (firingEnabled) {
588             SettingsChangeListener[] listeners = (SettingsChangeListener[])
589                                                  listenerList.getListeners(SettingsChangeListener.class);
590             SettingsChangeEvent evt = new SettingsChangeEvent(Settings.class,
591                                       kitClass, settingName, oldValue, newValue);
592             for (int i = 0; i < listeners.length; i++) {
593                 listeners[i].settingsChange(evt);
594             }
595         }
596     }
597
598     /** Get (and possibly create) kit map for particular kit */
599     private static Map JavaDoc getKitMap(Class JavaDoc kitClass, boolean forceCreation) {
600         Map JavaDoc kitMap = (Map JavaDoc)kit2Maps.get(kitClass);
601         if (kitMap == null) {
602             Map JavaDoc emptyMap = (Map JavaDoc) emptyMaps.get(kitClass);
603             if (emptyMap != null) {
604                 // recursive initialization, return what we have collected so far
605
return emptyMap;
606             }
607             
608             if (emptyMap == null) {
609                 if (LOG.isLoggable(Level.FINE)) {
610                     emptyMap = new LoggingMap(kitClass, Level.FINE);
611                 } else {
612                     emptyMap = new HashMap JavaDoc();
613                 }
614                 emptyMaps.put(kitClass, emptyMap);
615             }
616
617             // Go through all the initializers
618
List JavaDoc [] lists = getListsOfInitializers();
619             for (int i = 0; i < lists.length; i++) {
620                 Iterator JavaDoc it = ((List JavaDoc) lists[i]).iterator();
621                 while (it.hasNext()) {
622                     Initializer initializer = (Initializer)it.next();
623
624                     // A call to initializer shouldn't break the whole updating
625
try {
626                         initializer.updateSettingsMap(kitClass, emptyMap);
627                     } catch (Throwable JavaDoc t) {
628                         LOG.log(Level.WARNING, null, t);
629                     }
630                 }
631             }
632
633             if (emptyMap.size() > 0) {
634                 kitMap = emptyMap;
635             }
636
637             if (kitMap == null) { // no initialization done for this kit
638
kitMap = NULL_MAP; // initializer will not be called again
639
}
640             kit2Maps.put(kitClass, kitMap);
641             emptyMaps.remove(kitClass);
642         }
643
644         if (kitMap == NULL_MAP) {
645             if (!forceCreation) {
646                 return null;
647             } else {
648                 if (LOG.isLoggable(Level.FINE)) {
649                     kitMap = new LoggingMap(kitClass, Level.FINE); // create empty map
650
} else {
651                     kitMap = new HashMap JavaDoc();
652                 }
653                 kit2Maps.put(kitClass, kitMap);
654             }
655         }
656
657         return kitMap;
658     }
659
660
661     /** Kit class and value pair */
662     public static class KitAndValue {
663
664         public Class JavaDoc kitClass;
665
666         public Object JavaDoc value;
667
668         public KitAndValue(Class JavaDoc kitClass, Object JavaDoc value) {
669             this.kitClass = kitClass;
670             this.value = value;
671         }
672
673     }
674
675
676     /** Initializer of the settings updates the map filled
677     * with settings for the particular kit class when asked.
678     * If the settings are being initialized all the initializers registered
679     * by the <tt>Settings.addInitializer()</tt> are being asked to update
680     * the settings-map through calling their <tt>updateSettingsMap()</tt>.
681     */

682     public static interface Initializer {
683
684         /** Each initializer must have a name. The name should be unique.
685         * The name is used for identifying the initializer during removal
686         * and sort operations and for debuging purposes.
687         */

688         public String JavaDoc getName();
689
690         /** Update map filled with the settings.
691         * @param kitClass kit class for which the settings are being updated.
692         * It can be null which means the root of the whole kit class hierarchy.
693         * @param settingsMap map holding [setting-name, setting-value] pairs.
694         * The map can be empty if this is the first initializer
695         * that updates it or if no previous initializers updated it.
696         */

697         public void updateSettingsMap(Class JavaDoc kitClass, Map JavaDoc settingsMap);
698
699     }
700
701     /** Abstract implementation of the initializer dealing with the name. */
702     public static abstract class AbstractInitializer implements Initializer {
703
704         private String JavaDoc name;
705
706         public AbstractInitializer(String JavaDoc name) {
707             this.name = name;
708         }
709
710         public String JavaDoc getName() {
711             return name;
712         }
713
714         public String JavaDoc toString() {
715             return getName();
716         }
717
718     }
719
720     /** Sort the settings initializers that were added to the settings.
721     * There can be only one sorter for the Settings, but it can delegate
722     * to previously registered sorter.
723     */

724     public static interface InitializerSorter {
725
726         public void sort(List JavaDoc initializersList);
727
728     }
729
730     /** Initializer sorter that delegates to another sorter. */
731     public static abstract class FilterInitializerSorter {
732
733         private InitializerSorter delegate;
734
735         public FilterInitializerSorter(InitializerSorter delegate) {
736             this.delegate = delegate;
737         }
738
739         public void sort(List JavaDoc initializersList) {
740             if (delegate != null) {
741                 delegate.sort(initializersList);
742             }
743         }
744
745     }
746
747
748
749     /** Evaluator can be used in cases when value of some setting
750     * depends on the value for other setting and it allows to compute
751     * the value dynamically based on the other setting(s) value.
752     * The <tt>Evaluator</tt> instance can be used as the value
753     * in the <tt>Settings.setValue()</tt> call. In that case the call
754     * to the <tt>Settings.getValue()</tt> call will 'evaluate' the Evaluator
755     * by calling its <tt>getValue()</tt>.
756     */

757     public static interface Evaluator {
758
759         /** Compute the particular setting's value.
760         * @param kitClass kit class for which the setting is being retrieved.
761         * @param settingName name of the setting to retrieve. Although the Evaluator
762         * are usually constructed only for the concrete setting, this parameter
763         * allows creation of the Evaluator for multiple settings.
764         * @return the value for the requested setting. The substitution
765         * is not attempted again, so the return value cannot be another
766         * Evaluator instance. If the returned value is null, the same
767         * action is taken as if there would no value set on the particular
768         * kit level.
769         *
770         */

771         public Object JavaDoc getValue(Class JavaDoc kitClass, String JavaDoc settingName);
772
773     }
774
775
776     /** Filter is applied on every value or KitAndValue pairs returned from getValue().
777     * The filter can be registered by calling <tt>Settings.addFilter()</tt>.
778     * Each call to <tt>Settings.getValue()</tt> will first retrieve the value and
779     * then call the <tt>Filter.filterValue()</tt> to get the final value. Each call
780     * to <tt>Settings.getValueHierarchy()</tt> will first retrieve the kit-and-value
781     * array and then call the <tt>Filter.filterValueHierarchy()</tt>.
782     * If more filters are registered they are all used in the order they were added.
783     */

784     public static interface Filter {
785
786         /** Filter single value. The value can be substituted here.
787         * @param kitClass class of the kit for which the value is retrieved
788         * @param settingName name of the retrieved setting
789         * @param value value to be optionally filtered
790         */

791         public Object JavaDoc filterValue(Class JavaDoc kitClass, String JavaDoc settingName, Object JavaDoc value);
792
793         /** Filter array of kit-class and value pairs. The pairs can be completely
794         * substituted with an array with different length and different members.
795         * @param kitClass class of the kit for which the value is retrieved
796         * @param settingName name of the retrieved setting
797         * @param kavArray kit-class and value array to be filtered
798         */

799         public KitAndValue[] filterValueHierarchy(Class JavaDoc kitClass, String JavaDoc settingName,
800                 KitAndValue[] kavArray);
801
802     }
803
804     // This is just for debugging and should not normally be used.
805
private static final class LoggingMap extends HashMap JavaDoc {
806         
807         private Class JavaDoc kitClass;
808         private Level JavaDoc logLevel;
809         
810         public LoggingMap(Class JavaDoc kitClass, Level JavaDoc logLevel) {
811             super();
812             this.kitClass = kitClass;
813             this.logLevel = logLevel;
814         }
815         
816         @Override JavaDoc
817         public Object JavaDoc put(Object JavaDoc key,Object JavaDoc value) {
818             if (key != null &&
819                 (key.equals(SettingsNames.RENDERING_HINTS) ||
820                  key.equals("textAntialiasing") //NOI18N
821
)) {
822                 String JavaDoc msg = "Settings map: put('" + key + "' to '" + value + "') for kitClass=" + kitClass; //NOI18N
823
LOG.log(logLevel, msg, new Throwable JavaDoc());
824             }
825             return super.put(key, value);
826         }
827     } // End of LoggingMap class
828
}
829
Popular Tags