Merge remote-tracking branch 'origin/GP-773_ghidravore_graph_visualization_options--SQUASHED'

This commit is contained in:
Ryan Kurtz 2021-08-09 14:13:19 -04:00
commit 69e8119211
84 changed files with 4102 additions and 1822 deletions

View file

@ -15,6 +15,8 @@
*/
package ghidra.app.plugin.core.datamgr.actions;
import java.awt.Color;
import ghidra.app.util.ToolTipUtils;
import ghidra.program.model.data.*;
import ghidra.service.graph.*;
@ -35,9 +37,8 @@ public class TypeGraphTask extends Task {
private String graphTitle;
private GraphDisplayProvider graphService;
public static final String TYPE_ATTRIBUTE = "Type";
public static final String EMBEDDED = "Composite";
public static final String POINTER = "Reference";
public static final String COMPOSITE = "Composite";
public static final String REFERENCE = "Reference";
/*
* Constructor
@ -57,8 +58,18 @@ public class TypeGraphTask extends Task {
@Override
public void run(TaskMonitor monitor) throws CancelledException {
GraphType graphType = new GraphTypeBuilder("Data Graph")
.edgeType(REFERENCE)
.edgeType(COMPOSITE)
.build();
AttributedGraph graph = new AttributedGraph();
GraphDisplayOptions options = new GraphDisplayOptionsBuilder(graphType)
.defaultVertexColor(Color.BLUE)
.edge(COMPOSITE, Color.MAGENTA)
.edge(REFERENCE, Color.BLUE)
.build();
AttributedGraph graph = new AttributedGraph(graphTitle, graphType);
try {
if (type instanceof Pointer) {
recursePointer((Pointer) type, graph, null, monitor);
@ -75,7 +86,7 @@ public class TypeGraphTask extends Task {
GraphDisplay display;
try {
display = graphService.getGraphDisplay(false, monitor);
display.setGraph(graph, graphTitle, false, monitor);
display.setGraph(graph, options, graphTitle, false, monitor);
}
catch (GraphException e) {
Msg.showError(this, null, "Data Type Graph Error",
@ -94,11 +105,8 @@ public class TypeGraphTask extends Task {
}
else {
AttributedEdge edge = graph.addEdge(lastVertex, newVertex);
if (edgeType == POINTER) {
edge.setAttribute("Color", "Blue");
}
edge.setAttribute(TYPE_ATTRIBUTE, edgeType);
if (edge.hasAttribute("Weight")) {
edge.setEdgeType(edgeType);
if (edge.hasAttribute(AttributedGraph.WEIGHT)) {
//did this already, don't cycle
return;
}
@ -115,7 +123,7 @@ public class TypeGraphTask extends Task {
recursePointer((Pointer) dt, graph, newVertex, monitor);
}
else if (dt instanceof Composite) {
recurseComposite((Composite) dt, graph, newVertex, EMBEDDED, monitor);
recurseComposite((Composite) dt, graph, newVertex, COMPOSITE, monitor);
}
}
}
@ -135,7 +143,7 @@ public class TypeGraphTask extends Task {
recursePointer((Pointer) ptrType, graph, lastVertex, monitor);
}
else if (ptrType instanceof Composite) {
recurseComposite((Composite) ptrType, graph, lastVertex, POINTER, monitor);
recurseComposite((Composite) ptrType, graph, lastVertex, REFERENCE, monitor);
}
}

View file

@ -148,10 +148,11 @@ public class GraphDisplayBrokerPlugin extends Plugin
}
@Override
public GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, Map<String, String> properties,
TaskMonitor monitor) throws GraphException {
public GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, TaskMonitor monitor)
throws GraphException {
if (defaultGraphDisplayProvider != null) {
return defaultGraphDisplayProvider.getGraphDisplay(reuseGraph, properties, monitor);
return defaultGraphDisplayProvider.getGraphDisplay(reuseGraph, monitor);
}
return null;
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.services;
import java.util.*;
import java.util.List;
import ghidra.app.plugin.core.graph.GraphDisplayBrokerListener;
import ghidra.app.plugin.core.graph.GraphDisplayBrokerPlugin;
@ -60,25 +60,7 @@ public interface GraphDisplayBroker {
* @return a {@link GraphDisplay} object to sends graphs to be displayed or exported.
* @throws GraphException thrown if an error occurs trying to get a graph display
*/
public default GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, TaskMonitor monitor)
throws GraphException {
return getDefaultGraphDisplay(reuseGraph, Collections.emptyMap(), monitor);
}
/**
* A convenience method for getting a {@link GraphDisplay} from the currently active provider
*
* <p>This method allows users to override default graph properties for the graph provider
* being created. See the graph provider implementation for a list of supported properties
*
* @param reuseGraph if true, the provider will attempt to re-use a current graph display
* @param properties a {@code Map} of property key/values that can be used to customize the display
* @param monitor the {@link TaskMonitor} that can be used to cancel the operation
* @return a {@link GraphDisplay} object to sends graphs to be displayed or exported.
* @throws GraphException thrown if an error occurs trying to get a graph display
*/
public GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, Map<String, String> properties,
TaskMonitor monitor)
public GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, TaskMonitor monitor)
throws GraphException;
/**

View file

@ -0,0 +1,24 @@
/* ###
* IP: GHIDRA
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.graph;
public class BlockFlowGraphType extends ProgramGraphType {
public BlockFlowGraphType() {
super("Block Flow Graph", "Shows program basic block flow");
}
}

View file

@ -0,0 +1,24 @@
/* ###
* IP: GHIDRA
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.graph;
public class CallGraphType extends ProgramGraphType {
public CallGraphType() {
super("Call Graph", "Shows relationships between functions");
}
}

View file

@ -0,0 +1,25 @@
/* ###
* IP: GHIDRA
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.graph;
public class CodeFlowGraphType extends ProgramGraphType {
public CodeFlowGraphType() {
super("Code Flow Graph",
"Shows code block flow (similar to Block Flow graph type, but shows the code in each veretx)");
}
}

View file

@ -0,0 +1,24 @@
/* ###
* IP: GHIDRA
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.graph;
public class DataFlowGraphType extends ProgramGraphType {
public DataFlowGraphType() {
super("Data Flow Graph", "Shows program data relationships");
}
}

View file

@ -0,0 +1,98 @@
/* ###
* IP: GHIDRA
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.graph;
import static ghidra.graph.ProgramGraphType.*;
import static ghidra.service.graph.VertexShape.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.service.graph.GraphDisplayOptions;
import ghidra.service.graph.VertexShape;
import ghidra.util.WebColors;
/**
* {@link GraphDisplayOptions} for {@link ProgramGraphType}
*/
public class ProgramGraphDisplayOptions extends GraphDisplayOptions {
/**
* constructor
* @param graphType the specific ProgramGraphType subclass for these options
* @param tool if non-null, will load values from tool options
*/
public ProgramGraphDisplayOptions(ProgramGraphType graphType, PluginTool tool) {
super(graphType, tool);
}
@Override
protected void initializeDefaults() {
setDefaultVertexShape(ELLIPSE);
setDefaultVertexColor(WebColors.RED);
setDefaultEdgeColor(WebColors.RED);
setFavoredEdgeType(FALL_THROUGH);
configureVertexType(BODY, RECTANGLE, WebColors.BLUE);
configureVertexType(ENTRY, TRIANGLE_DOWN, WebColors.DARK_ORANGE);
configureVertexType(EXIT, TRIANGLE_UP, WebColors.DARK_MAGENTA);
configureVertexType(SWITCH, DIAMOND, WebColors.DARK_CYAN);
configureVertexType(EXTERNAL, RECTANGLE, WebColors.DARK_GREEN);
configureVertexType(BAD, ELLIPSE, WebColors.RED);
configureVertexType(DATA, ELLIPSE, WebColors.PINK);
configureVertexType(ENTRY_NEXUS, ELLIPSE, WebColors.WHEAT);
configureVertexType(INSTRUCTION, VertexShape.HEXAGON, WebColors.BLUE);
configureVertexType(STACK, RECTANGLE, WebColors.GREEN);
configureEdgeType(ENTRY_EDGE, WebColors.GRAY);
configureEdgeType(FALL_THROUGH, WebColors.BLUE);
configureEdgeType(UNCONDITIONAL_JUMP, WebColors.DARK_GREEN);
configureEdgeType(UNCONDITIONAL_CALL, WebColors.DARK_ORANGE);
configureEdgeType(TERMINATOR, WebColors.PURPLE);
configureEdgeType(JUMP_TERMINATOR, WebColors.PURPLE);
configureEdgeType(INDIRECTION, WebColors.PINK);
configureEdgeType(CONDITIONAL_JUMP, WebColors.DARK_GOLDENROD);
configureEdgeType(CONDITIONAL_CALL, WebColors.DARK_ORANGE);
configureEdgeType(CONDITIONAL_TERMINATOR, WebColors.PURPLE);
configureEdgeType(CONDITIONAL_CALL_TERMINATOR, WebColors.PURPLE);
configureEdgeType(COMPUTED_JUMP, WebColors.CYAN);
configureEdgeType(COMPUTED_CALL, WebColors.CYAN);
configureEdgeType(COMPUTED_CALL_TERMINATOR, WebColors.PURPLE);
configureEdgeType(CONDITIONAL_COMPUTED_CALL, WebColors.CYAN);
configureEdgeType(CONDITIONAL_COMPUTED_JUMP, WebColors.CYAN);
configureEdgeType(CALL_OVERRIDE_UNCONDITIONAL, WebColors.RED);
configureEdgeType(JUMP_OVERRIDE_UNCONDITIONAL, WebColors.RED);
configureEdgeType(CALLOTHER_OVERRIDE_CALL, WebColors.RED);
configureEdgeType(CALLOTHER_OVERRIDE_JUMP, WebColors.RED);
configureEdgeType(READ, WebColors.GREEN);
configureEdgeType(WRITE, WebColors.RED);
configureEdgeType(READ_WRITE, WebColors.DARK_GOLDENROD);
configureEdgeType(UNKNOWN_DATA, WebColors.BLACK);
configureEdgeType(EXTERNAL_REF, WebColors.PURPLE);
configureEdgeType(READ_INDIRECT, WebColors.DARK_GREEN);
configureEdgeType(WRITE_INDIRECT, WebColors.DARK_RED);
configureEdgeType(READ_WRITE_INDIRECT, WebColors.BROWN);
configureEdgeType(DATA_INDIRECT, WebColors.DARK_ORANGE);
configureEdgeType(PARAM, WebColors.CYAN);
configureEdgeType(THUNK, WebColors.BLUE);
}
}

View file

@ -0,0 +1,126 @@
/* ###
* IP: GHIDRA
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.graph;
import java.util.*;
import org.apache.commons.text.WordUtils;
import ghidra.program.model.symbol.RefType;
import ghidra.service.graph.GraphType;
/**
* Defines a common set of vertex and edge types {@link GraphType} for program code and data flow
* graphs. Each specific type of program graph will use a subclass to specifically identify the
* graph type.
*/
public abstract class ProgramGraphType extends GraphType {
private static Map<RefType, String> refTypeToEdgeTypeMap = new HashMap<>();
private static List<String> vertexTypes = new ArrayList<>();
private static List<String> edgeTypes = new ArrayList<>();
//@formatter:off
// Vertex Types
public static final String BODY = vertex("Body");
public static final String ENTRY = vertex("Entry");
public static final String EXIT = vertex("Exit");
public static final String SWITCH = vertex("Switch");
public static final String EXTERNAL = vertex("External");
public static final String BAD = vertex("Bad");
public static final String INSTRUCTION = vertex("Instruction");
public static final String DATA = vertex("Data");
public static final String ENTRY_NEXUS = vertex("Entry-Nexus");
public static final String STACK = vertex("Stack");
// Edge Types - Flow
public static final String ENTRY_EDGE = edge("Entry"); // This edge if for adding an "Entry Nexus" Vertex
public static final String FALL_THROUGH = edge(map(RefType.FALL_THROUGH));
public static final String UNCONDITIONAL_JUMP = edge(map(RefType.UNCONDITIONAL_JUMP));
public static final String UNCONDITIONAL_CALL = edge(map(RefType.UNCONDITIONAL_CALL));
public static final String TERMINATOR = edge(map(RefType.TERMINATOR));
public static final String JUMP_TERMINATOR = edge(map(RefType.JUMP_TERMINATOR));
public static final String INDIRECTION = edge(map(RefType.INDIRECTION));
public static final String CONDITIONAL_JUMP = edge(map(RefType.CONDITIONAL_JUMP));
public static final String CONDITIONAL_CALL = edge(map(RefType.CONDITIONAL_CALL));
public static final String CONDITIONAL_TERMINATOR = edge(map(RefType.CONDITIONAL_TERMINATOR));
public static final String CONDITIONAL_CALL_TERMINATOR =edge(map(RefType.CONDITIONAL_CALL_TERMINATOR));
public static final String COMPUTED_JUMP = edge(map(RefType.COMPUTED_JUMP));
public static final String COMPUTED_CALL = edge(map(RefType.COMPUTED_CALL));
public static final String COMPUTED_CALL_TERMINATOR = edge(map(RefType.COMPUTED_CALL_TERMINATOR));
public static final String CONDITIONAL_COMPUTED_CALL = edge(map(RefType.CONDITIONAL_COMPUTED_CALL));
public static final String CONDITIONAL_COMPUTED_JUMP =edge(map(RefType.CONDITIONAL_COMPUTED_JUMP));
public static final String CALL_OVERRIDE_UNCONDITIONAL = edge(map(RefType.CALL_OVERRIDE_UNCONDITIONAL));
public static final String JUMP_OVERRIDE_UNCONDITIONAL = edge(map(RefType.CALL_OVERRIDE_UNCONDITIONAL));
public static final String CALLOTHER_OVERRIDE_CALL = edge(map(RefType.CALL_OVERRIDE_UNCONDITIONAL));
public static final String CALLOTHER_OVERRIDE_JUMP = edge(map(RefType.CALL_OVERRIDE_UNCONDITIONAL));
// Edge Types Data Refs
public static final String READ = edge(map(RefType.READ));
public static final String WRITE = edge(map(RefType.WRITE));
public static final String READ_WRITE = edge(map(RefType.READ_WRITE));
public static final String UNKNOWN_DATA = edge(map(RefType.DATA));
public static final String EXTERNAL_REF = edge(map(RefType.EXTERNAL_REF));
public static final String READ_INDIRECT = edge(map(RefType.READ_IND));
public static final String WRITE_INDIRECT = edge(map(RefType.WRITE_IND));
public static final String READ_WRITE_INDIRECT = edge(map(RefType.READ_WRITE_IND));
public static final String DATA_INDIRECT = edge(map(RefType.DATA_IND));
public static final String PARAM = edge(map(RefType.PARAM));
public static final String THUNK = edge(map(RefType.THUNK));
//@formatter:on
protected ProgramGraphType(String name, String description) {
super(name, description, vertexTypes, edgeTypes);
}
private static String vertex(String vertexType) {
vertexTypes.add(vertexType);
return vertexType;
}
private static String edge(String edgeType) {
edgeTypes.add(edgeType);
return edgeType;
}
private static String map(RefType refType) {
String edgeTypeName = fixup(refType.getName());
refTypeToEdgeTypeMap.put(refType, edgeTypeName);
return edgeTypeName;
}
private static String fixup(String name) {
name = name.replace('_', ' ');
return WordUtils.capitalizeFully(name);
}
public static String getEdgeType(RefType refType) {
return refTypeToEdgeTypeMap.get(refType);
}
@Override
public String getOptionsName() {
return "Program Graph Display Options";
}
}

View file

@ -161,11 +161,12 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
// get the options panel
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(consoleNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertNotNull(comp);
assertTrue(comp.isShowing());
String optionName = (String) getInstanceField("MAXIMUM_CHARACTERS_OPTION_NAME", textPane);
final Component component = findPairedComponent(simpleOptionsPanel, optionName);
final Component component = findPairedComponent(comp, optionName);
assertNotNull(component);
// click the option to toggle its state
@ -245,7 +246,8 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor editor = (ScrollableOptionsEditor) getEditorPanel(parentNode);
assertNotNull("Did not find options editor for name: " + simpleName, editor);
assertNotNull("simpleName = " + simpleName, findPairedComponent(editor, simpleName));
assertNotNull("simpleName = " + simpleName,
findPairedComponent(editor.getComponent(), simpleName));
}
}
@ -274,7 +276,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
}
ScrollableOptionsEditor p = (ScrollableOptionsEditor) getEditorPanel(parent);
assertNotNull(p);
assertNotNull(findPairedComponent(p, simpleName));
assertNotNull(findPairedComponent(p.getComponent(), simpleName));
}
}
@ -332,9 +334,10 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(toolNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertTrue(comp.isShowing());
Component component = findPairedComponent(simpleOptionsPanel, "Favorite Color");
Component component = findPairedComponent(comp, "Favorite Color");
assertNotNull(component);
Rectangle rect = component.getBounds();
clickMouse(component, 1, rect.x, rect.y, 2, 0);
@ -367,10 +370,11 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(buttonNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertTrue(comp.isShowing());
PropertySelector ps =
(PropertySelector) findPairedComponent(simpleOptionsPanel, "Mouse Button To Activate");
(PropertySelector) findPairedComponent(comp, "Mouse Button To Activate");
assertNotNull(ps);
runSwing(() -> ps.setSelectedIndex(0));
assertEquals("LEFT", ps.getSelectedItem());
@ -514,10 +518,12 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(buttonNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertTrue(comp.isShowing());
PropertySelector ps =
(PropertySelector) findPairedComponent(simpleOptionsPanel, "Mouse Button To Activate");
(PropertySelector) findPairedComponent(comp, "Mouse Button To Activate");
// change to "LEFT"
runSwing(() -> ps.setSelectedIndex(0));
@ -546,11 +552,13 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(buttonNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertTrue(comp.isShowing());
PropertySelector ps =
(PropertySelector) findPairedComponent(simpleOptionsPanel, "Mouse Button To Activate");
(PropertySelector) findPairedComponent(comp, "Mouse Button To Activate");
// change to "LEFT"
runSwing(() -> ps.setSelectedIndex(0));
@ -593,15 +601,17 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor p = (ScrollableOptionsEditor) getEditorPanel(testNode);
assertNotNull(p);
assertTrue(p.isShowing());
JComponent comp = p.getComponent();
JTextField field = (JTextField) findPairedComponent(p, "String Value 1");
assertTrue(comp.isShowing());
JTextField field = (JTextField) findPairedComponent(comp, "String Value 1");
assertNotNull(field);
field = (JTextField) findPairedComponent(p, "String Value 2");
field = (JTextField) findPairedComponent(comp, "String Value 2");
assertNotNull(field);
field = (JTextField) findPairedComponent(p, "String Value 3");
field = (JTextField) findPairedComponent(comp, "String Value 3");
assertNotNull(field);
field = (JTextField) findPairedComponent(p, "Int Value");
field = (JTextField) findPairedComponent(comp, "Int Value");
assertNotNull(field);
}
@ -615,9 +625,10 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(toolNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertTrue(comp.isShowing());
Component component = findPairedComponent(simpleOptionsPanel, "Favorite Color");
Component component = findPairedComponent(comp, "Favorite Color");
assertNotNull(component);
Rectangle rect = component.getBounds();
clickMouse(component, 1, rect.x, rect.y, 2, 0);
@ -660,9 +671,10 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor simpleOptionsPanel =
(ScrollableOptionsEditor) getEditorPanel(toolNode);
assertNotNull(simpleOptionsPanel);
assertTrue(simpleOptionsPanel.isShowing());
JComponent comp = simpleOptionsPanel.getComponent();
assertTrue(comp.isShowing());
Component canvas = findPairedComponent(simpleOptionsPanel, "Favorite Color");
Component canvas = findPairedComponent(comp, "Favorite Color");
assertNotNull(canvas);
Rectangle rect = canvas.getBounds();
clickMouse(canvas, 1, rect.x, rect.y, 2, 0);
@ -847,7 +859,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
}
private void pressBrowseButton(ScrollableOptionsEditor editor, String optionName) {
Component comp = findPairedComponent(editor, optionName);
Component comp = findPairedComponent(editor.getComponent(), optionName);
assertNotNull(comp);
AbstractButton button = findAbstractButtonByName((Container) comp, "BrowseButton");
assertNotNull(button);
@ -857,7 +869,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
}
private JTextField getEditorTextField(ScrollableOptionsEditor editor, String optionName) {
Component comp = findPairedComponent(editor, optionName);
Component comp = findPairedComponent(editor.getComponent(), optionName);
assertNotNull(comp);
JTextField tf = findComponent((Container) comp, JTextField.class);
@ -878,7 +890,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor editor = (ScrollableOptionsEditor) getEditorPanel(toolNode);
assertNotNull(editor);
assertTrue(editor.isShowing());
assertTrue(editor.getComponent().isShowing());
return editor;
}
@ -906,7 +918,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor editor =
selectSubNodeWithDefaultEditor(parentNodeName, childNodeName);
JCheckBox checkBox = (JCheckBox) findPairedComponent(editor, optionName);
JCheckBox checkBox = (JCheckBox) findPairedComponent(editor.getComponent(), optionName);
return checkBox.isSelected();
}
@ -915,7 +927,8 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor editor =
selectSubNodeWithDefaultEditor(parentNodeName, childNodeName);
final JCheckBox checkBox = (JCheckBox) findPairedComponent(editor, optionName);
final JCheckBox checkBox =
(JCheckBox) findPairedComponent(editor.getComponent(), optionName);
runSwing(() -> checkBox.setSelected(newValue));
assertEquals(newValue, checkBox.isSelected());
}
@ -924,7 +937,8 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
throws Exception {
ScrollableOptionsEditor editor = selectNodeWithDefaultEditor(parentNodeName);
JTextField textField = (JTextField) findPairedComponent(editor, childNodeName);
JTextField textField =
(JTextField) findPairedComponent(editor.getComponent(), childNodeName);
return getText(textField);
}
@ -932,7 +946,8 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
String newValue) throws Exception {
ScrollableOptionsEditor editor = selectNodeWithDefaultEditor(parentNodeName);
JTextField textField = (JTextField) findPairedComponent(editor, childNodeName);
JTextField textField =
(JTextField) findPairedComponent(editor.getComponent(), childNodeName);
setText(textField, newValue);
String updatedText = getText(textField);
@ -953,7 +968,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor editor = (ScrollableOptionsEditor) getEditorPanel(node);
assertNotNull(editor);
assertTrue(editor.isShowing());
assertTrue(editor.getComponent().isShowing());
return editor;
}
@ -976,7 +991,7 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest {
ScrollableOptionsEditor editor = (ScrollableOptionsEditor) getEditorPanel(childNode);
assertNotNull(editor);
assertTrue(editor.isShowing());
assertTrue(editor.getComponent().isShowing());
return editor;
}