/*
* Copyright 2011 Christian Thiemann <christian@spato.net>
* Developed at Northwestern University <http://rocs.northwestern.edu>
*
* This file is part of the SPaTo Visual Explorer (SPaTo).
*
* SPaTo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SPaTo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SPaTo. If not, see <http://www.gnu.org/licenses/>.
*/
package net.spato.sve.app;
import java.io.File;
import java.io.PrintWriter;
import java.util.Vector;
import java.util.zip.ZipFile;
import javax.swing.filechooser.FileFilter;
import net.spato.sve.app.util.FileDialogUtils;
import processing.xml.XMLElement;
import processing.xml.XMLWriter;
public class Workspace {
protected SPaTo_Visual_Explorer app = null;
protected File workspaceFile = null;
public boolean showWorkspaceRecoveryButton = true; // FIXME: should not be public
protected Vector<SPaToDocument> docs = new Vector<SPaToDocument>(); // all loaded documents
public SPaToDocument doc = null; // current document // FIXME: public?
public Workspace(SPaTo_Visual_Explorer app) {
this.app = app;
}
/*
* Document Management
*/
// This FileFilter accepts:
// 1) directories ending with ".spato" if they contain a document.xml
// 2) files ending with ".spato" if they are zip files
// 3) files named "document.xml" if they are in directory ending with ".spato"
// It's probably a good idea to allow case (3), because selecting directories might
// seem unusally awkward for some users (it's still possible, though).
public static final FileFilter ffDocuments = new FileFilter() {
public String getDescription() { return "SPaTo Documents"; }
public boolean accept(File f) {
if (f.getName().endsWith(".spato")) {
if (f.isDirectory()) { // accept .spato directory if it contains a document.xml
for (File ff : f.listFiles())
if (ff.getName().equals("document.xml"))
return true;
return false;
} else // accept .spato files if it's a zip file
try { new ZipFile(f); return true; } catch (Exception e) { return false; }
}
if (f.getName().equals("document.xml")) // accept document.xml if it's inside a .spato directory
return f.getParent().endsWith(".spato");
return false;
}
};
public File[] selectDocumentFilesToOpen() {
File result[] = FileDialogUtils.selectFiles(app, FileDialogUtils.OPENMULTIPLE, "Open document", ffDocuments);
for (int i = 0; i < result.length; i++) // normalize filename if some
if (result[i].getName().equals("document.xml")) // blabla.spato/document.xml
result[i] = result[i].getParentFile(); // was selected
return result;
}
public File selectDocumentFileToWrite() { return selectDocumentFileToWrite(null); }
public File selectDocumentFileToWrite(File selectedFile) {
return FileDialogUtils.ensureExtension("spato",
FileDialogUtils.selectFile(app, FileDialogUtils.SAVE, "Save document", ffDocuments, selectedFile));
}
public void newDocument() {
SPaToDocument newdoc = new SPaToDocument(app);
docs.add(newdoc);
switchToNetwork(newdoc);
}
public void openDocument() { openDocuments(selectDocumentFilesToOpen()); }
public void openDocument(File file) { if (file != null) openDocuments(new File[] { file }); }
public void openDocuments(File files[]) {
if (files == null) return;
for (File f : files) {
SPaToDocument newdoc = null;
for (SPaToDocument d : docs)
if (d.getFile().equals(f))
newdoc = d; // this document is already open
if (newdoc == null) { // load if not already open
newdoc = new SPaToDocument(app, f);
docs.add(newdoc);
app.worker.submit(newdoc.newLoadingTask());
}
switchToNetwork(newdoc);
}
}
public void closeDocument() {
int i = docs.indexOf(doc);
if (i == -1) return;
docs.remove(i);
switchToNetwork((docs.size() > 0) ? docs.get(i % docs.size()) : null);
}
public void saveDocument() { saveDocument(false); }
public void saveDocument(boolean forceSelect) {
if (doc == null) return;
File file = doc.getFile();
for (SPaToDocument d : docs)
if ((d != doc) && d.getFile().equals(file))
docs.remove(d); // prevent duplicate entries in docs
if ((file == null) || forceSelect) {
if ((file = selectDocumentFileToWrite(file)) == null) return;
boolean compressed = !file.exists() || !file.isDirectory(); // save compressed by default
doc.setFile(file, compressed);
updateWorkspacePref();
}
app.worker.submit(doc.newSavingTask());
}
public boolean switchToNetwork(String name) {
SPaToDocument newdoc = null;
for (int i = 0; i < docs.size(); i++)
if (name.equals(docs.get(i).getName()))
newdoc = docs.get(i);
return switchToNetwork(newdoc);
}
public boolean switchToNetwork(SPaToDocument newdoc) {
app.gui.searchMatchesValid = false;
app.gui.searchMatches = null;
doc = newdoc;
app.doc = newdoc; // FIXME
app.gui.update();
updateWorkspacePref();
return doc != null;
}
/*
* Workspace Management
*/
public static final FileFilter ffWorkspace = FileDialogUtils.createFileFilter("sve", "SVE Workspaces");
public File selectWorkspaceFileToOpen() { return FileDialogUtils.selectFile(app, FileDialogUtils.OPEN, "Open workspace", ffWorkspace); }
public File selectWorkspaceFileToWrite() { return selectWorkspaceFileToWrite(null); }
public File selectWorkspaceFileToWrite(File selectedFile) {
return FileDialogUtils.ensureExtension("sve",
FileDialogUtils.selectFile(app, FileDialogUtils.SAVE, "Save workspace", ffWorkspace, selectedFile));
}
public void openWorkspace() { openWorkspace(selectWorkspaceFileToOpen()); }
public void openWorkspace(File file) {
if ((file == null) || file.equals(workspaceFile)) return;
try {
replaceWorkspace(new XMLElement(app, file.getAbsolutePath()));
} catch (Exception e) {
app.console.logError("Error reading workspace from " + file.getAbsolutePath() + ": ", e);
workspaceFile = null;
return;
}
app.console.logInfo("Opened workspace " + file.getAbsolutePath());
workspaceFile = file;
}
public void saveWorkspace() { saveWorkspace(false); }
public void saveWorkspace(boolean forceSelect) {
File file = workspaceFile;
if ((file == null) || forceSelect)
file = selectWorkspaceFileToWrite(file);
if (file == null) return;
try {
PrintWriter writer = app.createWriter(file.getAbsolutePath());
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
new XMLWriter(writer).write(XMLElement.parse(app.prefs.get("workspace", "<workspace />")), true);
writer.close();
} catch (Exception e) {
app.console.logError("Error saving workspace to " + file.getAbsolutePath() + ": ", e);
return;
}
app.console.logInfo("Workspace saved to " + file.getAbsolutePath());
workspaceFile = file;
}
public void updateWorkspacePref() {
String workspace = "";
for (SPaToDocument d : docs)
if (d.getFile() != null)
workspace += "<document src=\"" + d.getFile().getAbsolutePath() + "\"" +
((d == doc) ? " selected=\"true\"" : "") + " />";
workspace = "<workspace>" + workspace + "</workspace>";
app.prefs.put("workspace", workspace);
showWorkspaceRecoveryButton = false;
}
public void replaceWorkspace(XMLElement workspace) {
if (workspace == null) return;
doc = null;
docs.clear();
XMLElement xmlDocuments[] = workspace.getChildren("document");
for (XMLElement xmlDocument : xmlDocuments) {
String src = xmlDocument.getString("src");
if (src == null) continue; // should not happen...
SPaToDocument newdoc = new SPaToDocument(app, new File(src));
docs.add(newdoc);
app.worker.submit(newdoc.newLoadingTask());
if (xmlDocument.getBoolean("selected"))
switchToNetwork(newdoc);
}
if ((doc == null) && (docs.size() > 0)) switchToNetwork(docs.get(0));
updateWorkspacePref();
app.gui.update();
}
}