mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GT-2869 - Key Bindings - review fixes
This commit is contained in:
parent
43fa7e3f92
commit
2de5c40cd6
23 changed files with 142 additions and 455 deletions
|
@ -102,7 +102,7 @@ public class CreateHelpTemplateScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DockingActionIf> getActions(PluginTool tool, Plugin plugin) {
|
private List<DockingActionIf> getActions(PluginTool tool, Plugin plugin) {
|
||||||
Set<DockingActionIf> actions = KeyBindingUtils.getKeyBindingActions(tool, plugin.getName());
|
Set<DockingActionIf> actions = KeyBindingUtils.getKeyBindingActionsForOwner(tool, plugin.getName());
|
||||||
List<DockingActionIf> list = new ArrayList<>(actions);
|
List<DockingActionIf> list = new ArrayList<>(actions);
|
||||||
Comparator<DockingActionIf> comparator = (action1, action2) -> {
|
Comparator<DockingActionIf> comparator = (action1, action2) -> {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -186,8 +186,8 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
public DockingAction getKeyBindingAction() {
|
public DockingAction getKeyBindingAction() {
|
||||||
DockingWindowManager dwm = DockingWindowManager.getInstance(tool.getToolFrame());
|
DockingWindowManager dwm = DockingWindowManager.getInstance(tool.getToolFrame());
|
||||||
DockingActionManager dockingActionManager =
|
ActionToGuiMapper dockingActionManager =
|
||||||
(DockingActionManager) getInstanceField("actionManager", dwm);
|
(ActionToGuiMapper) getInstanceField("actionManager", dwm);
|
||||||
return (DockingAction) getInstanceField("keyBindingsAction", dockingActionManager);
|
return (DockingAction) getInstanceField("keyBindingsAction", dockingActionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import java.util.*;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import docking.actions.DockingToolActionManager;
|
import docking.actions.ToolActions;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ import ghidra.util.SystemUtilities;
|
||||||
public abstract class AbstractDockingTool implements DockingTool {
|
public abstract class AbstractDockingTool implements DockingTool {
|
||||||
|
|
||||||
protected DockingWindowManager winMgr;
|
protected DockingWindowManager winMgr;
|
||||||
protected DockingToolActionManager actionMgr;
|
protected ToolActions actionMgr;
|
||||||
protected Map<String, ToolOptions> optionsMap = new HashMap<>();
|
protected Map<String, ToolOptions> optionsMap = new HashMap<>();
|
||||||
protected boolean configChangedFlag;
|
protected boolean configChangedFlag;
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ public abstract class AbstractDockingTool implements DockingTool {
|
||||||
@Override
|
@Override
|
||||||
public Set<DockingActionIf> getAllActions() {
|
public Set<DockingActionIf> getAllActions() {
|
||||||
Set<DockingActionIf> actions = actionMgr.getAllActions();
|
Set<DockingActionIf> actions = actionMgr.getAllActions();
|
||||||
DockingActionManager am = winMgr.getActionManager();
|
ActionToGuiMapper am = winMgr.getActionManager();
|
||||||
actions.addAll(am.getAllActions());
|
actions.addAll(am.getAllActions());
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import ghidra.util.*;
|
||||||
/**
|
/**
|
||||||
* Manages the global actions for the menu and toolbar.
|
* Manages the global actions for the menu and toolbar.
|
||||||
*/
|
*/
|
||||||
public class DockingActionManager {
|
public class ActionToGuiMapper {
|
||||||
|
|
||||||
private HashSet<DockingActionIf> globalActions = new LinkedHashSet<>();
|
private HashSet<DockingActionIf> globalActions = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public class DockingActionManager {
|
||||||
private PopupActionManager popupActionManager;
|
private PopupActionManager popupActionManager;
|
||||||
private DockingAction keyBindingsAction;
|
private DockingAction keyBindingsAction;
|
||||||
|
|
||||||
DockingActionManager(DockingWindowManager winMgr) {
|
ActionToGuiMapper(DockingWindowManager winMgr) {
|
||||||
menuGroupMap = new MenuGroupMap();
|
menuGroupMap = new MenuGroupMap();
|
||||||
|
|
||||||
menuBarMenuHandler = new MenuBarMenuHandler(winMgr);
|
menuBarMenuHandler = new MenuBarMenuHandler(winMgr);
|
|
@ -69,7 +69,7 @@ public class DialogComponentProviderPopupActionManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DockingActionManager actionManager = dwm.getActionManager();
|
ActionToGuiMapper actionManager = dwm.getActionManager();
|
||||||
MenuGroupMap menuGroupMap = actionManager.getMenuGroupMap();
|
MenuGroupMap menuGroupMap = actionManager.getMenuGroupMap();
|
||||||
MenuManager menuMgr =
|
MenuManager menuMgr =
|
||||||
new MenuManager("Popup", '\0', null, true, popupMenuHandler, menuGroupMap);
|
new MenuManager("Popup", '\0', null, true, popupMenuHandler, menuGroupMap);
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class DockableComponent extends JPanel implements ContainerListener {
|
||||||
private JComponent providerComp;
|
private JComponent providerComp;
|
||||||
private Component focusedComponent;
|
private Component focusedComponent;
|
||||||
private DockingWindowManager winMgr;
|
private DockingWindowManager winMgr;
|
||||||
private DockingActionManager actionMgr;
|
private ActionToGuiMapper actionMgr;
|
||||||
private DropTarget dockableDropTarget;
|
private DropTarget dockableDropTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -60,7 +60,7 @@ class DockableToolBarManager {
|
||||||
ComponentPlaceholder placeholder = dockableComp.getComponentWindowingPlaceholder();
|
ComponentPlaceholder placeholder = dockableComp.getComponentWindowingPlaceholder();
|
||||||
DockingWindowManager winMgr =
|
DockingWindowManager winMgr =
|
||||||
dockableComp.getComponentWindowingPlaceholder().getNode().winMgr;
|
dockableComp.getComponentWindowingPlaceholder().getNode().winMgr;
|
||||||
DockingActionManager actionManager = winMgr.getActionManager();
|
ActionToGuiMapper actionManager = winMgr.getActionManager();
|
||||||
menuGroupMap = actionManager.getMenuGroupMap();
|
menuGroupMap = actionManager.getMenuGroupMap();
|
||||||
|
|
||||||
MenuHandler menuHandler = actionManager.getMenuHandler();
|
MenuHandler menuHandler = actionManager.getMenuHandler();
|
||||||
|
|
|
@ -24,11 +24,11 @@ import docking.action.DockingActionIf;
|
||||||
* {@link DockingWindowManager}. This allows the manager's interface to hide methods that
|
* {@link DockingWindowManager}. This allows the manager's interface to hide methods that
|
||||||
* don't make sense for public consumption.
|
* don't make sense for public consumption.
|
||||||
*/
|
*/
|
||||||
public class DockingWindowManagerActionUpdater {
|
public class DockingActionPackageHelper {
|
||||||
|
|
||||||
private DockingWindowManager windowManager;
|
private DockingWindowManager windowManager;
|
||||||
|
|
||||||
public DockingWindowManagerActionUpdater(DockingWindowManager windowManager) {
|
public DockingActionPackageHelper(DockingWindowManager windowManager) {
|
||||||
this.windowManager = windowManager;
|
this.windowManager = windowManager;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
private Map<String, ComponentProvider> providerNameCache = new HashMap<>();
|
private Map<String, ComponentProvider> providerNameCache = new HashMap<>();
|
||||||
private Map<String, PreferenceState> preferenceStateMap = new HashMap<>();
|
private Map<String, PreferenceState> preferenceStateMap = new HashMap<>();
|
||||||
private DockWinListener docListener;
|
private DockWinListener docListener;
|
||||||
private DockingActionManager actionManager;
|
private ActionToGuiMapper actionManager;
|
||||||
|
|
||||||
private WeakSet<DockingContextListener> contextListeners =
|
private WeakSet<DockingContextListener> contextListeners =
|
||||||
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
|
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
|
||||||
|
@ -140,7 +140,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
}
|
}
|
||||||
|
|
||||||
root = new RootNode(this, toolName, images, modal, factory);
|
root = new RootNode(this, toolName, images, modal, factory);
|
||||||
actionManager = new DockingActionManager(this);
|
actionManager = new ActionToGuiMapper(this);
|
||||||
|
|
||||||
KeyboardFocusManager km = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
KeyboardFocusManager km = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
km.addPropertyChangeListener("permanentFocusOwner", this);
|
km.addPropertyChangeListener("permanentFocusOwner", this);
|
||||||
|
@ -161,7 +161,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
* @param enable
|
* @param enable
|
||||||
*/
|
*/
|
||||||
public static void enableDiagnosticActions(boolean enable) {
|
public static void enableDiagnosticActions(boolean enable) {
|
||||||
DockingActionManager.enableDiagnosticActions(enable);
|
ActionToGuiMapper.enableDiagnosticActions(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -293,7 +293,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
* @param helpLocation help content location
|
* @param helpLocation help content location
|
||||||
*/
|
*/
|
||||||
public static void setHelpLocation(JComponent c, HelpLocation helpLocation) {
|
public static void setHelpLocation(JComponent c, HelpLocation helpLocation) {
|
||||||
DockingActionManager.setHelpLocation(c, helpLocation);
|
ActionToGuiMapper.setHelpLocation(c, helpLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -338,7 +338,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
return placeholderManager;
|
return placeholderManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
DockingActionManager getActionManager() {
|
ActionToGuiMapper getActionManager() {
|
||||||
return actionManager;
|
return actionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ public class GlobalMenuAndToolBarManager implements DockingWindowListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DockingActionIf> getActionsForWindow(WindowNode windowNode) {
|
private List<DockingActionIf> getActionsForWindow(WindowNode windowNode) {
|
||||||
DockingActionManager actionManager = windowManager.getActionManager();
|
ActionToGuiMapper actionManager = windowManager.getActionManager();
|
||||||
Collection<DockingActionIf> globalActions = actionManager.getGlobalActions();
|
Collection<DockingActionIf> globalActions = actionManager.getGlobalActions();
|
||||||
List<DockingActionIf> actionsForWindow = new ArrayList<>(globalActions.size());
|
List<DockingActionIf> actionsForWindow = new ArrayList<>(globalActions.size());
|
||||||
Set<Class<?>> contextTypes = windowNode.getContextTypes();
|
Set<Class<?>> contextTypes = windowNode.getContextTypes();
|
||||||
|
|
|
@ -24,9 +24,9 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.ReservedKeyBindings;
|
import ghidra.util.ReservedKeyBindings;
|
||||||
|
|
||||||
public class KeyBindingAction extends DockingAction {
|
public class KeyBindingAction extends DockingAction {
|
||||||
private final DockingActionManager dockingActionManager;
|
private final ActionToGuiMapper dockingActionManager;
|
||||||
|
|
||||||
public KeyBindingAction(DockingActionManager dockingActionManager) {
|
public KeyBindingAction(ActionToGuiMapper dockingActionManager) {
|
||||||
super("Set KeyBinding", DockingWindowManager.DOCKING_WINDOWS_OWNER);
|
super("Set KeyBinding", DockingWindowManager.DOCKING_WINDOWS_OWNER);
|
||||||
this.dockingActionManager = dockingActionManager;
|
this.dockingActionManager = dockingActionManager;
|
||||||
createReservedKeyBinding(ReservedKeyBindings.UPDATE_KEY_BINDINGS_KEY);
|
createReservedKeyBinding(ReservedKeyBindings.UPDATE_KEY_BINDINGS_KEY);
|
||||||
|
|
|
@ -35,7 +35,7 @@ import resources.ResourceManager;
|
||||||
*/
|
*/
|
||||||
public class KeyEntryDialog extends DialogComponentProvider {
|
public class KeyEntryDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private DockingActionManager actionManager;
|
private ActionToGuiMapper actionManager;
|
||||||
private DockingActionIf action;
|
private DockingActionIf action;
|
||||||
private JPanel defaultPanel;
|
private JPanel defaultPanel;
|
||||||
private KeyEntryTextField keyEntryField;
|
private KeyEntryTextField keyEntryField;
|
||||||
|
@ -45,7 +45,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
|
||||||
private SimpleAttributeSet textAttrSet;
|
private SimpleAttributeSet textAttrSet;
|
||||||
private Color bgColor;
|
private Color bgColor;
|
||||||
|
|
||||||
public KeyEntryDialog(DockingActionIf action, DockingActionManager actionManager) {
|
public KeyEntryDialog(DockingActionIf action, ActionToGuiMapper actionManager) {
|
||||||
super("Set Key Binding for " + action.getName(), true);
|
super("Set Key Binding for " + action.getName(), true);
|
||||||
this.actionManager = actionManager;
|
this.actionManager = actionManager;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
|
|
@ -336,7 +336,7 @@ public class KeyBindingUtils {
|
||||||
* @param tool the tool containing the actions
|
* @param tool the tool containing the actions
|
||||||
* @return the actions mapped by their full name (e.g., 'Name (OwnerName)')
|
* @return the actions mapped by their full name (e.g., 'Name (OwnerName)')
|
||||||
*/
|
*/
|
||||||
public static Map<String, DockingActionIf> getAllKeyBindingActions(DockingTool tool) {
|
public static Map<String, DockingActionIf> getAllKeyBindingActionsByFullName(DockingTool tool) {
|
||||||
|
|
||||||
Map<String, DockingActionIf> deduper = new HashMap<>();
|
Map<String, DockingActionIf> deduper = new HashMap<>();
|
||||||
Set<DockingActionIf> actions = tool.getAllActions();
|
Set<DockingActionIf> actions = tool.getAllActions();
|
||||||
|
@ -363,7 +363,8 @@ public class KeyBindingUtils {
|
||||||
* @param owner the action owner name
|
* @param owner the action owner name
|
||||||
* @return the actions
|
* @return the actions
|
||||||
*/
|
*/
|
||||||
public static Set<DockingActionIf> getKeyBindingActions(DockingTool tool, String owner) {
|
public static Set<DockingActionIf> getKeyBindingActionsForOwner(DockingTool tool,
|
||||||
|
String owner) {
|
||||||
|
|
||||||
Map<String, DockingActionIf> deduper = new HashMap<>();
|
Map<String, DockingActionIf> deduper = new HashMap<>();
|
||||||
Set<DockingActionIf> actions = tool.getDockingActionsByOwnerName(owner);
|
Set<DockingActionIf> actions = tool.getDockingActionsByOwnerName(owner);
|
||||||
|
@ -381,19 +382,6 @@ public class KeyBindingUtils {
|
||||||
return CollectionUtils.asSet(deduper.values());
|
return CollectionUtils.asSet(deduper.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all actions that match the given owner and name
|
|
||||||
*
|
|
||||||
* @param tool the tool containing the actions
|
|
||||||
* @param owner the owner
|
|
||||||
* @param name the name
|
|
||||||
* @return the actions
|
|
||||||
*/
|
|
||||||
public static Set<DockingActionIf> getActions(DockingTool tool, String owner, String name) {
|
|
||||||
Set<DockingActionIf> actions = tool.getDockingActionsByOwnerName(owner);
|
|
||||||
return getActions(actions, owner, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all actions that match the given owner and name
|
* Returns all actions that match the given owner and name
|
||||||
*
|
*
|
||||||
|
@ -421,16 +409,17 @@ public class KeyBindingUtils {
|
||||||
public static DockingActionIf getSharedKeyBindingAction(Set<DockingActionIf> allActions,
|
public static DockingActionIf getSharedKeyBindingAction(Set<DockingActionIf> allActions,
|
||||||
String sharedName) {
|
String sharedName) {
|
||||||
|
|
||||||
Set<DockingActionIf> toolActions = getActions(allActions, "Tool", sharedName);
|
String owner = "Tool";
|
||||||
|
for (DockingActionIf action : allActions) {
|
||||||
|
if (!(action instanceof SharedStubKeyBindingAction)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//@formatter:off
|
if (action.getOwner().equals(owner) && action.getName().equals(sharedName)) {
|
||||||
return toolActions
|
return action;
|
||||||
.stream()
|
}
|
||||||
.filter(action -> action instanceof SharedStubKeyBindingAction)
|
}
|
||||||
.findAny()
|
return null;
|
||||||
.orElse(null)
|
|
||||||
;
|
|
||||||
//@formatter:on
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isIgnored(DockingActionIf action) {
|
private static boolean isIgnored(DockingActionIf action) {
|
||||||
|
@ -456,8 +445,15 @@ public class KeyBindingUtils {
|
||||||
return new ActionAdapter(action);
|
return new ActionAdapter(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks each action in the given collection against the given new action to make sure that
|
||||||
|
* they share the same default key binding.
|
||||||
|
*
|
||||||
|
* @param newAction the action to check
|
||||||
|
* @param existingActions the actions that have already been checked
|
||||||
|
*/
|
||||||
public static void assertSameDefaultKeyBindings(DockingActionIf newAction,
|
public static void assertSameDefaultKeyBindings(DockingActionIf newAction,
|
||||||
List<DockingActionIf> existingActions) {
|
Collection<DockingActionIf> existingActions) {
|
||||||
|
|
||||||
KeyBindingData newDefaultBinding = newAction.getDefaultKeyBindingData();
|
KeyBindingData newDefaultBinding = newAction.getDefaultKeyBindingData();
|
||||||
KeyStroke defaultKs = getKeyStroke(newDefaultBinding);
|
KeyStroke defaultKs = getKeyStroke(newDefaultBinding);
|
||||||
|
@ -471,6 +467,14 @@ public class KeyBindingUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a warning message for the two given actions to signal that they do not share the
|
||||||
|
* same default key binding
|
||||||
|
*
|
||||||
|
* @param newAction the new action
|
||||||
|
* @param existingAction the action that has already been validated
|
||||||
|
* @param existingDefaultKs the current validated key stroke
|
||||||
|
*/
|
||||||
public static void logDifferentKeyBindingsWarnigMessage(DockingActionIf newAction,
|
public static void logDifferentKeyBindingsWarnigMessage(DockingActionIf newAction,
|
||||||
DockingActionIf existingAction, KeyStroke existingDefaultKs) {
|
DockingActionIf existingAction, KeyStroke existingDefaultKs) {
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ package docking.actions;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
|
@ -33,14 +33,22 @@ import ghidra.util.exception.AssertException;
|
||||||
/**
|
/**
|
||||||
* An class to manage actions registered with the tool
|
* An class to manage actions registered with the tool
|
||||||
*/
|
*/
|
||||||
public class DockingToolActionManager implements PropertyChangeListener {
|
public class ToolActions implements PropertyChangeListener {
|
||||||
|
|
||||||
private DockingWindowManager winMgr;
|
private DockingWindowManager winMgr;
|
||||||
private DockingWindowManagerActionUpdater winMgrActionUpdater;
|
private DockingActionPackageHelper actionGuiHelper;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Map of Maps of Sets
|
||||||
|
|
||||||
|
Owner Name ->
|
||||||
|
Action Name -> Set of Actions
|
||||||
|
*/
|
||||||
|
private Map<String, Map<String, Set<DockingActionIf>>> actionsByNameByOwner = LazyMap.lazyMap(
|
||||||
|
new HashMap<>(), () -> LazyMap.lazyMap(new HashMap<>(), () -> new HashSet<>()));
|
||||||
|
|
||||||
private Map<String, List<DockingActionIf>> actionMap =
|
|
||||||
LazyMap.lazyMap(new HashMap<>(), () -> new ArrayList<>());
|
|
||||||
private Map<String, SharedStubKeyBindingAction> sharedActionMap = new HashMap<>();
|
private Map<String, SharedStubKeyBindingAction> sharedActionMap = new HashMap<>();
|
||||||
|
|
||||||
private ToolOptions keyBindingOptions;
|
private ToolOptions keyBindingOptions;
|
||||||
private DockingTool dockingTool;
|
private DockingTool dockingTool;
|
||||||
|
|
||||||
|
@ -51,32 +59,27 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
* @param windowManager manager of the "Docking" arrangement of a set of components
|
* @param windowManager manager of the "Docking" arrangement of a set of components
|
||||||
* and actions in the tool
|
* and actions in the tool
|
||||||
*/
|
*/
|
||||||
public DockingToolActionManager(DockingTool tool, DockingWindowManager windowManager) {
|
public ToolActions(DockingTool tool, DockingWindowManager windowManager) {
|
||||||
this.dockingTool = tool;
|
this.dockingTool = tool;
|
||||||
this.winMgr = windowManager;
|
this.winMgr = windowManager;
|
||||||
this.winMgrActionUpdater = new DockingWindowManagerActionUpdater(winMgr);
|
this.actionGuiHelper = new DockingActionPackageHelper(winMgr);
|
||||||
keyBindingOptions = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
keyBindingOptions = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
actionMap.clear();
|
actionsByNameByOwner.clear();
|
||||||
|
sharedActionMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addActionToMap(DockingActionIf action) {
|
private void addActionToMap(DockingActionIf action) {
|
||||||
String name = action.getFullName();
|
|
||||||
List<DockingActionIf> actionList = actionMap.get(name);
|
|
||||||
|
|
||||||
List<DockingActionIf> list = actionMap.get(name);
|
Set<DockingActionIf> actions = getActionStorage(action);
|
||||||
if (!list.isEmpty()) {
|
KeyBindingUtils.assertSameDefaultKeyBindings(action, actions);
|
||||||
KeyBindingUtils.assertSameDefaultKeyBindings(action, actionList);
|
actions.add(action);
|
||||||
}
|
|
||||||
|
|
||||||
actionList.add(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeActionFromMap(DockingActionIf action) {
|
private void removeActionFromMap(DockingActionIf action) {
|
||||||
String name = action.getFullName();
|
getActionStorage(action).remove(action);
|
||||||
actionMap.get(name).remove(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,7 +93,7 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
action.addPropertyChangeListener(this);
|
action.addPropertyChangeListener(this);
|
||||||
addActionToMap(action);
|
addActionToMap(action);
|
||||||
setKeyBindingOption(action);
|
setKeyBindingOption(action);
|
||||||
winMgrActionUpdater.addLocalAction(provider, action);
|
actionGuiHelper.addLocalAction(provider, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +104,7 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
action.addPropertyChangeListener(this);
|
action.addPropertyChangeListener(this);
|
||||||
addActionToMap(action);
|
addActionToMap(action);
|
||||||
setKeyBindingOption(action);
|
setKeyBindingOption(action);
|
||||||
winMgrActionUpdater.addToolAction(action);
|
actionGuiHelper.addToolAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setKeyBindingOption(DockingActionIf action) {
|
private void setKeyBindingOption(DockingActionIf action) {
|
||||||
|
@ -148,7 +151,7 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
public synchronized void removeToolAction(DockingActionIf action) {
|
public synchronized void removeToolAction(DockingActionIf action) {
|
||||||
action.removePropertyChangeListener(this);
|
action.removePropertyChangeListener(this);
|
||||||
removeActionFromMap(action);
|
removeActionFromMap(action);
|
||||||
winMgrActionUpdater.removeToolAction(action);
|
actionGuiHelper.removeToolAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,19 +159,23 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
* @param owner owner of the actions to remove
|
* @param owner owner of the actions to remove
|
||||||
*/
|
*/
|
||||||
public synchronized void removeToolActions(String owner) {
|
public synchronized void removeToolActions(String owner) {
|
||||||
Predicate<String> ownerMatches = actionOwner -> actionOwner.equals(owner);
|
|
||||||
Set<DockingActionIf> actions = getActions(ownerMatches);
|
//@formatter:off
|
||||||
for (DockingActionIf action : actions) {
|
Set<DockingActionIf> toRemove = actionsByNameByOwner.get(owner).values()
|
||||||
removeToolAction(action);
|
.stream()
|
||||||
}
|
.flatMap(set -> set.stream())
|
||||||
|
.collect(Collectors.toSet())
|
||||||
|
;
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
// must do this later to avoid concurrent modification exceptions
|
||||||
|
toRemove.forEach(action -> removeToolAction(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForAlreadyAddedAction(ComponentProvider provider, DockingActionIf action) {
|
private void checkForAlreadyAddedAction(ComponentProvider provider, DockingActionIf action) {
|
||||||
String name = action.getFullName();
|
if (getActionStorage(action).contains(action)) {
|
||||||
List<DockingActionIf> actionList = actionMap.get(name);
|
|
||||||
if (actionList.contains(action)) {
|
|
||||||
throw new AssertException("Cannot add the same action more than once. Provider " +
|
throw new AssertException("Cannot add the same action more than once. Provider " +
|
||||||
provider.getName() + " - action: " + name);
|
provider.getName() + " - action: " + action.getFullName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,46 +191,6 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
winMgr.removeProviderAction(provider, action);
|
winMgr.removeProviderAction(provider, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all actions that have the action name which includes the action owner's name.
|
|
||||||
*
|
|
||||||
* @param fullName full name for the action, e.g., "My Action (My Plugin)"
|
|
||||||
* @return list of actions; empty if no action exists with the given name
|
|
||||||
*/
|
|
||||||
public Set<DockingActionIf> getDockingActionsByFullActionName(String fullName) {
|
|
||||||
List<DockingActionIf> list = actionMap.get(fullName);
|
|
||||||
return new HashSet<>(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of actions whose owner matches the given predicate.
|
|
||||||
*
|
|
||||||
* Note: Actions with the same name are assumed to be different instances of the same action.
|
|
||||||
*
|
|
||||||
* @param ownerFilter the predicate that is used to test if the owners are the same; to get
|
|
||||||
* all actions, return an 'always true' predicate
|
|
||||||
* @return a list of deduped actions.
|
|
||||||
*/
|
|
||||||
private Set<DockingActionIf> getActions(Predicate<String> ownerFilter) {
|
|
||||||
|
|
||||||
Set<DockingActionIf> result = new HashSet<>();
|
|
||||||
for (List<DockingActionIf> list : actionMap.values()) {
|
|
||||||
for (DockingActionIf action : list) {
|
|
||||||
if (ownerFilter.test(action.getOwner())) {
|
|
||||||
result.addAll(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (DockingActionIf action : sharedActionMap.values()) {
|
|
||||||
if (ownerFilter.test(action.getOwner())) {
|
|
||||||
result.add(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all actions for the given owner.
|
* Get all actions for the given owner.
|
||||||
* @param owner owner of the actions
|
* @param owner owner of the actions
|
||||||
|
@ -231,24 +198,42 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
* action exists with the given name
|
* action exists with the given name
|
||||||
*/
|
*/
|
||||||
public synchronized Set<DockingActionIf> getActions(String owner) {
|
public synchronized Set<DockingActionIf> getActions(String owner) {
|
||||||
Predicate<String> ownerMatches = actionOwner -> actionOwner.equals(owner);
|
|
||||||
return getActions(ownerMatches);
|
Set<DockingActionIf> result = new HashSet<>();
|
||||||
|
Map<String, Set<DockingActionIf>> actionsByName = actionsByNameByOwner.get(owner);
|
||||||
|
for (Set<DockingActionIf> actions : actionsByName.values()) {
|
||||||
|
result.addAll(actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SharedStubKeyBindingAction.SHARED_OWNER.equals(owner)) {
|
||||||
|
result.addAll(sharedActionMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of all actions in the tool
|
* Get a set of all actions in the tool
|
||||||
* @return list of PluginAction objects
|
* @return the actions
|
||||||
*/
|
*/
|
||||||
public synchronized Set<DockingActionIf> getAllActions() {
|
public synchronized Set<DockingActionIf> getAllActions() {
|
||||||
Predicate<String> allOwnersMatch = name -> true;
|
|
||||||
return getActions(allOwnersMatch);
|
Set<DockingActionIf> result = new HashSet<>();
|
||||||
|
Collection<Map<String, Set<DockingActionIf>>> maps = actionsByNameByOwner.values();
|
||||||
|
for (Map<String, Set<DockingActionIf>> actionsByName : maps) {
|
||||||
|
for (Set<DockingActionIf> actions : actionsByName.values()) {
|
||||||
|
result.addAll(actions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addAll(sharedActionMap.values());
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the keybindings for each action so that they are still registered
|
* Get the keybindings for each action so that they are still registered as being used;
|
||||||
* as being used; otherwise the options will be removed because they
|
* otherwise the options will be removed because they are noted as not being used.
|
||||||
* are noted as not being used.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public synchronized void restoreKeyBindings() {
|
public synchronized void restoreKeyBindings() {
|
||||||
keyBindingOptions = dockingTool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
keyBindingOptions = dockingTool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
||||||
|
@ -272,12 +257,16 @@ public class DockingToolActionManager implements PropertyChangeListener {
|
||||||
public void removeComponentActions(ComponentProvider provider) {
|
public void removeComponentActions(ComponentProvider provider) {
|
||||||
Iterator<DockingActionIf> iterator = winMgr.getComponentActions(provider);
|
Iterator<DockingActionIf> iterator = winMgr.getComponentActions(provider);
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
DockingActionIf action = iterator.next();
|
removeActionFromMap(iterator.next());
|
||||||
String name = action.getFullName();
|
|
||||||
actionMap.get(name).remove(action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<DockingActionIf> getActionStorage(DockingActionIf action) {
|
||||||
|
String owner = action.getOwner();
|
||||||
|
String name = action.getName();
|
||||||
|
return actionsByNameByOwner.get(owner).get(name);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (evt.getPropertyName().equals(DockingActionIf.KEYBINDING_DATA_PROPERTY)) {
|
if (evt.getPropertyName().equals(DockingActionIf.KEYBINDING_DATA_PROPERTY)) {
|
|
@ -442,9 +442,10 @@ public abstract class AbstractSortedTableModel<T> extends AbstractGTableModel<T>
|
||||||
public int compare(T t1, T t2) {
|
public int compare(T t1, T t2) {
|
||||||
|
|
||||||
// at this point we compare the rows, since all of the sorting column values are equal
|
// at this point we compare the rows, since all of the sorting column values are equal
|
||||||
// (Warning: there is a chance that the two objects are comparable, but not on each
|
// (Warning: due to comparable being specific to the class upon which it is defined,
|
||||||
// other. In this case, a ClassCastException will be thrown)
|
// we have to make sure the class is the same to prevent class cast
|
||||||
if (t1 instanceof Comparable && t2 instanceof Comparable) {
|
// exceptions when the table has mixed implementations of 'T')
|
||||||
|
if (t1 instanceof Comparable && t1.getClass().equals(t2.getClass())) {
|
||||||
return ((Comparable) t1).compareTo(t2);
|
return ((Comparable) t1).compareTo(t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,8 +357,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private void assertSharedStubInTool() {
|
private void assertSharedStubInTool() {
|
||||||
DockingToolActionManager actionManager =
|
ToolActions actionManager =
|
||||||
(DockingToolActionManager) getInstanceField("actionMgr", tool);
|
(ToolActions) getInstanceField("actionMgr", tool);
|
||||||
DockingActionIf action = actionManager.getSharedStubKeyBindingAction(SHARED_NAME);
|
DockingActionIf action = actionManager.getSharedStubKeyBindingAction(SHARED_NAME);
|
||||||
assertNotNull("Shared action stub is not in the tool", action);
|
assertNotNull("Shared action stub is not in the tool", action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import docking.actions.DockingToolActionManager;
|
import docking.actions.ToolActions;
|
||||||
import docking.framework.ApplicationInformationDisplayFactory;
|
import docking.framework.ApplicationInformationDisplayFactory;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public class FakeDockingTool extends AbstractDockingTool {
|
||||||
List<Image> windowIcons = ApplicationInformationDisplayFactory.getWindowIcons();
|
List<Image> windowIcons = ApplicationInformationDisplayFactory.getWindowIcons();
|
||||||
winMgr = new DockingWindowManager("EMPTY", windowIcons, listener, false /*isModal*/,
|
winMgr = new DockingWindowManager("EMPTY", windowIcons, listener, false /*isModal*/,
|
||||||
true /*isDockable*/, true /*hasStatus*/, null /*DropTargetFactory*/);
|
true /*isDockable*/, true /*hasStatus*/, null /*DropTargetFactory*/);
|
||||||
actionMgr = new DockingToolActionManager(this, winMgr);
|
actionMgr = new ToolActions(this, winMgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.util;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -857,18 +858,9 @@ public class StringUtilities {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
String asString =
|
||||||
StringBuffer buffer = new StringBuffer("[ ");
|
collection.stream().map(o -> o.toString()).collect(Collectors.joining(separator));
|
||||||
for (Object o : collection) {
|
return "[ " + asString + " ]";
|
||||||
buffer.append(o.toString());
|
|
||||||
if (i + 1 < collection.size()) {
|
|
||||||
buffer.append(separator);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.append(" ]");
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toStringWithIndent(Object o) {
|
public static String toStringWithIndent(Object o) {
|
||||||
|
|
|
@ -218,7 +218,7 @@ public class PluginConfigurationModel {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyBindingUtils.getKeyBindingActions(tool, pluginDescription.getName());
|
return KeyBindingUtils.getKeyBindingActionsForOwner(tool, pluginDescription.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.jdom.Element;
|
||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.actions.DockingToolActionManager;
|
import docking.actions.ToolActions;
|
||||||
import docking.framework.AboutDialog;
|
import docking.framework.AboutDialog;
|
||||||
import docking.framework.ApplicationInformationDisplayFactory;
|
import docking.framework.ApplicationInformationDisplayFactory;
|
||||||
import docking.framework.SplashScreen;
|
import docking.framework.SplashScreen;
|
||||||
|
@ -158,7 +158,7 @@ public abstract class PluginTool extends AbstractDockingTool
|
||||||
eventMgr = new EventManager(this);
|
eventMgr = new EventManager(this);
|
||||||
serviceMgr = new ServiceManager();
|
serviceMgr = new ServiceManager();
|
||||||
installServices();
|
installServices();
|
||||||
actionMgr = new DockingToolActionManager(this, winMgr);
|
actionMgr = new ToolActions(this, winMgr);
|
||||||
pluginMgr = new PluginManager(this, serviceMgr);
|
pluginMgr = new PluginManager(this, serviceMgr);
|
||||||
dialogMgr = new DialogManager(this);
|
dialogMgr = new DialogManager(this);
|
||||||
initActions();
|
initActions();
|
||||||
|
|
|
@ -171,7 +171,7 @@ public class KeyBindingsPanel extends JPanel {
|
||||||
originalValues = new HashMap<>();
|
originalValues = new HashMap<>();
|
||||||
String longestName = "";
|
String longestName = "";
|
||||||
|
|
||||||
actionsByFullName = KeyBindingUtils.getAllKeyBindingActions(tool);
|
actionsByFullName = KeyBindingUtils.getAllKeyBindingActionsByFullName(tool);
|
||||||
Set<Entry<String, DockingActionIf>> entries = actionsByFullName.entrySet();
|
Set<Entry<String, DockingActionIf>> entries = actionsByFullName.entrySet();
|
||||||
for (Entry<String, DockingActionIf> entry : entries) {
|
for (Entry<String, DockingActionIf> entry : entries) {
|
||||||
|
|
||||||
|
|
|
@ -1,299 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.framework.plugintool.mgr;
|
|
||||||
|
|
||||||
import java.beans.PropertyChangeEvent;
|
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import javax.swing.KeyStroke;
|
|
||||||
|
|
||||||
import docking.*;
|
|
||||||
import docking.action.*;
|
|
||||||
import docking.tool.util.DockingToolConstants;
|
|
||||||
import ghidra.framework.options.OptionType;
|
|
||||||
import ghidra.framework.options.Options;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
|
||||||
import ghidra.util.exception.AssertException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class to manage plugin actions for the tool.
|
|
||||||
*/
|
|
||||||
public class ProjectActionManager implements PropertyChangeListener {
|
|
||||||
|
|
||||||
private DockingWindowManager winMgr;
|
|
||||||
private DockingWindowManagerActionUpdater winMgrActionUpdater;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO does this class need the shared action concept (probably not)
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
private Map<String, List<DockingActionIf>> actionMap;
|
|
||||||
private Options keyBindingOptions;
|
|
||||||
private PluginTool tool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct an ActionManager
|
|
||||||
* @param tool plugin tool using this ActionManager
|
|
||||||
* @param winMgr manager of the "Docking" arrangement
|
|
||||||
* of a set of components and actions in the tool
|
|
||||||
*/
|
|
||||||
public ProjectActionManager(PluginTool tool, DockingWindowManager winMgr) {
|
|
||||||
this.tool = tool;
|
|
||||||
this.winMgr = winMgr;
|
|
||||||
this.winMgrActionUpdater = new DockingWindowManagerActionUpdater(winMgr);
|
|
||||||
actionMap = new HashMap<>();
|
|
||||||
keyBindingOptions = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispose() {
|
|
||||||
actionMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addActionToMap(DockingActionIf action) {
|
|
||||||
String name = action.getFullName();
|
|
||||||
List<DockingActionIf> actionList = actionMap.get(name);
|
|
||||||
if (actionList == null) {
|
|
||||||
List<DockingActionIf> newList = new ArrayList<>();
|
|
||||||
newList.add(action);
|
|
||||||
actionMap.put(name, newList);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
actionList.add(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeActionFromMap(DockingActionIf action) {
|
|
||||||
String name = action.getFullName();
|
|
||||||
List<DockingActionIf> actionList = actionMap.get(name);
|
|
||||||
if (actionList == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionList.remove(action) && actionList.isEmpty()) {
|
|
||||||
actionMap.remove(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the action to the tool.
|
|
||||||
* @param action the action to be added.
|
|
||||||
*/
|
|
||||||
public synchronized void addToolAction(DockingActionIf action) {
|
|
||||||
action.addPropertyChangeListener(this);
|
|
||||||
addActionToMap(action);
|
|
||||||
if (action.isKeyBindingManaged()) {
|
|
||||||
KeyStroke ks = action.getKeyBinding();
|
|
||||||
keyBindingOptions.registerOption(action.getFullName(), OptionType.KEYSTROKE_TYPE, ks,
|
|
||||||
null, null);
|
|
||||||
KeyStroke newKs = keyBindingOptions.getKeyStroke(action.getFullName(), ks);
|
|
||||||
if (ks != newKs) {
|
|
||||||
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
winMgrActionUpdater.addToolAction(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given action from the tool
|
|
||||||
* @param action the action to be removed.
|
|
||||||
*/
|
|
||||||
public synchronized void removeToolAction(DockingActionIf action) {
|
|
||||||
action.removePropertyChangeListener(this);
|
|
||||||
removeActionFromMap(action);
|
|
||||||
winMgrActionUpdater.removeToolAction(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all actions that have the given owner.
|
|
||||||
* @param owner owner of the actions to remove
|
|
||||||
*/
|
|
||||||
public synchronized void removeToolActions(String owner) {
|
|
||||||
List<DockingActionIf> actions = getActions(owner);
|
|
||||||
for (DockingActionIf action : actions) {
|
|
||||||
removeToolAction(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an action that works specifically with a component provider.
|
|
||||||
* @param provider provider associated with the action
|
|
||||||
* @param action local action to the provider
|
|
||||||
*/
|
|
||||||
public synchronized void addLocalAction(ComponentProvider provider, DockingActionIf action) {
|
|
||||||
checkForAlreadyAddedAction(provider, action);
|
|
||||||
|
|
||||||
action.addPropertyChangeListener(this);
|
|
||||||
addActionToMap(action);
|
|
||||||
if (action.isKeyBindingManaged()) {
|
|
||||||
KeyStroke ks = action.getKeyBinding();
|
|
||||||
keyBindingOptions.registerOption(action.getFullName(), OptionType.KEYSTROKE_TYPE, ks,
|
|
||||||
null, null);
|
|
||||||
KeyStroke newKs = keyBindingOptions.getKeyStroke(action.getFullName(), ks);
|
|
||||||
if (ks != newKs) {
|
|
||||||
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
winMgrActionUpdater.addLocalAction(provider, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkForAlreadyAddedAction(ComponentProvider provider, DockingActionIf action) {
|
|
||||||
String name = action.getFullName();
|
|
||||||
List<DockingActionIf> actionList = actionMap.get(name);
|
|
||||||
if (actionList == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (actionList.contains(action)) {
|
|
||||||
throw new AssertException("Cannot add the same action more than once. Provider " +
|
|
||||||
provider.getName() + " - action: " + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an action that works specifically with a component provider.
|
|
||||||
* @param provider provider associated with the action
|
|
||||||
* @param action local action to the provider
|
|
||||||
*/
|
|
||||||
public synchronized void removeProviderAction(ComponentProvider provider,
|
|
||||||
DockingActionIf action) {
|
|
||||||
action.removePropertyChangeListener(this);
|
|
||||||
removeActionFromMap(action);
|
|
||||||
winMgr.removeProviderAction(provider, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO delete me
|
|
||||||
/**
|
|
||||||
* Get all actions that have the action name which includes the action owner's name.
|
|
||||||
*
|
|
||||||
* @param fullName full name for the action, e.g., "My Action (My Plugin)"
|
|
||||||
* @return list of actions; empty if no action exists with the given name
|
|
||||||
*/
|
|
||||||
public List<DockingActionIf> getDockingActionsByFullActionName(String fullName) {
|
|
||||||
List<DockingActionIf> list = actionMap.get(fullName);
|
|
||||||
if (list == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
return new ArrayList<>(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of actions whose owner matches the given owner or all actions if the given
|
|
||||||
* owner is null.
|
|
||||||
* <p>
|
|
||||||
* This method will only return a single instance of any named action, even if multiple
|
|
||||||
* actions have been registered with the same name.
|
|
||||||
* <p>
|
|
||||||
* Note: Actions with the same name are assumed to be different instances of the same action.
|
|
||||||
*
|
|
||||||
* @param owner The of the action, or null to get all actions
|
|
||||||
* @return a list of deduped actions.
|
|
||||||
*/
|
|
||||||
private List<DockingActionIf> getUniqueActionList(String owner) {
|
|
||||||
List<DockingActionIf> matchingActionList = new ArrayList<>();
|
|
||||||
|
|
||||||
for (List<DockingActionIf> actionList : actionMap.values()) {
|
|
||||||
// we only want *one* instance of duplicate actions
|
|
||||||
DockingActionIf action = actionList.get(0);
|
|
||||||
if (owner == null || action.getOwner().equals(owner)) {
|
|
||||||
matchingActionList.add(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchingActionList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all actions for the given owner.
|
|
||||||
* @param owner owner of the actions
|
|
||||||
* @return array of actions; zero length array is returned if no
|
|
||||||
* action exists with the given name
|
|
||||||
*/
|
|
||||||
public synchronized List<DockingActionIf> getActions(String owner) {
|
|
||||||
List<DockingActionIf> list = getUniqueActionList(owner);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of all actions in the tool.
|
|
||||||
* @return list of PluginAction objects
|
|
||||||
*/
|
|
||||||
public List<DockingActionIf> getAllActions() {
|
|
||||||
return getUniqueActionList(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the keybindings for each action so that they are still registered
|
|
||||||
* as being used; otherwise the options will be removed because they
|
|
||||||
* are noted as not being used.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public synchronized void restoreKeyBindings() {
|
|
||||||
keyBindingOptions = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
|
||||||
List<DockingActionIf> actions = getAllActions();
|
|
||||||
for (DockingActionIf action : actions) {
|
|
||||||
if (!action.isKeyBindingManaged()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
KeyStroke ks = action.getKeyBinding();
|
|
||||||
KeyStroke newKs = keyBindingOptions.getKeyStroke(action.getFullName(), ks);
|
|
||||||
if (ks != newKs) {
|
|
||||||
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the actions for the given provider and remove them from the
|
|
||||||
* actionMap; call the window manager to remove the provider.
|
|
||||||
* @param provider provider to be removed
|
|
||||||
*/
|
|
||||||
public void removeComponent(ComponentProvider provider) {
|
|
||||||
Iterator<DockingActionIf> iterator = winMgr.getComponentActions(provider);
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
DockingActionIf action = iterator.next();
|
|
||||||
String name = action.getFullName();
|
|
||||||
List<DockingActionIf> actionList = actionMap.get(name);
|
|
||||||
if (actionList != null && actionList.remove(action) && actionList.isEmpty()) {
|
|
||||||
actionMap.remove(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
winMgr.removeComponent(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
|
||||||
if (evt.getPropertyName().equals(DockingActionIf.KEYBINDING_DATA_PROPERTY)) {
|
|
||||||
DockingAction action = (DockingAction) evt.getSource();
|
|
||||||
if (!action.isKeyBindingManaged()) {
|
|
||||||
tool.setConfigChanged(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
KeyBindingData keyBindingData = (KeyBindingData) evt.getNewValue();
|
|
||||||
KeyStroke newKeyStroke = keyBindingData.getKeyBinding();
|
|
||||||
Options opt = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
|
||||||
KeyStroke optKeyStroke = opt.getKeyStroke(action.getFullName(), null);
|
|
||||||
if (newKeyStroke == null) {
|
|
||||||
opt.removeOption(action.getFullName());
|
|
||||||
}
|
|
||||||
else if (!newKeyStroke.equals(optKeyStroke)) {
|
|
||||||
opt.setKeyStroke(action.getFullName(), newKeyStroke);
|
|
||||||
tool.setConfigChanged(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -281,8 +281,8 @@ public class ToolScreenShots extends GhidraScreenShotGenerator {
|
||||||
|
|
||||||
tool = env.launchDefaultTool();
|
tool = env.launchDefaultTool();
|
||||||
DockingWindowManager windowManager = tool.getWindowManager();
|
DockingWindowManager windowManager = tool.getWindowManager();
|
||||||
DockingActionManager actionMgr =
|
ActionToGuiMapper actionMgr =
|
||||||
(DockingActionManager) getInstanceField("actionManager", windowManager);
|
(ActionToGuiMapper) getInstanceField("actionManager", windowManager);
|
||||||
|
|
||||||
DockingActionIf action = getAction(tool, "FunctionPlugin", "Delete Function");
|
DockingActionIf action = getAction(tool, "FunctionPlugin", "Delete Function");
|
||||||
final KeyEntryDialog keyEntryDialog = new KeyEntryDialog(action, actionMgr);
|
final KeyEntryDialog keyEntryDialog = new KeyEntryDialog(action, actionMgr);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue