From c5422e1606d2430ac7fac2d3c617cf5c1b1c23d6 Mon Sep 17 00:00:00 2001 From: ghidragon <106987263+ghidragon@users.noreply.github.com> Date: Mon, 15 Sep 2025 14:05:42 -0400 Subject: [PATCH] GP-1 fixed bugs related to the new toggle variables feature --- .../core/codebrowser/CodeViewerProvider.java | 21 ++++++++-------- .../actions/CollapseAllDataAction.java | 7 +++--- .../actions/ExpandAllDataAction.java | 11 +++++---- .../ToggleExpandCollapseDataAction.java | 3 ++- .../util/viewer/format/FieldFormatModel.java | 24 ++++++++++++------- .../app/util/viewer/format/FormatManager.java | 24 +++++++++++++++++++ 6 files changed, 62 insertions(+), 28 deletions(-) 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 351d1c2c29..0bce2b4696 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 @@ -481,22 +481,23 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter action = new GotoNextFunctionAction(tool, plugin.getName()); tool.addAction(action); - toggleVariablesAction = new ToggleActionBuilder("Show Function Variables", plugin.getName()) - .popupMenuPath("Show/Hide All Variables") - .popupMenuGroup("Variables") - .helpLocation(new HelpLocation("CodeBrowserPlugin", "Show_All_Variables")) - .selected(true) - .withContext(ProgramLocationActionContext.class) - .enabledWhen(this::isInFunctionArea) - .onAction(c -> showVariablesForAllFunctions(toggleVariablesAction.isSelected())) - .buildAndInstallLocal(this); + toggleVariablesAction = + new ToggleActionBuilder("Show All Function Variables", plugin.getName()) + .popupMenuPath("Function", "Show/Hide All Variables") + .popupMenuGroup("Variables") + .helpLocation(new HelpLocation("CodeBrowserPlugin", "Show_All_Variables")) + .selected(true) + .withContext(ProgramLocationActionContext.class) + .onAction(c -> showVariablesForAllFunctions(toggleVariablesAction.isSelected())) + .buildAndInstallLocal(this); new ActionBuilder("Toggle Show Function Variables", plugin.getName()) - .popupMenuPath("Show/Hide Variables") + .popupMenuPath("Function", "Show/Hide Variables") .popupMenuGroup("Variables") .helpLocation(new HelpLocation("CodeBrowserPlugin", "Show_Variables")) .keyBinding("SPACE") .withContext(ProgramLocationActionContext.class) + .validWhen(this::isInFunctionArea) .enabledWhen(this::isInFunctionArea) .onAction(c -> toggleShowVariables(c.getAddress())) .buildAndInstallLocal(this); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CollapseAllDataAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CollapseAllDataAction.java index b9e6e82b17..576cc27a87 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CollapseAllDataAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CollapseAllDataAction.java @@ -4,9 +4,9 @@ * 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. @@ -42,7 +42,8 @@ public class CollapseAllDataAction extends ProgramLocationContextAction { super("Collapse All Data", provider.getOwner()); this.provider = provider; - setPopupMenuData(new MenuData(new String[] { "Collapse All Data" }, null, "Structure")); + setPopupMenuData( + new MenuData(new String[] { "Data", "Collapse All Data" }, null, "BasicData2")); setHelpLocation(new HelpLocation("CodeBrowserPlugin", "ExpandCollapseActions")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java index 284292031d..b56a3d7a7f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java @@ -4,9 +4,9 @@ * 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. @@ -39,7 +39,8 @@ public class ExpandAllDataAction extends ProgramLocationContextAction { super("Expand All Data", provider.getOwner()); this.provider = provider; - setPopupMenuData(new MenuData(new String[] { "Expand All Data" }, null, "Structure")); + setPopupMenuData( + new MenuData(new String[] { "Data", "Expand All Data" }, null, "BasicData2")); setDescription("Open all data recursively from the current location downward."); setHelpLocation(new HelpLocation("CodeBrowserPlugin", "ExpandCollapseActions")); @@ -83,11 +84,11 @@ public class ExpandAllDataAction extends ProgramLocationContextAction { private void updatePopupMenuName(boolean hasSelection) { if (hasSelection) { - getPopupMenuData().setMenuPath(new String[] { "Expand All Data In Selection" }); + getPopupMenuData().setMenuPath(new String[] { "Data", "Expand All Data In Selection" }); setDescription("Open all data recursively in the current selection."); } else { - getPopupMenuData().setMenuPath(new String[] { "Expand All Data" }); + getPopupMenuData().setMenuPath(new String[] { "Data", "Expand All Data" }); setDescription("Open all data recursively from the current location downward."); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ToggleExpandCollapseDataAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ToggleExpandCollapseDataAction.java index c4c90b39e9..dfc4cad780 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ToggleExpandCollapseDataAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ToggleExpandCollapseDataAction.java @@ -42,7 +42,8 @@ public class ToggleExpandCollapseDataAction extends ProgramLocationContextAction this.provider = provider; setPopupMenuData( - new MenuData(new String[] { "Toggle Expand/Collapse Data" }, null, "Structure")); + new MenuData(new String[] { "Data", "Toggle Expand/Collapse Data" }, null, + "BasicData2")); setKeyBindingData(new KeyBindingData(' ', 0)); setHelpLocation(new HelpLocation("CodeBrowserPlugin", "ExpandCollapseActions")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java index fef9b401ac..dfcc9d3f8d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java @@ -4,9 +4,9 @@ * 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. @@ -83,7 +83,7 @@ public class FieldFormatModel { } /** - * Returns the formatMgr that is managing this model. + * {@return the FormatManager managing this format.} */ public FormatManager getFormatManager() { return formatMgr; @@ -109,6 +109,7 @@ public class FieldFormatModel { /** * Adds new empty row at the given position. The position must be in the * interval [0,numRows]. + * @param index the index to add a new row * @exception IllegalArgumentException thrown if the position is outside the * interval [0,numRows]. */ @@ -186,21 +187,23 @@ public class FieldFormatModel { } /** - * Returns the number of rows in the model. + * {@return the number of rows in this format} */ public int getNumRows() { return rows.size(); } /** - * Returns the name of this format model. + * {@return the name of this format model.} */ public String getName() { return name; } /** - * Returns the number of FieldFactorys on any given row. + * Returns the number of factories on the given row. + * @param row the row to get the number of factories for + * @return the number of factories on the given row */ public int getNumFactorys(int row) { if ((row < 0) || (row >= rows.size())) { @@ -210,14 +213,16 @@ public class FieldFormatModel { } /** - * Returns the FieldFactorys on a given row. + * Returns the factories on the given row. + * @param row the row to factories for + * @return the FieldFactorys for a given row */ public FieldFactory[] getFactorys(int row) { return (rows.get(row)).getFactorys(); } /** - * Returns the list factories valid for this format. + * {@return the list of factories used in this format.} */ public FieldFactory[] getFactorys() { return factories.clone(); @@ -251,7 +256,7 @@ public class FieldFormatModel { } /** - * Returns the width of this model + * {@return the width of this format.} */ public int getWidth() { return width; @@ -280,6 +285,7 @@ public class FieldFormatModel { /** * Saves this format to XML. + * @return the XML element for the saved format */ public Element saveToXml() { Element root = new Element("FORMAT"); 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 dcc2ea52c9..73bc310f82 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 @@ -959,6 +959,9 @@ public class FormatManager implements OptionsChangeListener { for (int i = 0; i < NUM_MODELS; i++) { if (saveState.hasValue(models[i].getName())) { models[i].restoreFromXml(saveState.getXmlElement(models[i].getName())); + // hack to make sure the new open/close variables field is present + // If missing, we are just going to reset it to the default format + checkForMissingOpenCloseField(models[i]); } else { models[i].restoreFromXml(getDefaultModel(i)); @@ -968,6 +971,27 @@ public class FormatManager implements OptionsChangeListener { modelChanged(null); } + // This is a hack to make sure the new variables open/close field is present. + // This was added in version 12.0 and can probably be removed in a few releases. + private void checkForMissingOpenCloseField(FieldFormatModel model) { + if (!model.getName().equals("Variable")) { + return; + } + if (!hasField(model, "+")) { + model.restoreFromXml(getDefaultVariableFormat()); + } + } + + private boolean hasField(FieldFormatModel model, String fieldName) { + FieldFactory[] unusedFactories = model.getUnusedFactories(); + for (FieldFactory fieldFactory : unusedFactories) { + if (fieldFactory.getFieldName().equals("+")) { + return false; + } + } + return true; + } + public ServiceProvider getServiceProvider() { return serviceProvider; }