? projects.diff Index: projectapi/apichanges.xml =================================================================== RCS file: /cvs/projects/projectapi/apichanges.xml,v retrieving revision 1.3 diff -u -r1.3 apichanges.xml --- projectapi/apichanges.xml 27 May 2005 09:54:06 -0000 1.3 +++ projectapi/apichanges.xml 20 Jun 2005 10:50:05 -0000 @@ -76,6 +76,32 @@ + + + Support for project delete + + + + +

+ As only the ProjectManager is allowed to implement ProjectState interface, + this change should not directly affect any clients. +

+
+ +

+ The notifyDeleted action is added to the ProjectState, + allowing the project implmentation to let the ProjectManager + know that the project has been deleted. +

+

+ ProjectOperations and ProjectOperationsImplementation added to support + project delete operation. +

+
+ +
+ The FileOwnerQuery.markExternalOwner allows registration of individal files and URIs Index: projectapi/src/org/netbeans/api/project/ProjectManager.java =================================================================== RCS file: /cvs/projects/projectapi/src/org/netbeans/api/project/ProjectManager.java,v retrieving revision 1.14 diff -u -r1.14 ProjectManager.java --- projectapi/src/org/netbeans/api/project/ProjectManager.java 5 Apr 2005 00:19:20 -0000 1.14 +++ projectapi/src/org/netbeans/api/project/ProjectManager.java 20 Jun 2005 10:50:06 -0000 @@ -15,6 +15,7 @@ import java.io.IOException; import java.lang.ref.Reference; +import java.net.URI; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; @@ -455,7 +456,23 @@ } }); } - + + public void notifyDeleted() throws IllegalStateException { + assert p != null; + mutex().writeAccess(new Mutex.Action() { + public Object run() { + if (proj2Factory.get(p) == null) { + throw new IllegalStateException("An attempt to call notifyDeleted more than once. Project: " + p.getProjectDirectory()); + } + + dir2Proj.remove(p.getProjectDirectory()); + proj2Factory.remove(p); + modifiedProjects.remove(p); + return null; + } + }); + } + } /** @@ -548,6 +565,21 @@ } catch (MutexException e) { throw (IOException)e.getException(); } + } + + /** + * Check whether a given project is still valid (ie. not deleted). + *

Acquires read access.

+ * @param p a project loaded by this manager + */ + public boolean isValid(final Project p) { + return ((Boolean)mutex().readAccess(new Mutex.Action() { + public Object run() { + synchronized (dir2Proj) { + return Boolean.valueOf(proj2Factory.containsKey(p)); + } + } + })).booleanValue(); } /** Index: projectapi/src/org/netbeans/api/project/ProjectOperations.java =================================================================== RCS file: projectapi/src/org/netbeans/api/project/ProjectOperations.java diff -N projectapi/src/org/netbeans/api/project/ProjectOperations.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projectapi/src/org/netbeans/api/project/ProjectOperations.java 20 Jun 2005 10:50:06 -0000 @@ -0,0 +1,134 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.api.project; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.netbeans.spi.project.ProjectOperationsImplementation.DataFilesProviderImplementation; +import org.netbeans.spi.project.ProjectOperationsImplementation.DeleteOperationImplementation; +import org.openide.util.Lookup; + +/**Allows gathering information for vaious project operations (currently only project delete, but will + * be extended in the future). + * + *

Project Delete Operation + * + * Consists of {@link #getMetadataFiles(Project) getMetadataFiles}, + * {@link #getDataFiles(Project) getDataFiles}, {@link #performClean(Project) performClean} + * and {@link #notifyDeleted(Project) notifyDeleted}. + * + * The delete operation should run in two phases: preparation, when + * {@link #getMetadataFiles(Project) getMetadataFiles} and {@link #getDataFiles(Project) getDataFiles} + * (any number of times, + * in any order) are called and performing, when {@link #performClean(Project) performClean} should be called, + * then the files previously returned should be deleted (as required by the user) + * and finally {@link #notifyDeleted(Project) notifyDeleted} should be called. + * + * @since 1.6 + * @author Jan Lahoda + */ +public final class ProjectOperations { + + private static ProjectOperations INSTANCE = null; + + public static synchronized ProjectOperations getDefault() { + if (INSTANCE == null) { + INSTANCE = new ProjectOperations(); + } + + return INSTANCE; + } + + private ProjectOperations() { + } + + /**Return list of files that are considered metadata files and folders for the given project. + * Returns meaningfull values only if some of the is*Supported methods + * return true. + * + * @param prj project to test + * @return list of metadata files/folders + */ + public List/**/ getMetadataFiles(Project prj) { + List/**/ result = new ArrayList(); + + for (Iterator i = getProjectsOperationsImplementation(prj).iterator(); i.hasNext(); ) { + result.addAll(((DataFilesProviderImplementation) i.next()).getMetadataFiles()); + } + + return result; + } + + /**Return list of files that are considered source files and folders for the given project. + * Returns meaningfull values only if some of the is*Supported methods + * return true. + * + * @param prj project to test + * @return list of data files/folders + */ + public List/**/ getDataFiles(Project prj) { + List/**/ result = new ArrayList(); + + for (Iterator i = getProjectsOperationsImplementation(prj).iterator(); i.hasNext(); ) { + result.addAll(((DataFilesProviderImplementation) i.next()).getDataFiles()); + } + + return result; + } + + /**Test whether the delete operation is supported on the given project. + * + * + * @param prj project to test + * @return true if the project supports delete operation, + * false otherwise + */ + public boolean isDeleteOperationSupported(Project prj) { + return !getDeleteOperationImplementation(prj).isEmpty(); + } + + /**Performs pre-delete clean of the project. Should be called immediatelly before + * the project is deleted. + * + * @param prj project to clean + */ + public void performClean(Project prj) throws IOException { + for (Iterator i = getDeleteOperationImplementation(prj).iterator(); i.hasNext(); ) { + ((DeleteOperationImplementation) i.next()).performClean(); + } + } + + /**Post-delete notification that the project has been deleted.. Should be called immediatelly after + * the project is deleted. + * + * @param prj deleted project + */ + public void notifyDeleted(Project prj) throws IOException { + for (Iterator i = getDeleteOperationImplementation(prj).iterator(); i.hasNext(); ) { + ((DeleteOperationImplementation) i.next()).notifyDeleted(); + } + } + + private Collection/**/ getDeleteOperationImplementation(Project prj) { + return prj.getLookup().lookup(new Lookup.Template(DeleteOperationImplementation.class)).allInstances(); + } + + private Collection/**/ getProjectsOperationsImplementation(Project prj) { + return prj.getLookup().lookup(new Lookup.Template(DataFilesProviderImplementation.class)).allInstances(); + } + +} Index: projectapi/src/org/netbeans/spi/project/ActionProvider.java =================================================================== RCS file: /cvs/projects/projectapi/src/org/netbeans/spi/project/ActionProvider.java,v retrieving revision 1.6 diff -u -r1.6 ActionProvider.java --- projectapi/src/org/netbeans/spi/project/ActionProvider.java 2 Jun 2004 03:49:09 -0000 1.6 +++ projectapi/src/org/netbeans/spi/project/ActionProvider.java 20 Jun 2005 10:50:06 -0000 @@ -86,7 +86,13 @@ */ String COMMAND_DEBUG_STEP_INTO = "debug.stepinto"; // NOI18N - + /** + * Standard command for deleting the project. + * + * @since 1.6 + */ + String COMMAND_DELETE = "delete"; // NOI18N + /** * Get a list of all commands which this project supports. * @return a list of command names suitable for {@link #invokeAction} Index: projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java =================================================================== RCS file: projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java diff -N projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java 20 Jun 2005 10:50:06 -0000 @@ -0,0 +1,84 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.spi.project; + +import java.io.IOException; +import java.util.List; +import org.netbeans.api.project.ProjectOperations; + +/**This is only a scope class that holds several project operation interfaces. + * See particular interface for more information: + *

  • + *
      {@link DeleteOperationImplementation DeleteOperationImplementation}
    + *
  • + * + * @since 1.6 + * @author Jan Lahoda + */ +public final class ProjectOperationsImplementation { + + /** + * Base for various Project Operations, allows to gather metadata and data files + * for a project. + */ + public interface DataFilesProviderImplementation { + + /** + * Returns list of {@link FileObject}s the are considered to be metadata files + * and folders belonging into this project. + * See {@link ProjectOperations#getMetadataFiles()} for more information. + * + * @return list of {@link FileObject}s that are considered metadata files and folders. + */ + public List/**/ getMetadataFiles(); + + /** + * Returns list of {@link FileObject}s the are considered to be data files and folders + * belonging into this project. + * See {@link ProjectOperations#getDataFiles()} for more information. + * + * @return list of {@link FileObject}s that are considered data files and folders. + */ + public List/**/ getDataFiles(); + + } + + /** + * Project Delete Operation. Allows to gather information necessary for project + * delete and also provides callbacks to the project type to handle special + * checkpoints during the delete. + * + * An implementation of this interface should be registered in the project to support + * delete operation. + */ + public interface DeleteOperationImplementation extends DataFilesProviderImplementation { + + /**Pre-delete clean. The exact meaning is left on the project implementors, but + * typically this means to undeloy the application and remove all artifacts + * created by the build project. + * + * @throws IOException if an I/O operation fails. + */ + public void performClean() throws IOException; + + /**Notification that the delete operation has finished. Is supposed to perform + * final cleanup and to call {@link ProjectState#notifyDeleted}. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyDeleted() throws IOException; + + } + +} Index: projectapi/src/org/netbeans/spi/project/ProjectState.java =================================================================== RCS file: /cvs/projects/projectapi/src/org/netbeans/spi/project/ProjectState.java,v retrieving revision 1.3 diff -u -r1.3 ProjectState.java --- projectapi/src/org/netbeans/spi/project/ProjectState.java 26 Apr 2004 22:12:18 -0000 1.3 +++ projectapi/src/org/netbeans/spi/project/ProjectState.java 20 Jun 2005 10:50:06 -0000 @@ -19,8 +19,9 @@ /** * Callback permitting {@link Project}s to inform the {@link ProjectManager} * of important lifecycle events. - * Currently the only available event is modification of the project metadata. - * However in the future other events may be added, such as moving or deleting + * Currently the only available events are modification of the project metadata + * and project deletion notification. + * However in the future other events may be added, such as moving * the project, which the project manager would need to be informed of. *

    * This interface may only be implemented by the project manager. A @@ -38,5 +39,21 @@ *

    Acquires write access. */ void markModified(); + + /** + *

    Inform the manager that the project has been deleted. The project will + * be removed from any {@link ProjectManager}'s mappings. + * If {@link ProjectManager#findProject} is called on the project directory, + * the {@link ProjectFactory ProjectFactories} are asked again to recognize + * the project.

    + * + *

    The project is no longer recognized as created by the {@link ProjectManager}.

    + * + *

    Acquires write access.

    + * + * @throws IllegalStateException if notifyDeleted is called more than once for a project. + * @since 1.4 + */ + void notifyDeleted() throws IllegalStateException ; } Index: projectapi/test/unit/src/org/netbeans/api/project/ProjectManagerTest.java =================================================================== RCS file: /cvs/projects/projectapi/test/unit/src/org/netbeans/api/project/ProjectManagerTest.java,v retrieving revision 1.9 diff -u -r1.9 ProjectManagerTest.java --- projectapi/test/unit/src/org/netbeans/api/project/ProjectManagerTest.java 5 Apr 2005 00:19:20 -0000 1.9 +++ projectapi/test/unit/src/org/netbeans/api/project/ProjectManagerTest.java 20 Jun 2005 10:50:07 -0000 @@ -373,4 +373,75 @@ } } + public void testNotifyDeleted() throws Exception { + FileObject p1 = scratch.createFolder("p1"); + FileObject p1TestProject = p1.createFolder("testproject"); + + Project project1 = pm.findProject(p1); + + assertNotNull("project1 is recognized", project1); + p1TestProject.delete(); + TestUtil.notifyDeleted(project1); + + assertFalse("project1 is not valid", pm.isValid(project1)); + assertNull("project1 is deleted", pm.findProject(p1)); + + FileObject p2 = scratch.createFolder("p2"); + FileObject p2TestProject = p2.createFolder("testproject"); + + Project project2 = pm.findProject(p2); + + assertNotNull("project2 is recognized", project2); + TestUtil.notifyDeleted(project2); + + assertFalse("project2 is not valid", pm.isValid(project2)); + + Project project2b = pm.findProject(p2); + + assertTrue("project2 is newly recognized", project2b != project2); + assertNotNull("project2 is newly recognized", project2b); + + FileObject p3 = scratch.createFolder("p3"); + FileObject p3TestProject = p3.createFolder("testproject"); + + Project project3 = pm.findProject(p3); + + assertNotNull("project3 is recognized", project3); + TestUtil.modify(project3); + assertTrue("project3 is modified", pm.isModified(project3)); + TestUtil.notifyDeleted(project3); + + assertFalse("project3 is not valid", pm.isValid(project3)); + + boolean wasException = false; + try { + pm.isModified(project3); + } catch (IllegalArgumentException e) { + //the project is no longer recognized by the ProjectManager. + wasException = true; + } + + assertTrue("the project is no longer recognized by the ProjectManager", wasException); + + FileObject p4 = scratch.createFolder("p4"); + FileObject p4TestProject = p4.createFolder("testproject"); + + Project project4 = pm.findProject(p4); + + assertNotNull("project4 is recognized", project4); + TestUtil.notifyDeleted(project4); + + assertFalse("project4 is not valid", pm.isValid(project3)); + + wasException = false; + try { + TestUtil.notifyDeleted(project4); + } catch (IllegalStateException e) { + //the project is no longer recognized by the ProjectManager. + wasException = true; + } + + assertTrue("An IllegalStateException was thrown when calling notifyDeleted twice.", wasException); + } + } Index: projectapi/test/unit/src/org/netbeans/api/project/TestUtil.java =================================================================== RCS file: /cvs/projects/projectapi/test/unit/src/org/netbeans/api/project/TestUtil.java,v retrieving revision 1.10 diff -u -r1.10 TestUtil.java --- projectapi/test/unit/src/org/netbeans/api/project/TestUtil.java 18 Apr 2005 22:17:13 -0000 1.10 +++ projectapi/test/unit/src/org/netbeans/api/project/TestUtil.java 20 Jun 2005 10:50:07 -0000 @@ -192,6 +192,14 @@ } /** + * Mark a test project as modified. + * @param p a test project + */ + public static void notifyDeleted(Project p) { + ((TestProject)p).state.notifyDeleted(); + } + + /** * If set to something non-null, loading a broken project will wait for * notification on this monitor before throwing an exception. * @see ProjectManagerTest#testLoadExceptionWithConcurrentLoad Index: projectui/src/org/netbeans/modules/project/ui/OpenProjectList.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/OpenProjectList.java,v retrieving revision 1.33 diff -u -r1.33 OpenProjectList.java --- projectui/src/org/netbeans/modules/project/ui/OpenProjectList.java 20 May 2005 20:41:49 -0000 1.33 +++ projectui/src/org/netbeans/modules/project/ui/OpenProjectList.java 20 Jun 2005 10:50:09 -0000 @@ -735,7 +735,11 @@ if ( projectReference != null ) { // Reference to project exists p = (Project)projectReference.get(); if ( p != null ) { - return p; // And refers to some project + // And refers to some project, check for validity: + if ( ProjectManager.getDefault().isValid( p ) ) + return p; + else + return null; } } Index: projectui/src/org/netbeans/modules/project/ui/ProjectTab.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/ProjectTab.java,v retrieving revision 1.24 diff -u -r1.24 ProjectTab.java --- projectui/src/org/netbeans/modules/project/ui/ProjectTab.java 31 Mar 2005 15:39:13 -0000 1.24 +++ projectui/src/org/netbeans/modules/project/ui/ProjectTab.java 20 Jun 2005 10:50:10 -0000 @@ -16,6 +16,9 @@ import java.awt.BorderLayout; import java.awt.Image; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.io.IOException; import java.io.ObjectInput; @@ -26,6 +29,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.SwingUtilities; import javax.swing.text.DefaultEditorKit; @@ -33,6 +38,8 @@ import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeModel; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.ActionProvider; import org.openide.ErrorManager; import org.openide.awt.StatusDisplayer; import org.openide.explorer.ExplorerManager; @@ -87,7 +94,7 @@ map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager)); map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager)); map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager)); - map.put("delete", ExplorerUtils.actionDelete(manager, true)); + map.put("delete", new DelegatingAction(ActionProvider.COMMAND_DELETE, ExplorerUtils.actionDelete(manager, true))); initComponents(); @@ -525,6 +532,68 @@ catch ( NodeNotFoundException e ) { return null; } + } + + } + + private class DelegatingAction extends AbstractAction implements PropertyChangeListener { + + private Action explorerAction; + private String projectAction; + + public DelegatingAction(String projectAction, Action explorerAction) { + this.projectAction = projectAction; + this.explorerAction = explorerAction; + + manager.addPropertyChangeListener(this); + explorerAction.addPropertyChangeListener(this); + } + + private boolean isProject() { + Node[] nodes = manager.getSelectedNodes(); + + if (nodes.length == 1) { + return nodes[0].getParentNode() == rootNode; + } + + return false; + } + + public void actionPerformed(ActionEvent e) { + if (isProject()) { + Node[] nodes = manager.getSelectedNodes(); + Project p = (Project) nodes[0].getLookup().lookup(Project.class); + + assert p != null; + + ActionProvider ap = (ActionProvider) p.getLookup().lookup(ActionProvider.class); + + ap.invokeAction(projectAction, nodes[0].getLookup()); + } else { + explorerAction.actionPerformed(e); + } + } + + public void updateIsEnabled() { + if (isProject()) { + Node[] nodes = manager.getSelectedNodes(); + Project p = (Project) nodes[0].getLookup().lookup(Project.class); + + if (p == null) { + setEnabled(false); + } + + ActionProvider ap = (ActionProvider) p.getLookup().lookup(ActionProvider.class); + + setEnabled(ap.isActionEnabled(projectAction, nodes[0].getLookup())); + } else { + setEnabled(explorerAction.isEnabled()); + } + } + + public void propertyChange(PropertyChangeEvent evt) { + //a bit brute force: + updateIsEnabled(); } } Index: projectui/src/org/netbeans/modules/project/ui/actions/Actions.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/actions/Actions.java,v retrieving revision 1.21 diff -u -r1.21 Actions.java --- projectui/src/org/netbeans/modules/project/ui/actions/Actions.java 17 May 2005 10:05:15 -0000 1.21 +++ projectui/src/org/netbeans/modules/project/ui/actions/Actions.java 20 Jun 2005 10:50:10 -0000 @@ -22,6 +22,7 @@ import org.netbeans.modules.project.uiapi.ActionsFactory; import org.netbeans.spi.project.ActionProvider; import org.netbeans.spi.project.ui.support.ProjectActionPerformer; +import org.openide.actions.DeleteAction; import org.openide.nodes.Node; import org.openide.util.ContextAwareAction; import org.openide.util.HelpCtx; @@ -48,6 +49,7 @@ private static Action OPEN_SUBPROJECTS; private static Action CLOSE_PROJECT; private static Action NEW_FILE; + private static Action DELETE_PROJECT; public synchronized Action setAsMainProjectAction() { if ( SET_AS_MAIN_PROJECT == null ) { @@ -84,11 +86,14 @@ return NEW_FILE; } + public Action deleteProjectAction() { + return deleteProject(); + } + public synchronized Action newProjectAction() { return new NewProject(); } - public Action projectCommandAction(String command, String namePattern, Icon icon ) { return new ProjectAction( command, namePattern, icon, null ); } @@ -162,6 +167,14 @@ return a; } + public static synchronized Action deleteProject() { + if (DELETE_PROJECT == null) { + DELETE_PROJECT = DeleteAction.get(DeleteAction.class); + } + + return DELETE_PROJECT; + } + // 1-off actions ----------------------------------------------------------- public static Action compileSingle() { @@ -257,5 +270,5 @@ a.putValue("iconBase","org/netbeans/modules/project/ui/resources/debugProject.gif"); //NOI18N return a; } - + } Index: projectui/src/org/netbeans/modules/project/ui/actions/Bundle.properties =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/actions/Bundle.properties,v retrieving revision 1.21 diff -u -r1.21 Bundle.properties --- projectui/src/org/netbeans/modules/project/ui/actions/Bundle.properties 24 Nov 2004 20:06:56 -0000 1.21 +++ projectui/src/org/netbeans/modules/project/ui/actions/Bundle.properties 20 Jun 2005 10:50:10 -0000 @@ -42,6 +42,7 @@ LBL_TestProjectAction_Name=Test {0,choice,0#Project|1#"{1}"|1<{0} Projects} LBL_CompileSingleAction_Name=Co&mpile {0,choice,0#File|1#"{1}"|1 - - + + Index: projectui/test/unit/src/org/netbeans/modules/project/ui/OpenProjectListTest.java =================================================================== RCS file: /cvs/projects/projectui/test/unit/src/org/netbeans/modules/project/ui/OpenProjectListTest.java,v retrieving revision 1.4 diff -u -r1.4 OpenProjectListTest.java --- projectui/test/unit/src/org/netbeans/modules/project/ui/OpenProjectListTest.java 12 May 2005 09:00:25 -0000 1.4 +++ projectui/test/unit/src/org/netbeans/modules/project/ui/OpenProjectListTest.java 20 Jun 2005 10:50:11 -0000 @@ -177,6 +177,42 @@ assertEquals("both close hooks were called", 2, TestProjectOpenedHookImpl.closed); } + public void testNotifyDeleted() throws Exception { + FileObject workDir = FileUtil.toFileObject (getWorkDir ()); + + FileObject p1 = workDir.createFolder("p1"); + FileObject p1TestProject = p1.createFolder("testproject"); + + Project project1 = ProjectManager.getDefault().findProject(p1); + + assertNotNull("project1 is recognized", project1); + + OpenProjectList.getDefault().open(project1); + + OpenProjectList.getDefault().close(new Project[] {project1}); + + p1TestProject.delete(); + TestSupport.notifyDeleted(project1); + + assertNull("project1 is deleted", ProjectManager.getDefault().findProject(p1)); + + assertFalse("project1 is not in recent projects list", OpenProjectList.getDefault().getRecentProjects().contains(project1)); + + FileObject p2 = workDir.createFolder("p2"); + FileObject p2TestProject = p2.createFolder("testproject"); + + Project project2 = ProjectManager.getDefault().findProject(p2); + + assertNotNull("project2 is recognized", project2); + OpenProjectList.getDefault().open(project1); + + OpenProjectList.getDefault().close(new Project[] {project1}); + + TestSupport.notifyDeleted(project2); + + assertFalse("project2 is not in recent projects list", OpenProjectList.getDefault().getRecentProjects().contains(project2)); + } + // helper code private static class MySubprojectProvider implements SubprojectProvider { Index: projectui/test/unit/src/org/netbeans/modules/project/ui/actions/TestSupport.java =================================================================== RCS file: /cvs/projects/projectui/test/unit/src/org/netbeans/modules/project/ui/actions/TestSupport.java,v retrieving revision 1.3 diff -u -r1.3 TestSupport.java --- projectui/test/unit/src/org/netbeans/modules/project/ui/actions/TestSupport.java 14 Dec 2004 16:54:58 -0000 1.3 +++ projectui/test/unit/src/org/netbeans/modules/project/ui/actions/TestSupport.java 20 Jun 2005 10:50:11 -0000 @@ -50,6 +50,9 @@ return new TestProjectFactory(); } + public static void notifyDeleted(Project p) { + ((TestProject) p).state.notifyDeleted(); + } private static final class TestProjectFactory implements ProjectFactory { Index: projectuiapi/apichanges.xml =================================================================== RCS file: /cvs/projects/projectuiapi/apichanges.xml,v retrieving revision 1.12 diff -u -r1.12 apichanges.xml --- projectuiapi/apichanges.xml 17 May 2005 17:31:06 -0000 1.12 +++ projectuiapi/apichanges.xml 20 Jun 2005 10:50:16 -0000 @@ -76,6 +76,22 @@ + + + Delete Action Added + + + + + + Introduced: +
      +
    • CommonProjectActions.deleteProjectAction method
    • +
    +
    + +
    + New Project Wizard Action Index: projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java =================================================================== RCS file: /cvs/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java,v retrieving revision 1.7 diff -u -r1.7 ActionsFactory.java --- projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java 17 May 2005 10:05:16 -0000 1.7 +++ projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java 20 Jun 2005 10:50:16 -0000 @@ -35,6 +35,8 @@ public Action newFileAction(); + public Action deleteProjectAction(); + public Action newProjectAction(); // Actions sensitive to project selection Index: projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java =================================================================== RCS file: /cvs/projects/projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java,v retrieving revision 1.10 diff -u -r1.10 CommonProjectActions.java --- projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java 26 May 2005 19:11:46 -0000 1.10 +++ projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java 20 Jun 2005 10:50:16 -0000 @@ -99,6 +99,20 @@ } /** + * Create an action "Delete Project". + * It should be invoked with an action context containing + * one or more {@link org.netbeans.api.project.Project}s. + *

    + * You might include this in the context menu of a logical view. + *

    + * @since 1.4 + * @return an action + */ + public static Action deleteProjectAction() { + return Utilities.getActionsFactory().deleteProjectAction(); + } + + /** * Creates action that invokes New Project wizard. * *

    {@link #EXISTING_SOURCES_FOLDER} keyed action