KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > options > CategoryModel


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.modules.options;
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.lang.ref.Reference JavaDoc;
24 import java.lang.ref.WeakReference JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Arrays JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.Collections JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.LinkedHashMap JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.concurrent.SynchronousQueue JavaDoc;
35 import javax.swing.Icon JavaDoc;
36 import javax.swing.JComponent JavaDoc;
37 import org.netbeans.spi.options.OptionsCategory;
38 import org.netbeans.spi.options.OptionsPanelController;
39 import org.openide.filesystems.FileObject;
40 import org.openide.filesystems.Repository;
41 import org.openide.loaders.DataFolder;
42 import org.openide.loaders.FolderLookup;
43 import org.openide.util.HelpCtx;
44 import org.openide.util.Lookup;
45 import org.openide.util.LookupEvent;
46 import org.openide.util.LookupListener;
47 import org.openide.util.RequestProcessor;
48 import org.openide.util.lookup.ProxyLookup;
49
50 /**
51  * @author Radek Matous
52  */

53 public final class CategoryModel implements LookupListener {
54     private static Reference JavaDoc<CategoryModel> INSTANCE = new WeakReference JavaDoc<CategoryModel>(new CategoryModel());
55     private final RequestProcessor RP = new RequestProcessor();
56     private static String JavaDoc currentCategoryID = null;
57     private String JavaDoc highlitedCategoryID = null;
58     private boolean categoriesValid = true;
59     private final Map JavaDoc<String JavaDoc, CategoryModel.Category> id2Category =
60             Collections.synchronizedMap(new LinkedHashMap JavaDoc<String JavaDoc, CategoryModel.Category>());
61     private MasterLookup masterLookup;
62     private final RequestProcessor.Task masterLookupTask = RP.create(new Runnable JavaDoc() {
63         public void run() {
64             String JavaDoc[] categoryIDs = getCategoryIDs();
65             List JavaDoc<Lookup> all = new ArrayList JavaDoc<Lookup>();
66             for (int i = 0; i < categoryIDs.length; i++) {
67                 Category item = getCategory(categoryIDs[i]);
68                 Lookup lkp = item.getLookup();
69                 assert lkp != null;
70                 if (lkp != Lookup.EMPTY) {
71                     all.add(lkp);
72                 }
73             }
74             getMasterLookup().setLookups(all);
75         }
76     },true);
77     private final RequestProcessor.Task categoryTask = RP.create(new Runnable JavaDoc() {
78         public void run() {
79             Map JavaDoc<String JavaDoc, OptionsCategory> all = loadOptionsCategories();
80             Map JavaDoc<String JavaDoc, CategoryModel.Category> temp = new LinkedHashMap JavaDoc<String JavaDoc, CategoryModel.Category>();
81             for (Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, OptionsCategory>> it = all.entrySet().iterator(); it.hasNext();) {
82                 Map.Entry JavaDoc<String JavaDoc, OptionsCategory> entry = it.next();
83                 OptionsCategory oc = entry.getValue();
84                 String JavaDoc id = entry.getKey();
85                 Category cat = new Category(id, oc);
86                 temp.put(cat.getID(), cat);
87             }
88             id2Category.clear();
89             id2Category.putAll(temp);
90             masterLookupTask.schedule(0);
91         }
92     },true);
93     
94     private CategoryModel() {
95         categoryTask.schedule(0);
96     }
97         
98     public static CategoryModel getInstance() {
99         CategoryModel retval = (CategoryModel)INSTANCE.get();
100         if (retval == null) {
101             retval = new CategoryModel();
102             INSTANCE = new WeakReference JavaDoc<CategoryModel>(retval);
103         }
104         return retval;
105     }
106     
107     boolean needsReinit() {
108         synchronized(CategoryModel.class) {
109             return !categoriesValid;
110         }
111     }
112     
113     boolean isInitialized() {
114         return categoryTask.isFinished();
115     }
116     
117     boolean isLookupInitialized() {
118         return masterLookupTask.isFinished();
119     }
120     
121     
122     void waitForInitialization() {
123         categoryTask.waitFinished();
124     }
125         
126     public String JavaDoc getCurrentCategoryID() {
127         return verifyCategoryID(currentCategoryID);
128     }
129     
130     public void setCurrentCategoryID(String JavaDoc categoryID) {
131         currentCategoryID = verifyCategoryID(categoryID);
132     }
133     
134
135     String JavaDoc getHighlitedCategoryID() {
136         return verifyCategoryID(highlitedCategoryID);
137     }
138         
139     private String JavaDoc verifyCategoryID(String JavaDoc categoryID) {
140         String JavaDoc retval = findCurrentCategoryID(categoryID) != -1 ? categoryID : null;
141         if (retval == null) {
142             String JavaDoc[] categoryIDs = getCategoryIDs();
143             if (categoryIDs.length > 0) {
144                 retval = categoryID = categoryIDs[0];
145             }
146         }
147         return retval;
148     }
149     
150     private int findCurrentCategoryID(String JavaDoc categoryID) {
151         return categoryID == null ? -1 : Arrays.asList(getCategoryIDs()).indexOf(categoryID);
152     }
153     
154     public String JavaDoc[] getCategoryIDs() {
155         categoryTask.waitFinished();
156         Set JavaDoc<String JavaDoc> keys = id2Category.keySet();
157         return keys.toArray(new String JavaDoc[keys.size()]);
158     }
159     
160     Category getCurrent() {
161         String JavaDoc categoryID = getCurrentCategoryID();
162         return (categoryID == null) ? null : getCategory(categoryID);
163     }
164     
165     void setCurrent(Category item) {
166         item.setCurrent();
167     }
168
169     void setHighlited(Category item) {
170         item.setHighlited();
171     }
172             
173     HelpCtx getHelpCtx() {
174         final CategoryModel.Category category = getCurrent();
175         return (category == null) ? null : category.getHelpCtx();
176     }
177     
178     void update(PropertyChangeListener JavaDoc l, boolean force) {
179         String JavaDoc[] categoryIDs = getCategoryIDs();
180         for (int i = 0; i < categoryIDs.length; i++) {
181             CategoryModel.Category item = getCategory(categoryIDs[i]);
182             item.update(l, force);
183         }
184     }
185     
186     void save() {
187         String JavaDoc[] categoryIDs = getCategoryIDs();
188         for (int i = 0; i < categoryIDs.length; i++) {
189             CategoryModel.Category item = getCategory(categoryIDs[i]);
190             item.applyChanges();
191         }
192     }
193     
194     void cancel() {
195         String JavaDoc[] categoryIDs = getCategoryIDs();
196         for (int i = 0; i < categoryIDs.length; i++) {
197             CategoryModel.Category item = getCategory(categoryIDs[i]);
198             item.cancel();
199         }
200     }
201     
202     boolean dataValid() {
203         boolean retval = true;
204         String JavaDoc[] categoryIDs = getCategoryIDs();
205         for (int i = 0; retval && i < categoryIDs.length; i++) {
206             CategoryModel.Category item = getCategory(categoryIDs[i]);
207             retval = item.isValid();
208         }
209         return retval;
210     }
211     
212     boolean isChanged() {
213         boolean retval = false;
214         String JavaDoc[] categoryIDs = getCategoryIDs();
215         for (int i = 0; !retval && i < categoryIDs.length; i++) {
216             CategoryModel.Category item = getCategory(categoryIDs[i]);
217             retval = item.isChanged();
218         }
219         return retval;
220     }
221     
222     
223     void setNextCategoryAsCurrent() {
224         int idx = findCurrentCategoryID(getCurrentCategoryID());
225         String JavaDoc[] categoryIDs = getCategoryIDs();
226         if (idx >= 0 && idx+1 < categoryIDs.length) {
227             currentCategoryID = categoryIDs[idx+1];
228         } else {
229             currentCategoryID = null;
230         }
231     }
232     
233     void setPreviousCategoryAsCurrent() {
234         int idx = findCurrentCategoryID(getCurrentCategoryID());
235         String JavaDoc[] categoryIDs = getCategoryIDs();
236         if (idx >= 0 && idx < categoryIDs.length && categoryIDs.length > 0) {
237             if (idx-1 >= 0) {
238                 currentCategoryID = categoryIDs[idx-1];
239             } else {
240                 currentCategoryID = categoryIDs[categoryIDs.length-1];
241             }
242         } else {
243             currentCategoryID = null;
244         }
245     }
246     
247     
248     Category getCategory(String JavaDoc categoryID) {
249         categoryTask.waitFinished();
250         return (Category)id2Category.get(categoryID);
251     }
252         
253     private MasterLookup getMasterLookup() {
254         if (masterLookup == null) {
255             masterLookup = new MasterLookup();
256         }
257         return masterLookup;
258     }
259     
260     private Map JavaDoc<String JavaDoc, OptionsCategory> loadOptionsCategories() {
261         FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource("OptionsDialog");// NOI18N
262
if (fo != null) {
263             Lookup lookup = new FolderLookup(DataFolder.findFolder(fo),null).getLookup();//NOI18N
264
Lookup.Result<OptionsCategory> result = lookup.lookup(new Lookup.Template<OptionsCategory>(OptionsCategory.class));
265             result.addLookupListener(this);
266             Map JavaDoc<String JavaDoc, OptionsCategory> m = new LinkedHashMap JavaDoc<String JavaDoc, OptionsCategory>();
267             for (Iterator JavaDoc<? extends Lookup.Item<OptionsCategory>> it = result.allItems().iterator(); it.hasNext();) {
268                 Lookup.Item<OptionsCategory> item = it.next();
269                 m.put(item.getId(), item.getInstance());
270             }
271             return Collections.unmodifiableMap(m);
272         }
273         return Collections.<String JavaDoc, OptionsCategory>emptyMap();
274     }
275
276     public void resultChanged(LookupEvent ev) {
277         synchronized(CategoryModel.class) {
278             categoriesValid = false;
279             INSTANCE = new WeakReference JavaDoc<CategoryModel>(new CategoryModel());
280         }
281     }
282     
283     final class Category {
284         private OptionsCategory category;
285         private OptionsPanelController controller;
286         private boolean isUpdated;
287         private HelpCtx helpCtx;
288         private JComponent JavaDoc component;
289         private Lookup lookup;
290         private final String JavaDoc id;
291         
292         private Category(final String JavaDoc id, final OptionsCategory category) {
293             this.category = category;
294             this.id = id;
295         }
296         
297         boolean isCurrent() {
298             return getID().equals(getCurrentCategoryID());
299         }
300         
301         boolean isHighlited() {
302             return getID().equals(getHighlitedCategoryID());
303         }
304                 
305         private void setCurrent() {
306             setCurrentCategoryID(getID());
307         }
308
309         private void setHighlited() {
310             highlitedCategoryID = getID();
311         }
312                         
313         public Icon JavaDoc getIcon() {
314             return category.getIcon();
315         }
316
317         //whatever ID representing category (dataObject name,category name, just mnemonic, ...)
318
//for impl. #74855: Add an API for opening the Options dialog
319
public String JavaDoc getID() {
320             return id;
321         }
322         
323         public String JavaDoc getCategoryName() {
324             return category.getCategoryName();
325         }
326         
327         public String JavaDoc getTitle() {
328             return category.getTitle();
329         }
330         
331         private synchronized OptionsPanelController create() {
332             if (controller == null) {
333                 controller = category.create();
334             }
335             return controller;
336         }
337         
338         final void update(PropertyChangeListener JavaDoc l, boolean forceUpdate) {
339             if ((!isUpdated && !forceUpdate) || (isUpdated && forceUpdate)) {
340                 isUpdated = true;
341                 getComponent();
342                 create().update();
343                 if (l != null) {
344                     create().addPropertyChangeListener(l);
345                 }
346             }
347         }
348         
349         private void applyChanges() {
350             if (isUpdated) {
351                 create().applyChanges();
352             }
353         }
354         
355         private void cancel() {
356             if (isUpdated) {
357                 create().cancel();
358             }
359         }
360         
361         private boolean isValid() {
362             boolean retval = true;
363             if (isUpdated) {
364                 retval = create().isValid();
365             }
366             return retval;
367         }
368         
369         private boolean isChanged() {
370             boolean retval = false;
371             if (isUpdated) {
372                 retval = create().isChanged();
373             }
374             return retval;
375         }
376         
377         public JComponent JavaDoc getComponent() {
378             if (component == null) {
379                 component = create().getComponent(getMasterLookup());
380             }
381             return component;
382         }
383         
384         private HelpCtx getHelpCtx() {
385             if (helpCtx == null && isUpdated) {
386                 helpCtx = create().getHelpCtx();
387             }
388             return helpCtx;
389         }
390         
391         
392         private Lookup getLookup() {
393             if (lookup == null) {
394                 lookup = create().getLookup();
395             }
396             return lookup;
397         }
398     }
399     
400     private class MasterLookup extends ProxyLookup {
401         private void setLookups(List JavaDoc<Lookup> lookups) {
402             setLookups(lookups.toArray(new Lookup[lookups.size()]));
403         }
404         protected void beforeLookup(Lookup.Template template) {
405             super.beforeLookup(template);
406             masterLookupTask.waitFinished();
407         }
408     }
409 }
410
Popular Tags