mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/ghidravore_action_builder'
This commit is contained in:
commit
4dea312e59
8 changed files with 929 additions and 1 deletions
|
@ -255,7 +255,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
||||||
* Adds the given action to the system and associates it with this provider.
|
* Adds the given action to the system and associates it with this provider.
|
||||||
* @param action The action to add.
|
* @param action The action to add.
|
||||||
*/
|
*/
|
||||||
protected void addLocalAction(DockingActionIf action) {
|
public void addLocalAction(DockingActionIf action) {
|
||||||
if (actionSet.contains(action)) {
|
if (actionSet.contains(action)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
|
@ -72,6 +73,11 @@ public abstract class DockingAction implements DockingActionIf {
|
||||||
private PopupMenuData popupMenuData;
|
private PopupMenuData popupMenuData;
|
||||||
private ToolBarData toolBarData;
|
private ToolBarData toolBarData;
|
||||||
|
|
||||||
|
private Predicate<ActionContext> enabledPredicate;
|
||||||
|
private Predicate<ActionContext> popupPredicate;
|
||||||
|
private Predicate<ActionContext> validContextPredicate;
|
||||||
|
private Predicate<ActionContext> validGlobalContextPredicate;
|
||||||
|
|
||||||
public DockingAction(String name, String owner) {
|
public DockingAction(String name, String owner) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
|
@ -156,21 +162,33 @@ public abstract class DockingAction implements DockingActionIf {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAddToPopup(ActionContext context) {
|
public boolean isAddToPopup(ActionContext context) {
|
||||||
|
if (popupPredicate != null) {
|
||||||
|
return popupPredicate.test(context);
|
||||||
|
}
|
||||||
return isEnabledForContext(context);
|
return isEnabledForContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledForContext(ActionContext context) {
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
|
if (enabledPredicate != null) {
|
||||||
|
return enabledPredicate.test(context);
|
||||||
|
}
|
||||||
return isEnabled();
|
return isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidContext(ActionContext context) {
|
public boolean isValidContext(ActionContext context) {
|
||||||
|
if (validContextPredicate != null) {
|
||||||
|
return validContextPredicate.test(context);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidGlobalContext(ActionContext globalContext) {
|
public boolean isValidGlobalContext(ActionContext globalContext) {
|
||||||
|
if (validGlobalContextPredicate != null) {
|
||||||
|
return validGlobalContextPredicate.test(globalContext);
|
||||||
|
}
|
||||||
return isValidContext(globalContext);
|
return isValidContext(globalContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,6 +535,54 @@ public abstract class DockingAction implements DockingActionIf {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining the action's enabled state. If this
|
||||||
|
* predicate is not set, the action's enable state must be controlled directly using the
|
||||||
|
* {@link DockingAction#setEnabled(boolean)} method. See
|
||||||
|
* {@link DockingActionIf#isEnabledForContext(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* enabled state.
|
||||||
|
*/
|
||||||
|
public void enabledWhen(Predicate<ActionContext> predicate) {
|
||||||
|
enabledPredicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining if this action should be included in
|
||||||
|
* an impending pop-up menu. If this predicate is not set, the action's will be included
|
||||||
|
* in an impending pop-up, if it is enabled. See
|
||||||
|
* {@link DockingActionIf#isAddToPopup(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* enabled state.
|
||||||
|
*/
|
||||||
|
public void popupWhen(Predicate<ActionContext> predicate) {
|
||||||
|
popupPredicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining if this action is valid for the current
|
||||||
|
* {@link ActionContext}. See {@link DockingActionIf#isValidContext(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* validity for a given {@link ActionContext}
|
||||||
|
*/
|
||||||
|
public void validContextWhen(Predicate<ActionContext> predicate) {
|
||||||
|
validContextPredicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining if this action is valid for the current global
|
||||||
|
* {@link ActionContext}. See {@link DockingActionIf#isValidGlobalContext(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* validity for a given global {@link ActionContext}
|
||||||
|
*/
|
||||||
|
public void validGlobalContextWhen(Predicate<ActionContext> predicate) {
|
||||||
|
validGlobalContextPredicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Non-public methods
|
// Non-public methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
|
@ -28,6 +28,10 @@ public abstract class ToggleDockingAction extends DockingAction implements Toggl
|
||||||
super(name, owner);
|
super(name, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ToggleDockingAction(String name, String owner, KeyBindingType keyBindingType) {
|
||||||
|
super(name, owner, keyBindingType);
|
||||||
|
}
|
||||||
|
|
||||||
public ToggleDockingAction(String name, String owner, boolean supportsKeyBindings) {
|
public ToggleDockingAction(String name, String owner, boolean supportsKeyBindings) {
|
||||||
super(name, owner, supportsKeyBindings);
|
super(name, owner, supportsKeyBindings);
|
||||||
}
|
}
|
||||||
|
@ -61,4 +65,5 @@ public abstract class ToggleDockingAction extends DockingAction implements Toggl
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
// defined by subclasses
|
// defined by subclasses
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,513 @@
|
||||||
|
/* ###
|
||||||
|
* 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.action.builder;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import docking.*;
|
||||||
|
import docking.action.*;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
|
import resources.ResourceManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for DockingAction builders
|
||||||
|
*
|
||||||
|
* @param <T> The type of DockingAction to build
|
||||||
|
* @param <B> the Type of DockingActionBuilder
|
||||||
|
*/
|
||||||
|
public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends AbstractActionBuilder<T, B>> {
|
||||||
|
/**
|
||||||
|
* a name for the {@code DockingAction}
|
||||||
|
*/
|
||||||
|
protected String name;
|
||||||
|
/**
|
||||||
|
* an owner for the {@code DockingAction}
|
||||||
|
*/
|
||||||
|
protected String owner;
|
||||||
|
/**
|
||||||
|
* the {@code KeyBindingType} for this {@code DockingAction}
|
||||||
|
*/
|
||||||
|
protected KeyBindingType keyBindingType = KeyBindingType.INDIVIDUAL;
|
||||||
|
/**
|
||||||
|
* The callback to perform when the action is invoked
|
||||||
|
*/
|
||||||
|
protected Consumer<ActionContext> actionCallback;
|
||||||
|
/**
|
||||||
|
* a description for the {@code DockingAction}
|
||||||
|
*/
|
||||||
|
private String description = "";
|
||||||
|
/**
|
||||||
|
* whether this {@code DockingAction} is enabled
|
||||||
|
*/
|
||||||
|
private boolean isEnabled = true;
|
||||||
|
/**
|
||||||
|
* the {@code HelpLocation} for this {@code DockingAction}
|
||||||
|
*/
|
||||||
|
private HelpLocation helpLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The menu bar path. This is the key attribute for including the action on the menu bar
|
||||||
|
*/
|
||||||
|
private String[] menuPath;
|
||||||
|
/**
|
||||||
|
* The menu bar menu item icon. (optional)
|
||||||
|
*/
|
||||||
|
private Icon menuIcon;
|
||||||
|
/**
|
||||||
|
* The menu bar menu item sub group. (optional)
|
||||||
|
*/
|
||||||
|
private String menuSubGroup;
|
||||||
|
/**
|
||||||
|
* The menu bar menu item group. (optional)
|
||||||
|
*/
|
||||||
|
private String menuGroup;
|
||||||
|
/**
|
||||||
|
* The mnemonic for the menu action (optional)
|
||||||
|
*/
|
||||||
|
private int menuMnemonic;
|
||||||
|
/**
|
||||||
|
* The icon for the menu item (optional)
|
||||||
|
*/
|
||||||
|
private Icon popupIcon;
|
||||||
|
/**
|
||||||
|
* The menu path in a pop-up menu. This is the key attribute for pop-up menu actions
|
||||||
|
*/
|
||||||
|
private String[] popupPath;
|
||||||
|
/**
|
||||||
|
* The menu group for the item in the pop-up menu (optional)
|
||||||
|
*/
|
||||||
|
private String popupGroup;
|
||||||
|
/**
|
||||||
|
* The menu sub group for the item in the pop-up menu (optional)
|
||||||
|
*/
|
||||||
|
private String popupSubGroup;
|
||||||
|
/**
|
||||||
|
* The icon for the tool bar action. This is the key attribute for actions in the toolbar.
|
||||||
|
*/
|
||||||
|
private Icon toolbarIcon;
|
||||||
|
/**
|
||||||
|
* The group for the items on the tool bar (optional)
|
||||||
|
*/
|
||||||
|
private String toolBarGroup;
|
||||||
|
/**
|
||||||
|
* The menu group for the item in the tool bar menu (optional)
|
||||||
|
*/
|
||||||
|
private String toolBarSubGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Predicate for determining if an action is enabled for a given context
|
||||||
|
*/
|
||||||
|
private Predicate<ActionContext> enabledPredicate;
|
||||||
|
/**
|
||||||
|
* Predicate for determining if an action should be included on the pop-up menu
|
||||||
|
*/
|
||||||
|
private Predicate<ActionContext> popupPredicate;
|
||||||
|
/**
|
||||||
|
* Predicate for determining if an action is applicable for a given context
|
||||||
|
*/
|
||||||
|
private Predicate<ActionContext> validContextPredicate;
|
||||||
|
/**
|
||||||
|
* Predicate for determining if an action is applicable for a given global context
|
||||||
|
*/
|
||||||
|
private Predicate<ActionContext> validGlobalContextPredicate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder constructor
|
||||||
|
* @param name the name of the action to be built
|
||||||
|
* @param owner the owner of the action to be build
|
||||||
|
*/
|
||||||
|
public AbstractActionBuilder(String name, String owner) {
|
||||||
|
this.name = name;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns this (typed for subclass) for chaining
|
||||||
|
* @return this for chaining
|
||||||
|
*/
|
||||||
|
protected abstract B self();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds the action
|
||||||
|
* @return the newly build action
|
||||||
|
*/
|
||||||
|
public abstract T build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds and adds the action globally to the tool
|
||||||
|
*
|
||||||
|
* @param tool the tool to add the action to
|
||||||
|
* @return the newly created action
|
||||||
|
*/
|
||||||
|
public T buildAndInstall(DockingTool tool) {
|
||||||
|
T action = build();
|
||||||
|
tool.addAction(action);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds and adds the action as a local action for the given provider
|
||||||
|
*
|
||||||
|
* @param provider the provider to add the action to
|
||||||
|
* @return the newly created action
|
||||||
|
*/
|
||||||
|
public T buildAndInstallLocal(ComponentProvider provider) {
|
||||||
|
T action = build();
|
||||||
|
provider.addLocalAction(action);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the {@code String} description for this {@code DockingAction}
|
||||||
|
*
|
||||||
|
* @param text the description
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B description(String text) {
|
||||||
|
this.description = text;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure whether this {@code DockingAction} is enabled
|
||||||
|
*
|
||||||
|
* @param b {@code true} if enabled
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B enabled(boolean b) {
|
||||||
|
this.isEnabled = b;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure {@link KeyBindingType} for this {@code DockingAction}
|
||||||
|
* @param type the {@link KeyBindingType} to configure
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B keyBindingType(KeyBindingType type) {
|
||||||
|
this.keyBindingType = type;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure {@link HelpLocation} for this {@code DockingAction}
|
||||||
|
* @param help the {@link HelpLocation} to configure
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B helpLocation(HelpLocation help) {
|
||||||
|
this.helpLocation = help;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the menu bar path for the action. Setting this attribute is what causes the action
|
||||||
|
* to appear on the tools menu bar
|
||||||
|
* @param pathElement the menu bar path for the action
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B menuPath(String... pathElement) {
|
||||||
|
menuPath = pathElement;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the group for the action in the menu bar. Actions in the same group will appear
|
||||||
|
* next to other actions in the same group and actions in different groups will be separated
|
||||||
|
* by menu dividers
|
||||||
|
*
|
||||||
|
* @param group for this action
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B menuGroup(String group) {
|
||||||
|
menuGroup = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the group and sub-group for the action in the menu bar. Actions in the same group will appear
|
||||||
|
* next to other actions in the same group and actions in different groups will be separated
|
||||||
|
* by menu dividers. The sub-group is used to order the actions withing the group.
|
||||||
|
*
|
||||||
|
* @param group the group used to clump actions together.
|
||||||
|
* @param subGroup the sub-group used to order actions within a group.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B menuGroup(String group, String subGroup) {
|
||||||
|
menuSubGroup = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the icon to use in this action's menu bar item.
|
||||||
|
*
|
||||||
|
* @param icon the icon to use in the action's menu bar item.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B menuIcon(Icon icon) {
|
||||||
|
menuIcon = icon;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the mnemonic to use in this action's menu bar item.
|
||||||
|
*
|
||||||
|
* @param mnemonic the mnemonic to use for this action's menu bar item.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B menuMnemonic(int mnemonic) {
|
||||||
|
menuMnemonic = mnemonic;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pop-up menu path for the action. Setting this attribute is what causes the action
|
||||||
|
* to appear on the tools pop-up menu (Assuming it is applicable for the context)
|
||||||
|
*
|
||||||
|
* @param pathElement the menu path for the action in the pop-up menu
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B popupMenuPath(String... pathElement) {
|
||||||
|
popupPath = pathElement;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the group for the action in the pop-up menu. Actions in the same group will appear
|
||||||
|
* next to other actions in the same group and actions in different groups will be separated
|
||||||
|
* by menu dividers
|
||||||
|
*
|
||||||
|
* @param group for this action
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B popupMenuGroup(String group) {
|
||||||
|
popupGroup = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the group and sub-group for the action in the pop-up menu. Actions in the same group
|
||||||
|
* will appear next to other actions in the same group and actions in different groups will
|
||||||
|
* be separated by menu dividers. The sub-group is used to order the actions within the group
|
||||||
|
*
|
||||||
|
* @param group the group used to clump actions together.
|
||||||
|
* @param subGroup the sub-group used to order actions within a group.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B popupMenuGroup(String group, String subGroup) {
|
||||||
|
popupSubGroup = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the icon to use in this action's pop-up menu item.
|
||||||
|
*
|
||||||
|
* @param icon the icon to use in the action's pop-up menu item.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B popupMenuIcon(Icon icon) {
|
||||||
|
popupIcon = icon;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the icon to use in this action's tool bar button. Setting this attribute is what
|
||||||
|
* causes the action to appear on the tools or component provider's action tool bar.
|
||||||
|
*
|
||||||
|
* @param icon the icon to use in the action's tool bar.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B toolBarIcon(Icon icon) {
|
||||||
|
toolbarIcon = icon;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the path for the icon to use in this action's tool bar button. Setting this attribute
|
||||||
|
* causes the action to appear on the tools or component provider's action tool bar.
|
||||||
|
*
|
||||||
|
* @param iconFilepath the module relative path for the icon to use in the action's tool bar.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B toolBarIcon(String iconFilepath) {
|
||||||
|
toolbarIcon = ResourceManager.loadImage(iconFilepath);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the group for the action in the tool bar. Actions in the same group will appear
|
||||||
|
* next to other actions in the same group and actions in different groups will be separated
|
||||||
|
* by menu dividers
|
||||||
|
*
|
||||||
|
* @param group for this action
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B toolBarGroup(String group) {
|
||||||
|
toolBarGroup = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the group and sub-group for the action in the tool bar. Actions in the same group
|
||||||
|
* will appear next to other actions in the same group and actions in different groups will
|
||||||
|
* be separated by menu dividers. The sub-group is used to order the actions within the group
|
||||||
|
*
|
||||||
|
* @param group the group used to clump actions together.
|
||||||
|
* @param subGroup the sub-group used to order actions within a group.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B toolBarGroup(String group, String subGroup) {
|
||||||
|
toolBarSubGroup = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the primary callback to be executed when this action is invoked. This builder will
|
||||||
|
* throw an {@link IllegalStateException} if one of the build methods is called without
|
||||||
|
* providing this callback
|
||||||
|
*
|
||||||
|
* @param action the callback to execute when the action is invoked
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B onAction(Consumer<ActionContext> action) {
|
||||||
|
actionCallback = action;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining the action's enabled state. If this
|
||||||
|
* predicate is not set, the action's enable state must be controlled directly using the
|
||||||
|
* {@link DockingAction#setEnabled(boolean)} method. See
|
||||||
|
* {@link DockingActionIf#isEnabledForContext(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* enabled state.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B enabledWhen(Predicate<ActionContext> predicate) {
|
||||||
|
enabledPredicate = predicate;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining if this action should be included in
|
||||||
|
* an impending pop-up menu. If this predicate is not set, the action's will be included
|
||||||
|
* in an impending pop-up, if it is enabled. See
|
||||||
|
* {@link DockingActionIf#isAddToPopup(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* enabled state.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B popupWhen(Predicate<ActionContext> predicate) {
|
||||||
|
popupPredicate = predicate;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining if this action is valid for the current
|
||||||
|
* {@link ActionContext}. See {@link DockingActionIf#isValidContext(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* validity for a given {@link ActionContext}
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B validContextWhen(Predicate<ActionContext> predicate) {
|
||||||
|
validContextPredicate = predicate;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a predicate for dynamically determining if this action is valid for the current global
|
||||||
|
* {@link ActionContext}. See {@link DockingActionIf#isValidGlobalContext(ActionContext)}
|
||||||
|
*
|
||||||
|
* @param predicate the predicate that will be used to dynamically determine an action's
|
||||||
|
* validity for a given global {@link ActionContext}
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B validGlobalContextWhen(Predicate<ActionContext> predicate) {
|
||||||
|
validGlobalContextPredicate = predicate;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validate() {
|
||||||
|
if (actionCallback == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Can't build a DockingAction without an action callback");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void decorateAction(DockingAction action) {
|
||||||
|
action.setEnabled(isEnabled);
|
||||||
|
action.setDescription(description);
|
||||||
|
|
||||||
|
setMenuData(action);
|
||||||
|
setToolbarData(action);
|
||||||
|
setPopupMenuData(action);
|
||||||
|
|
||||||
|
if (helpLocation != null) {
|
||||||
|
action.setHelpLocation(helpLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabledPredicate != null) {
|
||||||
|
action.enabledWhen(enabledPredicate);
|
||||||
|
}
|
||||||
|
if (validContextPredicate != null) {
|
||||||
|
action.validContextWhen(validContextPredicate);
|
||||||
|
}
|
||||||
|
if (validGlobalContextPredicate != null) {
|
||||||
|
action.validGlobalContextWhen(validGlobalContextPredicate);
|
||||||
|
}
|
||||||
|
if (popupPredicate != null) {
|
||||||
|
action.popupWhen(enabledPredicate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPopupAction() {
|
||||||
|
return popupPath != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isToolbarAction() {
|
||||||
|
return toolbarIcon != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isMenuAction() {
|
||||||
|
return menuPath != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPopupMenuData(DockingAction action) {
|
||||||
|
if (isPopupAction()) {
|
||||||
|
action.setPopupMenuData(new MenuData(popupPath, popupIcon, popupGroup,
|
||||||
|
MenuData.NO_MNEMONIC, popupSubGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setToolbarData(DockingAction action) {
|
||||||
|
if (isToolbarAction()) {
|
||||||
|
action.setToolBarData(new ToolBarData(toolbarIcon, toolBarGroup, toolBarSubGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMenuData(DockingAction action) {
|
||||||
|
if (isMenuAction()) {
|
||||||
|
action.setMenuBarData(
|
||||||
|
new MenuData(menuPath, menuIcon, menuGroup, menuMnemonic, menuSubGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* ###
|
||||||
|
* 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.action.builder;
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.action.DockingAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link DockingAction}s
|
||||||
|
*/
|
||||||
|
public class ActionBuilder
|
||||||
|
extends AbstractActionBuilder<DockingAction, ActionBuilder> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder constructor
|
||||||
|
* @param name the name of the action to be built
|
||||||
|
* @param owner the owner of the action to be build
|
||||||
|
*/
|
||||||
|
public ActionBuilder(String name, String owner) {
|
||||||
|
super(name, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ActionBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DockingAction build() {
|
||||||
|
validate();
|
||||||
|
DockingAction action =
|
||||||
|
new DockingAction(name, owner, keyBindingType) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionContext context) {
|
||||||
|
actionCallback.accept(context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
decorateAction(action);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* ###
|
||||||
|
* 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.action.builder;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.action.DockingActionIf;
|
||||||
|
import docking.menu.MultiActionDockingAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link MultiActionDockingAction}
|
||||||
|
*/
|
||||||
|
public class MultiActionBuilder
|
||||||
|
extends AbstractActionBuilder<MultiActionDockingAction, MultiActionBuilder> {
|
||||||
|
/**
|
||||||
|
* List of actions for the the MultActionDockingAction
|
||||||
|
*/
|
||||||
|
private List<DockingActionIf> actionList = Collections.emptyList();
|
||||||
|
/**
|
||||||
|
* determines if the the main action is invokable
|
||||||
|
*/
|
||||||
|
private boolean performActionOnButtonClick = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder constructor
|
||||||
|
* @param name the name of the action to be built
|
||||||
|
* @param owner the owner of the action to be build
|
||||||
|
*/
|
||||||
|
public MultiActionBuilder(String name, String owner) {
|
||||||
|
super(name, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MultiActionBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultiActionDockingAction build() {
|
||||||
|
validate();
|
||||||
|
MultiActionDockingAction action =
|
||||||
|
new MultiActionDockingAction(name, owner) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionContext context) {
|
||||||
|
actionCallback.accept(context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
decorateAction(action);
|
||||||
|
action.setActions(actionList);
|
||||||
|
action.setPerformActionOnButtonClick(performActionOnButtonClick);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a {@link List} of {@link DockingActionIf} to provide to the {@link MultiActionDockingAction}
|
||||||
|
* @param list a {@link List} of {@link DockingActionIf} to provide to the {@link MultiActionDockingAction}
|
||||||
|
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||||
|
*/
|
||||||
|
public MultiActionBuilder withActions(List<DockingActionIf> list) {
|
||||||
|
this.actionList = list;
|
||||||
|
for (DockingActionIf action : actionList) {
|
||||||
|
if (action.getMenuBarData() == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"actions in the actionList must have MenuBarData defined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure whether to perform actions on a button click.
|
||||||
|
* See {@link MultiActionDockingAction#setPerformActionOnButtonClick(boolean)}
|
||||||
|
*
|
||||||
|
* @param b true if the main action is invokable
|
||||||
|
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||||
|
*/
|
||||||
|
public MultiActionBuilder performActionOnButtonClick(boolean b) {
|
||||||
|
this.performActionOnButtonClick = b;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validate() {
|
||||||
|
super.validate();
|
||||||
|
if (actionList == null) {
|
||||||
|
throw new IllegalStateException("No ActionList has been set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/* ###
|
||||||
|
* 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.action.builder;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.menu.*;
|
||||||
|
import docking.widgets.EventTrigger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link MultiStateDockingAction}
|
||||||
|
*
|
||||||
|
* @param <T> The action state type
|
||||||
|
*/
|
||||||
|
public class MultiStateActionBuilder<T> extends
|
||||||
|
AbstractActionBuilder<MultiStateDockingAction<T>, MultiStateActionBuilder<T>> {
|
||||||
|
|
||||||
|
private BiConsumer<ActionState<T>, EventTrigger> actionStateChangedCallback;
|
||||||
|
private boolean performActionOnButtonClick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder constructor
|
||||||
|
* @param name the name of the action to be built
|
||||||
|
* @param owner the owner of the action to be build
|
||||||
|
*/
|
||||||
|
public MultiStateActionBuilder(String name, String owner) {
|
||||||
|
super(name, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MultiStateActionBuilder<T> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the primary callback to be executed when this action changes its action state.
|
||||||
|
* This builder will throw an {@link IllegalStateException} if one of the build methods is
|
||||||
|
* called without providing this callback
|
||||||
|
*
|
||||||
|
* @param biConsumer the callback to execute when the selected action state is changed.
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public MultiStateActionBuilder<T> onActionStateChanged(
|
||||||
|
BiConsumer<ActionState<T>, EventTrigger> biConsumer) {
|
||||||
|
|
||||||
|
actionStateChangedCallback = biConsumer;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure whether to perform actions on a button click.
|
||||||
|
* See {@link MultiActionDockingAction#setPerformActionOnButtonClick(boolean)}
|
||||||
|
*
|
||||||
|
* @param b true if the main action is invokable
|
||||||
|
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||||
|
*/
|
||||||
|
public MultiStateActionBuilder<T> performActionOnButtonClick(boolean b) {
|
||||||
|
this.performActionOnButtonClick = b;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultiStateDockingAction<T> build() {
|
||||||
|
validate();
|
||||||
|
MultiStateDockingAction<T> action =
|
||||||
|
new MultiStateDockingAction<T>(name, owner, isToolbarAction()) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionStateChanged(ActionState<T> newActionState,
|
||||||
|
EventTrigger trigger) {
|
||||||
|
actionStateChangedCallback.accept(newActionState, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionPerformed(ActionContext context) {
|
||||||
|
if (actionCallback != null) {
|
||||||
|
actionCallback.accept(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
decorateAction(action);
|
||||||
|
action.setPerformActionOnPrimaryButtonClick(performActionOnButtonClick);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validate() {
|
||||||
|
if (performActionOnButtonClick) {
|
||||||
|
super.validate(); // require an action callback has been defined
|
||||||
|
}
|
||||||
|
if (actionStateChangedCallback == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Can't build a MultiStateDockingAction without an action state changed callback");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* ###
|
||||||
|
* 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.action.builder;
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.action.ToggleDockingAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link ToggleDockingAction}s
|
||||||
|
*/
|
||||||
|
public class ToggleActionBuilder extends
|
||||||
|
AbstractActionBuilder<ToggleDockingAction, ToggleActionBuilder> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial toggle state for the action
|
||||||
|
*/
|
||||||
|
private boolean select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder constructor
|
||||||
|
* @param name the name of the action to be built
|
||||||
|
* @param owner the owner of the action to be build
|
||||||
|
*/
|
||||||
|
public ToggleActionBuilder(String name, String owner) {
|
||||||
|
super(name, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ToggleActionBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ToggleDockingAction build() {
|
||||||
|
validate();
|
||||||
|
ToggleDockingAction action =
|
||||||
|
new ToggleDockingAction(name, owner, keyBindingType) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionContext context) {
|
||||||
|
actionCallback.accept(context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
decorateAction(action);
|
||||||
|
action.setSelected(select);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the initial select state for the toggle action.
|
||||||
|
* @param b the initial select state
|
||||||
|
*
|
||||||
|
* @return self Builder (for chaining)
|
||||||
|
*/
|
||||||
|
public ToggleActionBuilder selected(boolean b) {
|
||||||
|
this.select = b;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue