Index: projects/projectui/src/org/netbeans/modules/project/ui/ProjectUtilities.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/ProjectUtilities.java,v retrieving revision 1.9 diff -u -r1.9 ProjectUtilities.java --- projects/projectui/src/org/netbeans/modules/project/ui/ProjectUtilities.java 16 Aug 2004 09:37:53 -0000 1.9 +++ projects/projectui/src/org/netbeans/modules/project/ui/ProjectUtilities.java 4 Dec 2004 11:00:44 -0000 @@ -16,6 +16,8 @@ import java.awt.Component; import java.awt.Cursor; import java.awt.event.ActionEvent; +import java.net.MalformedURLException; +import java.net.URL; import java.util.*; import java.io.File; @@ -24,29 +26,39 @@ import javax.swing.SwingUtilities; import org.netbeans.api.project.FileOwnerQuery; import org.netbeans.api.project.Project; +import org.netbeans.spi.project.AuxiliaryConfiguration; import org.openide.ErrorManager; +import org.openide.cookies.OpenCookie; import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileStateInvalidException; import org.openide.filesystems.FileUtil; +import org.openide.filesystems.URLMapper; import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; import org.openide.nodes.Node; +import org.openide.nodes.Node.Cookie; import org.openide.text.CloneableEditorSupport; import org.openide.util.ContextAwareAction; import org.openide.util.Mutex; import org.openide.util.NbBundle; - - -import org.openide.util.Utilities; import org.openide.windows.Mode; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; - - +import org.openide.xml.XMLUtil; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; /** The util methods for projectui module. * * @author Jiri Rechtacek */ public class ProjectUtilities { + static final String OPEN_FILES_NS = "http://www.netbeans.org/ns/projectui-open-files/1"; // NOI18N + static final String OPEN_FILES_ELEMENT = "open-files"; // NOI18N + static final String FILE_ELEMENT = "file"; // NOI18N /** Creates a new instance of CloseAllProjectDocuments */ private ProjectUtilities () { @@ -60,46 +72,7 @@ * @return false if an user cancel the Save/Discard/Cancel dialog, true otherwise */ final public static boolean closeAllDocuments (Project[] projects) { - if (projects == null) { - throw new IllegalArgumentException ("No proects are specified."); // NOI18N - } - - if (projects.length == 0) { - // no projects to close, no documents will be closed - return true; - } - List/*Project*/ listOfProjects = Arrays.asList (projects); - Set/*DataObject*/ modifiedFiles = new HashSet (); - Set/*TopComponent*/ tc2close = new HashSet (); - Mode editorMode = WindowManager.getDefault ().findMode (CloneableEditorSupport.EDITOR_MODE); - TopComponent[] openTCs = editorMode.getTopComponents (); - for (int i = 0; i < openTCs.length; i++) { - DataObject dobj = (DataObject)openTCs[i].getLookup ().lookup (DataObject.class); - if (dobj != null) { - FileObject fobj = dobj.getPrimaryFile (); - Project owner = FileOwnerQuery.getOwner (fobj); - if (listOfProjects.contains (owner)) { - modifiedFiles.add (dobj); - tc2close.add (openTCs[i]); - } - } - } - - if (modifiedFiles.isEmpty ()) { - return true; - } - - boolean result = ExitDialog.showDialog (modifiedFiles); - - if (result) { - // close documents - Iterator it = tc2close.iterator (); - while (it.hasNext ()) { - ((TopComponent)it.next ()).close (); - } - } - - return result; + return closeAllDocuments (projects, false); } /** Closes all documents of the given project in editor area. If some documents @@ -238,6 +211,142 @@ ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, npe); } } + } + + /** Closes all documents in editor area which are owned by one of given projects. + * If some documents are modified then an user is notified by Save/Discard/Cancel dialog. + * Dialog is showed only once for all project's documents together. + * + * @param p project to close + * @return false if an user cancel the Save/Discard/Cancel dialog, true otherwise + */ + final public static boolean closeAllDocuments (Project[] projects, boolean storeDocuments) { + if (projects == null) { + throw new IllegalArgumentException ("No proects are specified."); // NOI18N + } + + if (projects.length == 0) { + // no projects to close, no documents will be closed + return true; + } + + List/**/ listOfProjects = Arrays.asList (projects); + Set/**/ openFiles = new HashSet (); + Set/**/ tc2close = new HashSet (); + Map files4project = new HashMap (); + Mode editorMode = WindowManager.getDefault ().findMode (CloneableEditorSupport.EDITOR_MODE); + TopComponent[] openTCs = editorMode.getTopComponents (); + for (int i = 0; i < openTCs.length; i++) { + DataObject dobj = (DataObject)openTCs[i].getLookup ().lookup (DataObject.class); + if (dobj != null) { + FileObject fobj = dobj.getPrimaryFile (); + Project owner = FileOwnerQuery.getOwner (fobj); + if (listOfProjects.contains (owner)) { + openFiles.add (dobj); + tc2close.add (openTCs[i]); + if (!files4project.containsKey (owner)) { + // add project + files4project.put (owner, new HashSet ()); + } + ((Set)files4project.get (owner)).add (dobj); + } + } + } + + if (openFiles.isEmpty ()) { + return true; + } + + boolean result = ExitDialog.showDialog (openFiles); + + if (result) { + // store project's documents + // loop all project being closed + Iterator loop = files4project.keySet ().iterator (); + Project p; + while (loop.hasNext ()) { + p = (Project)loop.next (); + storeProjectOpenFiles (p, (Set)files4project.get (p)); + } + + // close documents + Iterator it = tc2close.iterator (); + while (it.hasNext ()) { + ((TopComponent)it.next ()).close (); + } + } + + return result; + } + + static private void storeProjectOpenFiles (Project p, Set/**/ files) { + AuxiliaryConfiguration aux = (AuxiliaryConfiguration)p.getLookup ().lookup (AuxiliaryConfiguration.class); + if (aux != null) { + + // clean-up files before adding new one + aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false); + + Document xml = XMLUtil.createDocument (OPEN_FILES_ELEMENT, OPEN_FILES_NS, null, null); + Element fileEl; + + Element openFiles = xml.createElementNS (OPEN_FILES_NS, OPEN_FILES_ELEMENT); + + // loop all open files of given project + Iterator it = files.iterator (); + DataObject dobj; + while (it.hasNext ()) { + fileEl = openFiles.getOwnerDocument ().createElement (FILE_ELEMENT); + dobj = (DataObject)it.next (); + try { + fileEl.appendChild (fileEl.getOwnerDocument ().createTextNode (dobj.getPrimaryFile ().getURL ().toExternalForm ())); + } catch (FileStateInvalidException fsie) { + ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, fsie); + } + openFiles.appendChild (fileEl); + } + + aux.putConfigurationFragment (openFiles, false); + } + } + + final public static void openProjectFiles (Project p) { + AuxiliaryConfiguration aux = (AuxiliaryConfiguration)p.getLookup ().lookup (AuxiliaryConfiguration.class); + + if (aux == null) { + return ; + } + + Element openFiles = aux.getConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false); + if (openFiles == null) { + return; + } + + NodeList list = openFiles.getElementsByTagName (FILE_ELEMENT); + if (list == null) { + return ; + } + + FileObject fo; + DataObject dobj; + String url; + for (int i = 0; i < list.getLength (); i++) { + url = list.item (i).getChildNodes ().item (0).getNodeValue (); + try { + fo = URLMapper.findFileObject (new URL (url)); + dobj = DataObject.find (fo); + Cookie c = dobj.getCookie (OpenCookie.class); + if (c != null && c instanceof OpenCookie) { + ((OpenCookie)c).open (); + } + } catch (MalformedURLException mue) { + ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, mue); + } catch (DataObjectNotFoundException donfo) { + ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, donfo); + } + } + + // clean-up stored files + aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false); } } Index: projects/projectui/src/org/netbeans/modules/project/ui/actions/OpenProject.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/actions/OpenProject.java,v retrieving revision 1.6 diff -u -r1.6 OpenProject.java --- projects/projectui/src/org/netbeans/modules/project/ui/actions/OpenProject.java 19 May 2004 11:31:40 -0000 1.6 +++ projects/projectui/src/org/netbeans/modules/project/ui/actions/OpenProject.java 4 Dec 2004 11:00:44 -0000 @@ -24,6 +24,7 @@ import org.netbeans.modules.project.ui.OpenProjectListSettings; import org.netbeans.modules.project.ui.ProjectChooserAccessory; import org.netbeans.modules.project.ui.ProjectTab; +import org.netbeans.modules.project.ui.ProjectUtilities; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.filesystems.FileUtil; @@ -73,6 +74,9 @@ OpenProjectList.getDefault().setMainProject( project ); } final ProjectTab ptLogial = ProjectTab.findDefault (ProjectTab.ID_LOGICAL); + + // open project files + ProjectUtilities.openProjectFiles (project); // invoke later to select the being opened project if the focus is outside ProjectTab SwingUtilities.invokeLater (new Runnable () {