diff --git a/ATCS_JAR.jardesc b/ATCS_JAR.jardesc index 14ebad3..1bc3695 100644 --- a/ATCS_JAR.jardesc +++ b/ATCS_JAR.jardesc @@ -1,6 +1,6 @@ - + diff --git a/packaging/Windows/ATCS_Installer.nsi b/packaging/Windows/ATCS_Installer.nsi index 8d0031a..16b49c5 100644 --- a/packaging/Windows/ATCS_Installer.nsi +++ b/packaging/Windows/ATCS_Installer.nsi @@ -1,6 +1,6 @@ !include MUI2.nsh -!define VERSION "0.5.3" +!define VERSION "0.5.4" !define TRAINER_VERSION "0.1.3" !define JAVA_BIN "javaw" diff --git a/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java b/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java index 081d624..1752767 100644 --- a/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java +++ b/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java @@ -5,6 +5,8 @@ import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; +import java.util.LinkedList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -22,10 +24,13 @@ import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector; public class ATContentStudio { public static final String APP_NAME = "Andor's Trail Content Studio"; - public static final String APP_VERSION = "v0.5.3"; + public static final String APP_VERSION = "v0.5.4"; public static boolean STARTED = false; public static StudioFrame frame = null; + + //Need to keep a strong reference to it, to avoid garbage collection that'll reset these loggers. + public static final List configuredLoggers = new LinkedList(); /** * @param args @@ -34,8 +39,6 @@ public class ATContentStudio { ConfigCache.init(); - Logger.getLogger(ExpressionParser.class.getName()).setLevel(Level.OFF); - try { String laf = ConfigCache.getFavoriteLaFClassName(); if (laf == null) laf = UIManager.getSystemLookAndFeelClassName(); @@ -50,6 +53,10 @@ public class ATContentStudio { e.printStackTrace(); } + //Need to keep a strong reference to it, to avoid garbage collection that'll reset this setting. + Logger l = Logger.getLogger(ExpressionParser.class.getName()); + l.setLevel(Level.OFF); + configuredLoggers.add(l); final WorkspaceSelector wsSelect = new WorkspaceSelector(); wsSelect.pack(); @@ -69,7 +76,7 @@ public class ATContentStudio { Workspace.setActive(workspaceRoot); frame = new StudioFrame(APP_NAME+" "+APP_VERSION); frame.setVisible(true); - frame.setDefaultCloseOperation(StudioFrame.EXIT_ON_CLOSE); + frame.setDefaultCloseOperation(StudioFrame.DO_NOTHING_ON_CLOSE); }; }); for (File f : ConfigCache.getKnownWorkspaces()) { diff --git a/src/com/gpl/rpg/atcontentstudio/model/ClosedProject.java b/src/com/gpl/rpg/atcontentstudio/model/ClosedProject.java index 4fe6f4a..db92f88 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/ClosedProject.java +++ b/src/com/gpl/rpg/atcontentstudio/model/ClosedProject.java @@ -116,4 +116,9 @@ public class ClosedProject implements ProjectTreeNode { return true; } + @Override + public boolean needsSaving() { + return false; + } + } diff --git a/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java b/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java index 5497372..534b715 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java +++ b/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java @@ -176,6 +176,10 @@ public abstract class GameDataElement implements ProjectTreeNode, Serializable { return false; } + public boolean needsSaving() { + return this.state == State.modified || this.state == State.created; + } + public abstract String getProjectFilename(); public abstract void save(); diff --git a/src/com/gpl/rpg/atcontentstudio/model/GameSource.java b/src/com/gpl/rpg/atcontentstudio/model/GameSource.java index dcbf5a8..f94751e 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/GameSource.java +++ b/src/com/gpl/rpg/atcontentstudio/model/GameSource.java @@ -213,11 +213,11 @@ public class GameSource implements ProjectTreeNode, Serializable { @Override public String getDesc() { switch(type) { - case altered: return "Altered data"; - case created: return "Created data"; - case referenced: return "Referenced data"; - case source: return "AT Source"; //The fact that it is from "source" is already mentionned by its parent. - default: return "Game data"; + case altered: return (needsSaving() ? "*" : "")+"Altered data"; + case created: return (needsSaving() ? "*" : "")+"Created data"; + case referenced: return (needsSaving() ? "*" : "")+"Referenced data"; + case source: return (needsSaving() ? "*" : "")+"AT Source"; //The fact that it is from "source" is already mentionned by its parent. + default: return (needsSaving() ? "*" : "")+"Game data"; } } @@ -283,4 +283,12 @@ public class GameSource implements ProjectTreeNode, Serializable { public WorldmapSegment getWorldmapSegment(String id) { return worldmap.getWorldmapSegment(id); } + + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : v.getNonEmptyIterable()) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/Project.java b/src/com/gpl/rpg/atcontentstudio/model/Project.java index d46f830..4badae0 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/Project.java +++ b/src/com/gpl/rpg/atcontentstudio/model/Project.java @@ -191,7 +191,7 @@ public class Project implements ProjectTreeNode, Serializable { } @Override public String getDesc() { - return name; + return (needsSaving() ? "*" : "")+name; } @@ -265,7 +265,7 @@ public class Project implements ProjectTreeNode, Serializable { } } for (ProjectTreeNode node : baseContent.gameMaps.tmxMaps) { - ((TMXMap)node).parse(); + ((TMXMap)node).link(); } for (ProjectTreeNode node : alteredContent.gameData.v.getNonEmptyIterable()) { if (node instanceof GameDataCategory) { @@ -275,7 +275,7 @@ public class Project implements ProjectTreeNode, Serializable { } } for (ProjectTreeNode node : alteredContent.gameMaps.tmxMaps) { - ((TMXMap)node).parse(); + ((TMXMap)node).link(); } for (ProjectTreeNode node : createdContent.gameData.v.getNonEmptyIterable()) { if (node instanceof GameDataCategory) { @@ -285,9 +285,6 @@ public class Project implements ProjectTreeNode, Serializable { } } for (ProjectTreeNode node : createdContent.gameMaps.tmxMaps) { - ((TMXMap)node).parse(); - } - for (ProjectTreeNode node : baseContent.gameMaps.tmxMaps) { ((TMXMap)node).link(); } @@ -1131,6 +1128,13 @@ public class Project implements ProjectTreeNode, Serializable { } + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : v.getNonEmptyIterable()) { + if (node.needsSaving()) return true; + } + return false; + } diff --git a/src/com/gpl/rpg/atcontentstudio/model/ProjectTreeNode.java b/src/com/gpl/rpg/atcontentstudio/model/ProjectTreeNode.java index e8cd643..ae58d2c 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/ProjectTreeNode.java +++ b/src/com/gpl/rpg/atcontentstudio/model/ProjectTreeNode.java @@ -53,5 +53,7 @@ public interface ProjectTreeNode extends TreeNode { public GameSource.Type getDataType(); public boolean isEmpty(); + + public boolean needsSaving(); } diff --git a/src/com/gpl/rpg/atcontentstudio/model/Workspace.java b/src/com/gpl/rpg/atcontentstudio/model/Workspace.java index d91301e..7e12910 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/Workspace.java +++ b/src/com/gpl/rpg/atcontentstudio/model/Workspace.java @@ -140,8 +140,15 @@ public class Workspace implements ProjectTreeNode, Serializable { @Override public void childrenChanged(List path) { path.add(0, this); - if (projectsTreeModel != null) projectsTreeModel.changeNode(new TreePath(path.toArray())); - ATContentStudio.frame.editorChanged(path.get(path.size() - 1)); + 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 @@ -346,5 +353,14 @@ public class Workspace implements ProjectTreeNode, Serializable { public boolean isEmpty() { return projects.isEmpty(); } + + + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : projects) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/WorkspaceSettings.java b/src/com/gpl/rpg/atcontentstudio/model/WorkspaceSettings.java index 666e0f1..090be12 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/WorkspaceSettings.java +++ b/src/com/gpl/rpg/atcontentstudio/model/WorkspaceSettings.java @@ -63,20 +63,14 @@ public class WorkspaceSettings { reader = new FileReader(f); @SuppressWarnings("rawtypes") Map jsonSettings = (Map) parser.parse(reader); - Integer version = (Integer) jsonSettings.get(VERSION_KEY); + Integer version = ((Number) jsonSettings.get(VERSION_KEY)).intValue(); if (version != null) { if (version >= 1) { loadv1(jsonSettings); } } - } catch (FileNotFoundException e) { - Notification.addError("Error while parsing workspace settings: "+e.getMessage()); - e.printStackTrace(); - } catch (IOException e) { - Notification.addError("Error while parsing workspace settings: "+e.getMessage()); - e.printStackTrace(); - } catch (ParseException e) { + } catch (Exception e) { Notification.addError("Error while parsing workspace settings: "+e.getMessage()); e.printStackTrace(); } finally { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/ActorCondition.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/ActorCondition.java index f76a9cf..cc2b344 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/ActorCondition.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/ActorCondition.java @@ -88,7 +88,7 @@ public class ActorCondition extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+display_name+" ("+id+")"; + return (needsSaving() ? "*" : "")+display_name+" ("+id+")"; } @SuppressWarnings("rawtypes") diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java index 7772327..5e9fe13 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java @@ -92,7 +92,7 @@ public class Dialogue extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+id; + return (needsSaving() ? "*" : "")+id; } public static String getStaticDesc() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Droplist.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Droplist.java index e00224a..82b39f8 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Droplist.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Droplist.java @@ -47,7 +47,7 @@ public class Droplist extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+id; + return (needsSaving() ? "*" : "")+id; } public static String getStaticDesc() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataCategory.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataCategory.java index 0964ae6..9e9ac41 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataCategory.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataCategory.java @@ -102,7 +102,7 @@ public class GameDataCategory extends ArrayList implem } @Override public String getDesc() { - return this.name; + return (needsSaving() ? "*" : "")+this.name; } @Override @@ -208,7 +208,7 @@ public class GameDataCategory extends ArrayList implem impactedCategory = getProject().createdContent.gameData.getCategory(node.getClass()); impactedFileName = node.getProjectFilename(); } - } else if (node.state == GameDataElement.State.modified) { + } else if (node.needsSaving()) { events.add(new SaveEvent(SaveEvent.Type.alsoSave, node)); } if (containedIds.containsKey(node.id)) { @@ -242,5 +242,12 @@ public class GameDataCategory extends ArrayList implem return result; } + @Override + public boolean needsSaving() { + for (E node : this) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataSet.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataSet.java index 666eecf..187dbcb 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataSet.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/GameDataSet.java @@ -236,7 +236,7 @@ public class GameDataSet implements ProjectTreeNode, Serializable { } @Override public String getDesc() { - return "JSON data"; + return (needsSaving() ? "*" : "")+"JSON data"; } @@ -463,4 +463,11 @@ public class GameDataSet implements ProjectTreeNode, Serializable { return null; } + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : v.getNonEmptyIterable()) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Item.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Item.java index 886b8ae..5d0a87b 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Item.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Item.java @@ -102,7 +102,7 @@ public class Item extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+name+" ("+id+")"; + return (needsSaving() ? "*" : "")+name+" ("+id+")"; } public static String getStaticDesc() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/ItemCategory.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/ItemCategory.java index 3e311e0..7fcb7e2 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/ItemCategory.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/ItemCategory.java @@ -100,7 +100,7 @@ public class ItemCategory extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+name+" ("+id+")"; + return (needsSaving() ? "*" : "")+name+" ("+id+")"; } public static String getStaticDesc() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/NPC.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/NPC.java index e281ab1..7492e62 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/NPC.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/NPC.java @@ -96,7 +96,7 @@ public class NPC extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+name+" ("+id+")"; + return (needsSaving() ? "*" : "")+name+" ("+id+")"; } public static String getStaticDesc() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java index c00bd49..a45803f 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java @@ -49,7 +49,7 @@ public class Quest extends JSONElement { @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+name+" ("+id+")"; + return (needsSaving() ? "*" : "")+name+" ("+id+")"; } public static String getStaticDesc() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java index bb1fe8c..a67392c 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java @@ -120,6 +120,7 @@ public class Requirement extends JSONElement { break; } if (this.required_obj != null) this.required_obj.addBacklink((GameDataElement) this.parent); + this.state = State.linked; } @Override diff --git a/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java b/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java index c43e774..7efa41f 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java +++ b/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java @@ -62,7 +62,6 @@ public class TMXMap extends GameDataElement { public Integer outside = null; public ColorFilter colorFilter = null; - public boolean writable = false; public boolean changedOnDisk = false; public int dismissNextChangeNotif = 0; @@ -129,6 +128,7 @@ public class TMXMap extends GameDataElement { clone.groups = new ArrayList(); } MapObjectGroup group = new MapObjectGroup((tiled.core.ObjectGroup) layer, this); + group.link(); clone.groups.add(group); } } @@ -201,7 +201,7 @@ public class TMXMap extends GameDataElement { } @Override public String getDesc() { - return ((this.state == State.modified || this.state == State.created) ? "*" : "")+id; + return (needsSaving() ? "*" : "")+id; } @Override @@ -315,7 +315,7 @@ public class TMXMap extends GameDataElement { if (this.state == GameDataElement.State.init) { parse(); } - if (this.state == GameDataElement.State.parsed || this.state == GameDataElement.State.created) { + if (this.state == GameDataElement.State.parsed) { if (groups != null) { for (MapObjectGroup group : groups) { group.link(); diff --git a/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMapSet.java b/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMapSet.java index c9bcccd..5145383 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMapSet.java +++ b/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMapSet.java @@ -187,7 +187,7 @@ public class TMXMapSet implements ProjectTreeNode { } @Override public String getDesc() { - return "TMX Maps"; + return (needsSaving() ? "*" : "")+"TMX Maps"; } @Override @@ -262,4 +262,12 @@ public class TMXMapSet implements ProjectTreeNode { return tmxMaps.get(index); } + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : tmxMaps) { + if (node.needsSaving()) return true; + } + return false; + } + } diff --git a/src/com/gpl/rpg/atcontentstudio/model/maps/Worldmap.java b/src/com/gpl/rpg/atcontentstudio/model/maps/Worldmap.java index bce6d9a..6ef06fd 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/maps/Worldmap.java +++ b/src/com/gpl/rpg/atcontentstudio/model/maps/Worldmap.java @@ -173,7 +173,7 @@ public class Worldmap extends ArrayList implements ProjectTreeN @Override public String getDesc() { - return "Worldmap"; + return (needsSaving() ? "*" : "")+"Worldmap"; } @Override public void notifyCreated() { @@ -277,6 +277,13 @@ public class Worldmap extends ArrayList implements ProjectTreeN e.printStackTrace(); } } - + + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : this) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/maps/WorldmapSegment.java b/src/com/gpl/rpg/atcontentstudio/model/maps/WorldmapSegment.java index fc2d7e3..c12d472 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/maps/WorldmapSegment.java +++ b/src/com/gpl/rpg/atcontentstudio/model/maps/WorldmapSegment.java @@ -52,7 +52,7 @@ public class WorldmapSegment extends GameDataElement { @Override public String getDesc() { - return id; + return (needsSaving() ? "*" : "")+id; } @Override diff --git a/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGame.java b/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGame.java index 220789c..4cc3ef5 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGame.java +++ b/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGame.java @@ -97,7 +97,7 @@ public class SavedGame extends GameDataElement { } @Override public String getDesc() { - return loadedSave.displayInfo; + return (needsSaving() ? "*" : "")+loadedSave.displayInfo; } @Override diff --git a/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGamesSet.java b/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGamesSet.java index 39998a8..7e241a2 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGamesSet.java +++ b/src/com/gpl/rpg/atcontentstudio/model/saves/SavedGamesSet.java @@ -128,7 +128,7 @@ public class SavedGamesSet implements ProjectTreeNode, Serializable { } @Override public String getDesc() { - return "Saved games"; + return (needsSaving() ? "*" : "")+"Saved games"; } @Override @@ -168,4 +168,13 @@ public class SavedGamesSet implements ProjectTreeNode, Serializable { public boolean isEmpty() { return saves.isEmpty(); } + + + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : saves) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/sprites/SpriteSheetSet.java b/src/com/gpl/rpg/atcontentstudio/model/sprites/SpriteSheetSet.java index 9401cea..a361e49 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/sprites/SpriteSheetSet.java +++ b/src/com/gpl/rpg/atcontentstudio/model/sprites/SpriteSheetSet.java @@ -102,7 +102,7 @@ public class SpriteSheetSet implements ProjectTreeNode { } @Override public String getDesc() { - return "Spritesheets"; + return (needsSaving() ? "*" : "")+"Spritesheets"; } @Override @@ -151,4 +151,12 @@ public class SpriteSheetSet implements ProjectTreeNode { } return null; } + + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : spritesheets) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/sprites/Spritesheet.java b/src/com/gpl/rpg/atcontentstudio/model/sprites/Spritesheet.java index bbe79fb..60e3177 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/sprites/Spritesheet.java +++ b/src/com/gpl/rpg/atcontentstudio/model/sprites/Spritesheet.java @@ -118,7 +118,7 @@ public class Spritesheet extends GameDataElement { } @Override public String getDesc() { - return spritesheetFile.getName(); + return (needsSaving() ? "*" : "")+spritesheetFile.getName(); } @Override diff --git a/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeData.java b/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeData.java index 08bd303..17654a4 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeData.java +++ b/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeData.java @@ -413,7 +413,7 @@ public class WriterModeData extends GameDataElement { @Override public String getDesc() { - return (this.state == State.modified ? "*" : "")+id; + return (needsSaving() ? "*" : "")+id; } @Override public Project getProject() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeDataSet.java b/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeDataSet.java index d03ee2b..46f37dc 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeDataSet.java +++ b/src/com/gpl/rpg/atcontentstudio/model/tools/writermode/WriterModeDataSet.java @@ -110,7 +110,7 @@ public class WriterModeDataSet implements ProjectTreeNode, Serializable { @Override public String getDesc() { - return "Dialogue sketchs"; + return (needsSaving() ? "*" : "")+"Dialogue sketchs"; } @Override @@ -195,7 +195,7 @@ public class WriterModeDataSet implements ProjectTreeNode, Serializable { public List attemptSave() { List events = new ArrayList(); for (WriterModeData data : writerModeDataList) { - if (data.state == State.created || data.state == State.modified) { + if (data.needsSaving()) { events.add(new SaveEvent(SaveEvent.Type.alsoSave, data)); } } @@ -262,5 +262,14 @@ public class WriterModeDataSet implements ProjectTreeNode, Serializable { if (higherEmptyParent != null) higherEmptyParent.notifyCreated(); else node.notifyCreated(); } + + + @Override + public boolean needsSaving() { + for (ProjectTreeNode node : writerModeDataList) { + if (node.needsSaving()) return true; + } + return false; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/IdChangeImpactWizard.java b/src/com/gpl/rpg/atcontentstudio/ui/IdChangeImpactWizard.java new file mode 100644 index 0000000..932966e --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/ui/IdChangeImpactWizard.java @@ -0,0 +1,100 @@ +package com.gpl.rpg.atcontentstudio.ui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.Vector; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import com.gpl.rpg.atcontentstudio.ATContentStudio; +import com.gpl.rpg.atcontentstudio.model.GameDataElement; +import com.jidesoft.swing.JideBoxLayout; + +public class IdChangeImpactWizard extends JDialog { + + private static final long serialVersionUID = 8532169707953315739L; + + public static enum Result { + ok, cancel + } + + Result result = null; + + private IdChangeImpactWizard(GameDataElement changing, List toModify, List toAlter) { + super(ATContentStudio.frame, true); + JPanel pane = new JPanel(); + pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS)); + + pane.add(new JLabel("Changing the id for \""+changing.getDesc()+"\" has impacts on your project:"), JideBoxLayout.FIX); + pane.add(new JLabel("The following elements from your project will be modified:"), JideBoxLayout.FIX); + JList modifList = new JList(new Vector(toModify)); + modifList.setCellRenderer(new ChangeImpactListCellRenderer()); + pane.add(new JScrollPane(modifList), JideBoxLayout.FIX); + pane.add(new JLabel("The following elements from the game source will be altered:"), JideBoxLayout.FIX); + JList alterList = new JList(new Vector(toAlter)); + alterList.setCellRenderer(new ChangeImpactListCellRenderer()); + pane.add(new JScrollPane(alterList), JideBoxLayout.FIX); + pane.add(new JLabel("Press Ok to apply the changes, or Cancel to cancel your edition of the object's ID"), JideBoxLayout.FIX); + + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS)); + buttonPane.add(new JPanel(), JideBoxLayout.VARY); + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + result = Result.cancel; + dispose(); + } + }); + buttonPane.add(cancelButton, JideBoxLayout.FIX); + JButton okButton = new JButton("Ok"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + result = Result.ok; + dispose(); + } + }); + buttonPane.add(okButton, JideBoxLayout.FIX); + pane.add(buttonPane, JideBoxLayout.FIX); + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(pane, BorderLayout.CENTER); + pack(); + } + + + public static Result showIdChangeImapctWizard(GameDataElement changing, List toModify, List toAlter) { + IdChangeImpactWizard wizard = new IdChangeImpactWizard(changing, toModify, toAlter); + wizard.setVisible(true); + return wizard.result; + } + + public class ChangeImpactListCellRenderer extends DefaultListCellRenderer { + private static final long serialVersionUID = 5764079243906396333L; + + @Override + public Component getListCellRendererComponent(@SuppressWarnings("rawtypes") JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (c instanceof JLabel) { + JLabel label = (JLabel) c; + GameDataElement target = ((GameDataElement)value); + label.setIcon(new ImageIcon(target.getIcon())); + label.setText(target.getDataType().toString()+"/"+target.getDesc()); + } + return c; + } + + } + +} diff --git a/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java b/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java index 035cd1c..02d2c70 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java @@ -118,6 +118,7 @@ public class StudioFrame extends JFrame { @Override public void windowClosing(WindowEvent e) { Workspace.saveActive(); + actions.exitATCS.actionPerformed(null); } }); } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/WorkspaceActions.java b/src/com/gpl/rpg/atcontentstudio/ui/WorkspaceActions.java index 77761b2..d371f15 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/WorkspaceActions.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/WorkspaceActions.java @@ -95,14 +95,14 @@ public class WorkspaceActions { public void actionPerformed(ActionEvent e) { if (!(selectedNode instanceof GameDataElement)) return; final GameDataElement node = ((GameDataElement)selectedNode); - if (node.state == GameDataElement.State.modified){ + if (node.needsSaving()){ node.save(); ATContentStudio.frame.nodeChanged(node); } }; public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) { if (selectedNode instanceof GameDataElement) { - setEnabled(((GameDataElement)selectedNode).state == GameDataElement.State.modified); + setEnabled(((GameDataElement)selectedNode).needsSaving()); } else { setEnabled(false); } @@ -330,8 +330,14 @@ public class WorkspaceActions { public ATCSAction exitATCS = new ATCSAction("Exit", "Closes the program"){ public void actionPerformed(ActionEvent e) { - //TODO ouch. - System.exit(0); + if (Workspace.activeWorkspace.needsSaving()) { + int answer = JOptionPane.showConfirmDialog(ATContentStudio.frame, "There are unsaved changes in your workspace.\nExiting ATCS will discard these changes.\nDo you really want to exit?", "Unsaved changes. Confirm exit.", JOptionPane.YES_NO_OPTION); + if (answer == JOptionPane.YES_OPTION) { + System.exit(0); + } + } else { + System.exit(0); + } }; }; diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ActorConditionEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ActorConditionEditor.java index 30f6eb4..42c5e42 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ActorConditionEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ActorConditionEditor.java @@ -147,10 +147,22 @@ public class ActorConditionEditor extends JSONElementEditor { public void valueChanged(JComponent source, Object value) { ActorCondition aCond = (ActorCondition)target; if (source == idField) { - aCond.id = (String) value; - ActorConditionEditor.this.name = aCond.getDesc(); - aCond.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(ActorConditionEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + aCond.id = (String) value; + ActorConditionEditor.this.name = aCond.getDesc(); + aCond.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(ActorConditionEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == nameField) { aCond.display_name = (String) value; ActorConditionEditor.this.name = aCond.getDesc(); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java index 3a2ef62..b284535 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java @@ -1075,10 +1075,22 @@ public class DialogueEditor extends JSONElementEditor { public void valueChanged(JComponent source, Object value) { Dialogue dialogue = (Dialogue) target; if (source == idField) { - dialogue.id = (String) value; - DialogueEditor.this.name = dialogue.getDesc(); - dialogue.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(DialogueEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + dialogue.id = (String) value; + DialogueEditor.this.name = dialogue.getDesc(); + dialogue.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(DialogueEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == messageField) { dialogue.message = (String) value; } else if (source == switchToNpcBox) { diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DroplistEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DroplistEditor.java index cc8a7f2..e9d3c08 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DroplistEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DroplistEditor.java @@ -248,10 +248,22 @@ public class DroplistEditor extends JSONElementEditor { public void valueChanged(JComponent source, Object value) { Droplist droplist = ((Droplist)target); if (source == idField) { - droplist.id = (String) value; - DroplistEditor.this.name = droplist.getDesc(); - droplist.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(DroplistEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + droplist.id = (String) value; + DroplistEditor.this.name = droplist.getDesc(); + droplist.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(DroplistEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == itemCombo) { if (selectedItem.item != null) { selectedItem.item.removeBacklink(droplist); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemCategoryEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemCategoryEditor.java index 1c57767..a843b22 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemCategoryEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemCategoryEditor.java @@ -87,10 +87,22 @@ public class ItemCategoryEditor extends JSONElementEditor { public void valueChanged(JComponent source, Object value) { ItemCategory ic = (ItemCategory)target; if (source == idField) { - ic.id = (String) value; - ItemCategoryEditor.this.name = ic.getDesc(); - ic.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(ItemCategoryEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + ic.id = (String) value; + ItemCategoryEditor.this.name = ic.getDesc(); + ic.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(ItemCategoryEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == nameField) { ic.name = (String) value; ItemCategoryEditor.this.name = ic.getDesc(); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemEditor.java index b801691..0b1674d 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemEditor.java @@ -936,10 +936,22 @@ public class ItemEditor extends JSONElementEditor { boolean updatePrice, updateEquip, updateHit, updateKill; updatePrice = updateEquip = updateHit = updateKill = false; if (source == idField) { - item.id = (String) value; - ItemEditor.this.name = item.getDesc(); - item.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(ItemEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + item.id = (String) value; + ItemEditor.this.name = item.getDesc(); + item.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(ItemEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == nameField) { item.name = (String) value; ItemEditor.this.name = item.getDesc(); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java index 7b236a5..96278bf 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java @@ -6,6 +6,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -14,6 +15,8 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; @@ -26,10 +29,13 @@ import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode; import com.gpl.rpg.atcontentstudio.model.SaveEvent; import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory; import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement; +import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; +import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment; import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet; import com.gpl.rpg.atcontentstudio.ui.DefaultIcons; import com.gpl.rpg.atcontentstudio.ui.Editor; import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener; +import com.gpl.rpg.atcontentstudio.ui.IdChangeImpactWizard; import com.gpl.rpg.atcontentstudio.ui.SaveItemsWizard; import com.gpl.rpg.atcontentstudio.ui.sprites.SpriteChooser; import com.jidesoft.swing.JideBoxLayout; @@ -275,4 +281,64 @@ public abstract class JSONElementEditor extends Editor { message.revalidate(); message.repaint(); } + + + public boolean idChanging() { + JSONElement node = (JSONElement) target; + List toModify = new LinkedList(); + List toAlter = new LinkedList(); + for (GameDataElement element : node.getBacklinks()) { + GameDataElement activeElement = element; + if (element instanceof JSONElement) { + activeElement = node.getProject().getGameDataElement((Class) element.getClass(), element.id); + } else if (element instanceof TMXMap) { + activeElement = node.getProject().getMap(element.id); + } else if (element instanceof WorldmapSegment) { + activeElement = node.getProject().getWorldmapSegment(element.id); + } + if (activeElement.writable) { + //No need to alter. Check if we flag a new modification. + if (!activeElement.needsSaving()) { + toModify.add(activeElement); + } + } else { + toAlter.add(activeElement); + } + } + if (!(toModify.isEmpty() && toAlter.isEmpty())) { + IdChangeImpactWizard.Result result = IdChangeImpactWizard.showIdChangeImapctWizard(target, toModify, toAlter); + if (result == IdChangeImpactWizard.Result.ok) { + for (GameDataElement element : toModify) { + element.state = GameDataElement.State.modified; + element.childrenChanged(new ArrayList()); + } + for (GameDataElement element : toAlter) { + if (element instanceof JSONElement) { + node.getProject().makeWritable((JSONElement)element); + } else if (element instanceof TMXMap) { + node.getProject().makeWritable((TMXMap)element); + } else if (element instanceof WorldmapSegment) { + node.getProject().makeWritable((WorldmapSegment)element); + } + } + return true; + } + } else { + return true; + } + return false; + } + + //setText in cancelIdEdit generates to edit events, one replacing the contents with the empty string, and one with the target.id. We want to skip the first one. + public boolean skipNext = false; + public void cancelIdEdit(final JTextField idField) { + Runnable revertField = new Runnable(){ + @Override + public void run() { + skipNext = true; + idField.setText(target.id); + } + }; + SwingUtilities.invokeLater(revertField); + } } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/NPCEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/NPCEditor.java index a98c6ab..8f4ca06 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/NPCEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/NPCEditor.java @@ -166,7 +166,7 @@ public class NPCEditor extends JSONElementEditor { public void insertFormViewDataField(JPanel pane) { final NPC npc = (NPC) target; - final FieldUpdateListener listener = new NPCFieldUpdate(); + final FieldUpdateListener listener = new NPCFieldUpdater(); npcIcon = createButtonPane(pane, npc.getProject(), npc, NPC.class, npc.getImage(), Spritesheet.Category.monster, listener); @@ -504,17 +504,29 @@ public class NPCEditor extends JSONElementEditor { return true; } - public class NPCFieldUpdate implements FieldUpdateListener { + public class NPCFieldUpdater implements FieldUpdateListener { @Override public void valueChanged(JComponent source, Object value) { NPC npc = (NPC)target; boolean updateHit = false; if (source == idField) { - npc.id = (String) value; - NPCEditor.this.name = npc.getDesc(); - npc.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(NPCEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + npc.id = (String) value; + NPCEditor.this.name = npc.getDesc(); + npc.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(NPCEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == nameField) { npc.name = (String) value; NPCEditor.this.name = npc.getDesc(); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java index 2af7cdc..abb6588 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java @@ -314,10 +314,22 @@ public class QuestEditor extends JSONElementEditor { public void valueChanged(JComponent source, Object value) { Quest quest = (Quest) target; if (source == idField) { - quest.id = (String) value; - QuestEditor.this.name = quest.getDesc(); - quest.childrenChanged(new ArrayList()); - ATContentStudio.frame.editorChanged(QuestEditor.this); + //Events caused by cancel an ID edition. Dismiss. + if (skipNext) { + skipNext = false; + return; + } + if (target.id.equals((String) value)) return; + + if (idChanging()) { + quest.id = (String) value; + QuestEditor.this.name = quest.getDesc(); + quest.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(QuestEditor.this); + } else { + cancelIdEdit(idField); + return; + } } else if (source == nameField) { quest.name = (String) value; QuestEditor.this.name = quest.getDesc(); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java index 81b462b..03dd81b 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java @@ -1615,7 +1615,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe gdeIcon.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (map.state == GameDataElement.State.modified || map.state == GameDataElement.State.created) { + if (map.needsSaving()) { int confirm = JOptionPane.showConfirmDialog(TMXMapEditor.this, "You have unsaved changes in ATCS.\nYou'd better save your changes in ATCS before opening this map with the external editor.\nDo you want to save before opening the file?", "Save before opening?", JOptionPane.YES_NO_CANCEL_OPTION); if (confirm == JOptionPane.CANCEL_OPTION) return; if (confirm == JOptionPane.YES_OPTION) { @@ -1633,7 +1633,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { - if (map.state == GameDataElement.State.modified) { + if (map.needsSaving()) { int confirm = JOptionPane.showConfirmDialog(TMXMapEditor.this, "You modified this map in ATCS. All ATCS-made changes will be lost if you confirm.\n On the other hand, if you save using ATCS, all external changes will be lost.\n Do you want to reload?", "Confirm reload?", JOptionPane.OK_CANCEL_OPTION); if (confirm == JOptionPane.CANCEL_OPTION) return; } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java index 6b8cc73..d4e17f4 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java @@ -63,7 +63,8 @@ public class WorldMapEditor extends Editor { public String mapBeingAddedID = null; public String selectedLabel = null; - + WorldMapView mapView = null; + public WorldMapEditor(WorldmapSegment worldmap) { target = worldmap; this.name = worldmap.id; @@ -114,7 +115,7 @@ public class WorldMapEditor extends Editor { addLabelField(pane, "Worldmap File: ", ((Worldmap)worldmap.getParent()).worldmapFile.getAbsolutePath()); pane.add(createButtonPane(worldmap), JideBoxLayout.FIX); - final WorldMapView mapView = new WorldMapView(worldmap); + mapView = new WorldMapView(worldmap); JScrollPane mapScroller = new JScrollPane(mapView); final JViewport vPort = mapScroller.getViewport(); @@ -296,6 +297,7 @@ public class WorldMapEditor extends Editor { for (String s : mapView.selected) { map.labelledMaps.get(selectedLabel).add(s); } + notifyModelModified(); mapView.revalidate(); mapView.repaint(); } @@ -319,6 +321,7 @@ public class WorldMapEditor extends Editor { worldmap.labels.put(created.id, created); worldmap.labels.remove(selectedLabel); selectedLabel = created.id; + notifyModelModified(); mapView.revalidate(); mapView.repaint(); } @@ -334,6 +337,7 @@ public class WorldMapEditor extends Editor { worldmap.labelledMaps.remove(selectedLabel); worldmap.labels.remove(selectedLabel); selectedLabel = null; + notifyModelModified(); mapView.revalidate(); mapView.repaint(); } @@ -348,6 +352,7 @@ public class WorldMapEditor extends Editor { public void labelCreated(NamedArea created) { worldmap.labelledMaps.put(created.id, new ArrayList()); worldmap.labelledMaps.get(created.id).addAll(mapView.selected); + notifyModelModified(); mapView.revalidate(); mapView.repaint(); } @@ -436,11 +441,12 @@ public class WorldMapEditor extends Editor { mapView.selected.remove(selectedMap); mapSelectionChanged(); mapView.updateFromModel(); + notifyModelModified(); update = true; } else if (editMode == EditMode.addMap && mapBeingAddedID != null) { if (e.getButton() == MouseEvent.BUTTON1) { mapView.recomputeSize(); - mapView.pushToModel(); + pushToModel(); } mapView.updateFromModel(); update = true; @@ -463,7 +469,7 @@ public class WorldMapEditor extends Editor { public void mouseReleased(MouseEvent e) { dragStart = null; if (editMode == EditMode.moveMaps) { - mapView.pushToModel(); + pushToModel(); } } @@ -713,4 +719,16 @@ public class WorldMapEditor extends Editor { message.repaint(); } + public void pushToModel() { + mapView.pushToModel(); + notifyModelModified(); + } + + public void notifyModelModified() { + target.state = GameDataElement.State.modified; + this.name = ((WorldmapSegment)target).getDesc(); + target.childrenChanged(new ArrayList()); + } + + }