diff --git a/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/Browser_Field_Formatter.htm b/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/Browser_Field_Formatter.htm
index 2a73c57dd8..1dc739a1da 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/Browser_Field_Formatter.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/Browser_Field_Formatter.htm
@@ -191,6 +191,13 @@
Reset the formats for all categories to their default settings by right clicking on the
Browser Field Formatter and select Reset All Formats on the popup.
+
+ Quick Toggle Actions
+
+ Some fields have quick toggle actions that allow the field to be easily toggled on or
+ off. Currently, the only field with a quick toggle action is the PCode field and it has a
+ default keybinding is <CTRL SHIFT 1>.
+
Custom Formats
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java
index c3397beb21..ffc4d1ca5a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java
@@ -437,10 +437,7 @@ public abstract class AbstractCodeBrowserPlugin ex
else if (optionName.equals(MOUSE_WHEEL_HORIZONTAL_SCROLLING_OPTIONS_NAME)) {
fieldPanel.setHorizontalScrollingEnabled((Boolean) newValue);
}
-
- connectedProvider.fieldOptionChanged(optionName, newValue);
}
-
}
@Override
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java
index 1189d21ea9..b87ded62cb 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java
@@ -20,8 +20,7 @@ import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.util.*;
import javax.swing.Icon;
@@ -31,6 +30,7 @@ import javax.swing.event.ChangeListener;
import docking.*;
import docking.action.*;
+import docking.action.builder.ActionBuilder;
import docking.actions.PopupActionProvider;
import docking.dnd.*;
import docking.widgets.EventTrigger;
@@ -62,8 +62,7 @@ import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.Memory;
import ghidra.program.util.*;
-import ghidra.util.HelpLocation;
-import ghidra.util.Swing;
+import ghidra.util.*;
public class CodeViewerProvider extends NavigatableComponentProviderAdapter
implements ProgramLocationListener, ProgramSelectionListener, Draggable, Droppable,
@@ -471,21 +470,37 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
action = new GotoNextFunctionAction(tool, plugin.getName());
tool.addAction(action);
+ buildQuickTogleFieldActions();
+
}
- void fieldOptionChanged(String fieldName, Object newValue) {
- //TODO if (name.startsWith(OPERAND_OPTIONS_PREFIX) && (newValue instanceof Boolean)) {
- // for (int i = 0; i < toggleOperandMarkupActions.length; i++) {
- // ToggleOperandMarkupAction action = toggleOperandMarkupActions[i];
- // if (name.equals(action.getOptionName())) {
- // boolean newState = ((Boolean)newValue).booleanValue();
- // if (action.isSelected() != newState) {
- // action.setSelected(newState);
- // }
- // break;
- // }
- // }
- // }
+ private void buildQuickTogleFieldActions() {
+ List quickToggleFieldNames = formatMgr.getQuickToggleFieldNames();
+ int count = 0;
+ for (String fieldName : quickToggleFieldNames) {
+ DockingAction toggleAction = new ActionBuilder("Toggle " + fieldName, plugin.getName())
+ .popupMenuPath("Toggle Field", fieldName)
+ .popupMenuGroup("Field", "" + count)
+ .helpLocation(new HelpLocation("CodeBrowserPlugin", "Toggle_Field"))
+ // only show this action when over the listing field header
+ .popupWhen(c -> c.getContextObject() instanceof FieldHeaderLocation)
+ .onAction(c -> formatMgr.toggleField(fieldName))
+ .buildAndInstallLocal(this);
+
+ // automatically assign keybindings to the first 5 toggle fields.
+ if (count < 5) {
+ char c = (char) ('1' + count);
+ toggleAction.setKeyBindingData(
+ new KeyBindingData(c, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
+ }
+ else {
+ Msg.debug(this,
+ "Excessive Field Toggle actions . No keybinding assigned for field: " +
+ fieldName);
+ }
+ count++;
+ }
+ tool.setMenuGroup(new String[] { "Toggle Field" }, "Disassembly");
}
public ListingPanel getListingPanel() {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java
index de294807f8..5a9161c6ce 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java
@@ -32,6 +32,7 @@ import ghidra.program.model.data.Array;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.*;
import ghidra.program.model.scalar.Scalar;
+import ghidra.util.Msg;
import ghidra.util.classfinder.*;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
@@ -252,6 +253,25 @@ public class FormatManager implements OptionsChangeListener {
return models[FieldFormatModel.OPEN_DATA];
}
+ /**
+ * Toggle the enablement for the field with the given name.
+ * @param name the of the field to toggle
+ */
+ public void toggleField(String name) {
+ for (FieldFormatModel model : models) {
+ for (int i = 0; i < model.getNumRows(); i++) {
+ FieldFactory[] rowFactories = model.getFactorys(i);
+ for (FieldFactory fieldFactory : rowFactories) {
+ if (fieldFactory.getFieldName().equals(name)) {
+ fieldFactory.setEnabled(!fieldFactory.isEnabled());
+ return;
+ }
+ }
+ }
+ }
+ Msg.showError(this, null, "Toggle Field Failed!", "No field named \"" + name + "\"");
+ }
+
private boolean isPrimitiveArrayElement(Data data) {
Data parent = data.getParent();
if (parent == null) {
@@ -331,6 +351,13 @@ public class FormatManager implements OptionsChangeListener {
return maxRowCount;
}
+ /**
+ * {@return a list of field names that should have quick toggle actions.}
+ */
+ public List getQuickToggleFieldNames() {
+ return List.of("PCode");
+ }
+
private Element getDefaultModel(int modelID) {
switch (modelID) {
case FieldFormatModel.DIVIDER: