diff --git a/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm b/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm
index 99da150e3c..3bc0f20110 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm
@@ -359,7 +359,11 @@
| Use
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java
index c68b4c582d..5fd47fabea 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java
@@ -316,18 +316,7 @@ public final class LanguageProviderPlugin extends Plugin implements ApplicationL
try {
SwingUtilities.invokeAndWait(() -> {
ToolServices toolServices = tool.getToolServices();
- ToolTemplate defaultToolTemplate = toolServices.getDefaultToolTemplate(file);
- if (defaultToolTemplate != null) {
- String defaultToolName = defaultToolTemplate.getName();
- for (PluginTool t : toolServices.getRunningTools()) {
- if (t.getName().equals(defaultToolName)) {
- openTool = t;
- break;
- }
- }
- }
- if (openTool == null ||
- !openTool.acceptDomainFiles(new DomainFile[] { file })) {
+ if (toolServices.launchDefaultTool(domainFile) == null) {
Msg.showError(this, tool.getToolFrame(), "Failed to Open Program",
"A suitable default tool could not found!");
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/ContentHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/ContentHandler.java
index 9c48a7d8c6..f8406044b0 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/ContentHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/ContentHandler.java
@@ -185,8 +185,8 @@ public interface ContentHandler extends Extension
Icon getIcon();
/**
- * Returns the name of the default tool that should be used to open this content type.
- * @return associated default tool for this content type
+ * Returns the name of the default tool/template that should be used to open this content type.
+ * @return associated default tool name for this content type
*/
String getDefaultToolName();
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 0912d2a0c7..05f33daadc 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
@@ -1102,14 +1102,9 @@ public class FrontEndPlugin extends Plugin
}
Project project = tool.getProject();
- final ToolServices toolServices = project.getToolServices();
- ToolTemplate defaultToolTemplate = toolServices.getDefaultToolTemplate(domainFile);
- if (defaultToolTemplate != null) {
- ToolButton button = toolBar.getToolButtonForToolConfig(defaultToolTemplate);
- if (button != null) {
- button.launchTool(domainFile);
- return;
- }
+ ToolServices toolServices = project.getToolServices();
+ if (toolServices.launchDefaultTool(domainFile) != null) {
+ return;
}
Msg.showInfo(this, tool.getToolFrame(), "Cannot Find Tool",
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 49a8eed17f..c613a24d0a 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
@@ -87,6 +87,7 @@ import help.HelpService;
* manner.
*/
public class FrontEndTool extends PluginTool implements OptionsChangeListener {
+ public static final String DEFAULT_TOOL_LAUNCH_MODE = "Default Tool Launch Mode";
public static final String AUTOMATICALLY_SAVE_TOOLS = "Automatically Save Tools";
private static final String USE_ALERT_ANIMATION_OPTION_NAME = "Use Notification Animation";
@@ -122,6 +123,8 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
private WeakSet listeners;
private FrontEndPlugin plugin;
+ private DefaultLaunchMode defaultLaunchMode = DefaultLaunchMode.DEFAULT;
+
private ComponentProvider compProvider;
private LogComponentProvider logProvider;
@@ -315,11 +318,21 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
showComponentHeader(compProvider, false);
}
+ /**
+ * Get the preferred default tool launch mode
+ * @return default tool launch mode
+ */
+ public DefaultLaunchMode getDefaultLaunchMode() {
+ return defaultLaunchMode;
+ }
+
private void initFrontEndOptions() {
ToolOptions options = getOptions(ToolConstants.TOOL_OPTIONS);
HelpLocation help =
new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Front_End_Tool_Options");
+ options.registerOption(DEFAULT_TOOL_LAUNCH_MODE, DefaultLaunchMode.DEFAULT, help,
+ "Indicates if a new or already running tool should be used during default launch.");
options.registerOption(AUTOMATICALLY_SAVE_TOOLS, true, help,
"When enabled tools will be saved when they are closed");
options.registerOption(USE_ALERT_ANIMATION_OPTION_NAME, true, help,
@@ -332,6 +345,8 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
options.registerOption(RESTORE_PREVIOUS_PROJECT_NAME, Boolean.TRUE, help,
"Restore the previous project when Ghidra starts.");
+ defaultLaunchMode = options.getEnum(DEFAULT_TOOL_LAUNCH_MODE, defaultLaunchMode);
+
boolean autoSave = options.getBoolean(AUTOMATICALLY_SAVE_TOOLS, true);
GhidraTool.autoSave = autoSave;
@@ -350,6 +365,9 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
+ if (DEFAULT_TOOL_LAUNCH_MODE.equals(optionName)) {
+ defaultLaunchMode = (DefaultLaunchMode) newValue;
+ }
if (AUTOMATICALLY_SAVE_TOOLS.equals(optionName)) {
GhidraTool.autoSave = (Boolean) newValue;
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java
index 9b7b8aacaf..5937995c0c 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java
@@ -67,7 +67,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
private ToolTemplate template;
private PluginTool associatedRunningTool;
- private DefaultToolChangeListener toolChangeListener;
private ToolServices toolServices;
/**
@@ -132,8 +131,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
}
if (!isRunningTool()) {
- toolChangeListener = new ToolChangeListener(template);
- toolServices.addDefaultToolChangeListener(toolChangeListener);
setIcon(generateIcon());
}
}
@@ -503,8 +500,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
}
void dispose() {
- toolServices.removeDefaultToolChangeListener(toolChangeListener);
-
plugin = null;
template = null;
associatedRunningTool = null;
@@ -679,22 +674,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
// Inner Classes
//==================================================================================================
- private class ToolChangeListener implements DefaultToolChangeListener {
- private final ToolTemplate toolTemplate;
-
- public ToolChangeListener(ToolTemplate toolTemplate) {
- this.toolTemplate = toolTemplate;
- }
-
- @Override
- public void defaultToolChanged(String oldName, String newName) {
- String myName = toolTemplate.getName();
- if (myName.equals(oldName) || myName.equals(newName)) {
- setIcon(generateIcon());
- }
- }
- }
-
private class ToolButtonDropTgtAdapter extends DropTgtAdapter {
private boolean draggingOverValidDropTarget = false;
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataOpenDefaultToolAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataOpenDefaultToolAction.java
index 284ae2aa9d..506e2bb06f 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataOpenDefaultToolAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataOpenDefaultToolAction.java
@@ -21,8 +21,8 @@ import java.util.List;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.framework.main.AppInfo;
-import ghidra.framework.main.datatable.ProjectDataContext;
import ghidra.framework.main.datatable.FrontendProjectTreeAction;
+import ghidra.framework.main.datatable.ProjectDataContext;
import ghidra.framework.model.DomainFile;
public class ProjectDataOpenDefaultToolAction extends FrontendProjectTreeAction {
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultToolChangeListener.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java
similarity index 56%
rename from Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultToolChangeListener.java
rename to Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java
index f72c8e0d9d..f8cbbc1884 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultToolChangeListener.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +15,28 @@
*/
package ghidra.framework.model;
-/**
- * Listener that is notified when the default tool specification changes.
- */
-public interface DefaultToolChangeListener {
+import ghidra.framework.options.Options;
+
+/**
+ * {@link DefaultLaunchMode} provides an {@link Options} value which indicates how a default tool
+ * launch should be performed.
+ */
+public enum DefaultLaunchMode {
+
+ REUSE_TOOL("Reuse acceptable running tool"),
+ NEW_TOOL("Launch new default tool");
+
+ public static DefaultLaunchMode DEFAULT = NEW_TOOL;
+
+ private String str;
+
+ private DefaultLaunchMode(String str) {
+ this.str = str;
+ }
+
+ @Override
+ public String toString() {
+ return str;
+ }
- /**
- * Notification that the default tool specification changed
- * @param oldName name of the old default tool
- * @param newName name of the new default tool
- */
- void defaultToolChanged(String oldName, String newName);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java
index 11b2dd12e6..20150baa2c 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java
@@ -119,6 +119,7 @@ public interface ToolServices {
/**
* Launch the default tool and open the specified domainFile.
+ * NOTE: running tool re-use is implementation dependent
* @param domainFile the file to open
* @return the launched tool. Null returned if a suitable default tool
* for the file content type was not found.
@@ -136,7 +137,8 @@ public interface ToolServices {
/**
* Launch the default tool and open the specified Ghidra URL resource.
- * The tool choosen well be based upon the content type of the specified resource.
+ * The tool choosen will be based upon the content type of the specified resource.
+ * NOTE: running tool re-use is implementation dependent
* @param ghidraUrl resource to be opened (see {@link GhidraURL})
* @return the launched tool. Null returned if a failure occurs while accessing the specified
* resource or a suitable default tool for the file content type was not found.
@@ -155,18 +157,6 @@ public interface ToolServices {
*/
public PluginTool launchToolWithURL(String toolName, URL ghidraUrl);
- /**
- * Add a listener that will be notified when the default tool specification changes
- * @param listener the listener
- */
- public void addDefaultToolChangeListener(DefaultToolChangeListener listener);
-
- /**
- * Remove the listener
- * @param listener the listener
- */
- public void removeDefaultToolChangeListener(DefaultToolChangeListener listener);
-
/**
* Return array of running tools
* @return array of Tools
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java
index 91a3f4cf78..4890313862 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java
@@ -23,10 +23,6 @@ import ghidra.framework.model.*;
public class ToolServicesAdapter implements ToolServices {
- @Override
- public void addDefaultToolChangeListener(DefaultToolChangeListener listener) {
- }
-
@Override
public boolean canAutoSave(PluginTool tool) {
return true;
@@ -97,11 +93,6 @@ public class ToolServicesAdapter implements ToolServices {
return null;
}
- @Override
- public void removeDefaultToolChangeListener(DefaultToolChangeListener listener) {
- // override
- }
-
@Override
public void saveTool(PluginTool tool) {
// override
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java
index 77bd5fb2b1..04d1c1f036 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java
@@ -18,6 +18,7 @@ package ghidra.framework.project.tool;
import java.io.*;
import java.net.URL;
import java.util.*;
+import java.util.function.Function;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;
@@ -26,6 +27,8 @@ import docking.widgets.OptionDialog;
import docking.widgets.filechooser.GhidraFileChooser;
import ghidra.framework.ToolUtils;
import ghidra.framework.data.*;
+import ghidra.framework.main.AppInfo;
+import ghidra.framework.main.FrontEndTool;
import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginEvent;
import ghidra.framework.plugintool.PluginTool;
@@ -49,7 +52,6 @@ class ToolServicesImpl implements ToolServices {
private ToolChest toolChest;
private ToolManagerImpl toolManager;
- private List listeners = new ArrayList<>();
private ToolChestChangeListener toolChestChangeListener;
private Set> contentHandlers;
@@ -187,22 +189,60 @@ class ToolServicesImpl implements ToolServices {
matchingTool.firePluginEvent(event);
}
- @Override
- public PluginTool launchDefaultTool(DomainFile domainFile) {
- ToolTemplate template = getDefaultToolTemplate(domainFile);
- if (template == null) {
- return null;
+ private static DefaultLaunchMode getDefaultLaunchMode() {
+ DefaultLaunchMode defaultLaunchMode = DefaultLaunchMode.DEFAULT;
+ FrontEndTool frontEndTool = AppInfo.getFrontEndTool();
+ if (frontEndTool != null) {
+ defaultLaunchMode = frontEndTool.getDefaultLaunchMode();
}
+ return defaultLaunchMode;
+ }
+
+ private PluginTool defaultLaunch(ToolTemplate template,
+ Function openFunction) {
+
+ DefaultLaunchMode defaultLaunchMode = getDefaultLaunchMode();
+ if (defaultLaunchMode == DefaultLaunchMode.REUSE_TOOL) {
+ if (template != null) {
+ // attempt to reuse running tool with default name
+ String defaultToolName = template.getName();
+ for (PluginTool tool : getRunningTools()) {
+ if (tool.getName().equals(defaultToolName) && openFunction.apply(tool)) {
+ return tool;
+ }
+ }
+ }
+
+ // attempt to reuse any running tool
+ for (PluginTool tool : getRunningTools()) {
+ if (openFunction.apply(tool)) {
+ return tool;
+ }
+ }
+ }
+
+ if (template == null) {
+ return null; // unable to launch new tool
+ }
+
Workspace workspace = toolManager.getActiveWorkspace();
PluginTool tool = workspace.runTool(template);
if (tool == null) {
- return null;
+ return null; // tool launch failed
}
tool.setVisible(true);
- tool.acceptDomainFiles(new DomainFile[] { domainFile });
+ openFunction.apply(tool);
return tool;
}
+ @Override
+ public PluginTool launchDefaultTool(DomainFile domainFile) {
+ ToolTemplate template = getDefaultToolTemplate(domainFile);
+ return defaultLaunch(template, t -> {
+ return t.acceptDomainFiles(new DomainFile[] { domainFile });
+ });
+ }
+
@Override
public PluginTool launchTool(String toolName, DomainFile domainFile) {
ToolTemplate template = findToolChestToolTemplate(toolName);
@@ -228,17 +268,9 @@ class ToolServicesImpl implements ToolServices {
return null;
}
ToolTemplate template = getDefaultToolTemplate(contentType);
- if (template == null) {
- return null;
- }
- Workspace workspace = toolManager.getActiveWorkspace();
- PluginTool tool = workspace.runTool(template);
- if (tool == null) {
- return null;
- }
- tool.setVisible(true);
- tool.accept(ghidraUrl);
- return tool;
+ return defaultLaunch(template, t -> {
+ return t.accept(ghidraUrl);
+ });
}
@Override
@@ -475,16 +507,6 @@ class ToolServicesImpl implements ToolServices {
return contentHandlers;
}
- @Override
- public void addDefaultToolChangeListener(DefaultToolChangeListener listener) {
- listeners.add(listener);
- }
-
- @Override
- public void removeDefaultToolChangeListener(DefaultToolChangeListener listener) {
- listeners.remove(listener);
- }
-
private GhidraToolTemplate findToolChestToolTemplate(String toolName) {
if (toolName != null) {
return (GhidraToolTemplate) toolChest.getToolTemplate(toolName);
|