KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > scripting > php > webproject > ui > PhpProjectLogicalView


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.scripting.php.webproject.ui;
21
22 import java.awt.Image JavaDoc;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.util.AbstractCollection JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.Enumeration JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.ResourceBundle JavaDoc;
35 import java.util.Set JavaDoc;
36 import javax.swing.Action JavaDoc;
37 import javax.swing.JSeparator JavaDoc;
38 import javax.swing.SwingUtilities JavaDoc;
39 import javax.swing.event.ChangeEvent JavaDoc;
40 import javax.swing.event.ChangeListener JavaDoc;
41 import javax.swing.event.EventListenerList JavaDoc;
42 import org.netbeans.modules.scripting.php.webproject.PhpProject;
43 import org.netbeans.api.project.FileOwnerQuery;
44 import org.netbeans.api.project.Project;
45 import org.netbeans.api.project.ProjectUtils;
46 import org.netbeans.api.project.SourceGroup;
47 import org.netbeans.api.project.Sources;
48 import org.netbeans.api.queries.VisibilityQuery;
49 import org.netbeans.spi.project.ActionProvider;
50 import org.netbeans.spi.project.ui.LogicalViewProvider;
51 import org.netbeans.spi.project.ui.support.CommonProjectActions;
52 import org.netbeans.spi.project.ui.support.DefaultProjectOperations;
53 import org.netbeans.spi.project.ui.support.ProjectSensitiveActions;
54 import org.openide.ErrorManager;
55 import org.openide.actions.FileSystemAction;
56 import org.openide.actions.FindAction;
57 import org.openide.actions.PasteAction;
58 import org.openide.actions.ToolsAction;
59 import org.openide.filesystems.FileChangeListener;
60 import org.openide.filesystems.FileEvent;
61 import org.openide.filesystems.FileObject;
62 import org.openide.filesystems.FileRenameEvent;
63 import org.openide.filesystems.FileStateInvalidException;
64 import org.openide.filesystems.FileStatusEvent;
65 import org.openide.filesystems.FileStatusListener;
66 import org.openide.filesystems.FileSystem;
67 import org.openide.filesystems.FileUtil;
68 import org.openide.filesystems.Repository;
69 import org.openide.loaders.ChangeableDataFilter;
70 import org.openide.loaders.DataFilter;
71 import org.openide.loaders.DataFolder;
72 import org.openide.loaders.DataObject;
73 import org.openide.loaders.DataObjectNotFoundException;
74 import org.openide.loaders.FolderLookup;
75 import org.openide.nodes.AbstractNode;
76 import org.openide.nodes.Children;
77 import org.openide.nodes.FilterNode;
78 import org.openide.nodes.Node;
79 import org.openide.util.HelpCtx;
80 import org.openide.util.Lookup;
81 import org.openide.util.NbBundle;
82 import org.openide.util.RequestProcessor;
83 import org.openide.util.Utilities;
84 import org.openide.util.WeakListeners;
85 import org.openide.util.actions.SystemAction;
86 import org.openide.util.lookup.Lookups;
87
88 /**
89  *
90  * @author marcow
91  */

92 public class PhpProjectLogicalView implements LogicalViewProvider {
93     private static final String JavaDoc KEY_SOURCE_BASE = "srcBase"; // NOI18N
94
private static final String JavaDoc KEY_CONF_FILES = "confFiles"; //NOI18N
95
private static final Set JavaDoc<Object JavaDoc> EMPTY_SET = new HashSet JavaDoc<Object JavaDoc>();
96     
97     private final PhpProject project;
98     
99     /** Creates a new instance of PhpProjectLogicalView */
100     public PhpProjectLogicalView(PhpProject project) {
101         this.project = project;
102         assert project != null;
103     }
104     
105     public Node createLogicalView() {
106         return new PhpProjectRootNode();
107     }
108
109     public Node findPath(Node root, Object JavaDoc target) {
110         Project project = (Project) root.getLookup().lookup(Project.class);
111         if (project == null)
112             return null;
113
114         if (target instanceof FileObject) {
115             FileObject fo = (FileObject) target;
116             Project owner = FileOwnerQuery.getOwner(fo);
117             if (!project.equals(owner)) {
118                 return null; // Don't waste time if project does not own the fo
119
}
120             // XXX Find the right child
121
System.err.println("mw PhpProjectLogicalView.findPath(" + root + ", " + target + ") XXX");
122         }
123         
124         return null;
125     }
126
127     private static Lookup createLookup(Project project) {
128         DataFolder rootFolder = DataFolder.findFolder(project.getProjectDirectory());
129         // XXX Remove root folder after FindAction rewrite
130
return Lookups.fixed(new Object JavaDoc[] { project, rootFolder });
131     }
132     
133     
134     private final class PhpProjectRootNode extends AbstractNode
135             implements FileStatusListener, ChangeListener JavaDoc, PropertyChangeListener JavaDoc, Runnable JavaDoc {
136         private Set JavaDoc<FileObject> files;
137         private Map JavaDoc<FileSystem, FileStatusListener> fileSystemListeners;
138         private Map JavaDoc<SourceGroup, PropertyChangeListener JavaDoc> groupsListeners;
139         private final Object JavaDoc privateLock = new Object JavaDoc();
140         private ChangeListener JavaDoc sourcesListener;
141         private RequestProcessor.Task task;
142         private boolean iconChange;
143         private boolean nameChange;
144         
145         public PhpProjectRootNode() {
146             super(new LogicalViewChildren(project), createLookup(project));
147             setIconBaseWithExtension("org/netbeans/modules/scripting/php/webproject/resources/PhpProject.png");
148             super.setName(ProjectUtils.getInformation( project).getDisplayName());
149             setProjectFiles(project);
150         }
151         
152         public Image JavaDoc getIcon(int type) {
153             Image JavaDoc img = super.getIcon(type);
154
155             if (files != null && files.iterator().hasNext()) {
156                 try {
157                     FileObject fo = files.iterator().next();
158                     img = fo.getFileSystem().getStatus().annotateIcon(img, type, files);
159                 } catch (FileStateInvalidException e) {
160                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
161                 }
162             }
163
164             return img;
165         }
166
167         public Image JavaDoc getOpenedIcon(int type) {
168             Image JavaDoc img = super.getOpenedIcon(type);
169
170             if (files != null && files.iterator().hasNext()) {
171                 try {
172                     FileObject fo = files.iterator().next();
173                     img = fo.getFileSystem().getStatus().annotateIcon (img, type, files);
174                 } catch (FileStateInvalidException e) {
175                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
176                 }
177             }
178
179             return img;
180         }
181
182
183         public void run() {
184             boolean fireIcon;
185             boolean fireName;
186             
187             synchronized (privateLock) {
188                 fireIcon = iconChange;
189                 fireName = nameChange;
190                 iconChange = false;
191                 nameChange = false;
192             }
193             
194             if (fireIcon) {
195                 fireIconChange();
196                 fireOpenedIconChange();
197             }
198             
199             if (fireName) {
200                 fireDisplayNameChange(null, null);
201             }
202         }
203
204         public void annotationChanged(FileStatusEvent event) {
205             if (task == null) {
206                 task = RequestProcessor.getDefault().create(this);
207             }
208
209             synchronized (privateLock) {
210                 if ((iconChange == false && event.isIconChange()) ||
211                         (nameChange == false && event.isNameChange())) {
212                     Iterator JavaDoc<FileObject> it = files.iterator();
213                     
214                     while (it.hasNext()) {
215                         FileObject fo = it.next();
216                         
217                         if (event.hasChanged(fo)) {
218                             iconChange |= event.isIconChange();
219                             nameChange |= event.isNameChange();
220                         }
221                     }
222                 }
223             }
224
225             task.schedule(50); // batch by 50 ms
226
}
227
228          // sources change
229
public void stateChanged(ChangeEvent JavaDoc e) {
230             setProjectFiles(project);
231         }
232
233         // group change
234
public void propertyChange(PropertyChangeEvent JavaDoc evt) {
235             setProjectFiles(project);
236         }
237         
238         protected void setProjectFiles(Project project) {
239             Sources sources = ProjectUtils.getSources(project); // returns singleton
240

241             if (sourcesListener == null) {
242                 sourcesListener = WeakListeners.change(this, sources);
243                 sources.addChangeListener(sourcesListener);
244             }
245             
246             if (groupsListeners != null) {
247                 Iterator JavaDoc<SourceGroup> it = groupsListeners.keySet().iterator();
248                 while (it.hasNext()) {
249                     SourceGroup group = it.next();
250                     PropertyChangeListener JavaDoc pcl = groupsListeners.get(group);
251                     group.removePropertyChangeListener(pcl);
252                 }
253             }
254             
255             groupsListeners = new HashMap JavaDoc<SourceGroup, PropertyChangeListener JavaDoc>();
256             Set JavaDoc<FileObject> roots = new HashSet JavaDoc<FileObject>();
257             SourceGroup groups[] = sources.getSourceGroups(Sources.TYPE_GENERIC);
258             
259             for (int i = 0; i < groups.length; i++) {
260                 SourceGroup group = groups[i];
261                 PropertyChangeListener JavaDoc pcl = WeakListeners.propertyChange(this, group);
262                 groupsListeners.put(group, pcl);
263                 group.addPropertyChangeListener(pcl);
264                 FileObject fo = group.getRootFolder();
265                 
266                 if (project.getProjectDirectory().equals(fo)) {
267                     // add rather children of project's root folder than the
268
// folder itself (cf. #78994)
269
Enumeration JavaDoc<? extends FileObject> en = project.getProjectDirectory().getChildren(false);
270                     
271                     while (en.hasMoreElements()) {
272                         roots.add(en.nextElement());
273                     }
274                 } else {
275                     roots.add(fo);
276                 }
277             }
278             setFiles(roots);
279         }
280         
281         protected void setFiles(Set JavaDoc<FileObject> files) {
282             if (fileSystemListeners != null) {
283                 Iterator JavaDoc<FileSystem> it = fileSystemListeners.keySet().iterator();
284                 
285                 while (it.hasNext()) {
286                     FileSystem fs = it.next();
287                     FileStatusListener fsl = fileSystemListeners.get(fs);
288                     fs.removeFileStatusListener(fsl);
289                 }
290             }
291
292             fileSystemListeners = new HashMap JavaDoc<FileSystem, FileStatusListener>();
293             this.files = files;
294             
295             if (files == null) {
296                 return;
297             }
298
299             Iterator JavaDoc<FileObject> it = files.iterator();
300             Set JavaDoc<FileSystem> hookedFileSystems = new HashSet JavaDoc<FileSystem>();
301             
302             while (it.hasNext()) {
303                 FileObject fo = it.next();
304                 
305                 try {
306                     FileSystem fs = fo.getFileSystem();
307                     
308                     if (hookedFileSystems.contains(fs)) {
309                         continue;
310                     }
311                     
312                     hookedFileSystems.add(fs);
313                     FileStatusListener fsl = FileUtil.weakFileStatusListener(this, fs);
314                     fs.addFileStatusListener(fsl);
315                     fileSystemListeners.put(fs, fsl);
316                 } catch (FileStateInvalidException e) {
317                     ErrorManager err = ErrorManager.getDefault();
318                     err.annotate(e, "Can not get " + fo + " filesystem, ignoring..."); // NO18N
319
err.notify(ErrorManager.INFORMATIONAL, e);
320                 }
321             }
322         }
323         
324         public Action JavaDoc[] getActions(boolean context) {
325             if (context) {
326                 return super.getActions(true);
327             }
328             else {
329                 return getAdditionalActions();
330             }
331         }
332
333         public boolean canRename() {
334             return true;
335         }
336         
337         public void setName(String JavaDoc s) {
338             DefaultProjectOperations.performDefaultRenameOperation(project, s);
339         }
340
341         public HelpCtx getHelpCtx() {
342             return new HelpCtx(PhpProjectRootNode.class);
343         }
344         
345         private Action JavaDoc[] getAdditionalActions() {
346             ResourceBundle JavaDoc bundle = NbBundle.getBundle(PhpProjectRootNode.class);
347
348             List JavaDoc<Action JavaDoc> actions = new ArrayList JavaDoc<Action JavaDoc>();
349             
350             actions.add(CommonProjectActions.newFileAction());
351             actions.add(null);
352             actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_RUN,
353                     bundle.getString("LBL_RunAction_Name"), null)); // NOI18N
354
actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_DEBUG,
355                     bundle.getString("LBL_DebugAction_Name"), null)); // NOI18N
356
actions.add(null);
357             actions.add(CommonProjectActions.setAsMainProjectAction());
358             actions.add(CommonProjectActions.closeProjectAction());
359             actions.add(null);
360             actions.add(CommonProjectActions.renameProjectAction());
361             actions.add(CommonProjectActions.moveProjectAction());
362             actions.add(CommonProjectActions.copyProjectAction());
363             actions.add(CommonProjectActions.deleteProjectAction());
364             actions.add(null);
365             actions.add(SystemAction.get(FindAction.class));
366
367             // honor 57874 contact
368
try {
369                 Repository repository = Repository.getDefault();
370                 FileSystem sfs = repository.getDefaultFileSystem();
371                 FileObject fo = sfs.findResource("Projects/Actions"); // NOI18N
372

373                 if (fo != null) {
374                     DataObject dobj = DataObject.find(fo);
375                     FolderLookup actionRegistry = new FolderLookup((DataFolder)dobj);
376                     Lookup.Template<Object JavaDoc> query = new Lookup.Template<Object JavaDoc>(Object JavaDoc.class);
377                     Lookup lookup = actionRegistry.getLookup();
378                     Iterator JavaDoc it = lookup.lookup(query).allInstances().iterator();
379                     
380                     if (it.hasNext()) {
381                         actions.add(null);
382                     }
383                     
384                     while (it.hasNext()) {
385                         Object JavaDoc next = it.next();
386                         
387                         if (next instanceof Action JavaDoc) {
388                             actions.add((Action JavaDoc)next);
389                         } else if (next instanceof JSeparator JavaDoc) {
390                             actions.add(null);
391                         }
392                     }
393                 }
394             } catch (DataObjectNotFoundException ex) {
395                 // data folder for exitinf fileobject expected
396
ErrorManager.getDefault().notify(ex);
397             }
398
399             actions.add(null);
400             actions.add(SystemAction.get(ToolsAction.class));
401             actions.add(null);
402             actions.add(CommonProjectActions.customizeProjectAction());
403
404             return (Action JavaDoc[])actions.toArray(new Action JavaDoc[actions.size()]);
405         }
406     }
407     
408     private static final class LogicalViewChildren extends Children.Keys<Object JavaDoc>
409             implements ChangeListener JavaDoc, FileChangeListener {
410     
411         private final PhpProject project;
412         private final FileObject projectDir;
413         
414         public LogicalViewChildren(PhpProject project) {
415             assert project != null;
416             this.project = project;
417             this.projectDir = project.getProjectDirectory();
418         }
419
420         public void stateChanged(ChangeEvent JavaDoc e) {
421             rebuildKeys();
422         }
423
424         public void fileAttributeChanged(org.openide.filesystems.FileAttributeEvent fe) {
425         }
426
427         public void fileChanged(FileEvent fe) {
428         }
429
430         public void fileDataCreated(FileEvent fe) {
431             rebuildKeys();
432         }
433
434         public void fileDeleted(FileEvent fe) {
435             rebuildKeys();
436         }
437
438         public void fileFolderCreated(FileEvent fe) {
439             rebuildKeys();
440         }
441
442         public void fileRenamed(FileRenameEvent fe) {
443             rebuildKeys();
444         }
445
446         private void rebuildKeys() {
447             SwingUtilities.invokeLater(new Runnable JavaDoc() {
448                 public void run() {
449                     buildKeys();
450                 }
451             });
452         }
453         
454         
455         protected void addNotify() {
456             super.addNotify();
457             projectDir.addFileChangeListener(this);
458             
459             Sources sources = ProjectUtils.getSources(project);
460             
461             if (sources != null) {
462                 sources.addChangeListener(this);
463             }
464             buildKeys();
465         }
466
467         protected void removeNotify() {
468             setKeys(EMPTY_SET);
469             projectDir.removeFileChangeListener(this);
470
471             Sources sources = ProjectUtils.getSources(project);
472             
473             if (sources != null) {
474                 sources.removeChangeListener(this);
475             }
476             
477             super.removeNotify();
478         }
479         
480         private void buildKeys() {
481             List JavaDoc<String JavaDoc> l = new ArrayList JavaDoc<String JavaDoc>();
482             DataFolder sourceBaseDir = DataFolder.findFolder(projectDir);
483             
484             if (sourceBaseDir != null) {
485                 l.add(KEY_SOURCE_BASE);
486             }
487
488             l.add(KEY_CONF_FILES);
489             setKeys(l);
490         }
491
492         protected Node[] createNodes(Object JavaDoc key) {
493             Node n = null;
494             
495             if (key == KEY_SOURCE_BASE) {
496                 n = new SourceNode(DataFolder.findFolder(projectDir), project);
497             }
498             else if (key == KEY_CONF_FILES) {
499                 // XXX
500
}
501             
502             return n == null ? new Node[0] : new Node[] { n };
503         }
504         
505         
506     }
507     
508     private static final class SourceNode extends FilterNode {
509         private javax.swing.Action JavaDoc actions[];
510         private static final DataFilter VISIBILITY_QUERY_FILTER = new VisibilityQueryDataFilter();
511
512         private static Image JavaDoc PHP_PAGES_BADGE = Utilities.loadImage("org/netbeans/modules/scripting/php/webproject/resources/PhpBadge.png"); //NOI18N
513

514         private Project project;
515
516         SourceNode(DataFolder folder, Project project) {
517             super(folder.getNodeDelegate(), folder.createNodeChildren(VISIBILITY_QUERY_FILTER));
518             this.project = project;
519         }
520
521         public Image JavaDoc getIcon(int type) {
522             return computeIcon(false, type);
523         }
524
525         public Image JavaDoc getOpenedIcon(int type) {
526             return computeIcon(true, type);
527         }
528
529         private Node getDataFolderNodeDelegate() {
530             return ((DataFolder)getLookup().lookup(DataFolder.class)).getNodeDelegate();
531         }
532
533         private Image JavaDoc computeIcon(boolean opened, int type) {
534             Image JavaDoc image;
535
536             image = opened ? getDataFolderNodeDelegate().getOpenedIcon(type) : getDataFolderNodeDelegate().getIcon(type);
537             image = Utilities.mergeImages(image, PHP_PAGES_BADGE, 7, 7);
538
539             return image;
540         }
541
542         public String JavaDoc getDisplayName () {
543             return NbBundle.getMessage(PhpProjectLogicalView.class, "LBL_SourceNode"); //NOI18N
544
}
545
546         public javax.swing.Action JavaDoc[] getActions(boolean context) {
547             if (actions == null) {
548                 actions = new Action JavaDoc[7];
549                 actions[0] = CommonProjectActions.newFileAction();
550                 actions[1] = null;
551                 actions[2] = SystemAction.get(FileSystemAction.class);
552                 actions[3] = null;
553                 actions[4] = SystemAction.get(FindAction.class);
554                 actions[5] = null;
555                 actions[6] = SystemAction.get(PasteAction.class);
556             }
557             return actions;
558         }
559     }
560
561     private static final class VisibilityQueryDataFilter implements ChangeListener JavaDoc, ChangeableDataFilter {
562         EventListenerList JavaDoc ell = new EventListenerList JavaDoc();
563
564         public VisibilityQueryDataFilter() {
565             VisibilityQuery.getDefault().addChangeListener( this );
566         }
567
568         public boolean acceptDataObject(DataObject obj) {
569             FileObject fo = obj.getPrimaryFile();
570             
571             // Hide the nbproject folder from the source view.
572
if (fo.getName().equals("nbproject")) {
573                 return false;
574             }
575             
576             return VisibilityQuery.getDefault().isVisible(fo);
577         }
578
579         public void stateChanged(ChangeEvent JavaDoc e) {
580             Object JavaDoc[] listeners = ell.getListenerList();
581             ChangeEvent JavaDoc event = null;
582             
583             for (int i = listeners.length - 2; i >= 0; i -= 2) {
584                 if (listeners[i] == ChangeListener JavaDoc.class) {
585                     if (event == null) {
586                         event = new ChangeEvent JavaDoc(this);
587                     }
588                     
589                     ((ChangeListener JavaDoc)listeners[i + 1]).stateChanged(event);
590                 }
591             }
592         }
593
594         public void addChangeListener(ChangeListener JavaDoc listener) {
595             ell.add(ChangeListener JavaDoc.class, listener);
596         }
597
598         public void removeChangeListener(ChangeListener JavaDoc listener) {
599             ell.remove(ChangeListener JavaDoc.class, listener);
600         }
601     }
602 }
603
Popular Tags