mirror of
https://github.com/AndorsTrailRelease/ATCS.git
synced 2025-10-27 18:44:03 +01:00
same as with .workspace the .project file now saves as .project.json and falls back to .project
421 lines
15 KiB
Java
421 lines
15 KiB
Java
package com.gpl.rpg.atcontentstudio.model;
|
|
|
|
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
|
import com.gpl.rpg.atcontentstudio.Notification;
|
|
import com.gpl.rpg.atcontentstudio.io.JsonSerializable;
|
|
import com.gpl.rpg.atcontentstudio.io.SettingsSave;
|
|
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
|
|
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
|
|
import com.gpl.rpg.atcontentstudio.ui.ProjectsTree.ProjectsTreeModel;
|
|
import com.gpl.rpg.atcontentstudio.ui.WorkerDialog;
|
|
import com.gpl.rpg.atcontentstudio.utils.FileUtils;
|
|
import org.jsoup.SerializationException;
|
|
|
|
import javax.swing.tree.TreeNode;
|
|
import javax.swing.tree.TreePath;
|
|
import java.awt.*;
|
|
import java.io.*;
|
|
import java.nio.file.Files;
|
|
import java.util.List;
|
|
import java.util.*;
|
|
|
|
public class Workspace implements ProjectTreeNode, Serializable, JsonSerializable {
|
|
|
|
private static final long serialVersionUID = 7938633033601384956L;
|
|
|
|
public static final String WS_SETTINGS_FILE = ".workspace";
|
|
public static final String WS_SETTINGS_FILE_JSON = ".workspace.json";
|
|
|
|
public static Workspace activeWorkspace;
|
|
|
|
public Preferences preferences = new Preferences();
|
|
public File baseFolder;
|
|
public File settingsFile;
|
|
public transient WorkspaceSettings settings;
|
|
public transient List<ProjectTreeNode> projects = new ArrayList<ProjectTreeNode>();
|
|
public Set<String> projectsName = new HashSet<String>();
|
|
public Map<String, Boolean> projectsOpenByName = new HashMap<String, Boolean>();
|
|
public Set<File> knownMapSourcesFolders = new HashSet<File>();
|
|
|
|
public transient ProjectsTreeModel projectsTreeModel = null;
|
|
|
|
public Workspace(File workspaceRoot) {
|
|
boolean freshWorkspace = false;
|
|
baseFolder = workspaceRoot;
|
|
if (!workspaceRoot.exists()) {
|
|
try {
|
|
workspaceRoot.mkdir();
|
|
} catch (SecurityException e) {
|
|
Notification.addError("Error creating workspace directory: "
|
|
+ e.getMessage());
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
settings = new WorkspaceSettings(this);
|
|
settingsFile = new File(workspaceRoot, WS_SETTINGS_FILE_JSON);
|
|
if (!settingsFile.exists()) {
|
|
try {
|
|
settingsFile.createNewFile();
|
|
freshWorkspace = true;
|
|
} catch (IOException e) {
|
|
Notification.addError("Error creating workspace datafile: "
|
|
+ e.getMessage());
|
|
e.printStackTrace();
|
|
}
|
|
Notification.addSuccess("New workspace created: "
|
|
+ workspaceRoot.getAbsolutePath());
|
|
}
|
|
if (freshWorkspace)
|
|
save();
|
|
}
|
|
|
|
@Override
|
|
public Map toMap() {
|
|
Map map = new HashMap();
|
|
map.put("serialVersionUID", serialVersionUID);
|
|
map.put("preferences", preferences.toMap());
|
|
map.put("projectsName", (new ArrayList<String>(projectsName)));
|
|
map.put("projectsOpenByName", projectsOpenByName);
|
|
List<String> l = new ArrayList<>(knownMapSourcesFolders.size());
|
|
for (File f: knownMapSourcesFolders){
|
|
l.add(f.getPath());
|
|
}
|
|
map.put("knownMapSourcesFolders", l);
|
|
return map;
|
|
}
|
|
|
|
@Override
|
|
public void fromMap(Map map) {
|
|
if(serialVersionUID != (long) map.get("serialVersionUID")){
|
|
throw new SerializationException("wrong seriaVersionUID");
|
|
}
|
|
|
|
preferences.fromMap((Map) map.get("preferences"));
|
|
|
|
projectsName = new HashSet<>((List<String>) map.getOrDefault("projectsName", new HashSet<String>()));
|
|
|
|
projectsOpenByName = (Map<String, Boolean>) map.getOrDefault("projectsOpenByName", new HashMap<String, Boolean>() );
|
|
|
|
List<String> knownMapSourcesFolders1 = (List<String>) map.getOrDefault("knownMapSourcesFolders", new ArrayList<String>());
|
|
knownMapSourcesFolders = new HashSet<>();
|
|
if (knownMapSourcesFolders1 != null){
|
|
int size = knownMapSourcesFolders1.size();
|
|
for (String path: knownMapSourcesFolders1) {
|
|
//TODO: catch invalid paths...?
|
|
knownMapSourcesFolders.add(new File(path));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public static void setActive(File workspaceRoot) {
|
|
Workspace w;
|
|
File f2 = new File(workspaceRoot, WS_SETTINGS_FILE_JSON);
|
|
if (f2.exists()) {
|
|
w = loadWorkspaceFromJson(workspaceRoot, f2);
|
|
w.refreshTransients();
|
|
} else {
|
|
Notification.addInfo("Could not find json workspace file. Falling back to binary");
|
|
File f = new File(workspaceRoot, WS_SETTINGS_FILE);
|
|
if (!workspaceRoot.exists() || !f.exists()) {
|
|
w = new Workspace(workspaceRoot);
|
|
} else {
|
|
w = (Workspace) SettingsSave.loadInstance(f, "Workspace");
|
|
if (w == null) {
|
|
w = new Workspace(workspaceRoot);
|
|
w.save();
|
|
} else {
|
|
w.refreshTransients();
|
|
}
|
|
}
|
|
}
|
|
activeWorkspace = w;
|
|
}
|
|
|
|
private static Workspace loadWorkspaceFromJson(File workspaceRoot, File settingsFile) {
|
|
Workspace w = w = new Workspace(workspaceRoot);
|
|
Map json = FileUtils.mapFromJsonFile(settingsFile);
|
|
if (json!= null) {
|
|
w.fromMap(json);
|
|
}
|
|
return w;
|
|
}
|
|
|
|
public static void saveActive() {
|
|
activeWorkspace.save();
|
|
}
|
|
|
|
public void save() {
|
|
settings.save();
|
|
FileUtils.writeStringToFile(FileUtils.toJsonString(this), settingsFile, "Workspace");
|
|
}
|
|
|
|
@Override
|
|
public Enumeration<ProjectTreeNode> children() {
|
|
return Collections.enumeration(projects);
|
|
}
|
|
|
|
@Override
|
|
public boolean getAllowsChildren() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public TreeNode getChildAt(int arg0) {
|
|
return projects.get(arg0);
|
|
}
|
|
|
|
@Override
|
|
public int getChildCount() {
|
|
return projects.size();
|
|
}
|
|
|
|
@Override
|
|
public int getIndex(TreeNode arg0) {
|
|
return projects.indexOf(arg0);
|
|
}
|
|
|
|
@Override
|
|
public TreeNode getParent() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean isLeaf() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void childrenAdded(List<ProjectTreeNode> path) {
|
|
path.add(0, this);
|
|
if (projectsTreeModel != null)
|
|
projectsTreeModel.insertNode(new TreePath(path.toArray()));
|
|
}
|
|
|
|
@Override
|
|
public void childrenChanged(List<ProjectTreeNode> path) {
|
|
path.add(0, this);
|
|
ProjectTreeNode last = path.get(path.size() - 1);
|
|
if (projectsTreeModel != null) {
|
|
while (path.size() > 1) {
|
|
projectsTreeModel.changeNode(new TreePath(path.toArray()));
|
|
path.remove(path.size() - 1);
|
|
}
|
|
|
|
}
|
|
ATContentStudio.frame.editorChanged(last);
|
|
}
|
|
|
|
@Override
|
|
public void childrenRemoved(List<ProjectTreeNode> path) {
|
|
path.add(0, this);
|
|
if (projectsTreeModel != null)
|
|
projectsTreeModel.removeNode(new TreePath(path.toArray()));
|
|
}
|
|
|
|
@Override
|
|
public void notifyCreated() {
|
|
childrenAdded(new ArrayList<ProjectTreeNode>());
|
|
for (ProjectTreeNode node : projects) {
|
|
if (node != null)
|
|
node.notifyCreated();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getDesc() {
|
|
return "Workspace: " + baseFolder.getAbsolutePath();
|
|
}
|
|
|
|
public static void createProject(final String projectName,
|
|
final File gameSourceFolder, final Project.ResourceSet sourceSet) {
|
|
WorkerDialog.showTaskMessage("Creating project " + projectName + "...",
|
|
ATContentStudio.frame, new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (activeWorkspace.projectsName.contains(projectName)) {
|
|
Notification.addError("A project named "
|
|
+ projectName
|
|
+ " already exists in this workspace.");
|
|
return;
|
|
}
|
|
Project p = new Project(activeWorkspace, projectName,
|
|
gameSourceFolder, sourceSet);
|
|
activeWorkspace.projects.add(p);
|
|
activeWorkspace.projectsName.add(projectName);
|
|
activeWorkspace.projectsOpenByName.put(projectName,
|
|
p.open);
|
|
activeWorkspace.knownMapSourcesFolders
|
|
.add(gameSourceFolder);
|
|
p.notifyCreated();
|
|
Notification.addSuccess("Project " + projectName
|
|
+ " successfully created");
|
|
saveActive();
|
|
}
|
|
});
|
|
}
|
|
|
|
public static void closeProject(Project p) {
|
|
int index = activeWorkspace.projects.indexOf(p);
|
|
if (index < 0) {
|
|
Notification.addError("Cannot close unknown project " + p.name);
|
|
return;
|
|
}
|
|
p.close();
|
|
ClosedProject cp = new ClosedProject(activeWorkspace, p.name);
|
|
activeWorkspace.projects.set(index, cp);
|
|
activeWorkspace.projectsOpenByName.put(p.name, false);
|
|
cp.notifyCreated();
|
|
saveActive();
|
|
}
|
|
|
|
public static void openProject(final ClosedProject cp) {
|
|
WorkerDialog.showTaskMessage("Opening project " + cp.name + "...",
|
|
ATContentStudio.frame, new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
int index = activeWorkspace.projects.indexOf(cp);
|
|
if (index < 0) {
|
|
Notification
|
|
.addError("Cannot open unknown project "
|
|
+ cp.name);
|
|
return;
|
|
}
|
|
cp.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
|
Project p = Project.fromFolder(activeWorkspace,
|
|
new File(activeWorkspace.baseFolder, cp.name));
|
|
p.open();
|
|
activeWorkspace.projects.set(index, p);
|
|
activeWorkspace.projectsOpenByName.put(p.name, true);
|
|
p.notifyCreated();
|
|
saveActive();
|
|
}
|
|
});
|
|
}
|
|
|
|
public void refreshTransients() {
|
|
this.settings = new WorkspaceSettings(this);
|
|
this.projects = new ArrayList<ProjectTreeNode>();
|
|
Set<String> projectsFailed = new HashSet<String>();
|
|
for (String projectName : projectsName) {
|
|
if (projectsOpenByName.get(projectName)) {
|
|
File projRoot = new File(this.baseFolder, projectName);
|
|
if (projRoot.exists()) {
|
|
Project p = Project.fromFolder(this, projRoot);
|
|
if (p != null) {
|
|
projects.add(p);
|
|
} else {
|
|
Notification
|
|
.addError("Failed to open project "
|
|
+ projectName
|
|
+ ". Removing it from workspace (not from filesystem though).");
|
|
projectsFailed.add(projectName);
|
|
}
|
|
} else {
|
|
Notification.addError("Unable to find project "
|
|
+ projectName
|
|
+ "'s root folder. Removing it from workspace");
|
|
projectsFailed.add(projectName);
|
|
}
|
|
} else {
|
|
projects.add(new ClosedProject(this, projectName));
|
|
}
|
|
}
|
|
for (String projectName : projectsFailed) {
|
|
projectsName.remove(projectName);
|
|
projectsOpenByName.remove(projectName);
|
|
}
|
|
notifyCreated();
|
|
}
|
|
|
|
@Override
|
|
public Project getProject() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Image getIcon() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Image getClosedIcon() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Image getLeafIcon() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Image getOpenIcon() {
|
|
return null;
|
|
}
|
|
|
|
public static void deleteProject(ClosedProject cp) {
|
|
cp.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
|
activeWorkspace.projects.remove(cp);
|
|
activeWorkspace.projectsOpenByName.remove(cp.name);
|
|
activeWorkspace.projectsName.remove(cp.name);
|
|
if (delete(new File(activeWorkspace.baseFolder, cp.name))) {
|
|
Notification.addSuccess("Closed project " + cp.name
|
|
+ " successfully deleted.");
|
|
} else {
|
|
Notification.addError("Error while deleting closed project "
|
|
+ cp.name + ". Files may remain in the workspace.");
|
|
}
|
|
saveActive();
|
|
}
|
|
|
|
public static void deleteProject(Project p) {
|
|
p.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
|
activeWorkspace.projects.remove(p);
|
|
activeWorkspace.projectsOpenByName.remove(p.name);
|
|
activeWorkspace.projectsName.remove(p.name);
|
|
if (delete(p.baseFolder)) {
|
|
Notification.addSuccess("Project " + p.name
|
|
+ " successfully deleted.");
|
|
} else {
|
|
Notification.addError("Error while deleting project " + p.name
|
|
+ ". Files may remain in the workspace.");
|
|
}
|
|
saveActive();
|
|
}
|
|
|
|
private static boolean delete(File f) {
|
|
boolean b = true;
|
|
if (Files.isSymbolicLink(f.toPath())) {
|
|
b &= f.delete();
|
|
} else if (f.isDirectory()) {
|
|
for (File c : f.listFiles())
|
|
b &= delete(c);
|
|
}
|
|
return b & f.delete();
|
|
}
|
|
|
|
@Override
|
|
public GameDataSet getDataSet() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Type getDataType() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return projects.isEmpty();
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean needsSaving() {
|
|
for (ProjectTreeNode node : projects) {
|
|
if (node.needsSaving()) return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|