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: