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:
dragonmacher 2019-06-26 15:30:34 -04:00
parent f510ddf338
commit fa75f7dff6
32 changed files with 296 additions and 425 deletions

View file

@ -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;
}
}
}

View file

@ -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();

View file

@ -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();

View file

@ -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) {