diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java index d9da46b293..fd3bc48b18 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java @@ -52,7 +52,14 @@ import utilities.util.reflection.ReflectionUtilities; * method is used to determine if an action if applicable to the current context. Overriding this * method allows actions to manage their own enablement. Otherwise, the default behavior for this * method is to return the current enabled property of the action. This allows for the possibility - * for plugins to manage the enablement of its actions. + * for plugins to externally manage the enablement of its actions. + *

+ * NOTE: If you wish to do your own external enablement management for an action (which is highly + * discouraged), it is very important that you don't use any of the internal enablement mechanisms + * by setting the predicates {@link #enabledWhen(Predicate)}, {@link #validContextWhen(Predicate)} + * or overriding {@link #isValidContext(ActionContext)}. These predicates and methods trigger + * internal enablement management which will interfere with you own calls to + * {@link DockingAction#setEnabled(boolean)}. */ public abstract class DockingAction implements DockingActionIf { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java index c9eae2d655..5c4f49ffec 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java @@ -516,7 +516,8 @@ public abstract class AbstractActionBuilderIf this predicate is not set, the action's enable state must be controlled * directly using the {@link DockingAction#setEnabled(boolean)} method. We do not recommend - * controlling enablement directly. + * controlling enablement directly. And, of course, if you do set this predicate, you should + * not later call {@link DockingAction#setEnabled(boolean)} to manually manage enablement. * * @param predicate the predicate that will be used to dynamically determine an action's * enabled state @@ -556,6 +557,9 @@ public abstract class AbstractActionBuilderNote: most actions will not use this method, but rely instead on * {@link #enabledWhen(Predicate)}. + * + *

Note: this triggers automatic action enablement so you should not later call + * {@link DockingAction#setEnabled(boolean)} to manually manage action enablement. * * @param predicate the predicate that will be used to dynamically determine an action's * validity for a given {@link ActionContext} @@ -563,6 +567,13 @@ public abstract class AbstractActionBuilder predicate) { validContextPredicate = Objects.requireNonNull(predicate); + + // automatic enablement management triggered, make sure there is a existing enablement + // predicate. The default behavior of manual management interferes with automatic management. + if (enabledPredicate == null) { + enabledPredicate = ALWAYS_TRUE; + } + return self(); } @@ -614,6 +625,10 @@ public abstract class AbstractActionBuilder return context.isAwesome() }} * * + *

Note: this triggers automatic action enablement so you should not later call + * {@link DockingAction#setEnabled(boolean)} to manually manage action enablement. + * + * @param newActionContextClass the more specific ActionContext type. * @param The new ActionContext type (as determined by the newActionContextClass) that * the returned builder will have. @@ -629,6 +644,12 @@ public abstract class AbstractActionBuilder