KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > project > ui > actions > ActionsUtil


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.project.ui.actions;
21
22 import java.text.MessageFormat JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29 import javax.swing.Action JavaDoc;
30 import org.netbeans.api.project.FileOwnerQuery;
31 import org.netbeans.api.project.Project;
32 import org.netbeans.spi.project.ActionProvider;
33 import org.netbeans.api.project.ProjectUtils;
34 import org.openide.filesystems.FileObject;
35 import org.openide.loaders.DataObject;
36 import org.openide.util.Lookup;
37 import org.openide.util.WeakSet;
38
39 /** Nice utility methods to be used in ProjectBased Actions
40  *
41  * @author Pet Hrebejk
42  */

43 class ActionsUtil {
44     
45     /*
46     public static LookupResultsCache lookupResultsCache;
47      */

48     
49     public static final ShortcutsManager SHORCUTS_MANAGER = new ShortcutsManager();
50     
51     public static HashMap JavaDoc<String JavaDoc,MessageFormat JavaDoc> pattern2format = new HashMap JavaDoc<String JavaDoc,MessageFormat JavaDoc>();
52     
53     /** Finds all projects in given lookup. If the command is not null it will check
54      * whther given command is enabled on all projects. If and only if all projects
55      * have the command supported it will return array including the project. If there
56      * is one project with the command disabled it will return empty array.
57      */

58     public static Project[] getProjectsFromLookup( Lookup lookup, String JavaDoc command ) {
59         /*
60         if ( lookupResultsCache == null ) {
61             lookupResultsCache = new LookupResultsCache( new Class[] { Project.class, DataObject.class } );
62         }
63         
64         Project[] projectsArray = lookupResultsCache.getProjects( lookup );
65          */

66         // #74161: do not cache
67
// First find out whether there is a project directly in the Lookup
68
Set JavaDoc<Project> result = new HashSet JavaDoc<Project>();
69         for (Project p : lookup.lookupAll(Project.class)) {
70             result.add(p);
71         }
72         // Now try to guess the project from dataobjects
73
for (DataObject dObj : lookup.lookupAll(DataObject.class)) {
74             FileObject fObj = dObj.getPrimaryFile();
75             Project p = FileOwnerQuery.getOwner(fObj);
76             if ( p != null ) {
77                 result.add( p );
78             }
79         }
80         Project[] projectsArray = result.toArray(new Project[result.size()]);
81                 
82         if ( command != null ) {
83             // All projects have to have the command enabled
84
for (Project p : projectsArray) {
85                 if (!commandSupported(p, command, lookup)) {
86                     return new Project[0];
87                 }
88             }
89         }
90         
91         return projectsArray;
92     }
93
94     /** In given lookup will find all FileObjects owned by given project
95      * with given command supported.
96      */

97     public static FileObject[] getFilesFromLookup( Lookup lookup, Project project ) {
98         HashSet JavaDoc<FileObject> result = new HashSet JavaDoc<FileObject>();
99         for (DataObject dObj : lookup.lookupAll(DataObject.class)) {
100             FileObject fObj = dObj.getPrimaryFile();
101             Project p = FileOwnerQuery.getOwner(fObj);
102             if ( p != null && p.equals( project ) ) {
103                 result.add( fObj );
104             }
105
106         }
107         
108         FileObject[] fos = new FileObject[ result.size() ];
109         result.toArray( fos );
110         return fos;
111     }
112     
113     
114     /**
115      * Tests whether given command is available on the project and whether
116      * the action as to be enabled in current Context
117      * @param project Project to test
118      * @param command Command for test
119      * @param context Lookup representing current context or null if context
120      * does not matter.
121      */

122     public static boolean commandSupported( Project project, String JavaDoc command, Lookup context ) {
123         //We have to look whether the command is supported by the project
124
ActionProvider ap = (ActionProvider)project.getLookup().lookup( ActionProvider.class );
125         if ( ap != null ) {
126             List JavaDoc commands = Arrays.asList( ap.getSupportedActions() );
127             if ( commands.contains( command ) ) {
128                 if (context == null || ap.isActionEnabled(command, context)) {
129                     //System.err.println("cS: true project=" + project + " command=" + command + " context=" + context);
130
return true;
131                 }
132             }
133         }
134         //System.err.println("cS: false project=" + project + " command=" + command + " context=" + context);
135
return false;
136     }
137     
138     
139     
140     public static String JavaDoc formatProjectSensitiveName( String JavaDoc namePattern, Project projects[] ) {
141      
142         // Set the action's name
143
if ( projects == null || projects.length == 0 ) {
144             // No project selected
145
return ActionsUtil.formatName( namePattern, 0, null );
146         }
147         else {
148             // Some project selected
149
// XXX what about passing an object that computes the name lazily
150
return ActionsUtil.formatName( namePattern, projects.length, ProjectUtils.getInformation( projects[0] ).getDisplayName() );
151         }
152     }
153
154     
155     /** Good for formating names of actions with some two parameter pattern
156      * {0} nuber of objects (e.g. Projects or files ) and {1} name of one
157      * or first object (e.g. Project or file) or null if the number is == 0
158      * {2} whats the type of the name 0 == normal, 1 == menu, 2 == popup
159      */

160     public static String JavaDoc formatName( String JavaDoc namePattern, int numberOfObjects, String JavaDoc firstObjectName ) {
161         
162         MessageFormat JavaDoc mf = null;
163         
164         synchronized ( pattern2format ) {
165             mf = (MessageFormat JavaDoc)pattern2format.get( namePattern );
166             if ( mf == null ) {
167                 mf = new MessageFormat JavaDoc( namePattern );
168                 pattern2format.put( namePattern, mf );
169             }
170         }
171                 
172         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
173         
174         mf.format(
175             new Object JavaDoc[] {
176                 numberOfObjects,
177                 firstObjectName == null ? "" : firstObjectName,
178             },
179             result,
180             null );
181             
182         return result.toString();
183     }
184       
185     
186     // Innerclasses ------------------------------------------------------------
187

188     /** Manages shortcuts based on the action's command. Usefull for File and
189      * projects actions.
190      */

191     
192     public static class ShortcutsManager {
193         
194         // command -> shortcut
195
Map JavaDoc<String JavaDoc,Object JavaDoc> shorcuts = new HashMap JavaDoc<String JavaDoc, Object JavaDoc>();
196         
197         // command -> WeakSet of actions
198
HashMap JavaDoc<String JavaDoc, Set JavaDoc<Action JavaDoc>> actions = new HashMap JavaDoc<String JavaDoc, Set JavaDoc<Action JavaDoc>>();
199         
200         
201         public void registerAction( String JavaDoc command, Action JavaDoc action ) {
202             
203             synchronized ( this ) {
204                 Set JavaDoc<Action JavaDoc> commandActions = actions.get( command );
205
206                 if ( commandActions == null ) {
207                     commandActions = new WeakSet<Action JavaDoc>();
208                     actions.put( command, commandActions );
209                 }
210                 
211                 commandActions.add( action );
212                                 
213             }
214             
215             Object JavaDoc shorcut = getShortcut( command );
216             
217             if ( shorcut != null ) {
218                 action.putValue( Action.ACCELERATOR_KEY, shorcut );
219             }
220             
221         }
222         
223         
224         public void registerShortcut( String JavaDoc command, Object JavaDoc shortcut ) {
225             
226             Set JavaDoc<Action JavaDoc> actionsToChange = null;
227             
228             synchronized ( this ) {
229                 
230                 Object JavaDoc exShorcut = getShortcut( command );
231                 
232                 if ( ( exShorcut != null && exShorcut.equals( shortcut ) ) || // Shorcuts are equal
233
( exShorcut == null && shortcut == null ) ) { // or both are null
234
return; // No action needed
235
}
236                                 
237                 shorcuts.put( command, shortcut );
238                 
239                 Set JavaDoc<Action JavaDoc> commandActions = actions.get( command );
240                 if ( commandActions != null && !commandActions.isEmpty() ) {
241                     actionsToChange = new HashSet JavaDoc<Action JavaDoc>();
242                     actionsToChange.addAll( commandActions );
243                 }
244                 
245             }
246                         
247             if ( actionsToChange != null ) {
248                 // Need to change actions in existing actions
249
for (Action JavaDoc a : actionsToChange) {
250                     if ( a != null ) {
251                         a.putValue( Action.ACCELERATOR_KEY, shortcut );
252                     }
253                 }
254             }
255             
256         }
257         
258         public synchronized Object JavaDoc getShortcut( String JavaDoc command ) {
259             return shorcuts.get( command );
260         }
261                 
262     }
263     
264     /** Caches the projects and files included in the last quried lookup.
265      *
266      * Using weak references to fix issue #67846. Please note that holding the
267      * lookup results weak may cause that the cache will miss much more often
268      * than strictly necessary, but it is the best solution found so far.
269      * Holding the results weak should not break the correctness, it may only
270      * cause the cache will not work very well (or not at all).
271      *
272      * Please see also the tests.
273      */

274     /* XXX #74161: does not actually work
275     private static class LookupResultsCache implements LookupListener {
276         
277         private Class<?> watch[];
278         
279         private Reference<Lookup> lruLookup;
280         private List<Reference<Lookup.Result>> lruResults;
281         private Project[] projects;
282                 
283         LookupResultsCache( Class[] watch ) {
284             this.watch = watch;
285         }
286         
287         public synchronized Project[] getProjects( Lookup lookup ) {
288             Lookup lruLookupLocal = lruLookup != null ? lruLookup.get() : null;
289             
290             if ( lookup != lruLookupLocal ) { // Lookup changed
291                 if ( lruResults != null ) {
292                     for (Reference<Lookup.Result> r : lruResults) {
293                         Lookup.Result result = r.get();
294                         if (result != null) {
295                             result.removeLookupListener( this ); // Deregister
296                         }
297                     }
298                     lruResults = null;
299                 }
300                 makeDirty();
301                 lruLookupLocal = null;
302             }
303             
304             if ( lruLookupLocal == null ) { // Needs to attach to lookup
305                 lruLookup = new CleanableWeakReference<Lookup>(lruLookupLocal = lookup);
306                 lruResults = new ArrayList<Reference<Lookup.Result>>();
307                 for (Class<?> c : watch) {
308                     Lookup.Result result = lookup.lookupResult(c);
309                     
310                     result.allItems();
311                     result.addLookupListener( this );
312                     
313                     lruResults.add(new CleanableWeakReference<Lookup.Result>(result));
314                 }
315             }
316             
317             if ( isDirty() ) { // Needs to recompute the result
318                 
319                 Set<Project> result = new HashSet<Project>();
320
321                 // First find out whether there is a project directly in the Lookup
322                 for (Project p : lruLookupLocal.lookupAll(Project.class)) {
323                     result.add(p);
324                 }
325
326                 // Now try to guess the project from dataobjects
327                 for (DataObject dObj : lruLookupLocal.lookupAll(DataObject.class)) {
328                     FileObject fObj = dObj.getPrimaryFile();
329                     Project p = FileOwnerQuery.getOwner(fObj);
330                     if ( p != null ) {
331                         result.add( p );
332                     }
333
334                 }
335
336                 projects = new Project[ result.size() ];
337                 result.toArray( projects );
338
339             }
340                         
341             return projects;
342         }
343                         
344                 
345         private boolean isDirty() {
346             return projects == null;
347         }
348         
349         private synchronized void makeDirty() {
350             projects = null;
351         }
352                 
353         // Lookup listener implementation --------------------------------------
354         
355         public void resultChanged( LookupEvent e ) {
356             makeDirty();
357         }
358         
359         private class CleanableWeakReference<T> extends WeakReference<T> implements Runnable {
360             
361             public CleanableWeakReference(T o) {
362                 super(o, Utilities.activeReferenceQueue());
363             }
364
365             public void run() {
366                 synchronized (LookupResultsCache.this) {
367                     lruLookup = null;
368                     lruResults = null;
369                     projects = null;
370                 }
371             }
372         }
373         
374     }
375      */

376
377 }
378
Popular Tags