Saturday Jun 22, 2013

How to Open Any Folder as a Project in the NetBeans Platform

Typically, as described in the NetBeans Project Type Tutorial, you'll define a project type based on the presence of a file (e.g., "project.xml" or "customer.txt" or something like that) in a folder. I.e., if the file is there, then its parent, i.e., the folder that contains the file, is a project and should be opened in your application.

However, in some scenarios (as with the HTML5 project type introduced in NetBeans IDE 7.3), the user should be able to open absolutely any folder at all into the application. How to create a project type that is that liberal?

Here you go, the only condition that needs to be true is that the selected item in the "Open Project" dialog is a folder, as defined in the "isProject" method below. Nothing else. That's it. If you select a folder, it will be opened in your application, displaying absolutely everything as-is (since below there's no ProjectLogicalView defined):

import java.beans.PropertyChangeListener;
import java.io.IOException;
import javax.swing.Icon;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.spi.project.ProjectFactory;
import org.netbeans.spi.project.ProjectState;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.FilterNode;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ServiceProvider;

@ServiceProvider(service = ProjectFactory.class)
public class FolderProjectFactory implements ProjectFactory {
    @Override
    public boolean isProject(FileObject projectDirectory) {
        return DataFolder.findFolder(projectDirectory) != null;
    }
    @Override
    public Project loadProject(FileObject dir, ProjectState state) throws IOException {
        return isProject(dir) ? new FolderProject(dir) : null;
    }
    @Override
    public void saveProject(Project prjct) throws IOException, ClassCastException {
        // leave unimplemented for the moment
    }
    private class FolderProject implements Project {
        private final FileObject projectDir;
        private Lookup lkp;
        private FolderProject(FileObject dir) {
            this.projectDir = dir;
        }
        @Override
        public FileObject getProjectDirectory() {
            return projectDir;
        }
        @Override
        public Lookup getLookup() {
            if (lkp == null) {
                lkp = Lookups.fixed(new Object[]{
                    new Info(),
                });
            }
            return lkp;
        }
        private final class Info implements ProjectInformation {
            @Override
            public Icon getIcon() {
                Icon icon = null;
                try {
                    icon = ImageUtilities.image2Icon(
                            new FilterNode(DataFolder.find(
                            getProjectDirectory()).getNodeDelegate()).getIcon(1));
                } catch (DataObjectNotFoundException ex) {
                    Exceptions.printStackTrace(ex);
                }
                return icon;
            }
            @Override
            public String getName() {
                return getProjectDirectory().getName();
            }
            @Override
            public String getDisplayName() {
                return getName();
            }
            @Override
            public void addPropertyChangeListener(PropertyChangeListener pcl) {
                //do nothing, won't change
            }
            @Override
            public void removePropertyChangeListener(PropertyChangeListener pcl) {
                //do nothing, won't change
            }
            @Override
            public Project getProject() {
                return FolderProject.this;
            }
        }
    }
}

Even the ProjectInformation implementation really isn't needed at all, since it provides nothing more than the icon in the "Open Project" dialog, the rest (i.e., the display name in the "Open Project" dialog) is provided by default regardless of whether you have a ProjectInformation implementation or not.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« June 2013 »
SunMonTueWedThuFriSat
      
29
30
      
Today