|
What this is
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.project.ui;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
import javax.swing.Action;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.queries.VisibilityQuery;
import org.netbeans.modules.project.ui.actions.Actions;
import org.netbeans.modules.project.uiapi.ActionsFactory;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.spi.project.ui.LogicalViewProvider;
import org.netbeans.spi.project.ui.support.CommonProjectActions;
import org.openide.ErrorManager;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.WeakListeners;
import org.openide.util.actions.SystemAction;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.ChangeableDataFilter;
import org.openide.loaders.DataFilter;
import org.openide.loaders.DataFolder;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.NodeNotFoundException;
import org.openide.nodes.NodeOp;
import org.openide.util.ContextAwareAction;
import org.openide.util.NbBundle;
/**
* Support for creating logical views.
* @author Jesse Glick, Petr Hrebejk
*/
public class PhysicalView {
public static boolean isProjectDirNode( Node n ) {
return n instanceof GroupNode && ((GroupNode)n).isProjectDir;
}
public static Node[] createNodesForProject( Project p ) {
Sources s = ProjectUtils.getSources(p);
SourceGroup[] groups = s.getSourceGroups(Sources.TYPE_GENERIC);
FileObject projectDirectory = p.getProjectDirectory();
SourceGroup projectDirGroup = null;
// First find the source group which will represent the project
for( int i = 0; i < groups.length; i++ ) {
FileObject groupRoot = groups[i].getRootFolder();
if ( projectDirectory.equals( groupRoot ) ||
FileUtil.isParentOf( groupRoot, projectDirectory ) ) {
if ( projectDirGroup != null ) {
// more than once => Illegal
projectDirGroup = null;
break;
}
else {
projectDirGroup = groups[i];
}
}
}
if ( projectDirGroup == null ) {
// Illegal project
ErrorManager.getDefault().notify( ErrorManager.INFORMATIONAL,
new IllegalStateException( "Project " + p + // NOI18N
"either does not contain it's project directory under the " + // NOI18N
"Generic source groups or the project directory is under" + // NOI18N
"more than one source group" ) ); // NOI18N
return new Node[0];
}
// Create the nodes
ArrayList nodesList = new ArrayList( groups.length );
nodesList.add( new GroupNode( p, projectDirGroup, true, DataFolder.findFolder( projectDirGroup.getRootFolder() ) ) );
for( int i = 0; i < groups.length; i++ ) {
if ( groups[i] == projectDirGroup ) {
continue;
}
nodesList.add( new GroupNode( p, groups[i], false, DataFolder.findFolder( groups[i].getRootFolder() ) ) );
}
Node nodes[] = new Node[ nodesList.size() ];
nodesList.toArray( nodes );
return nodes;
}
static final class VisibilityQueryDataFilter implements ChangeListener, ChangeableDataFilter {
EventListenerList ell = new EventListenerList();
public VisibilityQueryDataFilter() {
VisibilityQuery.getDefault().addChangeListener( this );
}
public boolean acceptDataObject(DataObject obj) {
FileObject fo = obj.getPrimaryFile();
return VisibilityQuery.getDefault().isVisible( fo );
}
public void stateChanged( ChangeEvent e) {
Object[] listeners = ell.getListenerList();
ChangeEvent event = null;
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == ChangeListener.class) {
if ( event == null) {
event = new ChangeEvent( this );
}
((ChangeListener)listeners[i+1]).stateChanged( event );
}
}
}
public void addChangeListener( ChangeListener listener ) {
ell.add( ChangeListener.class, listener );
}
public void removeChangeListener( ChangeListener listener ) {
ell.remove( ChangeListener.class, listener );
}
}
static final class GroupNode extends FilterNode implements PropertyChangeListener {
private static final DataFilter VISIBILITY_QUERY_FILTER = new VisibilityQueryDataFilter();
static final String GROUP_NAME_PATTERN = NbBundle.getMessage(
PhysicalView.class, "FMT_PhysicalView_GroupName" ); // NOI18N
private Project project;
private ProjectInformation pi;
private SourceGroup group;
private boolean isProjectDir;
public GroupNode(Project project, SourceGroup group, boolean isProjectDir, DataFolder dataFolder ) {
super( dataFolder.getNodeDelegate(),
dataFolder.createNodeChildren( VISIBILITY_QUERY_FILTER ),
createLookup( project, group, dataFolder ) );
this.project = project;
this.pi = ProjectUtils.getInformation( project );
this.group = group;
this.isProjectDir = isProjectDir;
pi.addPropertyChangeListener(this);
group.addPropertyChangeListener( WeakListeners.propertyChange( this, group ) );
}
// XXX May need to change icons as well
public String getName() {
if ( isProjectDir ) {
return pi.getName();
}
else {
return group.getName();
}
}
public String getDisplayName() {
if ( isProjectDir ) {
return pi.getDisplayName();
}
else {
return MessageFormat.format( GROUP_NAME_PATTERN,
new Object[] { group.getDisplayName(), pi.getDisplayName(), getOriginal().getDisplayName() } );
}
}
public String getShortDescription() {
FileObject gdir = group.getRootFolder();
String dir = FileUtil.getFileDisplayName(gdir);
return NbBundle.getMessage(PhysicalView.class,
isProjectDir ? "HINT_project" : "HINT_group", // NOI18N
dir);
}
public boolean canRename() {
return false;
}
public boolean canCut() {
return false;
}
public boolean canCopy() {
// At least for now.
return false;
}
public boolean canDestroy() {
return false;
}
public Action[] getActions( boolean context ) {
if ( context ) {
return super.getActions( true );
}
else {
Action[] folderActions = super.getActions( false );
Action[] projectActions;
if ( isProjectDir ) {
// If this is project dir then the properties action
// has to be replaced to invoke project customizer
projectActions = new Action[ folderActions.length ];
for ( int i = 0; i < folderActions.length; i++ ) {
if ( folderActions[i] instanceof org.openide.actions.PropertiesAction ) {
projectActions[i] = CommonProjectActions.customizeProjectAction();
}
else {
projectActions[i] = folderActions[i];
}
}
}
else {
projectActions = folderActions;
}
return projectActions;
}
}
// Private methods -------------------------------------------------
public void propertyChange(PropertyChangeEvent evt) {
String prop = evt.getPropertyName();
if (ProjectInformation.PROP_DISPLAY_NAME.equals(prop)) {
fireDisplayNameChange(null, null);
} else if (ProjectInformation.PROP_NAME.equals(prop)) {
fireNameChange(null, null);
} else if (ProjectInformation.PROP_ICON.equals(prop)) {
// OK, ignore
} else if ( "name".equals(prop) ) { // NOI18N
fireNameChange(null, null);
} else if ( "displayName".equals(prop) ) { // NOI18N
fireDisplayNameChange(null, null);
} else if ( "icon".equals(prop) ) { // NOI18N
// OK, ignore
} else if ( "rootFolder".equals(prop) ) { // NOI18N
// XXX Do something to children and lookup
fireNameChange(null, null);
fireDisplayNameChange(null, null);
fireShortDescriptionChange(null, null);
} else {
assert false : "Attempt to fire an unsupported property change event from " + pi.getClass().getName() + ": " + prop;
}
}
private static Lookup createLookup( Project p, SourceGroup group, DataFolder dataFolder ) {
return new ProxyLookup(new Lookup[] {
dataFolder.getNodeDelegate().getLookup(),
Lookups.fixed( new Object[] { p, new PathFinder( group ) } ),
p.getLookup(),
});
}
}
public static class PathFinder {
private SourceGroup group;
public PathFinder( SourceGroup group ) {
this.group = group;
}
public Node findPath( Node root, Object object ) {
if ( !( object instanceof FileObject ) ) {
return null;
}
FileObject fo = (FileObject)object;
FileObject groupRoot = group.getRootFolder();
if ( FileUtil.isParentOf( groupRoot, fo ) /* && group.contains( fo ) */ ) {
// The group contains the object
String relPath = FileUtil.getRelativePath( groupRoot, fo );
ArrayList path = new ArrayList();
StringTokenizer strtok = new StringTokenizer( relPath, "/" );
while( strtok.hasMoreTokens() ) {
path.add( strtok.nextToken() );
}
path.set( path.size() - 1, fo.getName() );
try {
return NodeOp.findPath( root, Collections.enumeration( path ) );
}
catch ( NodeNotFoundException e ) {
return null;
}
}
else if ( groupRoot.equals( fo ) ) {
return root;
}
return null;
}
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.