diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/ShowInstructionInfo.htm b/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/ShowInstructionInfo.htm index df002a6ff5..715c12a5c4 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/ShowInstructionInfo.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/ShowInstructionInfo.htm @@ -115,7 +115,7 @@ (Mnemonic, Number of Operands, Address, Flow Type, Delay Slot Depth, Prototype Hash, Input Objects, Result Objects, Constructor line numbers, Instruction Bytes, etc.).
-The Operand columns (Op1, Op2, etc.) display information about a particular +
The Operand columns (Op0, Op1, etc.) display information about a particular operand. Each operand has a number of rows. At the end of the row is a descriptive name for the information displayed on that row.
@@ -197,13 +197,13 @@
-The Dynamic Update checkbox indicates whether the window should update when you - change the location in the Code Browser. By default, the checkbox is selected. As you - change your location - in the Code Browser, the window will be updated to show the info for the new - location. If you turn off the checkbox, the window does not update; the next time you - choose Instruction Info, a new tab is displayed in the Instruction Info - window.
+The
Dynamic Update toggle indicates whether the + window should update when you change the location in the Code Browser. By default, the + toggle is selected. As you change your + location in the Code + Browser, the window will be updated to show the info for the new location. If you turn + off the toggle, the window does not update; the next time you choose Instruction + Info, a new tab is displayed in the Instruction Info window.
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/images/ShowInstructionInfo.png b/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/images/ShowInstructionInfo.png index cff081a85d..bf2aabfba9 100644 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/images/ShowInstructionInfo.png and b/Ghidra/Features/Base/src/main/help/help/topics/ShowInstructionInfoPlugin/images/ShowInstructionInfo.png differ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java index 58c1761f2f..7aa3d2cec1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.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. @@ -15,12 +15,14 @@ */ package ghidra.app.plugin.core.processors; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import javax.swing.*; import javax.swing.table.DefaultTableModel; -import docking.widgets.checkbox.GCheckBox; +import docking.action.ToggleDockingAction; +import docking.action.builder.ToggleActionBuilder; import generic.theme.Gui; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger.SleighDebugMode; @@ -33,6 +35,7 @@ import ghidra.program.model.listing.*; import ghidra.program.util.InstructionUtils; import ghidra.util.HelpLocation; import ghidra.util.table.GhidraTable; +import resources.Icons; /** * Component provider to show the instruction info. @@ -48,7 +51,7 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain private JTextArea instructionText; private JTable opTable; - private JCheckBox dynamicUpdateCB; + private ToggleDockingAction dynamicUpdateAction; private OperandModel operandModel; private Address myAddr; @@ -57,10 +60,11 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain super(plugin.getTool(), "Instruction Info", plugin.getName()); this.plugin = plugin; - buildMainPanel(isDynamic); + buildMainPanel(); setTransient(); setWindowMenuGroup("Instruction Info"); addToTool(); + createActions(isDynamic); } @Override @@ -73,13 +77,23 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain return new HelpLocation(plugin.getName(), "Show_Instruction_Info_Window"); } + private void createActions(boolean isDynamic) { + dynamicUpdateAction = new ToggleActionBuilder("Dynamic Update", plugin.getName()) + .toolBarIcon(Icons.NAVIGATE_ON_INCOMING_EVENT_ICON) + .description("Update this panel with navigation") + .onAction(ctx -> dynamicStateChanged()) + .selected(isDynamic) + .buildAndInstallLocal(this); + dynamicStateChanged(); + } + boolean dynamicUpdateSelected() { - return dynamicUpdateCB.isSelected(); + return dynamicUpdateAction.isSelected(); } /** - * Set the status text on this dialog. - */ + * Set the status text on this dialog. + */ void setStatusText(String msg) { tool.setStatusInfo(msg); } @@ -101,7 +115,7 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain * * @return JPanel the completed
Main Panel
*/
- protected JPanel buildMainPanel(boolean isDynamic) {
+ protected JPanel buildMainPanel() {
mainPanel = new JPanel(new BorderLayout());
@@ -120,11 +134,6 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
pane.setResizeWeight(.25);
mainPanel.add(pane, BorderLayout.CENTER);
- dynamicUpdateCB = new GCheckBox("Dynamic Update", isDynamic);
- dynamicUpdateCB.setAlignmentX(Component.CENTER_ALIGNMENT);
- dynamicUpdateCB.addItemListener(e -> dynamicStateChanged());
-
- mainPanel.add(dynamicUpdateCB, BorderLayout.SOUTH);
mainPanel.validate();
return mainPanel;
@@ -194,8 +203,9 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
setAddress(myAddr);
}
- public void setNonDynamic() {
- dynamicUpdateCB.setSelected(false);
+ public void setDynamic(boolean dynamic) {
+ dynamicUpdateAction.setSelected(dynamic);
+ dynamicStateChanged();
}
public Program getProgram() {
@@ -225,6 +235,7 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
/**
* Returns the number of columns in this data table.
+ *
* @return the number of columns in the model
*/
@Override
@@ -234,10 +245,10 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
/**
* Returns the column name.
- * @return a name for this column using the string value of the
- * appropriate member in columnIdentfiers. If columnIdentfiers
- * is null or does not have and entry for this index return the default
- * name provided by the superclass.
+ *
+ * @return a name for this column using the string value of the appropriate member in
+ * columnIdentfiers. If columnIdentfiers is null or does not have and
+ * entry for this index return the default name provided by the superclass.
*/
@Override
public String getColumnName(int column) {
@@ -249,6 +260,7 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
/**
* Returns the number of rows in this data table.
+ *
* @return the number of rows in the model
*/
@Override
@@ -257,14 +269,12 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
}
/**
- * Returns an attribute value for the cell at row
- * and column.
+ * Returns an attribute value for the cell at row and column.
*
- * @param row the row whose value is to be looked up
- * @param column the column whose value is to be looked up
- * @return the value Object at the specified cell
- * @exception ArrayIndexOutOfBoundsException if an invalid row or
- * column was given.
+ * @param row the row whose value is to be looked up
+ * @param column the column whose value is to be looked up
+ * @return the value Object at the specified cell
+ * @exception ArrayIndexOutOfBoundsException if an invalid row or column was given.
*/
@Override
public Object getValueAt(int row, int column) {
@@ -272,56 +282,39 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain
return null;
}
if (column == 0) {
- switch (row) {
- case 0:
- return "Operand";
- case 1:
- return "Labeled";
- case 2:
- return "Type";
- case 3:
- return "Scalar";
- case 4:
- return "Address";
- case 5:
- return "Register";
- case 6:
- return "Op-Objects";
- case 7:
- return "Operand Mask";
- case 8:
- return "Masked Value";
- }
+ return switch (row) {
+ case 0 -> "Operand";
+ case 1 -> "Labeled";
+ case 2 -> "Type";
+ case 3 -> "Scalar";
+ case 4 -> "Address";
+ case 5 -> "Register";
+ case 6 -> "Op-Objects";
+ case 7 -> "Operand Mask";
+ case 8 -> "Masked Value";
+ default -> "";
+ };
}
int opIndex = column - 1;
if (opIndex >= instruction.getNumOperands()) {
return "";
}
- switch (row) {
- case 0:
- return instruction.getDefaultOperandRepresentation(opIndex);
- case 1:
- return CodeUnitFormat.DEFAULT.getOperandRepresentationList(instruction,
- opIndex);
- case 2:
- return OperandType.toString(instruction.getOperandType(opIndex));
- case 3:
- return instruction.getScalar(opIndex);
- case 4:
+ return switch (row) {
+ case 0 -> instruction.getDefaultOperandRepresentation(opIndex);
+ case 1 -> CodeUnitFormat.DEFAULT.getOperandRepresentationList(instruction, opIndex);
+ case 2 -> OperandType.toString(instruction.getOperandType(opIndex));
+ case 3 -> instruction.getScalar(opIndex);
+ case 4 -> {
Address addr = instruction.getAddress(opIndex);
- return addr != null ? addr.toString(true) : "";
- case 5:
- return instruction.getRegister(opIndex);
- case 6:
- return getString(
- InstructionUtils.getFormatedOperandObjects(instruction, opIndex));
- case 7:
- return debug != null ? debug.getFormattedInstructionMask(opIndex) : null;
- case 8:
- return debug != null ? debug.getFormattedMaskedValue(opIndex) : null;
- }
-
- return "";
+ yield addr != null ? addr.toString(true) : "";
+ }
+ case 5 -> instruction.getRegister(opIndex);
+ case 6 -> getString(
+ InstructionUtils.getFormatedOperandObjects(instruction, opIndex));
+ case 7 -> debug != null ? debug.getFormattedInstructionMask(opIndex) : null;
+ case 8 -> debug != null ? debug.getFormattedMaskedValue(opIndex) : null;
+ default -> "";
+ };
}
@Override
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPlugin.java
index 353fe1b2a2..9bcf2649c0 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPlugin.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.
@@ -344,8 +344,8 @@ public class ShowInstructionInfoPlugin extends ProgramPlugin {
}
/**
- * Subclass should override this method if it is interested in
- * program location events.
+ * Subclass should override this method if it is interested in program location events.
+ *
* @param loc location could be null
*/
@Override
@@ -463,7 +463,7 @@ public class ShowInstructionInfoPlugin extends ProgramPlugin {
}
else if (provider != connectedProvider && isDynamic) {
if (connectedProvider != null) {
- connectedProvider.setNonDynamic();
+ connectedProvider.setDynamic(false);
}
disconnectedProviders.remove(provider);
connectedProvider = provider;
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPluginTest.java
index 4e046c79f7..559e29f2d7 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPluginTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/processors/ShowInstructionInfoPluginTest.java
@@ -22,7 +22,8 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.swing.*;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
import org.junit.*;
@@ -150,6 +151,7 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
DockingActionIf infoAction = getAction(plugin, "Show Instruction Info");
// show the window
performAction(infoAction, cb.getProvider(), true);
+ InstructionInfoProvider provider = waitForComponentProvider(InstructionInfoProvider.class);
// make sure we are at an invalid Instruction
ListingActionContext context = getCurrentContext();
@@ -176,14 +178,8 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
componentProviderTablesHaveData());
// verify dynamic update has changed the window's contents
- ComponentProvider componentProvider = getCurrentComponentProviderFromPlugin();
- JComponent comp = componentProvider.getComponent();
-
- final JCheckBox dynamicCheckBox = findComponent(comp, JCheckBox.class);
// make sure dynamic update is enabled
- if (!dynamicCheckBox.isSelected()) {
- runSwing(() -> dynamicCheckBox.doClick());
- }
+ runSwing(() -> provider.setDynamic(true));
// change to another valid Instruction
currentInstruction = changeLocationToAddress("01000006");
@@ -200,7 +196,7 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
verifyAddressWithTableModels(currentInstruction.getMinAddress(), true, true);
// turn off dynamic update
- runSwing(() -> dynamicCheckBox.doClick());
+ runSwing(() -> provider.setDynamic(false));
// change to another valid Instruction
currentInstruction = changeLocationToAddress("01000009");
@@ -223,7 +219,7 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
// place
// turn dynamic update back on
- runSwing(() -> dynamicCheckBox.doClick());
+ runSwing(() -> provider.setDynamic(true));
// move to a valid location that has yet to be disassembled
currentInstruction = changeLocationToAddress("01000ffe");
@@ -269,13 +265,9 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
DockingActionIf infoAction = getAction(plugin, "Show Instruction Info");
// show the window
performAction(infoAction, cb.getProvider(), true);
+ InstructionInfoProvider provider = waitForComponentProvider(InstructionInfoProvider.class);
- ComponentProvider componentProvider = getCurrentComponentProviderFromPlugin();
- JComponent comp = componentProvider.getComponent();
-
- final JCheckBox dynamicCheckBox = findComponent(comp, JCheckBox.class);
- // turn off the checkbox
- runSwing(() -> dynamicCheckBox.setSelected(false));
+ runSwing(() -> provider.setDynamic(false));
changeLocationToAddress("01000006");
performAction(infoAction, cb.getProvider(), true);
@@ -352,7 +344,7 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
private void callGetUrl(ListingActionContext context, Language language) {
runSwing(() -> {
-
+
try {
plugin.getValidUrl(context, language);
}
@@ -363,12 +355,10 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
}
/**
- * Moves the program location to the given address and returns the
- * instruction at that location.
+ * Moves the program location to the given address and returns the instruction at that location.
*
* @param addressString The address location to move to.
- * @return The instruction at the new location or null if there is no
- * instruction.
+ * @return The instruction at the new location or null if there is no instruction.
*/
private Instruction changeLocationToAddress(String addressString) throws Exception {
CodeBrowserPlugin cbp = env.getPlugin(CodeBrowserPlugin.class);
@@ -395,18 +385,15 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
}
/**
- * Tests the addresses of the table models of the "Instruction Info" dialog.
- * The method will fail the current test if the result is not as
- * expected by the caller of this method. For example, if
- * {@code expectedSame} is true, then the method expects the values to
- * be the same when compared with the given address and will fail if
- * they are not. If {@code expectedSame} is false, then the method will
- * fail if the test values are the same.
+ * Tests the addresses of the table models of the "Instruction Info" dialog. The method will
+ * fail the current test if the result is not as expected by the caller of this method. For
+ * example, if {@code expectedSame} is true, then the method expects the values to be the same
+ * when compared with the given address and will fail if they are not. If {@code expectedSame}
+ * is false, then the method will fail if the test values are the same.
*
- * @param instructionAddress The address to compare against the address
- * stored in the table model of the dialog.
- * @param expectedSame True means a match is expected; false means a
- * match is not expected.
+ * @param instructionAddress The address to compare against the address stored in the table
+ * model of the dialog.
+ * @param expectedSame True means a match is expected; false means a match is not expected.
*/
private void verifyAddressWithTableModels(Address instructionAddress, boolean fromConnected,
boolean expectedSame) {
@@ -447,8 +434,7 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
}
/**
- * A simple method to test that the tables of the "Instruction Info"
- * dialog contain data.
+ * A simple method to test that the tables of the "Instruction Info" dialog contain data.
*
* @return True if either of the tables have data.
*/
@@ -459,9 +445,9 @@ public class ShowInstructionInfoPluginTest extends AbstractGhidraHeadedIntegrati
}
/**
- * Gets data from the two tables of the "Instruction Info" dialog.
+ * Gets data from the two tables of the "Instruction Info" dialog.
*
- * @return data from the two tables of the "Instruction Info" dialog.
+ * @return data from the two tables of the "Instruction Info" dialog.
*/
private Object[] getComponentProviderTableData(boolean fromConnected) {
ComponentProvider provider = fromConnected ? getCurrentComponentProviderFromPlugin()
diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java
index ed26a0326e..db468bf58a 100644
--- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java
+++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.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.
@@ -112,7 +112,9 @@ public class ShowInstructionInfoPluginScreenShots extends GhidraScreenShotGenera
performAction("Show Instruction Info", plugin.getName(), true);
- captureProviderWindow("Instruction Info", 1200, 500);
+ ComponentProvider provider =
+ tool.getWindowManager().getComponentProvider("Instruction Info");
+ captureIsolatedProvider(provider, 1200, 510);
// finished("ShowInstructionInfoPlugin", "ShowInstructionInfo.png");
}