mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Changed graph api to use vertex and edge object instead of ids.
This commit is contained in:
parent
3cd26120a3
commit
592b8a3cfc
14 changed files with 292 additions and 283 deletions
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.graph;
|
package ghidra.app.plugin.core.graph;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
|
@ -29,8 +28,7 @@ import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.*;
|
||||||
import ghidra.service.graph.GraphDisplay;
|
import ghidra.service.graph.*;
|
||||||
import ghidra.service.graph.GraphDisplayListener;
|
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +38,7 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
implements GraphDisplayListener, PluginEventListener, DomainObjectListener {
|
implements GraphDisplayListener, PluginEventListener, DomainObjectListener {
|
||||||
|
|
||||||
protected PluginTool tool;
|
protected PluginTool tool;
|
||||||
private GraphDisplay graphDisplay;
|
protected GraphDisplay graphDisplay;
|
||||||
protected Program program;
|
protected Program program;
|
||||||
private SymbolTable symbolTable;
|
private SymbolTable symbolTable;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -63,8 +61,8 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void locationFocusChanged(String vertexId) {
|
public void locationFocusChanged(AttributedVertex vertex) {
|
||||||
Address address = getAddressForVertexId(vertexId);
|
Address address = getAddress(vertex);
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
ProgramLocation location = new ProgramLocation(program, address);
|
ProgramLocation location = new ProgramLocation(program, address);
|
||||||
tool.firePluginEvent(new ProgramLocationPluginEvent(name, location, program));
|
tool.firePluginEvent(new ProgramLocationPluginEvent(name, location, program));
|
||||||
|
@ -72,8 +70,8 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectionChanged(List<String> vertexIds) {
|
public void selectionChanged(Set<AttributedVertex> vertices) {
|
||||||
AddressSet addressSet = getAddressSetForVertices(vertexIds);
|
AddressSet addressSet = getAddresses(vertices);
|
||||||
if (addressSet != null) {
|
if (addressSet != null) {
|
||||||
ProgramSelection selection = new ProgramSelection(addressSet);
|
ProgramSelection selection = new ProgramSelection(addressSet);
|
||||||
ProgramSelectionPluginEvent event =
|
ProgramSelectionPluginEvent event =
|
||||||
|
@ -99,16 +97,16 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
ProgramLocationPluginEvent ev = (ProgramLocationPluginEvent) event;
|
ProgramLocationPluginEvent ev = (ProgramLocationPluginEvent) event;
|
||||||
if (isMyProgram(ev.getProgram())) {
|
if (isMyProgram(ev.getProgram())) {
|
||||||
ProgramLocation location = ev.getLocation();
|
ProgramLocation location = ev.getLocation();
|
||||||
String id = getVertexIdForAddress(location.getAddress());
|
AttributedVertex vertex = getVertex(location.getAddress());
|
||||||
// update graph location, but tell it not to send out event
|
// update graph location, but tell it not to send out event
|
||||||
graphDisplay.setLocationFocus(id, EventTrigger.INTERNAL_ONLY);
|
graphDisplay.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event instanceof ProgramSelectionPluginEvent) {
|
else if (event instanceof ProgramSelectionPluginEvent) {
|
||||||
ProgramSelectionPluginEvent ev = (ProgramSelectionPluginEvent) event;
|
ProgramSelectionPluginEvent ev = (ProgramSelectionPluginEvent) event;
|
||||||
if (isMyProgram(ev.getProgram())) {
|
if (isMyProgram(ev.getProgram())) {
|
||||||
ProgramSelection selection = ev.getSelection();
|
ProgramSelection selection = ev.getSelection();
|
||||||
List<String> selectedVertices = getVertices(selection);
|
Set<AttributedVertex> selectedVertices = getVertices(selection);
|
||||||
if (selectedVertices != null) {
|
if (selectedVertices != null) {
|
||||||
// since we are responding to an event, tell the GraphDisplay not to send event
|
// since we are responding to an event, tell the GraphDisplay not to send event
|
||||||
graphDisplay.selectVertices(selectedVertices, EventTrigger.INTERNAL_ONLY);
|
graphDisplay.selectVertices(selectedVertices, EventTrigger.INTERNAL_ONLY);
|
||||||
|
@ -117,7 +115,15 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getVertexIdForAddress(Address address) {
|
public AttributedVertex getVertex(Address address) {
|
||||||
|
if (address == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String id = getVertexId(address);
|
||||||
|
return graphDisplay.getGraph().getVertex(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getVertexId(Address address) {
|
||||||
// vertex ids for external locations use symbol names since they don't have meaningful addresses.
|
// vertex ids for external locations use symbol names since they don't have meaningful addresses.
|
||||||
if (address.isExternalAddress()) {
|
if (address.isExternalAddress()) {
|
||||||
Symbol s = symbolTable.getPrimarySymbol(address);
|
Symbol s = symbolTable.getPrimarySymbol(address);
|
||||||
|
@ -153,13 +159,16 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Address getAddressForVertexId(String vertexId) {
|
protected Address getAddress(AttributedVertex vertex) {
|
||||||
return getAddress(vertexId);
|
if (vertex == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getAddress(vertex.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract List<String> getVertices(AddressSetView selection);
|
protected abstract Set<AttributedVertex> getVertices(AddressSetView selection);
|
||||||
|
|
||||||
protected abstract AddressSet getAddressSetForVertices(List<String> vertexIds);
|
protected abstract AddressSet getAddresses(Set<AttributedVertex> vertexIds);
|
||||||
|
|
||||||
private boolean isMyProgram(Program p) {
|
private boolean isMyProgram(Program p) {
|
||||||
return p == program;
|
return p == program;
|
||||||
|
@ -192,15 +201,18 @@ public abstract class AddressBasedGraphDisplayListener
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSymbolAddedOrRenamed(Address address, Symbol symbol) {
|
private void handleSymbolAddedOrRenamed(Address address, Symbol symbol) {
|
||||||
String id = getVertexIdForAddress(address);
|
AttributedVertex vertex = getVertex(address);
|
||||||
graphDisplay.updateVertexName(id, symbol.getName());
|
graphDisplay.updateVertexName(vertex, symbol.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSymbolRemoved(Address address) {
|
private void handleSymbolRemoved(Address address) {
|
||||||
String id = getVertexIdForAddress(address);
|
AttributedVertex vertex = getVertex(address);
|
||||||
|
if (vertex == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Symbol symbol = program.getSymbolTable().getPrimarySymbol(address);
|
Symbol symbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||||
String displayName = symbol == null ? address.toString() : symbol.getName();
|
String displayName = symbol == null ? address.toString() : symbol.getName();
|
||||||
graphDisplay.updateVertexName(id, displayName);
|
graphDisplay.updateVertexName(vertex, displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispose() {
|
private void dispose() {
|
||||||
|
|
|
@ -232,16 +232,15 @@ public class GraphAST extends GhidraScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<String> getVertices(AddressSetView selection) {
|
protected Set<AttributedVertex> getVertices(AddressSetView selection) {
|
||||||
List<String> ids = new ArrayList<String>();
|
return Collections.emptySet();
|
||||||
return ids;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AddressSet getAddressSetForVertices(List<String> vertexIds) {
|
protected AddressSet getAddresses(Set<AttributedVertex> vertices) {
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
for (String id : vertexIds) {
|
for (AttributedVertex vertex : vertices) {
|
||||||
Address address = getAddressForVertexId(id);
|
Address address = getAddress(vertex);
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
set.add(address);
|
set.add(address);
|
||||||
}
|
}
|
||||||
|
@ -250,7 +249,11 @@ public class GraphAST extends GhidraScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Address getAddressForVertexId(String vertexId) {
|
protected Address getAddress(AttributedVertex vertex) {
|
||||||
|
if (vertex == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String vertexId = vertex.getId();
|
||||||
int firstcolon = vertexId.indexOf(':');
|
int firstcolon = vertexId.indexOf(':');
|
||||||
if (firstcolon == -1) {
|
if (firstcolon == -1) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -17,8 +17,7 @@ package ghidra.app.plugin.core.decompile.actions;
|
||||||
|
|
||||||
import static ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType.*;
|
import static ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType;
|
import ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType;
|
||||||
import ghidra.app.plugin.core.graph.AddressBasedGraphDisplayListener;
|
import ghidra.app.plugin.core.graph.AddressBasedGraphDisplayListener;
|
||||||
|
@ -26,8 +25,7 @@ import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.pcode.HighFunction;
|
import ghidra.program.model.pcode.HighFunction;
|
||||||
import ghidra.program.model.pcode.PcodeBlockBasic;
|
import ghidra.program.model.pcode.PcodeBlockBasic;
|
||||||
import ghidra.service.graph.GraphDisplay;
|
import ghidra.service.graph.*;
|
||||||
import ghidra.service.graph.GraphDisplayListener;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,33 +43,37 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<String> getVertices(AddressSetView selection) {
|
protected Set<AttributedVertex> getVertices(AddressSetView selection) {
|
||||||
if (graphType != CONTROL_FLOW_GRAPH) {
|
if (graphType != CONTROL_FLOW_GRAPH) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<String> vertices = new ArrayList<>();
|
Set<AttributedVertex> vertices = new HashSet<>();
|
||||||
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
||||||
for (PcodeBlockBasic block : blocks) {
|
for (PcodeBlockBasic block : blocks) {
|
||||||
Address start = block.getStart();
|
Address start = block.getStart();
|
||||||
Address stop = block.getStop();
|
Address stop = block.getStop();
|
||||||
if (selection.intersects(start, stop)) {
|
if (selection.intersects(start, stop)) {
|
||||||
vertices.add(Integer.toString(block.getIndex()));
|
String id = Integer.toString(block.getIndex());
|
||||||
|
AttributedVertex vertex = graphDisplay.getGraph().getVertex(id);
|
||||||
|
if (vertex != null) {
|
||||||
|
vertices.add(vertex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AddressSet getAddressSetForVertices(List<String> vertexIds) {
|
protected AddressSet getAddresses(Set<AttributedVertex> vertices) {
|
||||||
if (graphType != CONTROL_FLOW_GRAPH) {
|
if (graphType != CONTROL_FLOW_GRAPH) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
||||||
for (String vertixId : vertexIds) {
|
for (AttributedVertex vertex : vertices) {
|
||||||
try {
|
try {
|
||||||
int index = Integer.parseInt(vertixId);
|
int index = Integer.parseInt(vertex.getId());
|
||||||
PcodeBlockBasic block = blocks.get(index);
|
PcodeBlockBasic block = blocks.get(index);
|
||||||
Address start = block.getStart();
|
Address start = block.getStart();
|
||||||
set.addRange(start, block.getStop());
|
set.addRange(start, block.getStop());
|
||||||
|
@ -84,7 +86,7 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getVertexIdForAddress(Address address) {
|
protected String getVertexId(Address address) {
|
||||||
if (graphType != CONTROL_FLOW_GRAPH) {
|
if (graphType != CONTROL_FLOW_GRAPH) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -96,25 +98,25 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||||
return Integer.toString(block.getIndex());
|
return Integer.toString(block.getIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.getVertexIdForAddress(address);
|
return super.getVertexId(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Address getAddressForVertexId(String vertexId) {
|
protected Address getAddress(AttributedVertex vertex) {
|
||||||
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int index = Integer.parseInt(vertexId);
|
int index = Integer.parseInt(vertex.getId());
|
||||||
PcodeBlockBasic block = blocks.get(index);
|
PcodeBlockBasic block = blocks.get(index);
|
||||||
return block.getStart();
|
return block.getStart();
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
throw new AssertException("Bad vertex id, expected a number but got " + vertexId);
|
throw new AssertException("Bad vertex id, expected a number but got " + vertex.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) {
|
public GraphDisplayListener cloneWith(GraphDisplay display) {
|
||||||
return new ASTGraphDisplayListener(tool, graphDisplay, hfunction, graphType);
|
return new ASTGraphDisplayListener(tool, graphDisplay, hfunction, graphType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,9 +124,9 @@ public class ASTGraphTask extends Task {
|
||||||
display.setGraph(graph, description, false, monitor);
|
display.setGraph(graph, description, false, monitor);
|
||||||
// set the graph location
|
// set the graph location
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
String id = displayListener.getVertexIdForAddress(location);
|
AttributedVertex vertex = displayListener.getVertex(location);
|
||||||
// update graph location, but don't have it send out event
|
// update graph location, but don't have it send out event
|
||||||
display.setLocationFocus(id, EventTrigger.INTERNAL_ONLY);
|
display.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.graph.export;
|
package ghidra.graph.export;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jgrapht.Graph;
|
import org.jgrapht.Graph;
|
||||||
|
|
||||||
|
@ -57,15 +58,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay {
|
||||||
// This display is not interactive, so N/A
|
// This display is not interactive, so N/A
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectVertices(List<String> vertexList, EventTrigger eventTrigger) {
|
|
||||||
// This display is not interactive, so N/A
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger) {
|
|
||||||
// This display is not interactive, so N/A
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the {@link AttributedGraph} for visualization
|
* set the {@link AttributedGraph} for visualization
|
||||||
|
@ -108,7 +101,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateVertexName(String id, String newName) {
|
public void updateVertexName(AttributedVertex vertex, String newName) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,13 +116,28 @@ class ExportAttributedGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFocusedVertexId() {
|
public AttributedVertex getFocusedVertex() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSelectedVertexIds() {
|
public Set<AttributedVertex> getSelectedVertices() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger) {
|
||||||
|
// not interactive, so N/A
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributedGraph getGraph() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectVertices(Set<AttributedVertex> vertexList, EventTrigger eventTrigger) {
|
||||||
|
// not interactive, so N/A
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -539,9 +539,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Set<AttributedVertex> selected = selectedVertexState.getSelected();
|
Set<AttributedVertex> selected = selectedVertexState.getSelected();
|
||||||
List<String> selectedIds =
|
notifySelectionChanged(selected);
|
||||||
selected.stream().map(AttributedVertex::getId).collect(Collectors.toList());
|
|
||||||
notifySelectionChanged(selectedIds);
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
switchableSelectionListener.setEnabled(true);
|
switchableSelectionListener.setEnabled(true);
|
||||||
|
@ -716,17 +714,18 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
setFocusedVertex(vertex, EventTrigger.API_CALL);
|
setFocusedVertex(vertex, EventTrigger.API_CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger) {
|
@Override
|
||||||
|
public void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger) {
|
||||||
boolean changed = this.focusedVertex != vertex;
|
boolean changed = this.focusedVertex != vertex;
|
||||||
this.focusedVertex = vertex;
|
this.focusedVertex = vertex;
|
||||||
if (focusedVertex != null) {
|
if (focusedVertex != null) {
|
||||||
if (changed && eventTrigger != EventTrigger.INTERNAL_ONLY) {
|
if (changed && eventTrigger != EventTrigger.INTERNAL_ONLY) {
|
||||||
notifyLocationFocusChanged(focusedVertex.getId());
|
notifyLocationFocusChanged(focusedVertex);
|
||||||
}
|
}
|
||||||
// make sure the vertex is visible, even if the vertex has not changed
|
// make sure the vertex is visible, even if the vertex has not changed
|
||||||
scrollToSelected(focusedVertex);
|
scrollToSelected(focusedVertex);
|
||||||
viewer.repaint();
|
|
||||||
}
|
}
|
||||||
|
viewer.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -769,22 +768,22 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fire an event to notify the selected vertices changed
|
* fire an event to notify the selected vertices changed
|
||||||
* @param vertexIds the list of vertexes
|
* @param selected the list of selected vertices
|
||||||
*/
|
*/
|
||||||
private void notifySelectionChanged(List<String> vertexIds) {
|
private void notifySelectionChanged(Set<AttributedVertex> selected) {
|
||||||
Swing.runLater(() -> listener.selectionChanged(vertexIds));
|
Swing.runLater(() -> listener.selectionChanged(selected));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fire and event to say the focused vertex changed
|
* fire and event to say the focused vertex changed
|
||||||
* @param vertexId the id of the focused vertex
|
* @param vertex the new focused vertex
|
||||||
*/
|
*/
|
||||||
private void notifyLocationFocusChanged(String vertexId) {
|
private void notifyLocationFocusChanged(AttributedVertex vertex) {
|
||||||
Swing.runLater(() -> listener.locationFocusChanged(vertexId));
|
Swing.runLater(() -> listener.locationFocusChanged(vertex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectVertices(List<String> vertexIdList, EventTrigger eventTrigger) {
|
public void selectVertices(Set<AttributedVertex> selected, EventTrigger eventTrigger) {
|
||||||
// if we are not to fire events, turn off the selection listener we provided to the
|
// if we are not to fire events, turn off the selection listener we provided to the
|
||||||
// graphing library.
|
// graphing library.
|
||||||
switchableSelectionListener.setEnabled(eventTrigger != EventTrigger.INTERNAL_ONLY);
|
switchableSelectionListener.setEnabled(eventTrigger != EventTrigger.INTERNAL_ONLY);
|
||||||
|
@ -792,8 +791,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
try {
|
try {
|
||||||
MutableSelectedState<AttributedVertex> nodeSelectedState =
|
MutableSelectedState<AttributedVertex> nodeSelectedState =
|
||||||
viewer.getSelectedVertexState();
|
viewer.getSelectedVertexState();
|
||||||
Set<AttributedVertex> selected = getVertices(vertexIdList);
|
if (selected.isEmpty()) {
|
||||||
if (vertexIdList.isEmpty()) {
|
|
||||||
nodeSelectedState.clear();
|
nodeSelectedState.clear();
|
||||||
}
|
}
|
||||||
else if (!Arrays.asList(nodeSelectedState.getSelectedObjects()).containsAll(selected)) {
|
else if (!Arrays.asList(nodeSelectedState.getSelectedObjects()).containsAll(selected)) {
|
||||||
|
@ -809,30 +807,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param vertexIds vertex ids of interest
|
|
||||||
* @return a {@code Set} containing the {@code AttributedVertex} for ths supplied ids
|
|
||||||
*/
|
|
||||||
private Set<AttributedVertex> getVertices(Collection<String> vertexIds) {
|
|
||||||
Set<String> vertexSet = new HashSet<>(vertexIds);
|
|
||||||
return graph.vertexSet()
|
|
||||||
.stream()
|
|
||||||
.filter(v -> vertexSet.contains(v.getId()))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger) {
|
|
||||||
Optional<AttributedVertex> vertexToFocus =
|
|
||||||
graph.vertexSet().stream().filter(v -> vertexID.equals(v.getId())).findFirst();
|
|
||||||
log.fine("picking address:" + vertexID + " returned " + vertexToFocus);
|
|
||||||
viewer.repaint();
|
|
||||||
vertexToFocus.ifPresent(v -> {
|
|
||||||
setFocusedVertex(v, eventTrigger);
|
|
||||||
});
|
|
||||||
viewer.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the {@link AttributedGraph} for visualization
|
* set the {@link AttributedGraph} for visualization
|
||||||
|
@ -1066,24 +1040,16 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
/**
|
/**
|
||||||
* process a request to update the name attribute value of the vertex with the
|
* process a request to update the name attribute value of the vertex with the
|
||||||
* supplied id
|
* supplied id
|
||||||
* @param id the vertix id
|
* @param vertex the vertex to update
|
||||||
* @param newName the new name of the vertex
|
* @param newName the new name of the vertex
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void updateVertexName(String id, String newName) {
|
public void updateVertexName(AttributedVertex vertex, String newName) {
|
||||||
// find the vertex, if present, change the name
|
|
||||||
Optional<AttributedVertex> optional = graph.vertexSet()
|
|
||||||
.stream()
|
|
||||||
.filter(v -> v.getId().equals(id))
|
|
||||||
.findFirst();
|
|
||||||
if (optional.isPresent()) {
|
|
||||||
AttributedVertex vertex = optional.get();
|
|
||||||
vertex.setName(newName);
|
vertex.setName(newName);
|
||||||
vertex.clearCache();
|
vertex.clearCache();
|
||||||
iconCache.evict(vertex);
|
iconCache.evict(vertex);
|
||||||
viewer.repaint();
|
viewer.repaint();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -1225,8 +1191,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
// vertices
|
// vertices
|
||||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
Collection<AttributedVertex> selectedVertices = getVertices(e.getItem());
|
Collection<AttributedVertex> selectedVertices = getVertices(e.getItem());
|
||||||
List<String> selectedVertexIds = toVertexIds(selectedVertices);
|
notifySelectionChanged(new HashSet<AttributedVertex>(selectedVertices));
|
||||||
notifySelectionChanged(selectedVertexIds);
|
|
||||||
|
|
||||||
if (selectedVertices.size() == 1) {
|
if (selectedVertices.size() == 1) {
|
||||||
// if only one vertex was selected, make it the focused vertex
|
// if only one vertex was selected, make it the focused vertex
|
||||||
|
@ -1239,7 +1204,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||||
notifySelectionChanged(Collections.emptyList());
|
notifySelectionChanged(Collections.emptySet());
|
||||||
}
|
}
|
||||||
viewer.repaint();
|
viewer.repaint();
|
||||||
}
|
}
|
||||||
|
@ -1255,14 +1220,13 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFocusedVertexId() {
|
public AttributedVertex getFocusedVertex() {
|
||||||
return focusedVertex == null ? null : focusedVertex.getId();
|
return focusedVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSelectedVertexIds() {
|
public Set<AttributedVertex> getSelectedVertices() {
|
||||||
Set<AttributedVertex> selectedVertices = getSelectedVertices();
|
return viewer.getSelectedVertexState().getSelected();
|
||||||
return selectedVertices.stream().map(v -> v.getId()).collect(Collectors.toSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionContext getActionContext(MouseEvent e) {
|
public ActionContext getActionContext(MouseEvent e) {
|
||||||
|
@ -1284,9 +1248,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<AttributedVertex> getSelectedVertices() {
|
|
||||||
return viewer.getSelectedVertexState().getSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the hide selected action states to determine what vertices are shown:
|
* Use the hide selected action states to determine what vertices are shown:
|
||||||
|
@ -1321,4 +1282,8 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||||
viewer.repaint();
|
viewer.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributedGraph getGraph() {
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,13 +157,13 @@ public class BlockGraphTask extends Task {
|
||||||
|
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
// initialize the graph location, but don't have the graph send an event
|
// initialize the graph location, but don't have the graph send an event
|
||||||
String id = listener.getVertexIdForAddress(location.getAddress());
|
AttributedVertex vertex = listener.getVertex(location.getAddress());
|
||||||
display.setLocationFocus(id, EventTrigger.INTERNAL_ONLY);
|
display.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY);
|
||||||
}
|
}
|
||||||
if (selection != null && !selection.isEmpty()) {
|
if (selection != null && !selection.isEmpty()) {
|
||||||
List<String> selectedVertices = listener.getVertices(selection);
|
Set<AttributedVertex> selectedVertices = listener.getVertices(selection);
|
||||||
if (selectedVertices != null) {
|
if (selectedVertices != null) {
|
||||||
// intialize the graph selection, but don't have the graph send an event
|
// initialize the graph selection, but don't have the graph send an event
|
||||||
display.selectVertices(selectedVertices, EventTrigger.INTERNAL_ONLY);
|
display.selectVertices(selectedVertices, EventTrigger.INTERNAL_ONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,28 +54,28 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getVertexIdForAddress(Address address) {
|
protected String getVertexId(Address address) {
|
||||||
try {
|
try {
|
||||||
CodeBlock[] blocks = blockModel.getCodeBlocksContaining(address, TaskMonitor.DUMMY);
|
CodeBlock[] blocks = blockModel.getCodeBlocksContaining(address, TaskMonitor.DUMMY);
|
||||||
if (blocks != null && blocks.length > 0) {
|
if (blocks != null && blocks.length > 0) {
|
||||||
return super.getVertexIdForAddress(blocks[0].getFirstStartAddress());
|
return super.getVertexId(blocks[0].getFirstStartAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
// Will not happen with dummyMonitor
|
// Will not happen with dummyMonitor
|
||||||
// Model has already done the work when the graph was created
|
// Model has already done the work when the graph was created
|
||||||
}
|
}
|
||||||
return super.getVertexIdForAddress(address);
|
return super.getVertexId(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<String> getVertices(AddressSetView addrSet) {
|
protected Set<AttributedVertex> getVertices(AddressSetView addrSet) {
|
||||||
if (addrSet.isEmpty()) {
|
if (addrSet.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify all blocks which have an entry point within the selection address set
|
// Identify all blocks which have an entry point within the selection address set
|
||||||
ArrayList<String> blockList = new ArrayList<String>();
|
Set<AttributedVertex> vertices = new HashSet<>();
|
||||||
try {
|
try {
|
||||||
SymbolTable symTable = program.getSymbolTable();
|
SymbolTable symTable = program.getSymbolTable();
|
||||||
CodeBlockIterator cbIter =
|
CodeBlockIterator cbIter =
|
||||||
|
@ -91,7 +91,10 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList
|
||||||
else {
|
else {
|
||||||
addrString = addr.toString();
|
addrString = addr.toString();
|
||||||
}
|
}
|
||||||
blockList.add(addrString);
|
AttributedVertex vertex = graphDisplay.getGraph().getVertex(addrString);
|
||||||
|
if (vertex != null) {
|
||||||
|
vertices.add(vertex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
|
@ -99,18 +102,18 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList
|
||||||
// Model has already done the work when the graph was created
|
// Model has already done the work when the graph was created
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockList;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AddressSet getAddressSetForVertices(List<String> vertexIds) {
|
protected AddressSet getAddresses(Set<AttributedVertex> vertices) {
|
||||||
AddressSet addrSet = new AddressSet();
|
AddressSet addrSet = new AddressSet();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// for each address string, translate it into a block
|
// for each address string, translate it into a block
|
||||||
// and add it to the address set.
|
// and add it to the address set.
|
||||||
for (String vertexId : vertexIds) {
|
for (AttributedVertex vertex : vertices) {
|
||||||
Address blockAddr = getAddressForVertexId(vertexId);
|
Address blockAddr = getAddress(vertex);
|
||||||
if (!isValidAddress(blockAddr)) {
|
if (!isValidAddress(blockAddr)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -150,8 +153,8 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateVertexName(VertexGraphActionContext context) {
|
private void updateVertexName(VertexGraphActionContext context) {
|
||||||
String vertexId = context.getClickedVertex().getId();
|
AttributedVertex vertex = context.getClickedVertex();
|
||||||
Address address = getAddressForVertexId(vertexId);
|
Address address = getAddress(vertex);
|
||||||
Symbol symbol = program.getSymbolTable().getPrimarySymbol(address);
|
Symbol symbol = program.getSymbolTable().getPrimarySymbol(address);
|
||||||
|
|
||||||
if (symbol == null) {
|
if (symbol == null) {
|
||||||
|
@ -165,8 +168,8 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) {
|
public GraphDisplayListener cloneWith(GraphDisplay newGraphDisplay) {
|
||||||
return new BlockModelGraphDisplayListener(tool, blockModel, graphDisplay);
|
return new BlockModelGraphDisplayListener(tool, blockModel, newGraphDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@ package ghidra.graph.program;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ import ghidra.program.model.block.CodeBlockModel;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.service.graph.AttributedGraph;
|
import ghidra.service.graph.AttributedGraph;
|
||||||
|
import ghidra.service.graph.AttributedVertex;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class BlockGraphEventTest extends AbstractBlockGraphTest {
|
public class BlockGraphEventTest extends AbstractBlockGraphTest {
|
||||||
|
@ -54,13 +56,13 @@ public class BlockGraphEventTest extends AbstractBlockGraphTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGhidraLocationChanged() {
|
public void testGhidraLocationChanged() {
|
||||||
codeBrowser.goTo(new ProgramLocation(program, addr(0x1002239)));
|
codeBrowser.goTo(new ProgramLocation(program, addr(0x1002239)));
|
||||||
assertEquals("01002239", display.getFocusedVertex());
|
assertEquals("01002239", display.getFocusedVertex().getId());
|
||||||
codeBrowser.goTo(new ProgramLocation(program, addr(0x1002200)));
|
codeBrowser.goTo(new ProgramLocation(program, addr(0x1002200)));
|
||||||
assertEquals("01002200", display.getFocusedVertex());
|
assertEquals("01002200", display.getFocusedVertex().getId());
|
||||||
|
|
||||||
// also try a location that is not the start of a block
|
// also try a location that is not the start of a block
|
||||||
codeBrowser.goTo(new ProgramLocation(program, addr(0x100223a)));
|
codeBrowser.goTo(new ProgramLocation(program, addr(0x100223a)));
|
||||||
assertEquals("01002239", display.getFocusedVertex());
|
assertEquals("01002239", display.getFocusedVertex().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,38 +73,38 @@ public class BlockGraphEventTest extends AbstractBlockGraphTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGhidraSelectionChanged() {
|
public void testGhidraSelectionChanged() {
|
||||||
setSelection(addrSet(0x1002239, 0x1002241));
|
setSelection(addrSet(0x1002239, 0x1002241));
|
||||||
Set<String> selected = new HashSet<>(display.getSelectedVertices());
|
Set<AttributedVertex> selected = new HashSet<>(display.getSelectedVertices());
|
||||||
assertEquals(3, selected.size());
|
assertEquals(3, selected.size());
|
||||||
assertTrue(selected.contains("01002239"));
|
assertTrue(selected.contains(graph.getVertex("01002239")));
|
||||||
assertTrue(selected.contains("0100223c"));
|
assertTrue(selected.contains(graph.getVertex("0100223c")));
|
||||||
assertTrue(selected.contains("0100223e"));
|
assertTrue(selected.contains(graph.getVertex("0100223e")));
|
||||||
|
|
||||||
setSelection(new AddressSet(addr(0x1002200), addr(0x1002210)));
|
setSelection(new AddressSet(addr(0x1002200), addr(0x1002210)));
|
||||||
selected = new HashSet<>(display.getSelectedVertices());
|
selected = new HashSet<>(display.getSelectedVertices());
|
||||||
assertEquals(2, selected.size());
|
assertEquals(2, selected.size());
|
||||||
assertTrue(selected.contains("01002200"));
|
assertTrue(selected.contains(graph.getVertex("01002200")));
|
||||||
assertTrue(selected.contains("01002203"));
|
assertTrue(selected.contains(graph.getVertex("01002203")));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGraphNodeFocused() {
|
public void testGraphNodeFocused() {
|
||||||
display.focusChanged("01002203");
|
display.focusChanged(graph.getVertex("01002203"));
|
||||||
assertEquals(addr(0x01002203), codeBrowser.getCurrentLocation().getAddress());
|
assertEquals(addr(0x01002203), codeBrowser.getCurrentLocation().getAddress());
|
||||||
|
|
||||||
display.focusChanged("0100223c");
|
display.focusChanged(graph.getVertex("0100223c"));
|
||||||
assertEquals(addr(0x0100223c), codeBrowser.getCurrentLocation().getAddress());
|
assertEquals(addr(0x0100223c), codeBrowser.getCurrentLocation().getAddress());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGraphNodesSelected() {
|
public void testGraphNodesSelected() {
|
||||||
display.selectionChanged(Arrays.asList("01002239", "0100223c"));
|
display.selectionChanged(Set.of(graph.getVertex("01002239"), graph.getVertex("0100223c")));
|
||||||
ProgramSelection selection = codeBrowser.getCurrentSelection();
|
ProgramSelection selection = codeBrowser.getCurrentSelection();
|
||||||
assertEquals(addr(0x01002239), selection.getMinAddress());
|
assertEquals(addr(0x01002239), selection.getMinAddress());
|
||||||
assertEquals(addr(0x0100223d), selection.getMaxAddress());
|
assertEquals(addr(0x0100223d), selection.getMaxAddress());
|
||||||
|
|
||||||
display.selectionChanged(Arrays.asList("01002200", "01002203"));
|
display.selectionChanged(Set.of(graph.getVertex("01002200"), graph.getVertex("01002203")));
|
||||||
selection = codeBrowser.getCurrentSelection();
|
selection = codeBrowser.getCurrentSelection();
|
||||||
assertEquals(addr(0x01002200), selection.getMinAddress());
|
assertEquals(addr(0x01002200), selection.getMinAddress());
|
||||||
assertEquals(addr(0x01002204), selection.getMaxAddress());
|
assertEquals(addr(0x01002204), selection.getMaxAddress());
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.graph.program;
|
package ghidra.graph.program;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
|
@ -26,12 +27,11 @@ import ghidra.util.task.TaskMonitor;
|
||||||
public class TestGraphDisplay implements GraphDisplay {
|
public class TestGraphDisplay implements GraphDisplay {
|
||||||
private Set<String> definedVertexAttributes = new HashSet<>();
|
private Set<String> definedVertexAttributes = new HashSet<>();
|
||||||
private Set<String> definedEdgeAttributes = new HashSet<>();
|
private Set<String> definedEdgeAttributes = new HashSet<>();
|
||||||
private String vertexAttributeName;
|
|
||||||
private AttributedGraph graph;
|
private AttributedGraph graph;
|
||||||
private String graphDescription;
|
private String graphDescription;
|
||||||
private GraphDisplayListener listener;
|
private GraphDisplayListener listener;
|
||||||
private String currentFocusedVertex;
|
private AttributedVertex focusedVertex;
|
||||||
private List<String> currentSelection;
|
private Set<AttributedVertex> currentSelection;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setGraphDisplayListener(GraphDisplayListener listener) {
|
public void setGraphDisplayListener(GraphDisplayListener listener) {
|
||||||
|
@ -39,20 +39,22 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger) {
|
public void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger) {
|
||||||
currentFocusedVertex = vertexID;
|
focusedVertex = vertex;
|
||||||
}
|
|
||||||
|
|
||||||
public String getFocusedVertex() {
|
|
||||||
return currentFocusedVertex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectVertices(List<String> vertexList, EventTrigger eventTrigger) {
|
public AttributedVertex getFocusedVertex() {
|
||||||
|
return focusedVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectVertices(Set<AttributedVertex> vertexList, EventTrigger eventTrigger) {
|
||||||
currentSelection = vertexList;
|
currentSelection = vertexList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getSelectedVertices() {
|
@Override
|
||||||
|
public Set<AttributedVertex> getSelectedVertices() {
|
||||||
return currentSelection;
|
return currentSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||||
@Override
|
@Override
|
||||||
public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace,
|
public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace,
|
||||||
int maxLines) {
|
int maxLines) {
|
||||||
vertexAttributeName = attributeName;
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,7 +93,7 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateVertexName(String id, String newName) {
|
public void updateVertexName(AttributedVertex vertex, String newName) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,16 +102,17 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||||
return graphDescription;
|
return graphDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public AttributedGraph getGraph() {
|
public AttributedGraph getGraph() {
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void focusChanged(String vertexId) {
|
public void focusChanged(AttributedVertex vertex) {
|
||||||
listener.locationFocusChanged(vertexId);
|
listener.locationFocusChanged(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectionChanged(List<String> vertexIds) {
|
public void selectionChanged(Set<AttributedVertex> vertices) {
|
||||||
listener.selectionChanged(vertexIds);
|
listener.selectionChanged(vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,14 +120,4 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||||
// do nothing, actions are not supported by this display
|
// do nothing, actions are not supported by this display
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFocusedVertexId() {
|
|
||||||
return currentFocusedVertex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getSelectedVertexIds() {
|
|
||||||
return new HashSet<String>(currentSelection);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.service.graph;
|
package ghidra.service.graph;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
public class DummyGraphDisplayListener implements GraphDisplayListener {
|
public class DummyGraphDisplayListener implements GraphDisplayListener {
|
||||||
|
|
||||||
|
@ -24,19 +24,19 @@ public class DummyGraphDisplayListener implements GraphDisplayListener {
|
||||||
// I'm a dummy
|
// I'm a dummy
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectionChanged(List<String> vertexIds) {
|
|
||||||
// I'm a dummy
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void locationFocusChanged(String vertexId) {
|
|
||||||
// I'm a dummy
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) {
|
public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) {
|
||||||
return new DummyGraphDisplayListener();
|
return new DummyGraphDisplayListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectionChanged(Set<AttributedVertex> vertices) {
|
||||||
|
// I'm a dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void locationFocusChanged(AttributedVertex vertex) {
|
||||||
|
// I'm a dummy
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.service.graph;
|
package ghidra.service.graph;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
|
@ -46,41 +45,46 @@ public interface GraphDisplay {
|
||||||
/**
|
/**
|
||||||
* Tells the graph display window to focus the vertex with the given id.
|
* Tells the graph display window to focus the vertex with the given id.
|
||||||
*
|
*
|
||||||
* @param vertexID the id of the vertex to focus
|
* @param vertex the vertex to focus
|
||||||
* @param eventTrigger Provides a hint to the GraphDisplay as to why we are updating the
|
* @param eventTrigger Provides a hint to the GraphDisplay as to why we are updating the
|
||||||
* graph location so that the GraphDisplay can decide if it should send out a notification via
|
* graph location so that the GraphDisplay can decide if it should send out a notification via
|
||||||
* the {@link GraphDisplayListener#locationFocusChanged(String)}. For example, if we are updating
|
* the {@link GraphDisplayListener#locationFocusChanged(AttributedVertex)}. For example, if we
|
||||||
* the the location due to an event from the main application, we don't want to notify the
|
* are updating the the location due to an event from the main application, we don't want to
|
||||||
* application the graph changed to avoid event cycles. See {@link EventTrigger} for more
|
* notify the application the graph changed to avoid event cycles. See {@link EventTrigger} for
|
||||||
* information.
|
* more information.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger);
|
public void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currently focused vertexID or null if no vertex is focussed.
|
* Returns the graph for this display
|
||||||
* @return the currently focused vertexID or null if no vertex is focussed.
|
* @return the graph for this display
|
||||||
*/
|
*/
|
||||||
public String getFocusedVertexId();
|
public AttributedGraph getGraph();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently focused vertex or null if no vertex is focused
|
||||||
|
* @return the currently focused vertex or null if no vertex is focused.
|
||||||
|
*/
|
||||||
|
public AttributedVertex getFocusedVertex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the graph display window to select the vertices with the given ids
|
* Tells the graph display window to select the vertices with the given ids
|
||||||
*
|
*
|
||||||
* @param vertexList the list of vertex ids to select
|
* @param vertexSet the set of vertices to select
|
||||||
* @param eventTrigger Provides a hint to the GraphDisplay as to why we are updating the
|
* @param eventTrigger Provides a hint to the GraphDisplay as to why we are updating the
|
||||||
* graph location so that the GraphDisplay can decide if it should send out a notification via
|
* graph location so that the GraphDisplay can decide if it should send out a notification via
|
||||||
* the {@link GraphDisplayListener#locationFocusChanged(String)}. For example, if we are updating
|
* the {@link GraphDisplayListener#selectionChanged(Set)}. For example, if we are updating
|
||||||
* the the location due to an event from the main application, we don't want to notify the
|
* the the location due to an event from the main application, we don't want to notify the
|
||||||
* application the graph changed to avoid event cycles. See {@link EventTrigger} for more
|
* application the graph changed to avoid event cycles. See {@link EventTrigger} for more
|
||||||
* information.
|
* information.
|
||||||
*/
|
*/
|
||||||
public void selectVertices(List<String> vertexList, EventTrigger eventTrigger);
|
public void selectVertices(Set<AttributedVertex> vertexSet, EventTrigger eventTrigger);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of vertex ids for all the currently selected vertices
|
* Returns a set of vertex ids for all the currently selected vertices
|
||||||
* @return a list of vertex ids for all the currently selected vertices
|
* @return a set of vertex ids for all the currently selected vertices
|
||||||
*/
|
*/
|
||||||
public Set<String> getSelectedVertexIds();
|
public Set<AttributedVertex> getSelectedVertices();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes this graph display window.
|
* Closes this graph display window.
|
||||||
|
@ -131,10 +135,10 @@ public interface GraphDisplay {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a vertex to a new name
|
* Updates a vertex to a new name
|
||||||
* @param id the vertex id
|
* @param vertex the vertex to rename
|
||||||
* @param newName the new name of the vertex
|
* @param newName the new name for the vertex
|
||||||
*/
|
*/
|
||||||
public void updateVertexName(String id, String newName);
|
public void updateVertexName(AttributedVertex vertex, String newName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the description of the current graph
|
* Returns the description of the current graph
|
||||||
|
@ -148,4 +152,5 @@ public interface GraphDisplay {
|
||||||
* @param action the action to add.
|
* @param action the action to add.
|
||||||
*/
|
*/
|
||||||
public void addAction(DockingAction action);
|
public void addAction(DockingAction action);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.service.graph;
|
package ghidra.service.graph;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for being notified when the user interacts with a visual graph display
|
* Interface for being notified when the user interacts with a visual graph display
|
||||||
|
@ -27,17 +27,17 @@ public interface GraphDisplayListener {
|
||||||
public void graphClosed();
|
public void graphClosed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that the list of selected vertices has changed
|
* Notification that the set of selected vertices has changed
|
||||||
*
|
*
|
||||||
* @param vertexIds the list of vertex ids for the currently selected vertices
|
* @param vertices the set of currently selected vertices
|
||||||
*/
|
*/
|
||||||
public void selectionChanged(List<String> vertexIds);
|
public void selectionChanged(Set<AttributedVertex> vertices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that the "focused" (active) vertex has changed
|
* Notification that the "focused" (active) vertex has changed
|
||||||
* @param vertexId the vertex id of the currently "focused" vertex
|
* @param vertex the vertex that is currently "focused"
|
||||||
*/
|
*/
|
||||||
public void locationFocusChanged(String vertexId);
|
public void locationFocusChanged(AttributedVertex vertex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a new GraphDisplayListener of the same type as the specific
|
* Makes a new GraphDisplayListener of the same type as the specific
|
||||||
|
|
|
@ -40,6 +40,12 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
private AttributedGraph graph;
|
private AttributedGraph graph;
|
||||||
private ComponentProvider graphComponentProvider;
|
private ComponentProvider graphComponentProvider;
|
||||||
private GraphDisplay display;
|
private GraphDisplay display;
|
||||||
|
private AttributedVertex a;
|
||||||
|
private AttributedVertex b;
|
||||||
|
private AttributedVertex c;
|
||||||
|
private AttributedVertex d;
|
||||||
|
private AttributedVertex e;
|
||||||
|
private AttributedVertex f;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
@ -60,7 +66,7 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectVertexAction() {
|
public void testSelectVertexAction() {
|
||||||
assertTrue(display.getSelectedVertexIds().isEmpty());
|
assertTrue(display.getSelectedVertices().isEmpty());
|
||||||
|
|
||||||
DockingActionIf action = getAction(tool, "Select Vertex");
|
DockingActionIf action = getAction(tool, "Select Vertex");
|
||||||
VertexGraphActionContext context =
|
VertexGraphActionContext context =
|
||||||
|
@ -68,25 +74,24 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
graph.getVertex("B"));
|
graph.getVertex("B"));
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVertexIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selectedVertices = display.getSelectedVertices();
|
||||||
assertEquals(1, selectedVertexIds.size());
|
assertEquals(1, selectedVertices.size());
|
||||||
assertTrue(selectedVertexIds.contains(graph.getVertex("B").getId()));
|
assertTrue(selectedVertices.contains(b));
|
||||||
|
|
||||||
// now try and select a second vertex
|
// now try and select a second vertex
|
||||||
context = new VertexGraphActionContext(graphComponentProvider, graph, null, null,
|
context = new VertexGraphActionContext(graphComponentProvider, graph, null, null,d);
|
||||||
graph.getVertex("D"));
|
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
selectedVertexIds = display.getSelectedVertexIds();
|
selectedVertices = display.getSelectedVertices();
|
||||||
assertEquals(2, selectedVertexIds.size());
|
assertEquals(2, selectedVertices.size());
|
||||||
assertTrue(selectedVertexIds.contains(graph.getVertex("B").getId()));
|
assertTrue(selectedVertices.contains(b));
|
||||||
assertTrue(selectedVertexIds.contains(graph.getVertex("D").getId()));
|
assertTrue(selectedVertices.contains(d));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeSelectVertexAction() {
|
public void testDeSelectVertexAction() {
|
||||||
display.selectVertices(Arrays.asList("A", "B", "C", "D"), EventTrigger.API_CALL);
|
select(a, b, c, d);
|
||||||
assertEquals(4, display.getSelectedVertexIds().size());
|
assertEquals(4, display.getSelectedVertices().size());
|
||||||
|
|
||||||
DockingActionIf action = getAction(tool, "Deselect Vertex");
|
DockingActionIf action = getAction(tool, "Deselect Vertex");
|
||||||
VertexGraphActionContext context =
|
VertexGraphActionContext context =
|
||||||
|
@ -94,18 +99,18 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
graph.getVertex("B"));
|
graph.getVertex("B"));
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVerticeIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selected = display.getSelectedVertices();
|
||||||
assertEquals(3, selectedVerticeIds.size());
|
assertEquals(3, selected.size());
|
||||||
assertTrue(selectedVerticeIds.contains(graph.getVertex("A").getId()));
|
assertTrue(selected.contains(a));
|
||||||
assertTrue(selectedVerticeIds.contains(graph.getVertex("D").getId()));
|
assertTrue(selected.contains(c));
|
||||||
assertTrue(selectedVerticeIds.contains(graph.getVertex("D").getId()));
|
assertTrue(selected.contains(d));
|
||||||
assertFalse(selectedVerticeIds.contains(graph.getVertex("B").getId()));
|
assertFalse(selected.contains(b));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectEdgeAction() {
|
public void testSelectEdgeAction() {
|
||||||
assertTrue(display.getSelectedVertexIds().isEmpty());
|
assertTrue(display.getSelectedVertices().isEmpty());
|
||||||
|
|
||||||
DockingActionIf action = getAction(tool, "Select Edge");
|
DockingActionIf action = getAction(tool, "Select Edge");
|
||||||
EdgeGraphActionContext context =
|
EdgeGraphActionContext context =
|
||||||
|
@ -113,10 +118,10 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVerticeIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selectedVerticeIds = display.getSelectedVertices();
|
||||||
assertEquals(2, selectedVerticeIds.size());
|
assertEquals(2, selectedVerticeIds.size());
|
||||||
assertTrue(selectedVerticeIds.contains(graph.getVertex("A").getId()));
|
assertTrue(selectedVerticeIds.contains(a));
|
||||||
assertTrue(selectedVerticeIds.contains(graph.getVertex("B").getId()));
|
assertTrue(selectedVerticeIds.contains(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -127,85 +132,85 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVerticeIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selectedVertices = display.getSelectedVertices();
|
||||||
assertEquals(2, selectedVerticeIds.size());
|
assertEquals(2, selectedVertices.size());
|
||||||
|
|
||||||
action = getAction(tool, "Deselect Edge");
|
action = getAction(tool, "Deselect Edge");
|
||||||
|
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
selectedVerticeIds = display.getSelectedVertexIds();
|
selectedVertices = display.getSelectedVertices();
|
||||||
assertEquals(0, selectedVerticeIds.size());
|
assertEquals(0, selectedVertices.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectEdgeSource() {
|
public void testSelectEdgeSource() {
|
||||||
display.setLocationFocus("D", EventTrigger.INTERNAL_ONLY);
|
setFocusedVertex(d);
|
||||||
DockingActionIf action = getAction(tool, "Edge Source");
|
DockingActionIf action = getAction(tool, "Edge Source");
|
||||||
EdgeGraphActionContext context =
|
EdgeGraphActionContext context =
|
||||||
new EdgeGraphActionContext(graphComponentProvider, graph, null, null,
|
new EdgeGraphActionContext(graphComponentProvider, graph, null, null,
|
||||||
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
assertEquals("A", display.getFocusedVertexId());
|
assertEquals(a, display.getFocusedVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectEdgeTarget() {
|
public void testSelectEdgeTarget() {
|
||||||
display.setLocationFocus("D", EventTrigger.INTERNAL_ONLY);
|
setFocusedVertex(d);
|
||||||
DockingActionIf action = getAction(tool, "Edge Target");
|
DockingActionIf action = getAction(tool, "Edge Target");
|
||||||
EdgeGraphActionContext context =
|
EdgeGraphActionContext context =
|
||||||
new EdgeGraphActionContext(graphComponentProvider, graph, null, null,
|
new EdgeGraphActionContext(graphComponentProvider, graph, null, null,
|
||||||
graph.getEdge(graph.getVertex("A"), graph.getVertex("B")));
|
graph.getEdge(a, b));
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
assertEquals("B", display.getFocusedVertexId());
|
assertEquals(b, display.getFocusedVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvertSelection() {
|
public void testInvertSelection() {
|
||||||
display.selectVertices(List.of("A", "C", "E"), EventTrigger.INTERNAL_ONLY);
|
select(a, c, e);
|
||||||
DockingActionIf action = getAction(tool, "Invert Selection");
|
DockingActionIf action = getAction(tool, "Invert Selection");
|
||||||
GraphActionContext context =
|
GraphActionContext context =
|
||||||
new GraphActionContext(graphComponentProvider, graph, null, null);
|
new GraphActionContext(graphComponentProvider, graph, null, null);
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVerticeIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selectedVertices = display.getSelectedVertices();
|
||||||
assertEquals(3, selectedVerticeIds.size());
|
assertEquals(3, selectedVertices.size());
|
||||||
assertTrue(selectedVerticeIds.contains("B"));
|
assertTrue(selectedVertices.contains(b));
|
||||||
assertTrue(selectedVerticeIds.contains("D"));
|
assertTrue(selectedVertices.contains(d));
|
||||||
assertTrue(selectedVerticeIds.contains("F"));
|
assertTrue(selectedVertices.contains(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGrowSelectionOut() {
|
public void testGrowSelectionOut() {
|
||||||
display.selectVertices(List.of("A"), EventTrigger.INTERNAL_ONLY);
|
select(a);
|
||||||
DockingActionIf action = getAction(tool, "Grow Selection To Targets");
|
DockingActionIf action = getAction(tool, "Grow Selection To Targets");
|
||||||
GraphActionContext context =
|
GraphActionContext context =
|
||||||
new GraphActionContext(graphComponentProvider, graph, null, null);
|
new GraphActionContext(graphComponentProvider, graph, null, null);
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVerticeIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selectedVerticeIds = display.getSelectedVertices();
|
||||||
assertEquals(3, selectedVerticeIds.size());
|
assertEquals(3, selectedVerticeIds.size());
|
||||||
assertTrue(selectedVerticeIds.contains("A"));
|
assertTrue(selectedVerticeIds.contains(a));
|
||||||
assertTrue(selectedVerticeIds.contains("B"));
|
assertTrue(selectedVerticeIds.contains(b));
|
||||||
assertTrue(selectedVerticeIds.contains("C"));
|
assertTrue(selectedVerticeIds.contains(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGrowSelectionIn() {
|
public void testGrowSelectionIn() {
|
||||||
display.selectVertices(List.of("D"), EventTrigger.INTERNAL_ONLY);
|
select(d);
|
||||||
DockingActionIf action = getAction(tool, "Grow Selection From Sources");
|
DockingActionIf action = getAction(tool, "Grow Selection From Sources");
|
||||||
GraphActionContext context =
|
GraphActionContext context =
|
||||||
new GraphActionContext(graphComponentProvider, graph, null, null);
|
new GraphActionContext(graphComponentProvider, graph, null, null);
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
Set<String> selectedVerticeIds = display.getSelectedVertexIds();
|
Set<AttributedVertex> selectedVertices = display.getSelectedVertices();
|
||||||
assertEquals(3, selectedVerticeIds.size());
|
assertEquals(3, selectedVertices.size());
|
||||||
assertTrue(selectedVerticeIds.contains("D"));
|
assertTrue(selectedVertices.contains(d));
|
||||||
assertTrue(selectedVerticeIds.contains("B"));
|
assertTrue(selectedVertices.contains(b));
|
||||||
assertTrue(selectedVerticeIds.contains("C"));
|
assertTrue(selectedVertices.contains(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -216,7 +221,7 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(1, graphProviders.size());
|
assertEquals(1, graphProviders.size());
|
||||||
DefaultGraphDisplayComponentProvider original = graphProviders.get(0);
|
DefaultGraphDisplayComponentProvider original = graphProviders.get(0);
|
||||||
|
|
||||||
display.selectVertices(List.of("B", "C", "D"), EventTrigger.INTERNAL_ONLY);
|
select(b, c, d);
|
||||||
DockingActionIf action = getAction(tool, "Create Subgraph");
|
DockingActionIf action = getAction(tool, "Create Subgraph");
|
||||||
GraphActionContext context =
|
GraphActionContext context =
|
||||||
new GraphActionContext(graphComponentProvider, graph, null, null);
|
new GraphActionContext(graphComponentProvider, graph, null, null);
|
||||||
|
@ -241,8 +246,8 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertFalse(contains(newGraph, "F"));
|
assertFalse(contains(newGraph, "F"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean contains(AttributedGraph graph, String vertexId) {
|
private boolean contains(AttributedGraph g, String vertexId) {
|
||||||
return graph.getVertex(vertexId) != null;
|
return g.getVertex(vertexId) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showGraph() throws Exception {
|
private void showGraph() throws Exception {
|
||||||
|
@ -253,6 +258,17 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
display.setGraphDisplayListener(new TestGraphDisplayListener("test"));
|
display.setGraphDisplayListener(new TestGraphDisplayListener("test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void select(AttributedVertex... vertices) {
|
||||||
|
runSwing(() -> {
|
||||||
|
Set<AttributedVertex> vetexSet = new HashSet<>(Arrays.asList(vertices));
|
||||||
|
display.selectVertices(vetexSet, EventTrigger.INTERNAL_ONLY);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFocusedVertex(AttributedVertex vertex) {
|
||||||
|
runSwing(() -> display.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY));
|
||||||
|
}
|
||||||
|
|
||||||
class TestGraphDisplayListener implements GraphDisplayListener {
|
class TestGraphDisplayListener implements GraphDisplayListener {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -267,20 +283,20 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectionChanged(List<String> vertexIds) {
|
public void selectionChanged(Set<AttributedVertex> verrtices) {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append(name);
|
buf.append(name);
|
||||||
buf.append(": selected: ");
|
buf.append(": selected: ");
|
||||||
for (String id : vertexIds) {
|
for (AttributedVertex vertex : verrtices) {
|
||||||
buf.append(id);
|
buf.append(vertex.getId());
|
||||||
buf.append(",");
|
buf.append(",");
|
||||||
}
|
}
|
||||||
listenerCalls.add(buf.toString());
|
listenerCalls.add(buf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void locationFocusChanged(String vertexId) {
|
public void locationFocusChanged(AttributedVertex vertex) {
|
||||||
listenerCalls.add(name + ": focus: " + vertexId);
|
listenerCalls.add(name + ": focus: " + vertex.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -292,12 +308,12 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private AttributedGraph createGraph() {
|
private AttributedGraph createGraph() {
|
||||||
AttributedGraph g = new AttributedGraph();
|
AttributedGraph g = new AttributedGraph();
|
||||||
AttributedVertex a = g.addVertex("A");
|
a = g.addVertex("A");
|
||||||
AttributedVertex b = g.addVertex("B");
|
b = g.addVertex("B");
|
||||||
AttributedVertex c = g.addVertex("C");
|
c = g.addVertex("C");
|
||||||
AttributedVertex d = g.addVertex("D");
|
d = g.addVertex("D");
|
||||||
AttributedVertex e = g.addVertex("E");
|
e = g.addVertex("E");
|
||||||
AttributedVertex f = g.addVertex("F");
|
f = g.addVertex("F");
|
||||||
|
|
||||||
g.addEdge(a, b);
|
g.addEdge(a, b);
|
||||||
g.addEdge(a, c);
|
g.addEdge(a, c);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue