1 19 20 package org.netbeans.modules.project.ui; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.text.MessageFormat ; 25 import java.util.ArrayList ; 26 import java.util.Collections ; 27 import java.util.StringTokenizer ; 28 import javax.swing.Action ; 29 import javax.swing.event.ChangeEvent ; 30 import javax.swing.event.ChangeListener ; 31 import javax.swing.event.EventListenerList ; 32 import org.netbeans.api.project.Project; 33 import org.netbeans.api.project.ProjectUtils; 34 import org.netbeans.api.project.ProjectInformation; 35 import org.netbeans.api.project.SourceGroup; 36 import org.netbeans.api.project.Sources; 37 import org.netbeans.api.queries.VisibilityQuery; 38 import org.netbeans.spi.project.ui.support.CommonProjectActions; 39 import org.openide.ErrorManager; 40 import org.openide.filesystems.FileObject; 41 import org.openide.filesystems.FileUtil; 42 import org.openide.loaders.ChangeableDataFilter; 43 import org.openide.loaders.DataFilter; 44 import org.openide.loaders.DataFolder; 45 import org.openide.loaders.DataObject; 46 import org.openide.loaders.DataObjectNotFoundException; 47 import org.openide.nodes.FilterNode; 48 import org.openide.nodes.Node; 49 import org.openide.nodes.NodeNotFoundException; 50 import org.openide.nodes.NodeOp; 51 import org.openide.util.NbBundle; 52 import org.openide.util.Lookup; 53 import org.openide.util.WeakListeners; 54 import org.openide.util.lookup.Lookups; 55 import org.openide.util.lookup.ProxyLookup; 56 57 61 public class PhysicalView { 62 63 public static boolean isProjectDirNode( Node n ) { 64 return n instanceof GroupNode && ((GroupNode)n).isProjectDir; 65 } 66 67 public static Node[] createNodesForProject( Project p ) { 68 Sources s = ProjectUtils.getSources(p); 69 SourceGroup[] groups = s.getSourceGroups(Sources.TYPE_GENERIC); 70 71 FileObject projectDirectory = p.getProjectDirectory(); 72 SourceGroup projectDirGroup = null; 73 74 for( int i = 0; i < groups.length; i++ ) { 76 FileObject groupRoot = groups[i].getRootFolder(); 77 if ( projectDirectory.equals( groupRoot ) || 78 FileUtil.isParentOf( groupRoot, projectDirectory ) ) { 79 if ( projectDirGroup != null ) { 80 projectDirGroup = null; 82 break; 83 } 84 else { 85 projectDirGroup = groups[i]; 86 } 87 } 88 } 89 90 if ( projectDirGroup == null ) { 91 ErrorManager.getDefault().log(ErrorManager.WARNING, 93 "Project " + p + "either does not contain it's project directory under the " + "Generic source groups or the project directory is under " + "more than one source group"); return new Node[0]; 98 } 99 100 101 ArrayList <Node> nodesList = new ArrayList <Node>( groups.length ); 103 nodesList.add(new GroupNode(p, projectDirGroup, true, DataFolder.findFolder(projectDirGroup.getRootFolder()))); 104 105 for( int i = 0; i < groups.length; i++ ) { 106 107 if ( groups[i] == projectDirGroup ) { 108 continue; 109 } 110 111 nodesList.add(new GroupNode(p, groups[i], false, DataFolder.findFolder(groups[i].getRootFolder()))); 112 } 113 114 Node nodes[] = new Node[ nodesList.size() ]; 115 nodesList.toArray( nodes ); 116 return nodes; 117 } 118 119 static final class VisibilityQueryDataFilter implements ChangeListener , ChangeableDataFilter { 120 121 EventListenerList ell = new EventListenerList (); 122 123 public VisibilityQueryDataFilter() { 124 VisibilityQuery.getDefault().addChangeListener( this ); 125 } 126 127 public boolean acceptDataObject(DataObject obj) { 128 FileObject fo = obj.getPrimaryFile(); 129 return VisibilityQuery.getDefault().isVisible( fo ); 130 } 131 132 public void stateChanged( ChangeEvent e) { 133 Object [] listeners = ell.getListenerList(); 134 ChangeEvent event = null; 135 for (int i = listeners.length-2; i>=0; i-=2) { 136 if (listeners[i] == ChangeListener .class) { 137 if ( event == null) { 138 event = new ChangeEvent ( this ); 139 } 140 ((ChangeListener )listeners[i+1]).stateChanged( event ); 141 } 142 } 143 } 144 145 public void addChangeListener( ChangeListener listener ) { 146 ell.add( ChangeListener .class, listener ); 147 } 148 149 public void removeChangeListener( ChangeListener listener ) { 150 ell.remove( ChangeListener .class, listener ); 151 } 152 153 } 154 155 static final class GroupNode extends FilterNode implements PropertyChangeListener { 156 157 private static final DataFilter VISIBILITY_QUERY_FILTER = new VisibilityQueryDataFilter(); 158 159 static final String GROUP_NAME_PATTERN = NbBundle.getMessage( 160 PhysicalView.class, "FMT_PhysicalView_GroupName" ); 162 private Project project; 163 private ProjectInformation pi; 164 private SourceGroup group; 165 private boolean isProjectDir; 166 167 public GroupNode(Project project, SourceGroup group, boolean isProjectDir, DataFolder dataFolder ) { 168 super( dataFolder.getNodeDelegate(), 169 dataFolder.createNodeChildren( VISIBILITY_QUERY_FILTER ), 170 createLookup( project, group, dataFolder ) ); 171 172 this.project = project; 173 this.pi = ProjectUtils.getInformation( project ); 174 this.group = group; 175 this.isProjectDir = isProjectDir; 176 pi.addPropertyChangeListener(WeakListeners.propertyChange(this, pi)); 177 group.addPropertyChangeListener( WeakListeners.propertyChange( this, group ) ); 178 } 179 180 182 public String getName() { 183 if ( isProjectDir ) { 184 return pi.getName(); 185 } 186 else { 187 String n = group.getName(); 188 if (n == null) { 189 n = "???"; ErrorManager.getDefault().log(ErrorManager.WARNING, "SourceGroup impl of type " + group.getClass().getName() + " specified a null getName(); this is illegal"); 191 } 192 return n; 193 } 194 } 195 196 public String getDisplayName() { 197 if ( isProjectDir ) { 198 return pi.getDisplayName(); 199 } 200 else { 201 return MessageFormat.format( GROUP_NAME_PATTERN, 202 new Object [] { group.getDisplayName(), pi.getDisplayName(), getOriginal().getDisplayName() } ); 203 } 204 } 205 206 public String getShortDescription() { 207 FileObject gdir = group.getRootFolder(); 208 String dir = FileUtil.getFileDisplayName(gdir); 209 return NbBundle.getMessage(PhysicalView.class, 210 isProjectDir ? "HINT_project" : "HINT_group", dir); 212 } 213 214 public boolean canRename() { 215 return false; 216 } 217 218 public boolean canCut() { 219 return false; 220 } 221 222 public boolean canCopy() { 223 return false; 225 } 226 227 public boolean canDestroy() { 228 return false; 229 } 230 231 public Action [] getActions( boolean context ) { 232 233 if ( context ) { 234 return super.getActions( true ); 235 } 236 else { 237 Action [] folderActions = super.getActions( false ); 238 Action [] projectActions; 239 240 if ( isProjectDir ) { 241 projectActions = new Action [ folderActions.length ]; 244 for ( int i = 0; i < folderActions.length; i++ ) { 245 if ( folderActions[i] instanceof org.openide.actions.PropertiesAction ) { 246 projectActions[i] = CommonProjectActions.customizeProjectAction(); 247 } 248 else { 249 projectActions[i] = folderActions[i]; 250 } 251 } 252 } 253 else { 254 projectActions = folderActions; 255 } 256 257 return projectActions; 258 } 259 } 260 261 263 public void propertyChange(PropertyChangeEvent evt) { 264 String prop = evt.getPropertyName(); 265 if (ProjectInformation.PROP_DISPLAY_NAME.equals(prop)) { 266 fireDisplayNameChange(null, null); 267 } else if (ProjectInformation.PROP_NAME.equals(prop)) { 268 fireNameChange(null, null); 269 } else if (ProjectInformation.PROP_ICON.equals(prop)) { 270 } else if ( "name".equals(prop) ) { fireNameChange(null, null); 273 } else if ( "displayName".equals(prop) ) { fireDisplayNameChange(null, null); 275 } else if ( "icon".equals(prop) ) { } else if ( "rootFolder".equals(prop) ) { fireNameChange(null, null); 280 fireDisplayNameChange(null, null); 281 fireShortDescriptionChange(null, null); 282 } else if (SourceGroup.PROP_CONTAINERSHIP.equals(prop)) { 283 } else { 285 assert false : "Attempt to fire an unsupported property change event from " + pi.getClass().getName() + ": " + prop; 286 } 287 } 288 289 private static Lookup createLookup( Project p, SourceGroup group, DataFolder dataFolder ) { 290 return new ProxyLookup(new Lookup[] { 291 dataFolder.getNodeDelegate().getLookup(), 292 Lookups.fixed( new Object [] { p, new PathFinder( group ) } ), 293 p.getLookup(), 294 }); 295 } 296 297 } 298 299 355 356 public static class PathFinder { 357 358 private SourceGroup group; 359 360 public PathFinder( SourceGroup group ) { 361 this.group = group; 362 } 363 364 public Node findPath( Node root, Object object ) { 365 366 if ( !( object instanceof FileObject ) ) { 367 return null; 368 } 369 370 FileObject fo = (FileObject)object; 371 FileObject groupRoot = group.getRootFolder(); 372 if ( FileUtil.isParentOf( groupRoot, fo ) ) { 373 375 String relPath = FileUtil.getRelativePath( groupRoot, fo ); 376 377 ArrayList <String > path = new ArrayList <String >(); 378 StringTokenizer strtok = new StringTokenizer ( relPath, "/" ); 379 while( strtok.hasMoreTokens() ) { 380 path.add( strtok.nextToken() ); 381 } 382 383 String name = fo.getName(); 384 385 try { 386 DataObject dobj = DataObject.find( fo ); 387 name = dobj.getNodeDelegate().getName(); 388 } 389 catch( DataObjectNotFoundException e ) { 390 } 391 392 path.set( path.size() - 1, name ); 393 394 try { 395 return NodeOp.findPath( root, Collections.enumeration( path ) ); 396 } 397 catch ( NodeNotFoundException e ) { 398 return null; 399 } 400 } 401 else if ( groupRoot.equals( fo ) ) { 402 return root; 403 } 404 405 return null; 406 } 407 408 } 409 410 } 411 | Popular Tags |