Skip to content

Commit

Permalink
Faster Unsaved Changes
Browse files Browse the repository at this point in the history
Use a single application global boolean to flag when the project has
been modified. This replaces the per resource boolean, without
sacrificing the improved accuracy over GM of whether the project
actually changed. Checking for unsaved changes at close is now only a
linear scan over the open frames, and not every resource in the project.
Creation of groups and deletion of resources is also now additionally
recognized by the check.
  • Loading branch information
RobertBColton committed Feb 24, 2021
1 parent 385f7f2 commit 391d1c7
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 61 deletions.
3 changes: 0 additions & 3 deletions org/lateralgm/components/impl/ResNode.java
Expand Up @@ -210,9 +210,6 @@ public void openFrame(boolean newRes)
{
this.newRes = newRes;
Resource<?,?> r = deRef();
if (r != null) {
r.changed = newRes;
}
if (SubframeInformer.fireSubframeRequest(r,this)) return;
ResourceFrame<?,?> rf = frame;
boolean wasVisible = false;
Expand Down
2 changes: 1 addition & 1 deletion org/lateralgm/main/FileChooser.java
Expand Up @@ -867,7 +867,7 @@ public boolean save(final URI uri, FormatFlavor flavor)
}

LGM.commitAll();
LGM.resetChanges();
LGM.setWindowModified(false);

String ext = selectedWriter.getExtension();
if (!uri.getPath().endsWith(ext))
Expand Down
73 changes: 21 additions & 52 deletions org/lateralgm/main/LGM.java
Expand Up @@ -47,9 +47,7 @@
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Scanner;
Expand Down Expand Up @@ -107,7 +105,6 @@
import org.lateralgm.file.ProjectFile;
import org.lateralgm.file.ProjectFile.ResourceHolder;
import org.lateralgm.file.ProjectFile.SingletonResourceHolder;
import org.lateralgm.file.ResourceList;
import org.lateralgm.file.iconio.ICOFile;
import org.lateralgm.file.iconio.ICOImageReaderSPI;
import org.lateralgm.file.iconio.WBMPImageReaderSpiFix;
Expand All @@ -131,7 +128,7 @@

public final class LGM
{
public static final String version = "1.8.226"; //$NON-NLS-1$
public static final String version = "1.8.227"; //$NON-NLS-1$

// TODO: This list holds the class loader for any loaded plugins which should be
// cleaned up and closed when the application closes.
Expand All @@ -145,7 +142,8 @@ public final class LGM
public static String iconspath = "org/lateralgm/icons/"; //$NON-NLS-1$
public static String iconspack = "Calico"; //$NON-NLS-1$
public static String themename = "Swing"; //$NON-NLS-1$
public static boolean themechanged = false;
private static boolean themechanged = false;
private static boolean windowModified = false;

public static int javaVersion;
public static File tempDir, workDir;
Expand Down Expand Up @@ -863,6 +861,7 @@ public static void commitAll()
public static void reload(boolean newRoot)
{
LGM.mdi.closeAll();
LGM.setWindowModified(false);

InvisibleTreeModel ml = new InvisibleTreeModel(LGM.root);
LGM.tree.setModel(ml);
Expand Down Expand Up @@ -1248,7 +1247,14 @@ public static void setSelectedTab(JTabbedPane tabs, String title)
tabs.setSelectedIndex(index);
}

public static boolean checkForChanges()
/**
* Determines whether the window has been modified since opening a project. This will be true if
* any open frames have been changed. It will also be true if any resources were already changed
* and their internal subframes closed by the save button.
*
* @return Whether the application has modified the open project.
*/
public static boolean isWindowModified()
{
//TODO: Detect tree model changes, e.g, sort by name.
//GM8.1 did this as well, perhaps use listener on the
Expand All @@ -1259,64 +1265,27 @@ public static boolean checkForChanges()
if (((ResourceFrame<?,?>) f).resourceChanged())
return true;

Iterator<?> it = currentFile.resMap.entrySet().iterator();
while (it.hasNext())
{
Entry<?,?> pairs = (Map.Entry<?,?>)it.next();
if (pairs.getValue() instanceof ResourceList)
{
ResourceList<?> list = (ResourceList<?>) pairs.getValue();
for (Resource<?,?> res : list)
if (res.changed)
return true;
}
else if (pairs.getValue() instanceof SingletonResourceHolder)
{
SingletonResourceHolder<?> rh = (SingletonResourceHolder<?>) pairs.getValue();
Resource<?,?> res = rh.getResource();
if (res.changed)
return true;
}
}
return false;
return LGM.windowModified;
}

/**
* When the user saves, reset all the resources to their unsaved state. We do not check the frames
* because they commit their changes allowing them to be written, while still allowing the user to
* revert the frame if they so choose.
* If the user has an open frame with changes basically, the save button will save the changes to
* file and if the user saves the frame then they will still be asked to save when they close, if
* they revert the changes to the frame they will exit right out. This is the expected behavior of
* these functions.
* Marks the application dirty or clears its status as having no modifications.
* When a resource is modified, this is set to true. When the project is saved
* or another project is opened, this is set to false.
*
* @param modified Whether the application has been modified.
*/
public static void resetChanges()
public static void setWindowModified(boolean modified)
{
Iterator<?> it = currentFile.resMap.entrySet().iterator();
while (it.hasNext())
{
Entry<?,?> pairs = (Map.Entry<?,?>)it.next();
if (pairs.getValue() instanceof ResourceList)
{
ResourceList<?> list = (ResourceList<?>) pairs.getValue();
for (Resource<?,?> res : list)
res.changed = false;
}
else if (pairs.getValue() instanceof SingletonResourceHolder)
{
SingletonResourceHolder<?> rh = (SingletonResourceHolder<?>) pairs.getValue();
Resource<?,?> res = rh.getResource();
res.changed = false;
}
}
LGM.windowModified = modified;
}

public static void onMainFrameClosed()
{
int result = JOptionPane.CANCEL_OPTION;
try
{
if (!checkForChanges()) { System.exit(0); }
if (!isWindowModified()) { System.exit(0); }
result = JOptionPane.showConfirmDialog(frame,Messages.getString("LGM.KEEPCHANGES"), //$NON-NLS-1$
Messages.getString("LGM.KEEPCHANGES_TITLE"),JOptionPane.YES_NO_CANCEL_OPTION); //$NON-NLS-1$
}
Expand Down
6 changes: 5 additions & 1 deletion org/lateralgm/main/Listener.java
Expand Up @@ -216,6 +216,7 @@ public static void putNode(JTree tree, ResNode node, ResNode parent, Class<?> r,
tree.expandPath(new TreePath(parent.getPath()));
tree.setSelectionPath(new TreePath(g.getPath()));
tree.updateUI();
LGM.setWindowModified(true);
return;
}

Expand All @@ -233,10 +234,12 @@ public static void putNode(JTree tree, ResNode node, ResNode parent, Class<?> r,
tree.expandPath(new TreePath(parent.getPath()));
tree.setSelectionPath(new TreePath(g.getPath()));
tree.updateUI();
LGM.setWindowModified(true);
g.openFrame(true);
}

/** Deletes the given resource nodes, including groups, and
/**
* Deletes the given resource nodes, including groups, and
* returns the index (row) of the last node that was deleted.
* @param resources An array of resource nodes to delete.
*/
Expand Down Expand Up @@ -274,6 +277,7 @@ else if (node.status == ResNode.STATUS_GROUP)
}
for (Resource<?,?> r : rs)
r.dispose();
LGM.setWindowModified(true);
return last;
}

Expand Down
1 change: 0 additions & 1 deletion org/lateralgm/resources/Resource.java
Expand Up @@ -41,7 +41,6 @@ public abstract class Resource<R extends Resource<R,P>, P extends Enum<P>> imple
public static final Map<Class<? extends Resource<?,?>>,String> kindNamesPlural = new LinkedHashMap<Class<? extends Resource<?,?>>,String>();
public static final List<Class<? extends Resource<?,?>>> kinds = new ArrayList<Class<? extends Resource<?,?>>>();
public static final boolean hasNode = true;
public boolean changed = false;

static
{
Expand Down
4 changes: 1 addition & 3 deletions org/lateralgm/subframes/ResourceFrame.java
Expand Up @@ -65,8 +65,6 @@ public abstract class ResourceFrame<R extends Resource<R,P>, P extends Enum<P>>
public R res;
/** Backup of res as it was before changes were made */
public R resOriginal;
/** Whether changes were made and reported by the PropertyUpdateListener **/
public boolean resChanged;
/** The ResNode this frame is linked to */
public final ResNode node;

Expand Down Expand Up @@ -214,7 +212,7 @@ public void updateResource(boolean commit)
@Override
public void setResourceChanged() {
if (frameListener != null) frameListener.setResourceChanged();
res.changed = true;
LGM.setWindowModified(true);
}

public void revertResource()
Expand Down

0 comments on commit 391d1c7

Please sign in to comment.