diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/workflow/ShowInterpreterDebuggerBot.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/workflow/ShowInterpreterDebuggerBot.java index ff04d78513..3dcf8978a2 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/workflow/ShowInterpreterDebuggerBot.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/workflow/ShowInterpreterDebuggerBot.java @@ -28,11 +28,11 @@ import ghidra.util.Msg; import ghidra.util.Swing; @DebuggerBotInfo( // - description = "Show debugger interpreters", // - details = "Listens for new debuggers supporting the interpreter interface," + - " and when found, displays that interpeter.", // - help = @HelpInfo(anchor = "show_interpreter"), // - enabledByDefault = true // + description = "Show debugger interpreters", // + details = "Listens for new debuggers supporting the interpreter interface," + + " and when found, displays that interpeter.", // + help = @HelpInfo(anchor = "show_interpreter"), // + enabledByDefault = true // ) public class ShowInterpreterDebuggerBot implements DebuggerBot { private DebuggerWorkflowServicePlugin plugin; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManager.java index 2d255499b5..8edab3c4ad 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManager.java @@ -26,8 +26,7 @@ import generic.util.WindowUtilities; import ghidra.framework.data.DomainObjectMergeManager; import ghidra.framework.model.DomainFile; import ghidra.framework.model.UndoableDomainObject; -import ghidra.framework.plugintool.ModalPluginTool; -import ghidra.framework.plugintool.PluginTool; +import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.util.PluginException; import ghidra.program.model.listing.DomainObjectChangeSet; import ghidra.util.*; @@ -502,7 +501,7 @@ public abstract class MergeManager implements DomainObjectMergeManager { if (mergePlugin != null) { mergePlugin.dispose(); } - mergeTool.exit(); // cleanup! + PluginToolAccessUtils.dispose(mergeTool); // cleanup! mergeTool = null; }); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java b/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java index 0b5bdbc056..db8e0cf423 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java @@ -42,7 +42,7 @@ public class TestTool extends GhidraTool { } Runnable r = () -> { - exit(); + dispose(); if (getProject().getToolServices() != null) { getProject().getToolServices().closeTool(TestTool.this); } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTSubToolManager.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTSubToolManager.java index e7e4b1dd14..7b87f176d9 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTSubToolManager.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTSubToolManager.java @@ -336,8 +336,8 @@ public class VTSubToolManager implements VTControllerListener, OptionsChangeList saveSubordinateToolConfig(sourceTool); saveSubordinateToolConfig(destinationTool); pluginList.clear(); - sourceTool.exit(); - destinationTool.exit(); + PluginToolAccessUtils.dispose(sourceTool); + PluginToolAccessUtils.dispose(destinationTool); sourceTool = null; destinationTool = null; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/AppInfo.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/AppInfo.java index c3fec12cae..17e89cbf9d 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/AppInfo.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/AppInfo.java @@ -46,7 +46,7 @@ public class AppInfo { public static void exitGhidra() { assertFrontEndRunning(); - tool.exit(); + tool.close(); // closing the front end tool will exit the application } private static void assertFrontEndRunning() { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java index 8b2f82f033..04dea7803d 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java @@ -35,6 +35,7 @@ import ghidra.framework.client.RepositoryAdapter; import ghidra.framework.model.*; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.PluginTool; +import ghidra.framework.plugintool.PluginToolAccessUtils; import ghidra.framework.store.LockException; import ghidra.util.*; import ghidra.util.exception.NotFoundException; @@ -123,7 +124,7 @@ class FileActionManager { closeProjectAction = new DockingAction("Close Project", plugin.getName()) { @Override public void actionPerformed(ActionContext context) { - closeProject(false); //not exiting + closeProject(false); // not exiting } }; closeProjectAction.setEnabled(false); @@ -187,7 +188,7 @@ class FileActionManager { // if all is well and we already have an active project, close it Project activeProject = plugin.getActiveProject(); if (activeProject != null) { - if (!closeProject(false)) { // false -->not exiting + if (!closeProject(false)) { // false --> not exiting return; // user canceled } } @@ -428,7 +429,7 @@ class FileActionManager { // check for any changes since last saved PluginTool[] runningTools = activeProject.getToolManager().getRunningTools(); for (PluginTool runningTool : runningTools) { - if (!runningTool.canClose(isExiting)) { + if (!PluginToolAccessUtils.canClose(runningTool)) { return false; } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java index 9272251a94..a2e6a5c606 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java @@ -445,23 +445,7 @@ public class FrontEndPlugin extends Plugin projectDataPanel.readDataState(saveState); } - /** - * Exit the Ghidra application; the parameter indicates whether - * the user should be prompted to save the project that is about - * to be closed - */ - void exitGhidra() { - boolean okToExit = closeActiveProject(); - if (okToExit) { - System.exit(0); - - } - else if (!tool.isVisible()) { - tool.setVisible(true); - } - } - - private boolean closeActiveProject() { + boolean closeActiveProject() { if (activeProject == null) { return true; } @@ -470,7 +454,7 @@ public class FrontEndPlugin extends Plugin } catch (Exception e) { Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); // Keep this. - int result = OptionDialog.showOptionDialog(tool.getToolFrame(), "Close Project Failed", + int result = OptionDialog.showOptionDialog(null, "Close Project Failed", "Error Description: [ " + e + " ]" + "\n" + "=====> Do you wish to exit Ghidra, possibly losing changes? <=====", "Exit Ghidra (Possibly Lose Changes)", OptionDialog.ERROR_MESSAGE); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndTool.java index 11dd1d1a49..44000e7246 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndTool.java @@ -166,12 +166,17 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener { } @Override - protected void dispose() { + public void dispose() { super.dispose(); if (logProvider != null) { logProvider.dispose(); } + shutdown(); + } + + protected void shutdown() { + System.exit(0); } private void ensureSize() { @@ -392,13 +397,8 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener { } @Override - public void exit() { - plugin.exitGhidra(); - } - - @Override - public void close() { - close(true); + public boolean canClose() { + return super.canClose() && plugin.closeActiveProject(); } /** diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectInfoDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectInfoDialog.java index feacb4ff20..2f1bb07961 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectInfoDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectInfoDialog.java @@ -38,6 +38,7 @@ import ghidra.framework.data.ConvertFileSystem; import ghidra.framework.data.TransientDataManager; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; +import ghidra.framework.plugintool.PluginToolAccessUtils; import ghidra.framework.remote.User; import ghidra.framework.store.local.*; import ghidra.util.*; @@ -95,9 +96,9 @@ public class ProjectInfoDialog extends DialogComponentProvider { connectionButton.setContentAreaFilled(false); connectionButton.setSelected(isConnected); - connectionButton.setBorder( - isConnected ? BorderFactory.createBevelBorder(BevelBorder.LOWERED) - : BorderFactory.createBevelBorder(BevelBorder.RAISED)); + connectionButton + .setBorder(isConnected ? BorderFactory.createBevelBorder(BevelBorder.LOWERED) + : BorderFactory.createBevelBorder(BevelBorder.RAISED)); updateConnectButtonToolTip(); if (isConnected) { try { @@ -181,8 +182,8 @@ public class ProjectInfoDialog extends DialogComponentProvider { String toolTipForChange = "Change server information or specify another repository."; String toolTipForConvert = "Convert project to be a shared project."; - changeConvertButton.setToolTipText( - repository != null ? toolTipForChange : toolTipForConvert); + changeConvertButton + .setToolTipText(repository != null ? toolTipForChange : toolTipForConvert); Class extends LocalFileSystem> fsClass = project.getProjectData().getLocalStorageClass(); String convertStorageButtonLabel = null; @@ -198,8 +199,8 @@ public class ProjectInfoDialog extends DialogComponentProvider { convertStorageButton.addActionListener(e -> convertToIndexedFilesystem()); help.registerHelp(changeConvertButton, new HelpLocation(GenericHelpTopics.FRONT_END, "Convert_Project_Storage")); - convertStorageButton.setToolTipText( - "Convert/Upgrade project storage to latest Indexed Filesystem"); + convertStorageButton + .setToolTipText("Convert/Upgrade project storage to latest Indexed Filesystem"); } JPanel p = new JPanel(new FlowLayout()); @@ -260,9 +261,9 @@ public class ProjectInfoDialog extends DialogComponentProvider { connectionButton.setName("Connect Button"); connectionButton.setContentAreaFilled(false); connectionButton.setSelected(isConnected); - connectionButton.setBorder( - isConnected ? BorderFactory.createBevelBorder(BevelBorder.LOWERED) - : BorderFactory.createBevelBorder(BevelBorder.RAISED)); + connectionButton + .setBorder(isConnected ? BorderFactory.createBevelBorder(BevelBorder.LOWERED) + : BorderFactory.createBevelBorder(BevelBorder.RAISED)); updateConnectButtonToolTip(); HelpService help = Help.getHelpService(); help.registerHelp(connectionButton, @@ -343,8 +344,7 @@ public class ProjectInfoDialog extends DialogComponentProvider { private void updateSharedProjectInfo() { int openCount = getOpenFileCount(); if (openCount != 0) { - Msg.showInfo(getClass(), getComponent(), - "Cannot Change Project Info with Open Files", + Msg.showInfo(getClass(), getComponent(), "Cannot Change Project Info with Open Files", "Found " + openCount + " open project file(s).\n" + "Before your project info can be updated, you must\n" + "close all open project files and tools."); @@ -392,7 +392,7 @@ public class ProjectInfoDialog extends DialogComponentProvider { private boolean checkToolsClose() { PluginTool[] runningTools = project.getToolManager().getRunningTools(); for (PluginTool runningTool : runningTools) { - if (!runningTool.canClose(false)) { + if (!PluginToolAccessUtils.canClose(runningTool)) { return false; } runningTool.close(); @@ -448,8 +448,7 @@ public class ProjectInfoDialog extends DialogComponentProvider { int openCount = getOpenFileCount(); if (openCount != 0) { - Msg.showInfo(getClass(), getComponent(), - "Cannot Convert Project with Open Files", + Msg.showInfo(getClass(), getComponent(), "Cannot Convert Project with Open Files", "Found " + openCount + " open project file(s).\n" + "Before your project can be converted, you must close\n" + "all open project files and tools."); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SaveDataDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SaveDataDialog.java index 213b92c76c..29952b28f1 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SaveDataDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SaveDataDialog.java @@ -126,8 +126,8 @@ public class SaveDataDialog extends DialogComponentProvider { } } if (list.size() > 0) { - DomainFile[] deleteFiles = new DomainFile[list.size()]; - SaveTask task = new SaveTask(list.toArray(deleteFiles)); + DomainFile[] saveFiles = new DomainFile[list.size()]; + SaveTask task = new SaveTask(list.toArray(saveFiles)); new TaskLauncher(task, getComponent()); } else { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/TestFrontEndTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/TestFrontEndTool.java index 921ed9437a..ab324df7e6 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/TestFrontEndTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/TestFrontEndTool.java @@ -28,6 +28,12 @@ public class TestFrontEndTool extends FrontEndTool { @Override public void close() { - setVisible(false); + // overridden to not ask to save + dispose(); + } + + @Override + protected void shutdown() { + // let test environment bring the system down } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java index 67a7db337b..303eac34cc 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java @@ -492,10 +492,6 @@ public abstract class PluginTool extends AbstractDockingTool { return eventMgr.hasToolListeners(); } - public void exit() { - dispose(); - } - protected void dispose() { isDisposed = true; @@ -525,6 +521,7 @@ public abstract class PluginTool extends AbstractDockingTool { disposeManagers(); winMgr.dispose(); + toolServices.closeTool(this); } private void disposeManagers() { @@ -1148,46 +1145,80 @@ public abstract class PluginTool extends AbstractDockingTool { } /** - * Close this tool: + * Closes this tool, possibly with input from the user. The following conditions are checked + * and can prompt the user for more info and allow them to cancel the close. *