mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-23 01:17:02 +08:00
Miscellanious bug fixes and code clean up.
This commit is contained in:
+7
-3
@@ -19,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.app.cmd.label.AddLabelCmd;
|
||||
import ghidra.app.cmd.label.RenameLabelCmd;
|
||||
import ghidra.app.events.*;
|
||||
@@ -65,7 +66,7 @@ public abstract class AddressBasedGraphDisplayListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void locationChanged(String vertexId) {
|
||||
public void locationFocusChanged(String vertexId) {
|
||||
Address address = getAddressForVertexId(vertexId);
|
||||
if (address != null) {
|
||||
ProgramLocation location = new ProgramLocation(program, address);
|
||||
@@ -101,7 +102,9 @@ public abstract class AddressBasedGraphDisplayListener
|
||||
ProgramLocationPluginEvent ev = (ProgramLocationPluginEvent) event;
|
||||
if (isMyProgram(ev.getProgram())) {
|
||||
ProgramLocation location = ev.getLocation();
|
||||
graphDisplay.setLocation(getVertexIdForAddress(location.getAddress()));
|
||||
String id = getVertexIdForAddress(location.getAddress());
|
||||
// update graph location, but tell it not to send out event
|
||||
graphDisplay.setLocationFocus(id, EventTrigger.INTERNAL_ONLY);
|
||||
}
|
||||
}
|
||||
else if (event instanceof ProgramSelectionPluginEvent) {
|
||||
@@ -110,7 +113,8 @@ public abstract class AddressBasedGraphDisplayListener
|
||||
ProgramSelection selection = ev.getSelection();
|
||||
List<String> selectedVertices = getVertices(selection);
|
||||
if (selectedVertices != null) {
|
||||
graphDisplay.selectVertices(selectedVertices);
|
||||
// since we are responding to an event, tell the GraphDisplay not to send event
|
||||
graphDisplay.selectVertices(selectedVertices, EventTrigger.INTERNAL_ONLY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-6
@@ -17,6 +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 ghidra.app.plugin.core.decompile.actions.ASTGraphTask.GraphType;
|
||||
@@ -26,6 +27,7 @@ import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.pcode.HighFunction;
|
||||
import ghidra.program.model.pcode.PcodeBlockBasic;
|
||||
import ghidra.service.graph.GraphDisplay;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* Listener for when an AST graph's nodes are selected.
|
||||
@@ -43,7 +45,19 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||
|
||||
@Override
|
||||
protected List<String> getVertices(AddressSetView selection) {
|
||||
return null;
|
||||
if (graphType != CONTROL_FLOW_GRAPH) {
|
||||
return null;
|
||||
}
|
||||
List<String> vertices = new ArrayList<>();
|
||||
List<PcodeBlockBasic> 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()));
|
||||
}
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,7 +67,6 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||
}
|
||||
|
||||
AddressSet set = new AddressSet();
|
||||
Address location = null;
|
||||
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
||||
for (String vertixId : vertexIds) {
|
||||
try {
|
||||
@@ -61,9 +74,6 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||
PcodeBlockBasic block = blocks.get(index);
|
||||
Address start = block.getStart();
|
||||
set.addRange(start, block.getStop());
|
||||
if (location == null || start.compareTo(location) < 0) {
|
||||
location = start;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// continue
|
||||
@@ -90,7 +100,16 @@ public class ASTGraphDisplayListener extends AddressBasedGraphDisplayListener {
|
||||
|
||||
@Override
|
||||
protected Address getAddressForVertexId(String vertexId) {
|
||||
return null;
|
||||
List<PcodeBlockBasic> blocks = hfunction.getBasicBlocks();
|
||||
|
||||
try {
|
||||
int index = Integer.parseInt(vertexId);
|
||||
PcodeBlockBasic block = blocks.get(index);
|
||||
return block.getStart();
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new AssertException("Bad vertex id, expected a number but got " + vertexId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@ package ghidra.app.plugin.core.decompile.actions;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.app.services.GraphDisplayBroker;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -122,7 +123,9 @@ public class ASTGraphTask extends Task {
|
||||
display.setGraph(graph, description, false, monitor);
|
||||
// set the graph location
|
||||
if (location != null) {
|
||||
display.setLocation(displayListener.getVertexIdForAddress(location));
|
||||
String id = displayListener.getVertexIdForAddress(location);
|
||||
// update graph location, but don't have it send out event
|
||||
display.setLocationFocus(id, EventTrigger.INTERNAL_ONLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ import java.util.List;
|
||||
|
||||
import org.jgrapht.Graph;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.Swing;
|
||||
@@ -56,12 +57,12 @@ class ExportAttributedGraphDisplay implements GraphDisplay {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectVertices(List<String> vertexList) {
|
||||
public void selectVertices(List<String> vertexList, EventTrigger eventTrigger) {
|
||||
// This display is not interactive, so N/A
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocation(String vertexID) {
|
||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger) {
|
||||
// This display is not interactive, so N/A
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -23,17 +23,15 @@ import org.jungrapht.visualization.MultiLayerTransformer;
|
||||
import org.jungrapht.visualization.VisualizationViewer;
|
||||
|
||||
import ghidra.graph.job.AbstractAnimatorJob;
|
||||
import ghidra.service.graph.AttributedEdge;
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
|
||||
public class CenterAnimation<V, E> extends AbstractAnimatorJob {
|
||||
public class CenterAnimationJob extends AbstractAnimatorJob {
|
||||
protected int duration = 1000;
|
||||
private final Point2D oldPoint;
|
||||
private final Point2D newPoint;
|
||||
private final Point2D lastPoint = new Point2D.Double();
|
||||
private final VisualizationViewer<V, E> viewer;
|
||||
private final VisualizationViewer<?, ?> viewer;
|
||||
|
||||
public CenterAnimation(VisualizationViewer<V, E> viewer,
|
||||
public CenterAnimationJob(VisualizationViewer<?, ?> viewer,
|
||||
Point2D oldPoint, Point2D newPoint) {
|
||||
this.viewer = viewer;
|
||||
this.oldPoint = oldPoint;
|
||||
+275
-252
File diff suppressed because it is too large
Load Diff
+21
-26
@@ -15,21 +15,14 @@
|
||||
*/
|
||||
package ghidra.graph.visualization;
|
||||
|
||||
import org.jungrapht.visualization.layout.algorithms.BalloonLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.CircleLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.EiglspergerLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.FRLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.GEMLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.KKLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.RadialTreeLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.TidierRadialTreeLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.TidierTreeLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.TreeLayoutAlgorithm;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jungrapht.visualization.layout.algorithms.*;
|
||||
import org.jungrapht.visualization.layout.algorithms.repulsion.BarnesHutFRRepulsion;
|
||||
import org.jungrapht.visualization.layout.algorithms.sugiyama.Layering;
|
||||
|
||||
import java.util.function.Function;
|
||||
import ghidra.service.graph.AttributedEdge;
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
|
||||
/**
|
||||
* A central location to list and provide all layout algorithms, their names, and their builders
|
||||
@@ -38,8 +31,8 @@ import java.util.function.Function;
|
||||
* This class provides LayoutAlgorithm builders instead of LayoutAlgorithms because some LayoutAlgorithms
|
||||
* accumulate state information (so are used only one time).
|
||||
*/
|
||||
class LayoutFunction<V, E>
|
||||
implements Function<String, LayoutAlgorithm.Builder<V, ?, ?>> {
|
||||
class LayoutFunction
|
||||
implements Function<String, LayoutAlgorithm.Builder<AttributedVertex, ?, ?>> {
|
||||
|
||||
static final String KAMADA_KAWAI = "Force Balanced";
|
||||
static final String FRUCTERMAN_REINGOLD = "Force Directed";
|
||||
@@ -64,51 +57,53 @@ class LayoutFunction<V, E>
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutAlgorithm.Builder<V, ?, ?> apply(String name) {
|
||||
public LayoutAlgorithm.Builder<AttributedVertex, ?, ?> apply(String name) {
|
||||
switch(name) {
|
||||
case GEM:
|
||||
return GEMLayoutAlgorithm.edgeAwareBuilder();
|
||||
case KAMADA_KAWAI:
|
||||
return KKLayoutAlgorithm.<V> builder()
|
||||
return KKLayoutAlgorithm.<AttributedVertex> builder()
|
||||
.preRelaxDuration(1000);
|
||||
case FRUCTERMAN_REINGOLD:
|
||||
return FRLayoutAlgorithm.<V> builder()
|
||||
return FRLayoutAlgorithm.<AttributedVertex> builder()
|
||||
.repulsionContractBuilder(BarnesHutFRRepulsion.builder());
|
||||
case CIRCLE_MINCROSS:
|
||||
return CircleLayoutAlgorithm.<V> builder()
|
||||
return CircleLayoutAlgorithm.<AttributedVertex> builder()
|
||||
.reduceEdgeCrossing(true);
|
||||
case TIDIER_RADIAL_TREE:
|
||||
return TidierRadialTreeLayoutAlgorithm.<V, E> edgeAwareBuilder();
|
||||
return TidierRadialTreeLayoutAlgorithm
|
||||
.<AttributedVertex, AttributedEdge> edgeAwareBuilder();
|
||||
case MIN_CROSS_TOP_DOWN:
|
||||
return EiglspergerLayoutAlgorithm
|
||||
.<V, E> edgeAwareBuilder()
|
||||
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
|
||||
.layering(Layering.TOP_DOWN);
|
||||
case MIN_CROSS_LONGEST_PATH:
|
||||
return EiglspergerLayoutAlgorithm
|
||||
.<V, E> edgeAwareBuilder()
|
||||
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
|
||||
.layering(Layering.LONGEST_PATH);
|
||||
case MIN_CROSS_NETWORK_SIMPLEX:
|
||||
return EiglspergerLayoutAlgorithm
|
||||
.<V, E> edgeAwareBuilder()
|
||||
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
|
||||
.layering(Layering.NETWORK_SIMPLEX);
|
||||
case MIN_CROSS_COFFMAN_GRAHAM:
|
||||
return EiglspergerLayoutAlgorithm
|
||||
.<V, E> edgeAwareBuilder()
|
||||
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
|
||||
.layering(Layering.COFFMAN_GRAHAM);
|
||||
case RADIAL:
|
||||
return RadialTreeLayoutAlgorithm
|
||||
.<V> builder()
|
||||
.<AttributedVertex> builder()
|
||||
.verticalVertexSpacing(300);
|
||||
case BALLOON:
|
||||
return BalloonLayoutAlgorithm
|
||||
.<V> builder()
|
||||
.<AttributedVertex> builder()
|
||||
.verticalVertexSpacing(300);
|
||||
case TREE:
|
||||
return TreeLayoutAlgorithm
|
||||
.builder();
|
||||
case TIDIER_TREE:
|
||||
default:
|
||||
return TidierTreeLayoutAlgorithm.<V, E> edgeAwareBuilder();
|
||||
return TidierTreeLayoutAlgorithm
|
||||
.<AttributedVertex, AttributedEdge> edgeAwareBuilder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-40
@@ -15,61 +15,57 @@
|
||||
*/
|
||||
package ghidra.graph.visualization;
|
||||
|
||||
import org.jungrapht.visualization.RenderContext;
|
||||
import org.jungrapht.visualization.VisualizationServer;
|
||||
import org.jungrapht.visualization.layout.algorithms.Balloon;
|
||||
import org.jungrapht.visualization.layout.algorithms.BalloonLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.EdgeSorting;
|
||||
import org.jungrapht.visualization.layout.algorithms.Layered;
|
||||
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.RadialTreeLayout;
|
||||
import org.jungrapht.visualization.layout.algorithms.RadialTreeLayoutAlgorithm;
|
||||
import org.jungrapht.visualization.layout.algorithms.TreeLayout;
|
||||
import org.jungrapht.visualization.layout.algorithms.util.VertexBoundsFunctionConsumer;
|
||||
import org.jungrapht.visualization.layout.model.Rectangle;
|
||||
import org.jungrapht.visualization.util.LayoutAlgorithmTransition;
|
||||
import org.jungrapht.visualization.util.LayoutPaintable;
|
||||
import static ghidra.graph.visualization.LayoutFunction.*;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static ghidra.graph.visualization.LayoutFunction.TIDIER_TREE;
|
||||
import org.jungrapht.visualization.RenderContext;
|
||||
import org.jungrapht.visualization.VisualizationServer;
|
||||
import org.jungrapht.visualization.layout.algorithms.*;
|
||||
import org.jungrapht.visualization.layout.algorithms.util.VertexBoundsFunctionConsumer;
|
||||
import org.jungrapht.visualization.layout.model.Rectangle;
|
||||
import org.jungrapht.visualization.util.LayoutAlgorithmTransition;
|
||||
import org.jungrapht.visualization.util.LayoutPaintable;
|
||||
|
||||
import ghidra.service.graph.AttributedEdge;
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
|
||||
/**
|
||||
* Manages the selection and transition from one {@link LayoutAlgorithm} to another
|
||||
*/
|
||||
class LayoutTransitionManager<V, E> {
|
||||
class LayoutTransitionManager {
|
||||
|
||||
LayoutFunction layoutFunction = new LayoutFunction();
|
||||
/**
|
||||
* the {@link VisualizationServer} used to display graphs using the requested {@link LayoutAlgorithm}
|
||||
*/
|
||||
VisualizationServer<V, E> visualizationServer;
|
||||
VisualizationServer<AttributedVertex, AttributedEdge> visualizationServer;
|
||||
|
||||
/**
|
||||
* a {@link Predicate} to assist in determining which vertices are root vertices (for Tree layouts)
|
||||
*/
|
||||
Predicate<V> rootPredicate;
|
||||
Predicate<AttributedVertex> rootPredicate;
|
||||
|
||||
/**
|
||||
* a {@link Comparator} to sort edges during layout graph traversal
|
||||
*/
|
||||
Comparator<E> edgeComparator = (e1, e2) -> 0;
|
||||
Comparator<AttributedEdge> edgeComparator = (e1, e2) -> 0;
|
||||
|
||||
/**
|
||||
* a {@link Function} to provide {@link Rectangle} (and thus bounds} for vertices
|
||||
*/
|
||||
Function<V, Rectangle> vertexBoundsFunction;
|
||||
Function<AttributedVertex, Rectangle> vertexBoundsFunction;
|
||||
|
||||
/**
|
||||
* the {@link RenderContext} used to draw the graph
|
||||
*/
|
||||
RenderContext<V, E> renderContext;
|
||||
RenderContext<AttributedVertex, AttributedEdge> renderContext;
|
||||
|
||||
LayoutPaintable.BalloonRings<V, E> balloonLayoutRings;
|
||||
LayoutPaintable.BalloonRings<AttributedVertex, AttributedEdge> balloonLayoutRings;
|
||||
|
||||
LayoutPaintable.RadialRings<V> radialLayoutRings;
|
||||
LayoutPaintable.RadialRings<AttributedVertex> radialLayoutRings;
|
||||
|
||||
|
||||
/**
|
||||
@@ -78,8 +74,8 @@ class LayoutTransitionManager<V, E> {
|
||||
* @param rootPredicate selects root vertices
|
||||
*/
|
||||
public LayoutTransitionManager(
|
||||
VisualizationServer<V, E> visualizationServer,
|
||||
Predicate<V> rootPredicate) {
|
||||
VisualizationServer<AttributedVertex, AttributedEdge> visualizationServer,
|
||||
Predicate<AttributedVertex> rootPredicate) {
|
||||
this.visualizationServer = visualizationServer;
|
||||
this.rootPredicate = rootPredicate;
|
||||
|
||||
@@ -87,7 +83,7 @@ class LayoutTransitionManager<V, E> {
|
||||
this.vertexBoundsFunction = visualizationServer.getRenderContext().getVertexBoundsFunction();
|
||||
}
|
||||
|
||||
public void setEdgeComparator(Comparator<E> edgeComparator) {
|
||||
public void setEdgeComparator(Comparator<AttributedEdge> edgeComparator) {
|
||||
this.edgeComparator = edgeComparator;
|
||||
}
|
||||
|
||||
@@ -97,19 +93,19 @@ class LayoutTransitionManager<V, E> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setLayout(String layoutName) {
|
||||
LayoutAlgorithm.Builder<V, ?, ?> builder = layoutFunction.apply(layoutName);
|
||||
LayoutAlgorithm<V> layoutAlgorithm = builder.build();
|
||||
LayoutAlgorithm.Builder<AttributedVertex, ?, ?> builder = layoutFunction.apply(layoutName);
|
||||
LayoutAlgorithm<AttributedVertex> layoutAlgorithm = builder.build();
|
||||
if (layoutAlgorithm instanceof VertexBoundsFunctionConsumer) {
|
||||
((VertexBoundsFunctionConsumer<V>) layoutAlgorithm)
|
||||
((VertexBoundsFunctionConsumer<AttributedVertex>) layoutAlgorithm)
|
||||
.setVertexBoundsFunction(vertexBoundsFunction);
|
||||
}
|
||||
if (layoutAlgorithm instanceof Layered) {
|
||||
((Layered<V, E>)layoutAlgorithm)
|
||||
((Layered<AttributedVertex, AttributedEdge>) layoutAlgorithm)
|
||||
.setMaxLevelCrossFunction(g ->
|
||||
Math.max(1, Math.min(10, 500 / g.vertexSet().size())));
|
||||
}
|
||||
if (layoutAlgorithm instanceof TreeLayout) {
|
||||
((TreeLayout<V>) layoutAlgorithm).setRootPredicate(rootPredicate);
|
||||
((TreeLayout<AttributedVertex>) layoutAlgorithm).setRootPredicate(rootPredicate);
|
||||
}
|
||||
// remove any previously added layout paintables
|
||||
removePaintable(radialLayoutRings);
|
||||
@@ -117,18 +113,19 @@ class LayoutTransitionManager<V, E> {
|
||||
if (layoutAlgorithm instanceof BalloonLayoutAlgorithm) {
|
||||
balloonLayoutRings =
|
||||
new LayoutPaintable.BalloonRings<>(
|
||||
visualizationServer, (BalloonLayoutAlgorithm<V>) layoutAlgorithm);
|
||||
visualizationServer,
|
||||
(BalloonLayoutAlgorithm<AttributedVertex>) layoutAlgorithm);
|
||||
visualizationServer.addPreRenderPaintable(balloonLayoutRings);
|
||||
}
|
||||
if (layoutAlgorithm instanceof RadialTreeLayout) {
|
||||
radialLayoutRings =
|
||||
new LayoutPaintable.RadialRings<>(
|
||||
visualizationServer, (RadialTreeLayout<V>) layoutAlgorithm);
|
||||
visualizationServer, (RadialTreeLayout<AttributedVertex>) layoutAlgorithm);
|
||||
visualizationServer.addPreRenderPaintable(radialLayoutRings);
|
||||
}
|
||||
|
||||
if (layoutAlgorithm instanceof EdgeSorting) {
|
||||
((EdgeSorting<E>) layoutAlgorithm).setEdgeComparator(edgeComparator);
|
||||
((EdgeSorting<AttributedEdge>) layoutAlgorithm).setEdgeComparator(edgeComparator);
|
||||
}
|
||||
LayoutAlgorithmTransition.apply(visualizationServer, layoutAlgorithm);
|
||||
}
|
||||
@@ -140,22 +137,22 @@ class LayoutTransitionManager<V, E> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public LayoutAlgorithm<V> getInitialLayoutAlgorithm() {
|
||||
LayoutAlgorithm<V> initialLayoutAlgorithm =
|
||||
public LayoutAlgorithm<AttributedVertex> getInitialLayoutAlgorithm() {
|
||||
LayoutAlgorithm<AttributedVertex> initialLayoutAlgorithm =
|
||||
layoutFunction.apply(TIDIER_TREE).build();
|
||||
|
||||
if (initialLayoutAlgorithm instanceof TreeLayout) {
|
||||
((TreeLayout<V>) initialLayoutAlgorithm)
|
||||
((TreeLayout<AttributedVertex>) initialLayoutAlgorithm)
|
||||
.setRootPredicate(rootPredicate);
|
||||
((TreeLayout<V>) initialLayoutAlgorithm)
|
||||
((TreeLayout<AttributedVertex>) initialLayoutAlgorithm)
|
||||
.setVertexBoundsFunction(vertexBoundsFunction);
|
||||
}
|
||||
if (initialLayoutAlgorithm instanceof EdgeSorting) {
|
||||
((EdgeSorting<E>) initialLayoutAlgorithm)
|
||||
((EdgeSorting<AttributedEdge>) initialLayoutAlgorithm)
|
||||
.setEdgeComparator(edgeComparator);
|
||||
}
|
||||
if (initialLayoutAlgorithm instanceof VertexBoundsFunctionConsumer) {
|
||||
((VertexBoundsFunctionConsumer<V>) initialLayoutAlgorithm)
|
||||
((VertexBoundsFunctionConsumer<AttributedVertex>) initialLayoutAlgorithm)
|
||||
.setVertexBoundsFunction(vertexBoundsFunction);
|
||||
}
|
||||
return initialLayoutAlgorithm;
|
||||
|
||||
@@ -18,6 +18,7 @@ package ghidra.graph.program;
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.app.plugin.core.colorizer.ColorizingService;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -156,12 +157,15 @@ public class BlockGraphTask extends Task {
|
||||
display.setGraph(graph, actionName, appendGraph, monitor);
|
||||
|
||||
if (location != null) {
|
||||
display.setLocation(listener.getVertexIdForAddress(location.getAddress()));
|
||||
// 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);
|
||||
}
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
List<String> selectedVertices = listener.getVertices(selection);
|
||||
if (selectedVertices != null) {
|
||||
display.selectVertices(selectedVertices);
|
||||
// intialize the graph selection, but don't have the graph send an event
|
||||
display.selectVertices(selectedVertices, EventTrigger.INTERNAL_ONLY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -17,6 +17,7 @@ package ghidra.graph.program;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
@@ -37,7 +38,7 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocation(String vertexID) {
|
||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger) {
|
||||
currentFocusedVertex = vertexID;
|
||||
}
|
||||
|
||||
@@ -46,7 +47,7 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectVertices(List<String> vertexList) {
|
||||
public void selectVertices(List<String> vertexList, EventTrigger eventTrigger) {
|
||||
currentSelection = vertexList;
|
||||
}
|
||||
|
||||
@@ -103,7 +104,7 @@ public class TestGraphDisplay implements GraphDisplay {
|
||||
}
|
||||
|
||||
public void focusChanged(String vertexId) {
|
||||
listener.locationChanged(vertexId);
|
||||
listener.locationFocusChanged(vertexId);
|
||||
}
|
||||
|
||||
public void selectionChanged(List<String> vertexIds) {
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class DummyGraphDisplayListener implements GraphDisplayListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void locationChanged(String vertexId) {
|
||||
public void locationFocusChanged(String vertexId) {
|
||||
// I'm a dummy
|
||||
}
|
||||
|
||||
|
||||
+18
-4
@@ -17,6 +17,7 @@ package ghidra.service.graph;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@@ -41,18 +42,31 @@ public interface GraphDisplay {
|
||||
public void setGraphDisplayListener(GraphDisplayListener listener);
|
||||
|
||||
/**
|
||||
* Tells the graph display window to focus
|
||||
* Tells the graph display window to focus the vertex with the given id.
|
||||
*
|
||||
* @param vertexID the id of 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.
|
||||
*
|
||||
*/
|
||||
public void setLocation(String vertexID);
|
||||
public void setLocationFocus(String vertexID, EventTrigger eventTrigger);
|
||||
|
||||
/**
|
||||
* Tells the graph display window to select the vertices with the given ids
|
||||
*
|
||||
* @param vertexList the list of vertex ids 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 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<String> vertexList);
|
||||
public void selectVertices(List<String> vertexList, EventTrigger eventTrigger);
|
||||
|
||||
/**
|
||||
* Closes this graph display window.
|
||||
@@ -103,7 +117,7 @@ public interface GraphDisplay {
|
||||
|
||||
/**
|
||||
* Updates a vertex to a new name
|
||||
* @param id the vertix id
|
||||
* @param id the vertex id
|
||||
* @param newName the new name of the vertex
|
||||
*/
|
||||
public void updateVertexName(String id, String newName);
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public interface GraphDisplayListener {
|
||||
* Notification that the "focused" (active) vertex has changed.
|
||||
* @param vertexId the vertex id of the currently "focused" vertex
|
||||
*/
|
||||
public void locationChanged(String vertexId);
|
||||
public void locationFocusChanged(String vertexId);
|
||||
|
||||
default boolean updateVertexName(String vertexId, String oldName, String newName) {
|
||||
// no op
|
||||
|
||||
Reference in New Issue
Block a user