diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java index c6dd82787c..f7f7185206 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java @@ -15,8 +15,7 @@ */ package ghidra.app.plugin.core.graph; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import docking.widgets.EventTrigger; @@ -29,8 +28,7 @@ import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.*; import ghidra.program.util.*; -import ghidra.service.graph.GraphDisplay; -import ghidra.service.graph.GraphDisplayListener; +import ghidra.service.graph.*; import ghidra.util.Swing; /** @@ -40,7 +38,7 @@ public abstract class AddressBasedGraphDisplayListener implements GraphDisplayListener, PluginEventListener, DomainObjectListener { protected PluginTool tool; - private GraphDisplay graphDisplay; + protected GraphDisplay graphDisplay; protected Program program; private SymbolTable symbolTable; private String name; @@ -63,8 +61,8 @@ public abstract class AddressBasedGraphDisplayListener } @Override - public void locationFocusChanged(String vertexId) { - Address address = getAddressForVertexId(vertexId); + public void locationFocusChanged(AttributedVertex vertex) { + Address address = getAddress(vertex); if (address != null) { ProgramLocation location = new ProgramLocation(program, address); tool.firePluginEvent(new ProgramLocationPluginEvent(name, location, program)); @@ -72,8 +70,8 @@ public abstract class AddressBasedGraphDisplayListener } @Override - public void selectionChanged(List vertexIds) { - AddressSet addressSet = getAddressSetForVertices(vertexIds); + public void selectionChanged(Set vertices) { + AddressSet addressSet = getAddresses(vertices); if (addressSet != null) { ProgramSelection selection = new ProgramSelection(addressSet); ProgramSelectionPluginEvent event = @@ -99,16 +97,16 @@ public abstract class AddressBasedGraphDisplayListener ProgramLocationPluginEvent ev = (ProgramLocationPluginEvent) event; if (isMyProgram(ev.getProgram())) { 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 - graphDisplay.setLocationFocus(id, EventTrigger.INTERNAL_ONLY); + graphDisplay.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY); } } else if (event instanceof ProgramSelectionPluginEvent) { ProgramSelectionPluginEvent ev = (ProgramSelectionPluginEvent) event; if (isMyProgram(ev.getProgram())) { ProgramSelection selection = ev.getSelection(); - List selectedVertices = getVertices(selection); + Set selectedVertices = getVertices(selection); if (selectedVertices != null) { // since we are responding to an event, tell the GraphDisplay not to send event 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. if (address.isExternalAddress()) { Symbol s = symbolTable.getPrimarySymbol(address); @@ -153,13 +159,16 @@ public abstract class AddressBasedGraphDisplayListener } - protected Address getAddressForVertexId(String vertexId) { - return getAddress(vertexId); + protected Address getAddress(AttributedVertex vertex) { + if (vertex == null) { + return null; + } + return getAddress(vertex.getId()); } - protected abstract List getVertices(AddressSetView selection); + protected abstract Set getVertices(AddressSetView selection); - protected abstract AddressSet getAddressSetForVertices(List vertexIds); + protected abstract AddressSet getAddresses(Set vertexIds); private boolean isMyProgram(Program p) { return p == program; @@ -192,15 +201,18 @@ public abstract class AddressBasedGraphDisplayListener } private void handleSymbolAddedOrRenamed(Address address, Symbol symbol) { - String id = getVertexIdForAddress(address); - graphDisplay.updateVertexName(id, symbol.getName()); + AttributedVertex vertex = getVertex(address); + graphDisplay.updateVertexName(vertex, symbol.getName()); } private void handleSymbolRemoved(Address address) { - String id = getVertexIdForAddress(address); + AttributedVertex vertex = getVertex(address); + if (vertex == null) { + return; + } Symbol symbol = program.getSymbolTable().getPrimarySymbol(address); String displayName = symbol == null ? address.toString() : symbol.getName(); - graphDisplay.updateVertexName(id, displayName); + graphDisplay.updateVertexName(vertex, displayName); } private void dispose() { diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java index 26598aacf8..87ddf30c9e 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/GraphAST.java @@ -232,16 +232,15 @@ public class GraphAST extends GhidraScript { } @Override - protected List getVertices(AddressSetView selection) { - List ids = new ArrayList(); - return ids; + protected Set getVertices(AddressSetView selection) { + return Collections.emptySet(); } @Override - protected AddressSet getAddressSetForVertices(List vertexIds) { + protected AddressSet getAddresses(Set vertices) { AddressSet set = new AddressSet(); - for (String id : vertexIds) { - Address address = getAddressForVertexId(id); + for (AttributedVertex vertex : vertices) { + Address address = getAddress(vertex); if (address != null) { set.add(address); } @@ -250,7 +249,11 @@ public class GraphAST extends GhidraScript { } @Override - protected Address getAddressForVertexId(String vertexId) { + protected Address getAddress(AttributedVertex vertex) { + if (vertex == null) { + return null; + } + String vertexId = vertex.getId(); int firstcolon = vertexId.indexOf(':'); if (firstcolon == -1) { return null; diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphDisplayListener.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphDisplayListener.java index 10a9f83c3b..26d207076d 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphDisplayListener.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphDisplayListener.java @@ -17,8 +17,7 @@ package ghidra.app.plugin.core.decompile.actions; import static ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType.*; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType; 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.pcode.HighFunction; import ghidra.program.model.pcode.PcodeBlockBasic; -import ghidra.service.graph.GraphDisplay; -import ghidra.service.graph.GraphDisplayListener; +import ghidra.service.graph.*; import ghidra.util.exception.AssertException; /** @@ -45,33 +43,37 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener { } @Override - protected List getVertices(AddressSetView selection) { + protected Set getVertices(AddressSetView selection) { if (graphType != CONTROL_FLOW_GRAPH) { return null; } - List vertices = new ArrayList<>(); + Set vertices = new HashSet<>(); List blocks = hfunction.getBasicBlocks(); for (PcodeBlockBasic block : blocks) { Address start = block.getStart(); Address stop = block.getStop(); 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; } @Override - protected AddressSet getAddressSetForVertices(List vertexIds) { + protected AddressSet getAddresses(Set vertices) { if (graphType != CONTROL_FLOW_GRAPH) { return null; } AddressSet set = new AddressSet(); List blocks = hfunction.getBasicBlocks(); - for (String vertixId : vertexIds) { + for (AttributedVertex vertex : vertices) { try { - int index = Integer.parseInt(vertixId); + int index = Integer.parseInt(vertex.getId()); PcodeBlockBasic block = blocks.get(index); Address start = block.getStart(); set.addRange(start, block.getStop()); @@ -84,7 +86,7 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener { } @Override - protected String getVertexIdForAddress(Address address) { + protected String getVertexId(Address address) { if (graphType != CONTROL_FLOW_GRAPH) { return null; } @@ -96,25 +98,25 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener { return Integer.toString(block.getIndex()); } } - return super.getVertexIdForAddress(address); + return super.getVertexId(address); } @Override - protected Address getAddressForVertexId(String vertexId) { + protected Address getAddress(AttributedVertex vertex) { List blocks = hfunction.getBasicBlocks(); try { - int index = Integer.parseInt(vertexId); + int index = Integer.parseInt(vertex.getId()); PcodeBlockBasic block = blocks.get(index); return block.getStart(); } 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 - public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) { + public GraphDisplayListener cloneWith(GraphDisplay display) { return new ASTGraphDisplayListener(tool, graphDisplay, hfunction, graphType); } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java index 933672c1c6..a90afdd28a 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ASTGraphTask.java @@ -124,9 +124,9 @@ public class ASTGraphTask extends Task { display.setGraph(graph, description, false, monitor); // set the graph location if (location != null) { - String id = displayListener.getVertexIdForAddress(location); + AttributedVertex vertex = displayListener.getVertex(location); // update graph location, but don't have it send out event - display.setLocationFocus(id, EventTrigger.INTERNAL_ONLY); + display.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY); } } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java index 12a4a0e14f..44fa500bbb 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java @@ -15,7 +15,8 @@ */ package ghidra.graph.export; -import java.util.*; +import java.util.Collections; +import java.util.Set; import org.jgrapht.Graph; @@ -57,15 +58,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay { // This display is not interactive, so N/A } - @Override - public void selectVertices(List 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 @@ -108,7 +101,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay { } @Override - public void updateVertexName(String id, String newName) { + public void updateVertexName(AttributedVertex vertex, String newName) { // do nothing } @@ -123,13 +116,28 @@ class ExportAttributedGraphDisplay implements GraphDisplay { } @Override - public String getFocusedVertexId() { + public AttributedVertex getFocusedVertex() { return null; } @Override - public Set getSelectedVertexIds() { + public Set getSelectedVertices() { 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 vertexList, EventTrigger eventTrigger) { + // not interactive, so N/A + } + } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 3a2b4300e3..d6e08558d4 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -539,9 +539,7 @@ public class DefaultGraphDisplay implements GraphDisplay { } }); Set selected = selectedVertexState.getSelected(); - List selectedIds = - selected.stream().map(AttributedVertex::getId).collect(Collectors.toList()); - notifySelectionChanged(selectedIds); + notifySelectionChanged(selected); } finally { switchableSelectionListener.setEnabled(true); @@ -716,17 +714,18 @@ public class DefaultGraphDisplay implements GraphDisplay { 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; this.focusedVertex = vertex; if (focusedVertex != null) { if (changed && eventTrigger != EventTrigger.INTERNAL_ONLY) { - notifyLocationFocusChanged(focusedVertex.getId()); + notifyLocationFocusChanged(focusedVertex); } // make sure the vertex is visible, even if the vertex has not changed scrollToSelected(focusedVertex); - viewer.repaint(); } + viewer.repaint(); } /** @@ -769,22 +768,22 @@ public class DefaultGraphDisplay implements GraphDisplay { /** * 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 vertexIds) { - Swing.runLater(() -> listener.selectionChanged(vertexIds)); + private void notifySelectionChanged(Set selected) { + Swing.runLater(() -> listener.selectionChanged(selected)); } /** * 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) { - Swing.runLater(() -> listener.locationFocusChanged(vertexId)); + private void notifyLocationFocusChanged(AttributedVertex vertex) { + Swing.runLater(() -> listener.locationFocusChanged(vertex)); } @Override - public void selectVertices(List vertexIdList, EventTrigger eventTrigger) { + public void selectVertices(Set selected, EventTrigger eventTrigger) { // if we are not to fire events, turn off the selection listener we provided to the // graphing library. switchableSelectionListener.setEnabled(eventTrigger != EventTrigger.INTERNAL_ONLY); @@ -792,8 +791,7 @@ public class DefaultGraphDisplay implements GraphDisplay { try { MutableSelectedState nodeSelectedState = viewer.getSelectedVertexState(); - Set selected = getVertices(vertexIdList); - if (vertexIdList.isEmpty()) { + if (selected.isEmpty()) { nodeSelectedState.clear(); } 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 getVertices(Collection vertexIds) { - Set 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 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 @@ -1066,23 +1040,15 @@ public class DefaultGraphDisplay implements GraphDisplay { /** * process a request to update the name attribute value of the vertex with the * supplied id - * @param id the vertix id + * @param vertex the vertex to update * @param newName the new name of the vertex */ @Override - public void updateVertexName(String id, String newName) { - // find the vertex, if present, change the name - Optional optional = graph.vertexSet() - .stream() - .filter(v -> v.getId().equals(id)) - .findFirst(); - if (optional.isPresent()) { - AttributedVertex vertex = optional.get(); - vertex.setName(newName); - vertex.clearCache(); - iconCache.evict(vertex); - viewer.repaint(); - } + public void updateVertexName(AttributedVertex vertex, String newName) { + vertex.setName(newName); + vertex.clearCache(); + iconCache.evict(vertex); + viewer.repaint(); } /** @@ -1225,8 +1191,7 @@ public class DefaultGraphDisplay implements GraphDisplay { // vertices if (e.getStateChange() == ItemEvent.SELECTED) { Collection selectedVertices = getVertices(e.getItem()); - List selectedVertexIds = toVertexIds(selectedVertices); - notifySelectionChanged(selectedVertexIds); + notifySelectionChanged(new HashSet(selectedVertices)); if (selectedVertices.size() == 1) { // 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) { - notifySelectionChanged(Collections.emptyList()); + notifySelectionChanged(Collections.emptySet()); } viewer.repaint(); } @@ -1255,14 +1220,13 @@ public class DefaultGraphDisplay implements GraphDisplay { } @Override - public String getFocusedVertexId() { - return focusedVertex == null ? null : focusedVertex.getId(); + public AttributedVertex getFocusedVertex() { + return focusedVertex; } @Override - public Set getSelectedVertexIds() { - Set selectedVertices = getSelectedVertices(); - return selectedVertices.stream().map(v -> v.getId()).collect(Collectors.toSet()); + public Set getSelectedVertices() { + return viewer.getSelectedVertexState().getSelected(); } public ActionContext getActionContext(MouseEvent e) { @@ -1284,9 +1248,6 @@ public class DefaultGraphDisplay implements GraphDisplay { } - private Set getSelectedVertices() { - return viewer.getSelectedVertexState().getSelected(); - } /** * Use the hide selected action states to determine what vertices are shown: @@ -1321,4 +1282,8 @@ public class DefaultGraphDisplay implements GraphDisplay { viewer.repaint(); } + @Override + public AttributedGraph getGraph() { + return graph; + } } diff --git a/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockGraphTask.java b/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockGraphTask.java index aec3bbd135..dfd5fa95ac 100644 --- a/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockGraphTask.java +++ b/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockGraphTask.java @@ -157,13 +157,13 @@ public class BlockGraphTask extends Task { if (location != null) { // initialize the graph location, but don't have the graph send an event - String id = listener.getVertexIdForAddress(location.getAddress()); - display.setLocationFocus(id, EventTrigger.INTERNAL_ONLY); + AttributedVertex vertex = listener.getVertex(location.getAddress()); + display.setFocusedVertex(vertex, EventTrigger.INTERNAL_ONLY); } if (selection != null && !selection.isEmpty()) { - List selectedVertices = listener.getVertices(selection); + Set selectedVertices = listener.getVertices(selection); 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); } } diff --git a/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockModelGraphDisplayListener.java b/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockModelGraphDisplayListener.java index d6f31eb730..858fc4a804 100644 --- a/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockModelGraphDisplayListener.java +++ b/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/BlockModelGraphDisplayListener.java @@ -54,28 +54,28 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList } @Override - protected String getVertexIdForAddress(Address address) { + protected String getVertexId(Address address) { try { CodeBlock[] blocks = blockModel.getCodeBlocksContaining(address, TaskMonitor.DUMMY); if (blocks != null && blocks.length > 0) { - return super.getVertexIdForAddress(blocks[0].getFirstStartAddress()); + return super.getVertexId(blocks[0].getFirstStartAddress()); } } catch (CancelledException e) { // Will not happen with dummyMonitor // Model has already done the work when the graph was created } - return super.getVertexIdForAddress(address); + return super.getVertexId(address); } @Override - protected List getVertices(AddressSetView addrSet) { + protected Set getVertices(AddressSetView addrSet) { if (addrSet.isEmpty()) { - return Collections.emptyList(); + return Collections.emptySet(); } // Identify all blocks which have an entry point within the selection address set - ArrayList blockList = new ArrayList(); + Set vertices = new HashSet<>(); try { SymbolTable symTable = program.getSymbolTable(); CodeBlockIterator cbIter = @@ -91,7 +91,10 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList else { addrString = addr.toString(); } - blockList.add(addrString); + AttributedVertex vertex = graphDisplay.getGraph().getVertex(addrString); + if (vertex != null) { + vertices.add(vertex); + } } } catch (CancelledException e) { @@ -99,18 +102,18 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList // Model has already done the work when the graph was created } - return blockList; + return vertices; } @Override - protected AddressSet getAddressSetForVertices(List vertexIds) { + protected AddressSet getAddresses(Set vertices) { AddressSet addrSet = new AddressSet(); try { // for each address string, translate it into a block // and add it to the address set. - for (String vertexId : vertexIds) { - Address blockAddr = getAddressForVertexId(vertexId); + for (AttributedVertex vertex : vertices) { + Address blockAddr = getAddress(vertex); if (!isValidAddress(blockAddr)) { continue; } @@ -150,8 +153,8 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList } private void updateVertexName(VertexGraphActionContext context) { - String vertexId = context.getClickedVertex().getId(); - Address address = getAddressForVertexId(vertexId); + AttributedVertex vertex = context.getClickedVertex(); + Address address = getAddress(vertex); Symbol symbol = program.getSymbolTable().getPrimarySymbol(address); if (symbol == null) { @@ -165,8 +168,8 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList } @Override - public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) { - return new BlockModelGraphDisplayListener(tool, blockModel, graphDisplay); + public GraphDisplayListener cloneWith(GraphDisplay newGraphDisplay) { + return new BlockModelGraphDisplayListener(tool, blockModel, newGraphDisplay); } } diff --git a/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/BlockGraphEventTest.java b/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/BlockGraphEventTest.java index 888948c729..f7135cdf5e 100644 --- a/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/BlockGraphEventTest.java +++ b/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/BlockGraphEventTest.java @@ -17,7 +17,8 @@ package ghidra.graph.program; import static org.junit.Assert.*; -import java.util.*; +import java.util.HashSet; +import java.util.Set; import org.junit.Test; @@ -27,6 +28,7 @@ import ghidra.program.model.block.CodeBlockModel; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; import ghidra.service.graph.AttributedGraph; +import ghidra.service.graph.AttributedVertex; import ghidra.util.task.TaskMonitor; public class BlockGraphEventTest extends AbstractBlockGraphTest { @@ -54,13 +56,13 @@ public class BlockGraphEventTest extends AbstractBlockGraphTest { @Test public void testGhidraLocationChanged() { codeBrowser.goTo(new ProgramLocation(program, addr(0x1002239))); - assertEquals("01002239", display.getFocusedVertex()); + assertEquals("01002239", display.getFocusedVertex().getId()); 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 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 public void testGhidraSelectionChanged() { setSelection(addrSet(0x1002239, 0x1002241)); - Set selected = new HashSet<>(display.getSelectedVertices()); + Set selected = new HashSet<>(display.getSelectedVertices()); assertEquals(3, selected.size()); - assertTrue(selected.contains("01002239")); - assertTrue(selected.contains("0100223c")); - assertTrue(selected.contains("0100223e")); + assertTrue(selected.contains(graph.getVertex("01002239"))); + assertTrue(selected.contains(graph.getVertex("0100223c"))); + assertTrue(selected.contains(graph.getVertex("0100223e"))); setSelection(new AddressSet(addr(0x1002200), addr(0x1002210))); selected = new HashSet<>(display.getSelectedVertices()); assertEquals(2, selected.size()); - assertTrue(selected.contains("01002200")); - assertTrue(selected.contains("01002203")); + assertTrue(selected.contains(graph.getVertex("01002200"))); + assertTrue(selected.contains(graph.getVertex("01002203"))); } @Test public void testGraphNodeFocused() { - display.focusChanged("01002203"); + display.focusChanged(graph.getVertex("01002203")); assertEquals(addr(0x01002203), codeBrowser.getCurrentLocation().getAddress()); - display.focusChanged("0100223c"); + display.focusChanged(graph.getVertex("0100223c")); assertEquals(addr(0x0100223c), codeBrowser.getCurrentLocation().getAddress()); } @Test public void testGraphNodesSelected() { - display.selectionChanged(Arrays.asList("01002239", "0100223c")); + display.selectionChanged(Set.of(graph.getVertex("01002239"), graph.getVertex("0100223c"))); ProgramSelection selection = codeBrowser.getCurrentSelection(); assertEquals(addr(0x01002239), selection.getMinAddress()); assertEquals(addr(0x0100223d), selection.getMaxAddress()); - display.selectionChanged(Arrays.asList("01002200", "01002203")); + display.selectionChanged(Set.of(graph.getVertex("01002200"), graph.getVertex("01002203"))); selection = codeBrowser.getCurrentSelection(); assertEquals(addr(0x01002200), selection.getMinAddress()); assertEquals(addr(0x01002204), selection.getMaxAddress()); diff --git a/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/TestGraphDisplay.java b/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/TestGraphDisplay.java index b0ac6fdd70..8a3ccab2a2 100644 --- a/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/TestGraphDisplay.java +++ b/Ghidra/Features/ProgramGraph/src/test/java/ghidra/graph/program/TestGraphDisplay.java @@ -15,7 +15,8 @@ */ package ghidra.graph.program; -import java.util.*; +import java.util.HashSet; +import java.util.Set; import docking.action.DockingAction; import docking.widgets.EventTrigger; @@ -26,12 +27,11 @@ import ghidra.util.task.TaskMonitor; public class TestGraphDisplay implements GraphDisplay { private Set definedVertexAttributes = new HashSet<>(); private Set definedEdgeAttributes = new HashSet<>(); - private String vertexAttributeName; private AttributedGraph graph; private String graphDescription; private GraphDisplayListener listener; - private String currentFocusedVertex; - private List currentSelection; + private AttributedVertex focusedVertex; + private Set currentSelection; @Override public void setGraphDisplayListener(GraphDisplayListener listener) { @@ -39,20 +39,22 @@ public class TestGraphDisplay implements GraphDisplay { } @Override - public void setLocationFocus(String vertexID, EventTrigger eventTrigger) { - currentFocusedVertex = vertexID; - } - - public String getFocusedVertex() { - return currentFocusedVertex; + public void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger) { + focusedVertex = vertex; } @Override - public void selectVertices(List vertexList, EventTrigger eventTrigger) { + public AttributedVertex getFocusedVertex() { + return focusedVertex; + } + + @Override + public void selectVertices(Set vertexList, EventTrigger eventTrigger) { currentSelection = vertexList; } - public List getSelectedVertices() { + @Override + public Set getSelectedVertices() { return currentSelection; } @@ -74,7 +76,7 @@ public class TestGraphDisplay implements GraphDisplay { @Override public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace, int maxLines) { - vertexAttributeName = attributeName; + // nothing } @Override @@ -91,7 +93,7 @@ public class TestGraphDisplay implements GraphDisplay { } @Override - public void updateVertexName(String id, String newName) { + public void updateVertexName(AttributedVertex vertex, String newName) { // nothing } @@ -100,16 +102,17 @@ public class TestGraphDisplay implements GraphDisplay { return graphDescription; } + @Override public AttributedGraph getGraph() { return graph; } - public void focusChanged(String vertexId) { - listener.locationFocusChanged(vertexId); + public void focusChanged(AttributedVertex vertex) { + listener.locationFocusChanged(vertex); } - public void selectionChanged(List vertexIds) { - listener.selectionChanged(vertexIds); + public void selectionChanged(Set vertices) { + listener.selectionChanged(vertices); } @Override @@ -117,14 +120,4 @@ public class TestGraphDisplay implements GraphDisplay { // do nothing, actions are not supported by this display } - @Override - public String getFocusedVertexId() { - return currentFocusedVertex; - } - - @Override - public Set getSelectedVertexIds() { - return new HashSet(currentSelection); - } - } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java index 77dd5a4514..11b056fcbb 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java @@ -15,7 +15,7 @@ */ package ghidra.service.graph; -import java.util.List; +import java.util.Set; public class DummyGraphDisplayListener implements GraphDisplayListener { @@ -24,19 +24,19 @@ public class DummyGraphDisplayListener implements GraphDisplayListener { // I'm a dummy } - @Override - public void selectionChanged(List vertexIds) { - // I'm a dummy - } - - @Override - public void locationFocusChanged(String vertexId) { - // I'm a dummy - } - @Override public GraphDisplayListener cloneWith(GraphDisplay graphDisplay) { return new DummyGraphDisplayListener(); } + @Override + public void selectionChanged(Set vertices) { + // I'm a dummy + } + + @Override + public void locationFocusChanged(AttributedVertex vertex) { + // I'm a dummy + } + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java index a4ae64fec1..ba57ffe0f1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplay.java @@ -15,7 +15,6 @@ */ package ghidra.service.graph; -import java.util.List; import java.util.Set; import docking.action.DockingAction; @@ -46,41 +45,46 @@ public interface GraphDisplay { /** * 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 * 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 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 - * information. - * + * the {@link GraphDisplayListener#locationFocusChanged(AttributedVertex)}. For example, if we + * are updating 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 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. - * @return the currently focused vertexID or null if no vertex is focussed. + * Returns the graph for this display + * @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 * - * @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 * 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 * application the graph changed to avoid event cycles. See {@link EventTrigger} for more * information. */ - public void selectVertices(List vertexList, EventTrigger eventTrigger); + public void selectVertices(Set vertexSet, EventTrigger eventTrigger); /** - * Returns a list of vertex ids for all the currently selected vertices - * @return 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 set of vertex ids for all the currently selected vertices */ - public Set getSelectedVertexIds(); + public Set getSelectedVertices(); /** * Closes this graph display window. @@ -131,10 +135,10 @@ public interface GraphDisplay { /** * Updates a vertex to a new name - * @param id the vertex id - * @param newName the new name of the vertex + * @param vertex the vertex to rename + * @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 @@ -148,4 +152,5 @@ public interface GraphDisplay { * @param action the action to add. */ public void addAction(DockingAction action); + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java index 011ae15cda..c763ea3977 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java @@ -15,7 +15,7 @@ */ 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 @@ -27,17 +27,17 @@ public interface GraphDisplayListener { 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 vertexIds); + public void selectionChanged(Set vertices); /** * 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 diff --git a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java index 9c69c0a0db..f20f320360 100644 --- a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java +++ b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java @@ -40,6 +40,12 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { private AttributedGraph graph; private ComponentProvider graphComponentProvider; private GraphDisplay display; + private AttributedVertex a; + private AttributedVertex b; + private AttributedVertex c; + private AttributedVertex d; + private AttributedVertex e; + private AttributedVertex f; @Before public void setUp() throws Exception { @@ -60,7 +66,7 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { @Test public void testSelectVertexAction() { - assertTrue(display.getSelectedVertexIds().isEmpty()); + assertTrue(display.getSelectedVertices().isEmpty()); DockingActionIf action = getAction(tool, "Select Vertex"); VertexGraphActionContext context = @@ -68,25 +74,24 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { graph.getVertex("B")); performAction(action, context, true); - Set selectedVertexIds = display.getSelectedVertexIds(); - assertEquals(1, selectedVertexIds.size()); - assertTrue(selectedVertexIds.contains(graph.getVertex("B").getId())); + Set selectedVertices = display.getSelectedVertices(); + assertEquals(1, selectedVertices.size()); + assertTrue(selectedVertices.contains(b)); // now try and select a second vertex - context = new VertexGraphActionContext(graphComponentProvider, graph, null, null, - graph.getVertex("D")); + context = new VertexGraphActionContext(graphComponentProvider, graph, null, null,d); performAction(action, context, true); - selectedVertexIds = display.getSelectedVertexIds(); - assertEquals(2, selectedVertexIds.size()); - assertTrue(selectedVertexIds.contains(graph.getVertex("B").getId())); - assertTrue(selectedVertexIds.contains(graph.getVertex("D").getId())); + selectedVertices = display.getSelectedVertices(); + assertEquals(2, selectedVertices.size()); + assertTrue(selectedVertices.contains(b)); + assertTrue(selectedVertices.contains(d)); } @Test public void testDeSelectVertexAction() { - display.selectVertices(Arrays.asList("A", "B", "C", "D"), EventTrigger.API_CALL); - assertEquals(4, display.getSelectedVertexIds().size()); + select(a, b, c, d); + assertEquals(4, display.getSelectedVertices().size()); DockingActionIf action = getAction(tool, "Deselect Vertex"); VertexGraphActionContext context = @@ -94,18 +99,18 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { graph.getVertex("B")); performAction(action, context, true); - Set selectedVerticeIds = display.getSelectedVertexIds(); - assertEquals(3, selectedVerticeIds.size()); - assertTrue(selectedVerticeIds.contains(graph.getVertex("A").getId())); - assertTrue(selectedVerticeIds.contains(graph.getVertex("D").getId())); - assertTrue(selectedVerticeIds.contains(graph.getVertex("D").getId())); - assertFalse(selectedVerticeIds.contains(graph.getVertex("B").getId())); + Set selected = display.getSelectedVertices(); + assertEquals(3, selected.size()); + assertTrue(selected.contains(a)); + assertTrue(selected.contains(c)); + assertTrue(selected.contains(d)); + assertFalse(selected.contains(b)); } @Test public void testSelectEdgeAction() { - assertTrue(display.getSelectedVertexIds().isEmpty()); + assertTrue(display.getSelectedVertices().isEmpty()); DockingActionIf action = getAction(tool, "Select Edge"); EdgeGraphActionContext context = @@ -113,10 +118,10 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { graph.getEdge(graph.getVertex("A"), graph.getVertex("B"))); performAction(action, context, true); - Set selectedVerticeIds = display.getSelectedVertexIds(); + Set selectedVerticeIds = display.getSelectedVertices(); assertEquals(2, selectedVerticeIds.size()); - assertTrue(selectedVerticeIds.contains(graph.getVertex("A").getId())); - assertTrue(selectedVerticeIds.contains(graph.getVertex("B").getId())); + assertTrue(selectedVerticeIds.contains(a)); + assertTrue(selectedVerticeIds.contains(b)); } @Test @@ -127,85 +132,85 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { graph.getEdge(graph.getVertex("A"), graph.getVertex("B"))); performAction(action, context, true); - Set selectedVerticeIds = display.getSelectedVertexIds(); - assertEquals(2, selectedVerticeIds.size()); + Set selectedVertices = display.getSelectedVertices(); + assertEquals(2, selectedVertices.size()); action = getAction(tool, "Deselect Edge"); performAction(action, context, true); - selectedVerticeIds = display.getSelectedVertexIds(); - assertEquals(0, selectedVerticeIds.size()); - + selectedVertices = display.getSelectedVertices(); + assertEquals(0, selectedVertices.size()); } @Test public void testSelectEdgeSource() { - display.setLocationFocus("D", EventTrigger.INTERNAL_ONLY); + setFocusedVertex(d); DockingActionIf action = getAction(tool, "Edge Source"); EdgeGraphActionContext context = new EdgeGraphActionContext(graphComponentProvider, graph, null, null, graph.getEdge(graph.getVertex("A"), graph.getVertex("B"))); performAction(action, context, true); - assertEquals("A", display.getFocusedVertexId()); + assertEquals(a, display.getFocusedVertex()); } @Test public void testSelectEdgeTarget() { - display.setLocationFocus("D", EventTrigger.INTERNAL_ONLY); + setFocusedVertex(d); DockingActionIf action = getAction(tool, "Edge Target"); EdgeGraphActionContext context = new EdgeGraphActionContext(graphComponentProvider, graph, null, null, - graph.getEdge(graph.getVertex("A"), graph.getVertex("B"))); + graph.getEdge(a, b)); performAction(action, context, true); - assertEquals("B", display.getFocusedVertexId()); + assertEquals(b, display.getFocusedVertex()); } @Test public void testInvertSelection() { - display.selectVertices(List.of("A", "C", "E"), EventTrigger.INTERNAL_ONLY); + select(a, c, e); DockingActionIf action = getAction(tool, "Invert Selection"); GraphActionContext context = new GraphActionContext(graphComponentProvider, graph, null, null); performAction(action, context, true); - Set selectedVerticeIds = display.getSelectedVertexIds(); - assertEquals(3, selectedVerticeIds.size()); - assertTrue(selectedVerticeIds.contains("B")); - assertTrue(selectedVerticeIds.contains("D")); - assertTrue(selectedVerticeIds.contains("F")); + Set selectedVertices = display.getSelectedVertices(); + assertEquals(3, selectedVertices.size()); + assertTrue(selectedVertices.contains(b)); + assertTrue(selectedVertices.contains(d)); + assertTrue(selectedVertices.contains(f)); } @Test public void testGrowSelectionOut() { - display.selectVertices(List.of("A"), EventTrigger.INTERNAL_ONLY); + select(a); DockingActionIf action = getAction(tool, "Grow Selection To Targets"); GraphActionContext context = new GraphActionContext(graphComponentProvider, graph, null, null); performAction(action, context, true); - Set selectedVerticeIds = display.getSelectedVertexIds(); + Set selectedVerticeIds = display.getSelectedVertices(); assertEquals(3, selectedVerticeIds.size()); - assertTrue(selectedVerticeIds.contains("A")); - assertTrue(selectedVerticeIds.contains("B")); - assertTrue(selectedVerticeIds.contains("C")); + assertTrue(selectedVerticeIds.contains(a)); + assertTrue(selectedVerticeIds.contains(b)); + assertTrue(selectedVerticeIds.contains(c)); } + @Test public void testGrowSelectionIn() { - display.selectVertices(List.of("D"), EventTrigger.INTERNAL_ONLY); + select(d); DockingActionIf action = getAction(tool, "Grow Selection From Sources"); GraphActionContext context = new GraphActionContext(graphComponentProvider, graph, null, null); performAction(action, context, true); - Set selectedVerticeIds = display.getSelectedVertexIds(); - assertEquals(3, selectedVerticeIds.size()); - assertTrue(selectedVerticeIds.contains("D")); - assertTrue(selectedVerticeIds.contains("B")); - assertTrue(selectedVerticeIds.contains("C")); + Set selectedVertices = display.getSelectedVertices(); + assertEquals(3, selectedVertices.size()); + assertTrue(selectedVertices.contains(d)); + assertTrue(selectedVertices.contains(b)); + assertTrue(selectedVertices.contains(c)); } @Test @@ -216,7 +221,7 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { assertEquals(1, graphProviders.size()); 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"); GraphActionContext context = new GraphActionContext(graphComponentProvider, graph, null, null); @@ -241,8 +246,8 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { assertFalse(contains(newGraph, "F")); } - private boolean contains(AttributedGraph graph, String vertexId) { - return graph.getVertex(vertexId) != null; + private boolean contains(AttributedGraph g, String vertexId) { + return g.getVertex(vertexId) != null; } private void showGraph() throws Exception { @@ -253,6 +258,17 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { display.setGraphDisplayListener(new TestGraphDisplayListener("test")); } + private void select(AttributedVertex... vertices) { + runSwing(() -> { + Set 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 { private String name; @@ -267,20 +283,20 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { } @Override - public void selectionChanged(List vertexIds) { + public void selectionChanged(Set verrtices) { StringBuilder buf = new StringBuilder(); buf.append(name); buf.append(": selected: "); - for (String id : vertexIds) { - buf.append(id); + for (AttributedVertex vertex : verrtices) { + buf.append(vertex.getId()); buf.append(","); } listenerCalls.add(buf.toString()); } @Override - public void locationFocusChanged(String vertexId) { - listenerCalls.add(name + ": focus: " + vertexId); + public void locationFocusChanged(AttributedVertex vertex) { + listenerCalls.add(name + ": focus: " + vertex.getId()); } @Override @@ -292,12 +308,12 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { private AttributedGraph createGraph() { AttributedGraph g = new AttributedGraph(); - AttributedVertex a = g.addVertex("A"); - AttributedVertex b = g.addVertex("B"); - AttributedVertex c = g.addVertex("C"); - AttributedVertex d = g.addVertex("D"); - AttributedVertex e = g.addVertex("E"); - AttributedVertex f = g.addVertex("F"); + a = g.addVertex("A"); + b = g.addVertex("B"); + c = g.addVertex("C"); + d = g.addVertex("D"); + e = g.addVertex("E"); + f = g.addVertex("F"); g.addEdge(a, b); g.addEdge(a, c);