1 19 20 package org.netbeans.modules.ant.freeform.ui; 21 22 import java.awt.Image ; 23 import java.awt.event.ActionEvent ; 24 import java.beans.PropertyChangeEvent ; 25 import java.beans.PropertyChangeListener ; 26 import java.util.ArrayList ; 27 import java.util.Arrays ; 28 import java.util.Collection ; 29 import java.util.HashMap ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import javax.swing.AbstractAction ; 36 import javax.swing.Action ; 37 import javax.swing.JSeparator ; 38 import javax.swing.event.ChangeEvent ; 39 import javax.swing.event.ChangeListener ; 40 import org.netbeans.api.project.Project; 41 import org.netbeans.api.project.ProjectUtils; 42 import org.netbeans.api.project.SourceGroup; 43 import org.netbeans.api.project.Sources; 44 import org.openide.ErrorManager; 45 import org.openide.filesystems.FileObject; 46 import org.openide.filesystems.FileStateInvalidException; 47 import org.openide.filesystems.FileStatusEvent; 48 import org.openide.filesystems.FileStatusListener; 49 import org.openide.filesystems.FileSystem; 50 import org.openide.filesystems.FileUtil; 51 import org.openide.filesystems.Repository; 52 import org.openide.loaders.DataFolder; 53 import org.openide.loaders.DataObject; 54 import org.openide.loaders.DataObjectNotFoundException; 55 import org.openide.loaders.FolderLookup; 56 import org.openide.nodes.FilterNode; 57 import org.openide.nodes.Node; 58 import org.openide.util.Lookup; 59 import org.openide.util.RequestProcessor; 60 import org.openide.util.WeakListeners; 61 62 63 73 public final class ProjectNodeWrapper extends FilterNode implements Runnable , FileStatusListener, ChangeListener , PropertyChangeListener { 74 75 private Set <FileObject> files; 76 private Map <FileSystem,FileStatusListener> fileSystemListeners; 77 private RequestProcessor.Task task; 78 private final Object privateLock = new Object (); 79 private boolean iconChange; 80 private boolean nameChange; 81 private ChangeListener sourcesListener; 82 private Map <SourceGroup,PropertyChangeListener > groupsListeners; 83 84 public static final Action GENERIC_PROJECTS_ACTIONS_MARKER = new AbstractAction () { 85 public void actionPerformed(ActionEvent e) { 86 } 87 }; 88 89 public ProjectNodeWrapper(Node toWrap) { 90 super(toWrap); 91 setProjectFiles(); 92 } 93 94 public Action [] getActions(boolean context) { 95 Action [] actions = super.getActions(context); 96 97 List <Action > result = new ArrayList <Action >(); 98 99 for (int cntr = 0; cntr < actions.length; cntr++) { 100 if (actions[cntr] != GENERIC_PROJECTS_ACTIONS_MARKER) { 101 result.add(actions[cntr]); 102 } else { 103 try { 105 Repository repository = Repository.getDefault(); 106 FileSystem sfs = repository.getDefaultFileSystem(); 107 FileObject fo = sfs.findResource("Projects/Actions"); if (fo != null) { 109 DataObject dobj = DataObject.find(fo); 110 FolderLookup actionRegistry = new FolderLookup((DataFolder)dobj); 111 Lookup lookup = actionRegistry.getLookup(); 112 Iterator <? extends Object > it = lookup.lookupAll(Object .class).iterator(); 113 if (it.hasNext()) { 114 result.add(null); 115 } 116 while (it.hasNext()) { 117 Object next = it.next(); 118 if (next instanceof Action ) { 119 result.add((Action ) next); 120 } else if (next instanceof JSeparator ) { 121 result.add(null); 122 } 123 } 124 } 125 } catch (DataObjectNotFoundException ex) { 126 ErrorManager.getDefault().notify(ex); 128 } 129 } 130 } 131 132 return result.toArray(new Action [result.size()]); 133 } 134 135 136 protected final void setProjectFiles() { 137 Project prj = getLookup().lookup(Project.class); 138 139 if (prj != null) { 140 setProjectFiles(prj); 141 } else { 142 ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Node: " + getOriginal() + " wrapped with ProjectNodeWrapper, but does not contain a Project in the lookup!"); 143 } 144 } 145 146 protected final void setProjectFiles(Project project) { 147 Sources sources = ProjectUtils.getSources(project); if (sourcesListener == null) { 149 sourcesListener = WeakListeners.change(this, sources); 150 sources.addChangeListener(sourcesListener); 151 } 152 setGroups(Arrays.asList(sources.getSourceGroups(Sources.TYPE_GENERIC))); 153 } 154 155 private final void setGroups(Collection <SourceGroup> groups) { 156 if (groupsListeners != null) { 157 for (Map.Entry <SourceGroup,PropertyChangeListener > entry : groupsListeners.entrySet()) { 158 entry.getKey().removePropertyChangeListener(entry.getValue()); 159 } 160 } 161 groupsListeners = new HashMap <SourceGroup,PropertyChangeListener >(); 162 Set <FileObject> roots = new HashSet <FileObject>(); 163 for (SourceGroup group : groups) { 164 PropertyChangeListener pcl = WeakListeners.propertyChange(this, group); 165 groupsListeners.put(group, pcl); 166 group.addPropertyChangeListener(pcl); 167 FileObject fo = group.getRootFolder(); 168 roots.add(fo); 169 } 170 setFiles(roots); 171 } 172 173 protected final void setFiles(Set <FileObject> files) { 174 if (fileSystemListeners != null) { 175 for (Map.Entry <FileSystem,FileStatusListener> entry : fileSystemListeners.entrySet()) { 176 entry.getKey().removeFileStatusListener(entry.getValue()); 177 } 178 } 179 180 fileSystemListeners = new HashMap <FileSystem,FileStatusListener>(); 181 this.files = files; 182 if (files == null) return; 183 184 Set <FileSystem> hookedFileSystems = new HashSet <FileSystem>(); 185 for (FileObject fo : files) { 186 try { 187 FileSystem fs = fo.getFileSystem(); 188 if (hookedFileSystems.contains(fs)) { 189 continue; 190 } 191 hookedFileSystems.add(fs); 192 FileStatusListener fsl = FileUtil.weakFileStatusListener(this, fs); 193 fs.addFileStatusListener(fsl); 194 fileSystemListeners.put(fs, fsl); 195 } catch (FileStateInvalidException e) { 196 ErrorManager err = ErrorManager.getDefault(); 197 err.annotate(e, "Can not get " + fo + " filesystem, ignoring..."); err.notify(ErrorManager.INFORMATIONAL, e); 199 } 200 } 201 } 202 203 241 public Image getIcon(int type) { 242 Image img = super.getIcon(type); 243 244 if (files != null && files.iterator().hasNext()) { 245 try { 246 FileObject fo = files.iterator().next(); 247 img = fo.getFileSystem().getStatus().annotateIcon(img, type, files); 248 } catch (FileStateInvalidException e) { 249 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 250 } 251 } 252 253 return img; 254 } 255 256 public Image getOpenedIcon(int type) { 257 Image img = super.getOpenedIcon(type); 258 259 if (files != null && files.iterator().hasNext()) { 260 try { 261 FileObject fo = files.iterator().next(); 262 img = fo.getFileSystem().getStatus().annotateIcon(img, type, files); 263 } catch (FileStateInvalidException e) { 264 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 265 } 266 } 267 268 return img; 269 } 270 271 public void run() { 272 boolean fireIcon; 273 boolean fireName; 274 synchronized (privateLock) { 275 fireIcon = iconChange; 276 fireName = nameChange; 277 iconChange = false; 278 nameChange = false; 279 } 280 if (fireIcon) { 281 fireIconChange(); 282 fireOpenedIconChange(); 283 } 284 if (fireName) { 285 fireDisplayNameChange(null, null); 286 } 287 } 288 289 public void annotationChanged(FileStatusEvent event) { 290 if (task == null) { 291 task = RequestProcessor.getDefault().create(this); 292 } 293 294 synchronized (privateLock) { 295 if ((iconChange == false && event.isIconChange()) || (nameChange == false && event.isNameChange())) { 296 for (FileObject fo : files) { 297 if (event.hasChanged(fo)) { 298 iconChange |= event.isIconChange(); 299 nameChange |= event.isNameChange(); 300 } 301 } 302 } 303 } 304 305 task.schedule(50); } 307 308 public void stateChanged(ChangeEvent e) { 310 setProjectFiles(); 311 } 312 313 public void propertyChange(PropertyChangeEvent evt) { 315 setProjectFiles(); 316 } 317 318 } 319 | Popular Tags |