mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GP-773_ghidravore_graph_visualization_options--SQUASHED'
This commit is contained in:
commit
69e8119211
84 changed files with 4102 additions and 1822 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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)");
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue