mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-2581: Allow dynamic listing and memory view to follow the adress of a watch.
This commit is contained in:
parent
dc76aa811e
commit
958afa58cc
60 changed files with 1632 additions and 552 deletions
|
@ -18,6 +18,7 @@ package docking.action.builder;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
|
@ -26,7 +27,7 @@ import docking.menu.ActionState;
|
|||
import docking.menu.MultiStateDockingAction;
|
||||
import docking.widgets.EventTrigger;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Builder for {@link MultiStateDockingAction}
|
||||
*
|
||||
* @param <T> The action state type
|
||||
|
@ -38,9 +39,11 @@ public class MultiStateActionBuilder<T> extends
|
|||
private boolean useCheckboxForIcons;
|
||||
|
||||
private List<ActionState<T>> states = new ArrayList<>();
|
||||
private Supplier<List<ActionState<T>>> generator = null;
|
||||
|
||||
/**
|
||||
* Builder constructor
|
||||
*
|
||||
* @param name the name of the action to be built
|
||||
* @param owner the owner of the action to be build
|
||||
*/
|
||||
|
@ -55,8 +58,10 @@ public class MultiStateActionBuilder<T> extends
|
|||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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)
|
||||
|
@ -69,10 +74,12 @@ public class MultiStateActionBuilder<T> extends
|
|||
}
|
||||
|
||||
/**
|
||||
* Overrides the default icons for actions shown in popup menu of the multi-state action. By
|
||||
* default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
||||
* By passing true to this method, icons will not be used in the popup menu. Instead, a
|
||||
* checkbox icon will be used to show the active action state.
|
||||
* Overrides the default icons for actions shown in popup menu of the multi-state action.
|
||||
*
|
||||
* <p>
|
||||
* By default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
||||
* By passing true to this method, icons will not be used in the popup menu. Instead, a checkbox
|
||||
* icon will be used to show the active action state.
|
||||
*
|
||||
* @param b true to use a checkbox
|
||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||
|
@ -83,7 +90,7 @@ public class MultiStateActionBuilder<T> extends
|
|||
}
|
||||
|
||||
/**
|
||||
* Add an action state
|
||||
* Add an action state
|
||||
*
|
||||
* @param displayName the name to appear in the action menu
|
||||
* @param icon the icon to appear in the action menu
|
||||
|
@ -96,7 +103,7 @@ public class MultiStateActionBuilder<T> extends
|
|||
}
|
||||
|
||||
/**
|
||||
* Add an action state
|
||||
* Add an action state
|
||||
*
|
||||
* @param actionState the action state to add
|
||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||
|
@ -107,7 +114,7 @@ public class MultiStateActionBuilder<T> extends
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a list of action states
|
||||
* Add a list of action states
|
||||
*
|
||||
* @param list a list of ActionStates;
|
||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||
|
@ -117,6 +124,21 @@ public class MultiStateActionBuilder<T> extends
|
|||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the states dynamically upon the user clicking the button
|
||||
*
|
||||
* <p>
|
||||
* It is highly recommended that the current state is included in the list of available states.
|
||||
* Otherwise, the user could become confused or frustrated.
|
||||
*
|
||||
* @param generator a function from action context to available states
|
||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||
*/
|
||||
public MultiStateActionBuilder<T> stateGenerator(Supplier<List<ActionState<T>>> generator) {
|
||||
this.generator = generator;
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiStateDockingAction<T> build() {
|
||||
validate();
|
||||
|
@ -138,6 +160,16 @@ public class MultiStateActionBuilder<T> extends
|
|||
super.actionPerformed(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ActionState<T>> getStates() {
|
||||
if (generator == null) {
|
||||
return super.getStates();
|
||||
}
|
||||
else {
|
||||
return generator.get();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (ActionState<T> actionState : states) {
|
||||
|
|
|
@ -15,15 +15,17 @@
|
|||
*/
|
||||
package docking.menu;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.SystemUtilities;
|
||||
|
||||
/**
|
||||
* Note: this class overrides the <code>equals(Object)</code> and relies upon the <code>equals</code>
|
||||
* method of the <code>userData</code> object. Thus, if it is important that equals work for you in
|
||||
* the non-standard identity way, then you must override <code>equals</code> in your user data objects.
|
||||
* Note: this class overrides the <code>equals(Object)</code> and relies upon the
|
||||
* <code>equals</code> method of the <code>userData</code> object. Thus, if it is important that
|
||||
* equals work for you in the non-standard identity way, then you must override <code>equals</code>
|
||||
* in your user data objects.
|
||||
*
|
||||
* @param <T> the type of the action state
|
||||
*/
|
||||
|
@ -73,7 +75,7 @@ public class ActionState<T> {
|
|||
|
||||
ActionState<?> otherState = (ActionState<?>) other;
|
||||
|
||||
if (!SystemUtilities.isEqual(userData, otherState.userData)) {
|
||||
if (!Objects.equals(userData, otherState.userData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,14 +31,18 @@ import help.Help;
|
|||
import resources.icons.EmptyIcon;
|
||||
|
||||
/**
|
||||
* An action that can be in one of multiple states. The button of this action has a
|
||||
* drop-down icon that allows users to change the state of the button. As the user changes the
|
||||
* state of this action, {@link #actionStateChanged(ActionState, EventTrigger)} will be called.
|
||||
* Clients may also use the button of this action to respond to button presses by overriding
|
||||
* An action that can be in one of multiple states.
|
||||
*
|
||||
* <p>
|
||||
* The button of this action has a drop-down icon that allows users to change the state of the
|
||||
* button. As the user changes the state of this action,
|
||||
* {@link #actionStateChanged(ActionState, EventTrigger)} will be called. Clients may also use the
|
||||
* button of this action to respond to button presses by overriding
|
||||
* {@link #actionPerformed(ActionContext)}.
|
||||
*
|
||||
* <p>This action is intended primarily for use as toolbar actions. Alternatively, some clients
|
||||
* use this action to add a button to custom widgets. In the custom usage case, clients should use
|
||||
* <p>
|
||||
* This action is intended primarily for use as toolbar actions. Alternatively, some clients use
|
||||
* this action to add a button to custom widgets. In the custom use case, clients should use
|
||||
* {@link NonToolbarMultiStateAction}.
|
||||
*
|
||||
* @param <T> the type of the user data
|
||||
|
@ -49,7 +53,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
private static Icon EMPTY_ICON = new EmptyIcon(16, 16);
|
||||
|
||||
private List<ActionState<T>> actionStates = new ArrayList<>();
|
||||
private int currentStateIndex = -1;
|
||||
private ActionState<T> currentState = null;
|
||||
private MultiActionDockingActionIf multiActionGenerator;
|
||||
private MultipleActionDockingToolbarButton multipleButton;
|
||||
|
||||
|
@ -57,11 +61,10 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
private boolean useCheckboxForIcons;
|
||||
|
||||
/**
|
||||
* Call this constructor with this action will not be added to a toolbar
|
||||
* Constructor
|
||||
*
|
||||
* @param name the action name
|
||||
* @param owner the owner
|
||||
* @see #MultiStateDockingAction(String, String, boolean)
|
||||
*/
|
||||
public MultiStateDockingAction(String name, String owner) {
|
||||
super(name, owner);
|
||||
|
@ -71,22 +74,9 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
super.setToolBarData(new ToolBarData(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this constructor explicitly when this action is used in a toolbar, passing true
|
||||
* for <code>isToolbarAction</code> (see the javadoc header note).
|
||||
*
|
||||
* @param name the action name
|
||||
* @param owner the owner
|
||||
* @param isToolbarAction true if this action is a toolbar action
|
||||
* @deprecated use {@link #MultiStateDockingAction(String, String)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "10.2")
|
||||
protected MultiStateDockingAction(String name, String owner, boolean isToolbarAction) {
|
||||
this(name, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called as the user changes the selected button state
|
||||
*
|
||||
* @param newActionState the newly selected state
|
||||
* @param trigger the source of the event
|
||||
*/
|
||||
|
@ -94,11 +84,12 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
|
||||
/**
|
||||
* This method is called when the user clicks the button <B>when this action is used as part of
|
||||
* the default {@link DockingAction} framework.</B>
|
||||
* the default {@link DockingAction} framework.</B>
|
||||
*
|
||||
* This is the callback to be overridden when the child wishes to respond to user button
|
||||
* presses that are on the button and not the drop-down. The default behavior is to show the
|
||||
* popup menu when the button is clicked.
|
||||
* <p>
|
||||
* This is the callback to be overridden when the child wishes to respond to user button presses
|
||||
* that are on the button and not the drop-down. The default behavior is to show the popup menu
|
||||
* when the button is clicked.
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
|
@ -106,10 +97,12 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
}
|
||||
|
||||
/**
|
||||
* Overrides the default icons for actions shown in popup menu of the multi-state action. By
|
||||
* default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
||||
* By passing true to this method, icons will not be used in the popup menu. Instead, a
|
||||
* checkbox icon will be used to show the active action state.
|
||||
* Overrides the default icons for actions shown in popup menu of the multi-state action.
|
||||
*
|
||||
* <p>
|
||||
* By default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
||||
* By passing true to this method, icons will not be used in the popup menu. Instead, a checkbox
|
||||
* icon will be used to show the active action state.
|
||||
*
|
||||
* @param useCheckboxForIcons true to use a checkbox
|
||||
*/
|
||||
|
@ -118,9 +111,11 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the icon to use if the active action state does not supply an icon. This is useful if
|
||||
* you wish for your action states to not use icon, but desire the action itself to have an
|
||||
* icon.
|
||||
* Sets the icon to use if the active action state does not supply an icon.
|
||||
*
|
||||
* <p>
|
||||
* This is useful if you wish for your action states to not use icon, but desire the action
|
||||
* itself to have an icon.
|
||||
*
|
||||
* @param icon the icon
|
||||
*/
|
||||
|
@ -128,18 +123,38 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
this.defaultIcon = icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point: Get the states to display when the button is clicked
|
||||
*
|
||||
* <p>
|
||||
* This is called when the button is clicked, immediately before the menu is displayed. It is
|
||||
* generally recommended to ensure the current state is included in this list. The states will
|
||||
* be displayed in the order of the returned list.
|
||||
*
|
||||
* @return the list of possible states
|
||||
*/
|
||||
protected List<ActionState<T>> getStates() {
|
||||
return actionStates;
|
||||
}
|
||||
|
||||
private void updateStates() {
|
||||
List<ActionState<T>> newStates = getStates();
|
||||
if (newStates.equals(actionStates)) {
|
||||
return;
|
||||
}
|
||||
actionStates.clear();
|
||||
actionStates.addAll(newStates);
|
||||
}
|
||||
|
||||
protected List<DockingActionIf> getStateActions() {
|
||||
ActionState<T> selectedState = actionStates.get(currentStateIndex);
|
||||
updateStates();
|
||||
List<DockingActionIf> actions = new ArrayList<>(actionStates.size());
|
||||
for (ActionState<T> actionState : actionStates) {
|
||||
|
||||
//@formatter:off
|
||||
boolean isSelected = actionState == selectedState;
|
||||
DockingActionIf a = useCheckboxForIcons ?
|
||||
new ActionStateToggleAction(actionState, isSelected) :
|
||||
new ActionStateAction(actionState, isSelected);
|
||||
boolean isSelected = actionState.equals(currentState);
|
||||
DockingActionIf a = useCheckboxForIcons
|
||||
? new ActionStateToggleAction(actionState, isSelected)
|
||||
: new ActionStateAction(actionState, isSelected);
|
||||
actions.add(a);
|
||||
//@formatter:on
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
@ -155,8 +170,8 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
}
|
||||
|
||||
/**
|
||||
* add the supplied {@code ActionState}
|
||||
* if {@code fireFirstEvent} is {@code true} the first one will fire its event
|
||||
* Add the supplied {@code ActionState}.
|
||||
*
|
||||
* @param actionState the {@code ActionState} to add
|
||||
*/
|
||||
public void addActionState(ActionState<T> actionState) {
|
||||
|
@ -175,11 +190,11 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
}
|
||||
|
||||
public T getCurrentUserData() {
|
||||
return actionStates.get(currentStateIndex).getUserData();
|
||||
return currentState == null ? null : currentState.getUserData();
|
||||
}
|
||||
|
||||
public ActionState<T> getCurrentState() {
|
||||
return actionStates.get(currentStateIndex);
|
||||
return currentState;
|
||||
}
|
||||
|
||||
public List<ActionState<T>> getAllActionStates() {
|
||||
|
@ -187,6 +202,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
}
|
||||
|
||||
public void setCurrentActionStateByUserData(T t) {
|
||||
updateStates();
|
||||
for (ActionState<T> actionState : actionStates) {
|
||||
|
||||
// Note: most clients will pass a T that is already in our list. However, to be more
|
||||
|
@ -194,7 +210,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
// problem using equals() here.
|
||||
// if (actionState.getUserData() == t) {
|
||||
if (actionState.getUserData().equals(t)) {
|
||||
setCurrentActionState(actionState);
|
||||
doSetCurrentActionState(actionState, EventTrigger.API_CALL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -208,13 +224,16 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
}
|
||||
|
||||
public void setCurrentActionStateWithTrigger(ActionState<T> actionState, EventTrigger trigger) {
|
||||
int indexOf = actionStates.indexOf(actionState);
|
||||
if (indexOf < 0) {
|
||||
updateStates();
|
||||
doSetCurrentActionState(actionState, trigger);
|
||||
}
|
||||
|
||||
protected void doSetCurrentActionState(ActionState<T> actionState, EventTrigger trigger) {
|
||||
if (!actionStates.contains(actionState)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Attempted to set actionState to unknown ActionState.");
|
||||
}
|
||||
currentStateIndex = indexOf;
|
||||
|
||||
currentState = actionState;
|
||||
setButtonState(actionState);
|
||||
|
||||
ToolBarData tbd = getToolBarData();
|
||||
|
@ -240,9 +259,8 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
@Override
|
||||
public JButton doCreateButton() {
|
||||
multipleButton = new MultipleActionDockingToolbarButton(multiActionGenerator);
|
||||
if (currentStateIndex >= 0) {
|
||||
ActionState<T> actionState = actionStates.get(currentStateIndex);
|
||||
setButtonState(actionState);
|
||||
if (currentState != null) {
|
||||
setButtonState(currentState);
|
||||
}
|
||||
|
||||
return multipleButton;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue