GT-2971 - Key Bindings - Added the ability to set a key binding for the

close button for all Component Providers
This commit is contained in:
dragonmacher 2019-07-19 11:00:43 -04:00
parent 8739d8e750
commit 380d863c96
113 changed files with 612 additions and 477 deletions

View file

@ -193,6 +193,30 @@ public class DockableComponent extends JPanel implements ContainerListener {
return componentInfo;
}
/**
* Returns the component provider attached to this dockable component; null if this object
* has been disposed
*
* @return the provider
*/
public ComponentProvider getComponentProvider() {
if (componentInfo == null) {
return null;
}
return componentInfo.getProvider();
}
/**
* Returns the docking window manager that owns this component
* @return the manager
*/
public DockingWindowManager getDockingWindowManager() {
if (componentInfo == null) {
return null;
}
return componentInfo.getNode().getDockingWindowManager();
}
@Override
public String toString() {
if (componentInfo == null) {

View file

@ -32,8 +32,8 @@ import resources.ResourceManager;
* Manages to toolbar for the dockable components.
*/
class DockableToolBarManager {
private static final ImageIcon closeIcon = ResourceManager.loadImage("images/close16.gif");
private static final ImageIcon menuIcon = ResourceManager.loadImage("images/menu16.gif");
private static final ImageIcon CLOSE_ICON = ResourceManager.loadImage("images/close16.gif");
private static final ImageIcon MENU_ICON = ResourceManager.loadImage("images/menu16.gif");
private GenericHeader dockableHeader;
private ToolBarManager toolBarManager;
@ -45,6 +45,7 @@ class DockableToolBarManager {
private SwingUpdateManager headerUpdater =
new SwingUpdateManager(() -> dockableHeader.update());
private DockableComponent dockableComponent;
DockableToolBarManager(GenericHeader header) {
this.dockableHeader = header;
@ -52,14 +53,16 @@ class DockableToolBarManager {
}
/**
* Constructs a new DockableToolBarManger for the given ComponentInfo.
* @param info the componentInfo object containing the component.
* Constructs a new DockableToolBarManger for the given ComponentInfo
*
* @param dockableComponent the component to which this toolbar belongs
* @param header the header to which this toolbar belongs
*/
DockableToolBarManager(DockableComponent dockableComp, DockableHeader header) {
DockableToolBarManager(DockableComponent dockableComponent, DockableHeader header) {
this.dockableComponent = dockableComponent;
this.dockableHeader = header;
ComponentPlaceholder placeholder = dockableComp.getComponentWindowingPlaceholder();
DockingWindowManager winMgr =
dockableComp.getComponentWindowingPlaceholder().getNode().winMgr;
ComponentPlaceholder placeholder = dockableComponent.getComponentWindowingPlaceholder();
DockingWindowManager winMgr = dockableComponent.getDockingWindowManager();
ActionToGuiMapper actionManager = winMgr.getActionToGuiMapper();
menuGroupMap = actionManager.getMenuGroupMap();
@ -67,7 +70,14 @@ class DockableToolBarManager {
Iterator<DockingActionIf> iter = placeholder.getActions();
initialize(winMgr, menuHandler, iter);
closeButtonManager = new ToolBarItemManager(new ToolBarCloseAction(dockableComp), winMgr);
ComponentProvider provider = placeholder.getProvider();
String owner = provider.getOwner();
ToolBarCloseAction closeAction = new ToolBarCloseAction(owner);
closeButtonManager = new ToolBarItemManager(closeAction, winMgr);
DockingTool tool = winMgr.getTool();
// we need to add this action to the tool in order to use key bindings
tool.addLocalAction(provider, closeAction);
}
private void initialize(DockingWindowManager winMgr, MenuHandler menuHandler,
@ -152,6 +162,12 @@ class DockableToolBarManager {
}
void dispose() {
DockingWindowManager dwm = dockableComponent.getDockingWindowManager();
DockingTool tool = dwm.getTool();
ComponentProvider provider = dockableComponent.getComponentProvider();
tool.removeLocalAction(provider, closeButtonManager.getAction());
headerUpdater.dispose();
menuManager.dispose();
toolBarManager.dispose();
@ -165,14 +181,11 @@ class DockableToolBarManager {
* Action added to toolbar for "hiding" the component.
*/
private class ToolBarCloseAction extends DockingAction {
private DockableComponent dockableComponent;
ToolBarCloseAction(DockableComponent dockableComponent) {
super("Close Window", DockingWindowManager.DOCKING_WINDOWS_OWNER,
KeyBindingType.UNSUPPORTED);
this.dockableComponent = dockableComponent;
ToolBarCloseAction(String owner) {
super("Close Window", owner, KeyBindingType.SHARED);
setDescription("Close Window");
setToolBarData(new ToolBarData(closeIcon, null));
setToolBarData(new ToolBarData(CLOSE_ICON, null));
}
@Override
@ -182,6 +195,12 @@ class DockableToolBarManager {
placeholder.close();
}
}
@Override
public boolean isEnabledForContext(ActionContext context) {
ComponentProvider provider = context.getComponentProvider();
return provider == dockableComponent.getComponentProvider();
}
}
/**
@ -192,7 +211,7 @@ class DockableToolBarManager {
ToolBarMenuAction() {
super("Local Menu", DockingWindowManager.DOCKING_WINDOWS_OWNER);
setDescription("Menu");
setToolBarData(new ToolBarData(menuIcon, null));
setToolBarData(new ToolBarData(MENU_ICON, null));
}
@Override

View file

@ -326,6 +326,14 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
return root;
}
/**
* Returns the tool that owns this manager
* @return the tool
*/
public DockingTool getTool() {
return tool;
}
/**
* Returns the root window frame.
* @return the root window frame.

View file

@ -37,6 +37,14 @@ abstract class Node {
this.winMgr = winMgr;
}
/**
* Returns this node's window manager
* @return the window manager
*/
DockingWindowManager getDockingWindowManager() {
return winMgr;
}
/**
* Gets all children of this node; an empty list if no children exist.
*
@ -50,20 +58,23 @@ abstract class Node {
abstract void close();
/**
* Returns a component that manages all the components from the nodes below it.
* Returns a component that manages all the components from the nodes below it
* @return the component
*/
abstract JComponent getComponent();
/**
* Determine if this node contains the specified component.
* Determine if this node contains the specified component
*
* @param info component information
* @return true if this node contains the specified component.
* @return true if this node contains the specified component
*/
abstract boolean contains(ComponentPlaceholder info);
/**
* Returns an JDOM element object that contains the configuration state of this node
* and its children.
* and its children
* @return the element
*/
abstract Element saveToXML();
@ -83,7 +94,8 @@ abstract class Node {
abstract WindowNode getTopLevelNode();
/**
* Returns list of active components.
* Puts into the given list all active components in this node
* @param list the results list
*/
abstract void populateActiveComponents(List<ComponentPlaceholder> list);
@ -98,11 +110,14 @@ abstract class Node {
}
/**
* Generates a node corresponding to the given XML element.
* @param elem the XML element for which to generate a node.
* @param mgr the DockingWindowsManager for the new node.
* @param parentNode the parent node for the new node.
* @return the new node generated from the XML element.
* Generates a node corresponding to the given XML element
*
* @param elem the XML element for which to generate a node
* @param mgr the DockingWindowsManager for the new node
* @param parentNode the parent node for the new node
* @param restoredPlaceholders a 'results' list into which will be placed any restored
* placeholders
* @return the new node generated from the XML element
*/
Node processChildElement(Element elem, DockingWindowManager mgr, Node parentNode,
List<ComponentPlaceholder> restoredPlaceholders) {

View file

@ -20,6 +20,7 @@ import javax.swing.Icon;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.actions.AutoGeneratedDockingAction;
import docking.tool.ToolConstants;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
@ -47,7 +48,7 @@ class ShowWindowAction extends DockingAction
this.node = node;
setMenuBarData(new MenuData(new String[] { MENU_WINDOW, getName() }, ICON, "WindowGroup"));
setHelpLocation(new HelpLocation("Tool", "DefaultTools")); // somewhat arbitrary location
setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "DefaultTools")); // somewhat arbitrary location
}
@Override

View file

@ -25,6 +25,7 @@ import javax.swing.text.*;
import docking.DialogComponentProvider;
import docking.KeyEntryTextField;
import docking.action.*;
import docking.tool.ToolConstants;
import docking.widgets.label.GIconLabel;
import ghidra.util.HelpLocation;
import ghidra.util.ReservedKeyBindings;
@ -54,7 +55,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
createPanel();
KeyStroke keyBinding = action.getKeyBinding();
updateCollisionPane(keyBinding);
setHelpLocation(new HelpLocation("Tool", "KeyBindingPopup"));
setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "KeyBindingPopup"));
}
private void createPanel() {
@ -161,8 +162,6 @@ public class KeyEntryDialog extends DialogComponentProvider {
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKeyStroke));
toolActions.keyBindingsChanged();
close();
}

View file

@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.ActionContext;
import docking.DockingWindowManager;
import docking.action.*;
import docking.tool.ToolConstants;
import ghidra.framework.options.OptionsChangeListener;
import ghidra.framework.options.ToolOptions;
@ -37,7 +38,7 @@ import ghidra.framework.options.ToolOptions;
*/
public class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeListener {
static final String SHARED_OWNER = "Tool";
static final String SHARED_OWNER = ToolConstants.TOOL_OWNER;
/**
* We save the client actions for later validate and options updating. We also need the
@ -109,6 +110,13 @@ public class SharedStubKeyBindingAction extends DockingAction implements Options
results.add(owner);
}
}
if (results.isEmpty()) {
// This implies we have an action owned by the DockingWindowManager
// (the DOCKING_WINDOWS_OWNER). In this case, use the Tool as the owner.
results.add(SHARED_OWNER);
}
return results;
}

View file

@ -376,6 +376,12 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
}
}
// triggered by a user-initiated action; called by propertyChange()
private void keyBindingsChanged() {
dockingTool.setConfigChanged(true);
actionGuiHelper.keyBindingsChanged();
}
@Override
public DockingActionIf getLocalAction(ComponentProvider provider, String actionName) {
@ -397,9 +403,4 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
return sharedActionMap.get(name);
}
// triggered by a user-initiated action
void keyBindingsChanged() {
dockingTool.setConfigChanged(true);
actionGuiHelper.keyBindingsChanged();
}
}

View file

@ -0,0 +1,131 @@
/* ###
* 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 docking.tool;
import docking.tool.util.DockingToolConstants;
/**
* Values used to define standard menu names and other miscellaneous constants
*/
public interface ToolConstants extends DockingToolConstants {
/**
* Used when placing an action in the "File" menu of the tool
*/
public static final String MENU_FILE = "&File";
/**
* Used when placing an action in the "Edit" menu of the tool
*/
public static final String MENU_EDIT = "&Edit";
/**
* Used when placing a PluginAction in the "Navigation" menu of the tool
*/
public static final String MENU_NAVIGATION = "&Navigation";
/**
* Group name for actions to navigate between windows
*/
public static final String MENU_NAVIGATION_GROUP_WINDOWS = "GoToWindow";
/**
* Used when placing an action in the "Search" menu of the tool
*/
public static final String MENU_SEARCH = "&Search";
/**
* Used when placing an action in the "Selection" menu of the tool
*/
public static final String MENU_SELECTION = "Se&lect";
/**
* Used when placing an action in the "About" menu of the tool
*/
public static final String MENU_HELP = "&Help";
/**
* Used when placing an action in the "Analysis" menu of the tool
*/
public static final String MENU_ANALYSIS = "&Analysis";
/**
* Used when placing an action in the "Project" menu of the tool
*/
public static final String MENU_PROJECT = "&Project";
/**
* Used when placing an action in the "Tools" menu of the tool
*/
public static final String MENU_TOOLS = "&Tools";
/** A group for actions that link directly to help content */
public static final String HELP_CONTENTS_MENU_GROUP = "AAAHelpContents";
/** Used for navigation-based action */
public static final String NEXT_CODE_UNIT_NAVIGATION_MENU_GROUP = "NextPrevCodeUnit";
/**
* Constant for the options menu group for the Tool Options menu item
*/
public static final String TOOL_OPTIONS_MENU_GROUP = "AOptions";
/**
* Node name used in the Data tree when a project is not open
*/
public static final String NO_ACTIVE_PROJECT = "NO ACTIVE PROJECT";
/**
* This is used when an action has the tool as its owner
*/
public static final String TOOL_OWNER = "Tool";
/**
* Name of options for a tool
*/
public static final String TOOL_OPTIONS = "Tool";
/**
* Name of the help topic for "About" domain objects and Ghidra
*/
public static final String ABOUT_HELP_TOPIC = "About";
/**
* Name of help topic for the front end (Ghidra Project Window)
*/
public static final String FRONT_END_HELP_TOPIC = "FrontEndPlugin";
/**
* Name of help topic for the Tool
*/
public static final String TOOL_HELP_TOPIC = "Tool";
/**
* The large icon size (height and width)
*/
public static final int LARGE_ICON_SIZE = 24;
/**
* The medium icon size (height and width)
*/
public static final int MEDIUM_ICON_SIZE = 22;
/**
* The small icon size (height and width)
*/
public static final int SMALL_ICON_SIZE = 16;
}

View file

@ -24,6 +24,7 @@ import javax.swing.*;
import docking.DialogComponentProvider;
import docking.DockingWindowManager;
import docking.tool.ToolConstants;
import docking.widgets.OptionDialog;
import ghidra.util.*;
import ghidra.util.exception.CancelledException;
@ -146,7 +147,7 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
}
// SPLIT the help for this dialog should not be in the front end plugin.
setHelpLocation(new HelpLocation("Tool", "TaskDialog"));
setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "TaskDialog"));
}
/**