1 19 20 package org.netbeans.modules.ruby.rubyproject.ui; 21 22 import java.awt.Image ; 23 import java.beans.PropertyChangeEvent ; 24 import java.beans.PropertyChangeListener ; 25 import java.util.ArrayList ; 26 import java.util.Collections ; 27 import java.util.List ; 28 import java.util.StringTokenizer ; 29 import javax.swing.Icon ; 30 import javax.swing.event.ChangeEvent ; 31 import javax.swing.event.ChangeListener ; 32 import javax.swing.event.EventListenerList ; 33 import org.netbeans.api.project.SourceGroup; 34 import org.netbeans.api.queries.VisibilityQuery; 35 import org.openide.DialogDisplayer; 36 import org.openide.NotifyDescriptor; 37 import org.openide.filesystems.FileObject; 38 import org.openide.filesystems.FileUtil; 39 import org.openide.loaders.ChangeableDataFilter; 40 import org.openide.loaders.DataFilter; 41 import org.openide.loaders.DataFolder; 42 import org.openide.loaders.DataObject; 43 import org.openide.nodes.FilterNode; 44 import org.openide.nodes.Node; 45 import org.openide.nodes.NodeNotFoundException; 46 import org.openide.nodes.NodeOp; 47 import org.openide.util.NbBundle; 48 import org.openide.util.Utilities; 49 import org.openide.util.WeakListeners; 50 import org.openide.util.lookup.Lookups; 51 import org.openide.util.lookup.ProxyLookup; 52 53 55 61 public final class TreeRootNode extends FilterNode implements PropertyChangeListener { 62 63 private static final DataFilter VISIBILITY_QUERY_FILTER = new VisibilityQueryDataFilter(); 64 65 private final SourceGroup g; 66 67 public TreeRootNode(SourceGroup g) { 68 this(DataFolder.findFolder(g.getRootFolder()), g); 69 } 70 71 private TreeRootNode(DataFolder folder, SourceGroup g) { 72 this (new FilterNode (folder.getNodeDelegate(), folder.createNodeChildren(VISIBILITY_QUERY_FILTER)),g); 73 } 74 75 private TreeRootNode (Node originalNode, SourceGroup g) { 76 super(originalNode, new PackageFilterChildren(originalNode), 77 new ProxyLookup( 78 originalNode.getLookup(), 79 Lookups.singleton(new PathFinder(g)) 80 )); 82 this.g = g; 83 g.addPropertyChangeListener(WeakListeners.propertyChange(this, g)); 84 } 85 86 static Image PACKAGE_BADGE = Utilities.loadImage( "org/netbeans/modules/ruby/rubyproject/ui/packageBadge.gif" ); 88 89 private Image computeIcon(boolean opened, int type) { 90 Icon icon = g.getIcon(opened); 91 if (icon == null) { 92 Image image = opened ? super.getOpenedIcon(type) : super.getIcon(type); 93 return Utilities.mergeImages(image, PACKAGE_BADGE, 7, 7); 94 } else { 95 return Utilities.icon2Image(icon); 96 } 97 } 98 99 public Image getIcon(int type) { 100 return computeIcon(false, type); 101 } 102 103 public Image getOpenedIcon(int type) { 104 return computeIcon(true, type); 105 } 106 107 public String getName() { 108 return g.getName(); 109 } 110 111 public String getDisplayName() { 112 return g.getDisplayName(); 113 } 114 115 public boolean canRename() { 116 return false; 117 } 118 119 public boolean canDestroy() { 120 return false; 121 } 122 123 public boolean canCut() { 124 return false; 125 } 126 127 public void propertyChange(PropertyChangeEvent ev) { 128 fireNameChange(null, null); 130 fireDisplayNameChange(null, null); 131 fireIconChange(); 132 fireOpenedIconChange(); 133 } 134 135 136 public static final class PathFinder { 137 138 private final SourceGroup g; 139 140 PathFinder(SourceGroup g) { 141 this.g = g; 142 } 143 144 public Node findPath(Node rootNode, Object o) { 145 FileObject fo; 146 if (o instanceof FileObject) { 147 fo = (FileObject) o; 148 } else if (o instanceof DataObject) { 149 fo = ((DataObject) o).getPrimaryFile(); 150 } else { 151 return null; 152 } 153 FileObject groupRoot = g.getRootFolder(); 154 if (FileUtil.isParentOf(groupRoot, fo) ) { 155 FileObject folder = fo.isFolder() ? fo : fo.getParent(); 156 String relPath = FileUtil.getRelativePath(groupRoot, folder); 157 List <String > path = new ArrayList <String >(); 158 StringTokenizer strtok = new StringTokenizer (relPath, "/"); while (strtok.hasMoreTokens()) { 160 String token = strtok.nextToken(); 161 path.add(token); 162 } 163 try { 164 Node folderNode = folder.equals(groupRoot) ? rootNode : NodeOp.findPath(rootNode, Collections.enumeration(path)); 165 if (fo.isFolder()) { 166 return folderNode; 167 } else { 168 Node[] childs = folderNode.getChildren().getNodes(true); 169 for (int i = 0; i < childs.length; i++) { 170 DataObject dobj = childs[i].getLookup().lookup(DataObject.class); 171 if (dobj != null && dobj.getPrimaryFile().getNameExt().equals(fo.getNameExt())) { 172 return childs[i]; 173 } 174 } 175 } 176 } catch (NodeNotFoundException e) { 177 e.printStackTrace(); 178 } 179 } else if (groupRoot.equals(fo)) { 180 return rootNode; 181 } 182 return null; 183 } 184 } 185 186 187 private static final class VisibilityQueryDataFilter implements ChangeListener , ChangeableDataFilter { 188 189 private static final long serialVersionUID = 1L; 191 private final EventListenerList ell = new EventListenerList (); 192 193 public VisibilityQueryDataFilter() { 194 VisibilityQuery.getDefault().addChangeListener(this); 195 } 196 197 public boolean acceptDataObject(DataObject obj) { 198 FileObject fo = obj.getPrimaryFile(); 199 return VisibilityQuery.getDefault().isVisible(fo); 200 } 201 202 public void stateChanged(ChangeEvent e) { 203 Object [] listeners = ell.getListenerList(); 204 ChangeEvent event = null; 205 for (int i = listeners.length - 2; i >= 0; i -= 2) { 206 if (listeners[i] == ChangeListener .class) { 207 if (event == null) { 208 event = new ChangeEvent (this); 209 } 210 ((ChangeListener ) listeners[i+1]).stateChanged(event); 211 } 212 } 213 } 214 215 public void addChangeListener(ChangeListener listener) { 216 ell.add(ChangeListener .class, listener); 217 } 218 219 public void removeChangeListener(ChangeListener listener) { 220 ell.remove(ChangeListener .class, listener); 221 } 222 223 } 224 225 226 private static final class PackageFilterChildren extends FilterNode.Children { 227 228 public PackageFilterChildren (final Node originalNode) { 229 super (originalNode); 230 } 231 232 @Override 233 protected Node copyNode(final Node originalNode) { 234 DataObject dobj = originalNode.getLookup().lookup(DataObject.class); 235 return (dobj instanceof DataFolder) ? new PackageFilterNode (originalNode) : super.copyNode(originalNode); 236 } 237 } 238 239 private static final class PackageFilterNode extends FilterNode { 240 241 public PackageFilterNode (final Node origNode) { 242 super (origNode, new PackageFilterChildren (origNode)); 243 } 244 245 @Override 246 public void setName (final String name) { 247 if (Utilities.isJavaIdentifier (name)) { 248 super.setName (name); 249 } 250 else { 251 DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message ( 252 NbBundle.getMessage(TreeRootNode.class,"MSG_InvalidPackageName"), NotifyDescriptor.INFORMATION_MESSAGE)); 253 } 254 } 255 256 } 257 258 } 259 | Popular Tags |