mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GT-2925 - Key Bindings - Support Window Menu Provider Key Bindings -
Step 3 - removed old plugin pattern of creating special actions to show their respective providers; updated inception information for new action
This commit is contained in:
parent
f510ddf338
commit
fa75f7dff6
32 changed files with 296 additions and 425 deletions
|
@ -76,6 +76,9 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
private static final String TRANSIENT_PROVIDER_TOOLBAR_WARNING_MESSAGE =
|
||||
"Transient providers are not added to the toolbar";
|
||||
|
||||
private static final String TRANSIENT_PROVIDER_KEY_BINDING_WARNING_MESSAGE =
|
||||
"Transient providers cannot have key bindings";
|
||||
|
||||
public static final String DEFAULT_WINDOW_GROUP = "Default";
|
||||
|
||||
private static final String TOOLBAR_GROUP = "View";
|
||||
|
@ -95,20 +98,23 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
/** True if this provider's action should appear in the toolbar */
|
||||
private boolean isToolbarAction;
|
||||
private boolean isTransient;
|
||||
private HelpLocation helpLocation;
|
||||
|
||||
private KeyBindingData defaultKeyBindingData;
|
||||
private Icon icon;
|
||||
|
||||
private String windowMenuGroup;
|
||||
private String group = DEFAULT_WINDOW_GROUP;
|
||||
private WindowPosition defaultWindowPosition = WindowPosition.WINDOW;
|
||||
private WindowPosition defaultIntraGroupPosition = WindowPosition.STACK;
|
||||
private DockingAction showProviderAction;
|
||||
|
||||
private HelpLocation helpLocation;
|
||||
private final Class<?> contextType;
|
||||
|
||||
private long instanceID = UniversalIdGenerator.nextID().getValue();
|
||||
private boolean instanceIDHasBeenInitialized;
|
||||
|
||||
private String inceptionInformation;
|
||||
|
||||
/**
|
||||
* Creates a new component provider with a default location of {@link WindowPosition#WINDOW}.
|
||||
* @param tool The tool will manage and show this provider
|
||||
|
@ -135,6 +141,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
this.owner = owner;
|
||||
this.title = name;
|
||||
this.contextType = contextType;
|
||||
|
||||
recordInception();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,15 +162,6 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
showProviderAction = new ShowProviderAction();
|
||||
}
|
||||
|
||||
private void removeShowProviderAction() {
|
||||
if (showProviderAction == null) {
|
||||
return; // not installed
|
||||
}
|
||||
|
||||
dockingTool.removeAction(showProviderAction);
|
||||
showProviderAction = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component to be displayed
|
||||
* @return the component to be displayed
|
||||
|
@ -493,6 +492,26 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
return tabText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default key binding that will show this provider when pressed
|
||||
* @param kbData the key binding
|
||||
*/
|
||||
public void setDefaultKeyBinding(KeyBindingData kbData) {
|
||||
|
||||
if (isInTool()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot set the default key binding after the provider is added to the tool");
|
||||
}
|
||||
|
||||
this.defaultKeyBindingData = kbData;
|
||||
|
||||
if (isTransient) {
|
||||
Msg.error(this, TRANSIENT_PROVIDER_KEY_BINDING_WARNING_MESSAGE,
|
||||
ReflectionUtilities.createJavaFilteredThrowable());
|
||||
this.defaultKeyBindingData = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for setting the provider's icon.
|
||||
* @param icon the icon to use for this provider.
|
||||
|
@ -530,8 +549,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
|
||||
4) Wire default 'close' action to keybinding
|
||||
5) Add global action for (show last provider)
|
||||
6) Remove plugin code that creates the 'show' actions
|
||||
|
||||
--Navigation menu?
|
||||
|
||||
Questions:
|
||||
|
||||
C) How to wire universal close action (it is focus-dependent)
|
||||
|
@ -539,7 +558,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
|
||||
Fix:
|
||||
|
||||
-Toolbar description for key doesn't match menu (goes away)
|
||||
-Update key binding methods to use an enum for: no management / full management / shared management
|
||||
-remove superfluous overrides of getIcon()
|
||||
|
||||
*/
|
||||
|
||||
|
@ -573,6 +593,12 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
protected void setTransient() {
|
||||
isTransient = true;
|
||||
|
||||
if (isInTool()) {
|
||||
throw new IllegalStateException(
|
||||
"A component provider cannot be marked as 'transient' " +
|
||||
"after it is added to the tool");
|
||||
}
|
||||
|
||||
// avoid visually disturbing the user by adding/removing toolbar actions for temp providers
|
||||
if (isToolbarAction) {
|
||||
isToolbarAction = false;
|
||||
|
@ -580,7 +606,11 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
ReflectionUtilities.createJavaFilteredThrowable());
|
||||
}
|
||||
|
||||
removeShowProviderAction();
|
||||
if (defaultKeyBindingData != null) {
|
||||
defaultKeyBindingData = null;
|
||||
Msg.error(this, TRANSIENT_PROVIDER_KEY_BINDING_WARNING_MESSAGE,
|
||||
ReflectionUtilities.createJavaFilteredThrowable());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -687,6 +717,22 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
return name + " - " + getTitle() + " - " + getSubTitle();
|
||||
}
|
||||
|
||||
private void recordInception() {
|
||||
if (!SystemUtilities.isInDevelopmentMode()) {
|
||||
inceptionInformation = "";
|
||||
return;
|
||||
}
|
||||
|
||||
inceptionInformation = getInceptionFromTheFirstClassThatIsNotUs();
|
||||
}
|
||||
|
||||
private String getInceptionFromTheFirstClassThatIsNotUs() {
|
||||
Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan(getClass());
|
||||
StackTraceElement[] trace = t.getStackTrace();
|
||||
String classInfo = trace[0].toString();
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any registered new provider name for the oldName/oldOwner pair.
|
||||
* @param oldOwner the old owner name
|
||||
|
@ -737,6 +783,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
if (isToolbarAction) {
|
||||
setToolBarData(new ToolBarData(icon, TOOLBAR_GROUP));
|
||||
}
|
||||
|
||||
if (defaultKeyBindingData != null) {
|
||||
// this action itself is not 'key binding managed', but the system *will* use
|
||||
// any key binding value we set when connecting 'shared' actions
|
||||
setKeyBindingData(defaultKeyBindingData);
|
||||
}
|
||||
|
||||
setDescription("Display " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -751,7 +805,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
|
||||
@Override
|
||||
public boolean usesSharedKeyBinding() {
|
||||
// we do not allow transient providers to have key bindings
|
||||
return !isTransient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInceptionFromTheFirstClassThatIsNotUs() {
|
||||
// overridden to show who created the provider, as that is what this action represents
|
||||
return inceptionInformation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,13 +143,17 @@ class ShowComponentAction extends DockingAction implements Comparable<ShowCompon
|
|||
public String getHelpInfo() {
|
||||
StringBuilder buffy = new StringBuilder(super.getHelpInfo());
|
||||
|
||||
Class<? extends ComponentProvider> clazz = info.getProvider().getClass();
|
||||
ComponentProvider provider = info.getProvider();
|
||||
Class<? extends ComponentProvider> clazz = provider.getClass();
|
||||
String className = clazz.getName();
|
||||
String filename = className.substring(className.lastIndexOf('.') + 1);
|
||||
String javaName = filename + ".java";
|
||||
|
||||
buffy.append(" ").append("PROVIDER: ").append(info.getName()).append(' ');
|
||||
buffy.append('(').append(javaName).append(":1)");
|
||||
DockingActionIf showAction = provider.getShowProviderAction();
|
||||
String realInception = showAction.getInceptionInformation();
|
||||
buffy.append(" ").append(realInception).append("\n ");
|
||||
|
||||
buffy.append(" ").append("PROVIDER: ").append(filename).append(' ');
|
||||
buffy.append('(').append(provider.getOwner()).append(")");
|
||||
buffy.append("\n ");
|
||||
|
||||
return buffy.toString();
|
||||
|
|
|
@ -489,7 +489,7 @@ public abstract class DockingAction implements DockingActionIf {
|
|||
inceptionInformation = getInceptionFromTheFirstClassThatIsNotUs();
|
||||
}
|
||||
|
||||
private String getInceptionFromTheFirstClassThatIsNotUs() {
|
||||
protected String getInceptionFromTheFirstClassThatIsNotUs() {
|
||||
Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan(getClass());
|
||||
StackTraceElement[] trace = t.getStackTrace();
|
||||
String classInfo = trace[0].toString();
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
import docking.*;
|
||||
import docking.action.*;
|
||||
import ghidra.docking.util.DockingWindowsLookAndFeelUtils;
|
||||
import ghidra.util.StringUtilities;
|
||||
|
||||
/**
|
||||
|
@ -79,7 +80,7 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||
}
|
||||
|
||||
private void setToolTipText(JButton button, DockingActionIf action, String toolTipText) {
|
||||
String keyBindingText = getKeyBindingAcceleratorText(action.getKeyBinding());
|
||||
String keyBindingText = getKeyBindingAcceleratorText(button, action.getKeyBinding());
|
||||
if (keyBindingText != null) {
|
||||
button.setToolTipText(combingToolTipTextWithKeyBinding(toolTipText, keyBindingText));
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||
return action.getName();
|
||||
}
|
||||
|
||||
private String getKeyBindingAcceleratorText(KeyStroke keyStroke) {
|
||||
private String getKeyBindingAcceleratorText(JButton button, KeyStroke keyStroke) {
|
||||
if (keyStroke == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -130,8 +131,12 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||
StringBuilder builder = new StringBuilder();
|
||||
int modifiers = keyStroke.getModifiers();
|
||||
if (modifiers > 0) {
|
||||
builder.append(KeyEvent.getKeyModifiersText(modifiers));
|
||||
builder.append('+');
|
||||
builder.append(InputEvent.getModifiersExText(modifiers));
|
||||
|
||||
// The Aqua LaF does not use the '+' symbol between modifiers
|
||||
if (!DockingWindowsLookAndFeelUtils.isUsingAquaUI(button.getUI())) {
|
||||
builder.append('+');
|
||||
}
|
||||
}
|
||||
int keyCode = keyStroke.getKeyCode();
|
||||
if (keyCode != 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue