mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-377 - Graphing - A few small refactorings
This commit is contained in:
parent
9f2090d71c
commit
8493c333c8
10 changed files with 112 additions and 130 deletions
|
@ -15,9 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.services;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.core.graph.GraphDisplayBrokerListener;
|
||||
import ghidra.app.plugin.core.graph.GraphDisplayBrokerPlugin;
|
||||
|
@ -62,20 +60,26 @@ public interface GraphDisplayBroker {
|
|||
* @return a {@link GraphDisplay} object to sends graphs to be displayed or exported.
|
||||
* @throws GraphException thrown if an error occurs trying to get a graph display
|
||||
*/
|
||||
default GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, TaskMonitor monitor)
|
||||
public default GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, TaskMonitor monitor)
|
||||
throws GraphException {
|
||||
return getDefaultGraphDisplay(reuseGraph, Collections.emptyMap(), monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for getting a {@link GraphDisplay} from the currently active provider
|
||||
*
|
||||
* <p>This method allows users to override default graph properties defined by
|
||||
* <b>jungrapht</b>. See that library for a complete list of available properties.
|
||||
* Default properties can be changed in the {@code jungrapht.properties} file.
|
||||
*
|
||||
* @param reuseGraph if true, the provider will attempt to re-use a current graph display
|
||||
* @param properties a {@code Map} of property key/values that can be used to customize the display
|
||||
* @param monitor the {@link TaskMonitor} that can be used to cancel the operation
|
||||
* @return a {@link GraphDisplay} object to sends graphs to be displayed or exported.
|
||||
* @throws GraphException thrown if an error occurs trying to get a graph display
|
||||
*/
|
||||
GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, Map<String, String> properties, TaskMonitor monitor)
|
||||
public GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, Map<String, String> properties,
|
||||
TaskMonitor monitor)
|
||||
throws GraphException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -122,7 +122,7 @@ public class ASTGraphTask extends Task {
|
|||
display.defineVertexAttribute(CODE_ATTRIBUTE);
|
||||
display.defineVertexAttribute(SYMBOLS_ATTRIBUTE);
|
||||
|
||||
display.setVertexLabel(CODE_ATTRIBUTE, GraphDisplay.ALIGN_LEFT, 12, true,
|
||||
display.setVertexLabelAttribute(CODE_ATTRIBUTE, GraphDisplay.ALIGN_LEFT, 12, true,
|
||||
graphType == GraphType.CONTROL_FLOW_GRAPH ? (codeLimitPerBlock + 1) : 1);
|
||||
|
||||
String description =
|
||||
|
|
|
@ -90,7 +90,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace,
|
||||
public void setVertexLabelAttribute(String attributeName, int alignment, int size, boolean monospace,
|
||||
int maxLines) {
|
||||
// no effect
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.jungrapht.visualization.layout.model.LayoutModel;
|
|||
import org.jungrapht.visualization.layout.model.Point;
|
||||
import org.jungrapht.visualization.renderers.*;
|
||||
import org.jungrapht.visualization.renderers.Renderer;
|
||||
import org.jungrapht.visualization.renderers.Renderer.VertexLabel;
|
||||
import org.jungrapht.visualization.selection.MutableSelectedState;
|
||||
import org.jungrapht.visualization.selection.VertexEndpointsSelectedEdgeSelectedState;
|
||||
import org.jungrapht.visualization.transform.*;
|
||||
|
@ -64,8 +65,7 @@ import ghidra.framework.plugintool.PluginTool;
|
|||
import ghidra.graph.AttributeFilters;
|
||||
import ghidra.graph.job.GraphJobRunner;
|
||||
import ghidra.graph.viewer.popup.*;
|
||||
import ghidra.graph.visualization.mouse.JgtPluggableGraphMouse;
|
||||
import ghidra.graph.visualization.mouse.JgtUtils;
|
||||
import ghidra.graph.visualization.mouse.*;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -82,6 +82,9 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
|
||||
private static final String FAVORED_EDGE = "Fall-Through";
|
||||
|
||||
/*
|
||||
A handful of jungrapht properties that re used by this graph
|
||||
*/
|
||||
private static final String SELECTED_VERTEX_COLOR = "selectedVertexColor";
|
||||
private static final String SELECTED_EDGE_COLOR = "selectedEdgeColor";
|
||||
private static final String INITIAL_LAYOUT_ALGORITHM = "initialLayoutAlgorithm";
|
||||
|
@ -94,7 +97,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
|
||||
private Logger log = Logger.getLogger(DefaultGraphDisplay.class.getName());
|
||||
|
||||
private Map<String, String> graphDisplayProperties = new HashMap<>();
|
||||
private Map<String, String> displayProperties = new HashMap<>();
|
||||
private GraphDisplayListener listener = new DummyGraphDisplayListener();
|
||||
private String title;
|
||||
|
||||
|
@ -162,7 +165,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
/**
|
||||
* Handles all mouse interaction
|
||||
*/
|
||||
private JgtPluggableGraphMouse graphMouse;
|
||||
private JgtGraphMouse graphMouse;
|
||||
|
||||
private ToggleDockingAction hideSelectedAction;
|
||||
private ToggleDockingAction hideUnselectedAction;
|
||||
|
@ -177,13 +180,15 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
/**
|
||||
* Create the initial display, the graph-less visualization viewer, and its controls
|
||||
* @param displayProvider provides a {@link PluginTool} for Docking features
|
||||
* @param displayProperties graph properties that will override the default graph properties
|
||||
* @param id the unique display id
|
||||
*/
|
||||
DefaultGraphDisplay(DefaultGraphDisplayProvider displayProvider, Map<String, String> graphDisplayProperties, int id) {
|
||||
DefaultGraphDisplay(DefaultGraphDisplayProvider displayProvider,
|
||||
Map<String, String> displayProperties, int id) {
|
||||
this.graphDisplayProvider = displayProvider;
|
||||
this.displayId = id;
|
||||
this.pluginTool = graphDisplayProvider.getPluginTool();
|
||||
this.graphDisplayProperties = graphDisplayProperties;
|
||||
this.displayProperties = displayProperties;
|
||||
this.viewer = createViewer();
|
||||
buildHighlighers();
|
||||
|
||||
|
@ -217,30 +222,15 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
connectSelectionStateListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String key, String value) {
|
||||
this.graphDisplayProperties.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(String key) {
|
||||
return graphDisplayProperties.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
return Collections.unmodifiableMap(graphDisplayProperties);
|
||||
}
|
||||
|
||||
private Color getSelectedVertexColor() {
|
||||
return Colors.getHexColor(graphDisplayProperties.getOrDefault(SELECTED_VERTEX_COLOR,
|
||||
"0xFF0000"));
|
||||
}
|
||||
|
||||
private Color getSelectedEdgeColor() {
|
||||
return Colors.getHexColor(graphDisplayProperties.getOrDefault(SELECTED_EDGE_COLOR, "0xFF0000"));
|
||||
return Colors.getHexColor(displayProperties.getOrDefault(SELECTED_VERTEX_COLOR,
|
||||
"0xFF0000"));
|
||||
}
|
||||
|
||||
// private Color getSelectedEdgeColor() {
|
||||
// return Colors
|
||||
// .getHexColor(displayProperties.getOrDefault(SELECTED_EDGE_COLOR, "0xFF0000"));
|
||||
// }
|
||||
|
||||
JComponent getComponent() {
|
||||
JComponent component = viewer.getComponent();
|
||||
|
@ -270,7 +260,8 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
// this lens' delegate is the viewer's VIEW layer
|
||||
.delegate(transformer)
|
||||
.build();
|
||||
LensGraphMouse lensGraphMouse = DefaultLensGraphMouse.builder().magnificationPlugin(magnificationPlugin).build();
|
||||
LensGraphMouse lensGraphMouse =
|
||||
DefaultLensGraphMouse.builder().magnificationPlugin(magnificationPlugin).build();
|
||||
return MagnifyImageLensSupport.builder(viewer)
|
||||
.lensTransformer(shapeTransformer)
|
||||
.lensGraphMouse(lensGraphMouse)
|
||||
|
@ -471,14 +462,15 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
new ActionBuilder("Grow Selection To Entire Component", ACTION_OWNER)
|
||||
.popupMenuPath("Grow Selection To Entire Component")
|
||||
.popupMenuGroup("z", "4")
|
||||
.description("Extends the current selection by including the target/source vertices " +
|
||||
.description(
|
||||
"Extends the current selection by including the target/source vertices " +
|
||||
"of all edges whose source/target is selected")
|
||||
.keyBinding("ctrl C")
|
||||
.enabledWhen(c -> !isAllSelected(getSourceVerticesFromSelected()) && !isAllSelected(getTargetVerticesFromSelected()))
|
||||
.enabledWhen(c -> !isAllSelected(getSourceVerticesFromSelected()) &&
|
||||
!isAllSelected(getTargetVerticesFromSelected()))
|
||||
.onAction(c -> growSelection(getAllComponentVerticesFromSelected()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
|
||||
new ActionBuilder("Clear Selection", ACTION_OWNER)
|
||||
.popupMenuPath("Clear Selection")
|
||||
.popupMenuGroup("z", "5")
|
||||
|
@ -615,9 +607,11 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
private Set<AttributedVertex> getUnselectedSourceVerticesFromSelected() {
|
||||
MutableSelectedState<AttributedVertex> selectedVertexState = viewer.getSelectedVertexState();
|
||||
MutableSelectedState<AttributedVertex> selectedVertexState =
|
||||
viewer.getSelectedVertexState();
|
||||
return getSourceVerticesFromSelected().stream()
|
||||
.filter(v -> !selectedVertexState.isSelected(v)).collect(Collectors.toSet());
|
||||
.filter(v -> !selectedVertexState.isSelected(v))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Set<AttributedVertex> getTargetVerticesFromSelected() {
|
||||
|
@ -631,13 +625,14 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
private Set<AttributedVertex> getUnselectedTargetVerticesFromSelected() {
|
||||
MutableSelectedState<AttributedVertex> selectedVertexState = viewer.getSelectedVertexState();
|
||||
MutableSelectedState<AttributedVertex> selectedVertexState =
|
||||
viewer.getSelectedVertexState();
|
||||
return getTargetVerticesFromSelected().stream()
|
||||
.filter(v -> !selectedVertexState.isSelected(v)).collect(Collectors.toSet());
|
||||
.filter(v -> !selectedVertexState.isSelected(v))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Set<AttributedVertex> getAllDownstreamVerticesFromSelected() {
|
||||
MutableSelectedState<AttributedVertex> selectedVertexState = viewer.getSelectedVertexState();
|
||||
Set<AttributedVertex> downstream = new HashSet<>();
|
||||
Set<AttributedVertex> targets = getUnselectedTargetVerticesFromSelected();
|
||||
while (!targets.isEmpty()) {
|
||||
|
@ -649,7 +644,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
private Set<AttributedVertex> getAllUpstreamVerticesFromSelected() {
|
||||
MutableSelectedState<AttributedVertex> selectedVertexState = viewer.getSelectedVertexState();
|
||||
Set<AttributedVertex> upstream = new HashSet<>();
|
||||
Set<AttributedVertex> sources = getUnselectedSourceVerticesFromSelected();
|
||||
while (!sources.isEmpty()) {
|
||||
|
@ -666,7 +660,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
return componentVertices;
|
||||
}
|
||||
|
||||
|
||||
private void invertSelection() {
|
||||
switchableSelectionListener.setEnabled(false);
|
||||
try {
|
||||
|
@ -756,7 +749,12 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
SatelliteVisualizationViewer.builder(parentViewer)
|
||||
.viewSize(satelliteSize)
|
||||
.build();
|
||||
satellite.setGraphMouse(new DefaultSatelliteGraphMouse<>());
|
||||
|
||||
//
|
||||
// JUNGRAPHT CHANGE 3
|
||||
//
|
||||
satellite.setGraphMouse(new JgtSatelliteGraphMouse());
|
||||
|
||||
satellite.getRenderContext().setEdgeDrawPaintFunction(Colors::getColor);
|
||||
satellite.getRenderContext()
|
||||
.setEdgeStrokeFunction(ProgramGraphFunctions::getEdgeStroke);
|
||||
|
@ -771,9 +769,11 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
satellite.getRenderContext().setVertexLabelFunction(n -> null);
|
||||
// always get the current predicate from the main view and test with it,
|
||||
satellite.getRenderContext()
|
||||
.setVertexIncludePredicate(v -> viewer.getRenderContext().getVertexIncludePredicate().test(v));
|
||||
.setVertexIncludePredicate(
|
||||
v -> viewer.getRenderContext().getVertexIncludePredicate().test(v));
|
||||
satellite.getRenderContext()
|
||||
.setEdgeIncludePredicate(e -> viewer.getRenderContext().getEdgeIncludePredicate().test(e));
|
||||
.setEdgeIncludePredicate(
|
||||
e -> viewer.getRenderContext().getEdgeIncludePredicate().test(e));
|
||||
satellite.getComponent().setBorder(BorderFactory.createEtchedBorder());
|
||||
parentViewer.getComponent().addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
|
@ -943,12 +943,13 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
private void setInitialLayoutAlgorithm() {
|
||||
if (graphDisplayProperties.containsKey(INITIAL_LAYOUT_ALGORITHM)) {
|
||||
String layoutAlgorithmName = graphDisplayProperties.get(INITIAL_LAYOUT_ALGORITHM);
|
||||
if (displayProperties.containsKey(INITIAL_LAYOUT_ALGORITHM)) {
|
||||
String layoutAlgorithmName = displayProperties.get(INITIAL_LAYOUT_ALGORITHM);
|
||||
layoutTransitionManager.setLayout(layoutAlgorithmName);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
LayoutAlgorithm<AttributedVertex> initialLayoutAlgorithm =
|
||||
layoutTransitionManager.getInitialLayoutAlgorithm();
|
||||
layoutTransitionManager.getInitialLayoutAlgorithm();
|
||||
initialLayoutAlgorithm.setAfter(() -> centerAndScale());
|
||||
viewer.getVisualizationModel().setLayoutAlgorithm(initialLayoutAlgorithm);
|
||||
}
|
||||
|
@ -1040,15 +1041,12 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
log.fine("defineEdgeAttribute " + attributeName + " is not implemented");
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.program.model.graph.GraphDisplay#setVertexLabel(java.lang.String, int, int, boolean, int)
|
||||
*/
|
||||
@Override
|
||||
public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace,
|
||||
public void setVertexLabelAttribute(String attributeName, int alignment, int size,
|
||||
boolean monospace,
|
||||
int maxLines) {
|
||||
log.fine("setVertexLabel " + attributeName);
|
||||
this.iconCache.setPreferredLabel(attributeName);
|
||||
// this would have to set the label function, the label font function
|
||||
this.iconCache.setPreferredVertexLabelAttribute(attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1184,15 +1182,11 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
/**
|
||||
* create and return a {@link VisualizationViewer} to display graphs
|
||||
* Create and return a {@link VisualizationViewer} to display graphs
|
||||
* @return the new VisualizationViewer
|
||||
*/
|
||||
public VisualizationViewer<AttributedVertex, AttributedEdge> createViewer() {
|
||||
Color selectedVertexColor =
|
||||
Colors.getHexColor(graphDisplayProperties.getOrDefault("selectedVertexColor", "0xFF0000"));
|
||||
Color selectedEdgeColor =
|
||||
Colors.getHexColor(graphDisplayProperties.getOrDefault("selectedEdgeColor", "0xFF0000"));
|
||||
final VisualizationViewer<AttributedVertex, AttributedEdge> vv =
|
||||
protected VisualizationViewer<AttributedVertex, AttributedEdge> createViewer() {
|
||||
VisualizationViewer<AttributedVertex, AttributedEdge> vv =
|
||||
VisualizationViewer.<AttributedVertex, AttributedEdge> builder()
|
||||
.multiSelectionStrategySupplier(
|
||||
() -> freeFormSelection ? MultiSelectionStrategy.arbitrary()
|
||||
|
@ -1247,7 +1241,11 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
renderContext.setEdgeStrokeFunction(
|
||||
e -> vv.getSelectedEdges().contains(e) ? new BasicStroke(20.f)
|
||||
: ProgramGraphFunctions.getEdgeStroke(e));
|
||||
|
||||
// selected edges will be drawn in red (instead of default)
|
||||
Color selectedEdgeColor =
|
||||
Colors.getHexColor(
|
||||
displayProperties.getOrDefault("selectedEdgeColor", "0xFF0000"));
|
||||
renderContext.setEdgeDrawPaintFunction(
|
||||
e -> vv.getSelectedEdges().contains(e) ? selectedEdgeColor
|
||||
: Colors.getColor(e));
|
||||
|
@ -1286,7 +1284,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
vv.getComponent().removeMouseListener(mouseListener);
|
||||
}
|
||||
|
||||
graphMouse = new JgtPluggableGraphMouse(this);
|
||||
graphMouse = new JgtGraphMouse(this);
|
||||
vv.setGraphMouse(graphMouse);
|
||||
|
||||
return vv;
|
||||
|
@ -1294,10 +1292,12 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
|
||||
private void setVertexPreferences(VisualizationViewer<AttributedVertex, AttributedEdge> vv) {
|
||||
RenderContext<AttributedVertex, AttributedEdge> renderContext = vv.getRenderContext();
|
||||
if (Boolean.parseBoolean(graphDisplayProperties.getOrDefault(DISPLAY_VERTICES_AS_ICONS, "true"))) {
|
||||
String useIcons =
|
||||
displayProperties.getOrDefault(DISPLAY_VERTICES_AS_ICONS, Boolean.TRUE.toString());
|
||||
if (Boolean.parseBoolean(useIcons)) {
|
||||
// set up the shape and color functions
|
||||
IconShapeFunction<AttributedVertex> nodeImageShapeFunction =
|
||||
new IconShapeFunction<>(new EllipseShapeFunction<>());
|
||||
new IconShapeFunction<>(new EllipseShapeFunction<>());
|
||||
|
||||
nodeImageShapeFunction.setIconFunction(iconCache::get);
|
||||
renderContext.setVertexShapeFunction(nodeImageShapeFunction);
|
||||
|
@ -1305,19 +1305,22 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
|||
|
||||
vv.setInitialDimensionFunction(InitialDimensionFunction
|
||||
.builder(
|
||||
nodeImageShapeFunction.andThen(s -> RectangleUtils.convert(s.getBounds2D())))
|
||||
nodeImageShapeFunction
|
||||
.andThen(s -> RectangleUtils.convert(s.getBounds2D())))
|
||||
.build());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vv.getRenderContext().setVertexShapeFunction(ProgramGraphFunctions::getVertexShape);
|
||||
vv.setInitialDimensionFunction(InitialDimensionFunction
|
||||
.builder(
|
||||
renderContext.getVertexShapeFunction()
|
||||
.andThen(s -> RectangleUtils.convert(s.getBounds2D())))
|
||||
renderContext.getVertexShapeFunction()
|
||||
.andThen(s -> RectangleUtils.convert(s.getBounds2D())))
|
||||
.build());
|
||||
vv.getRenderContext().setVertexLabelFunction(Object::toString);
|
||||
vv.getRenderContext().setVertexLabelPosition(
|
||||
VertexLabel.Position.valueOf(
|
||||
graphDisplayProperties.getOrDefault(VERTEX_LABEL_POSITION, "AUTO")));
|
||||
vv.getRenderContext()
|
||||
.setVertexLabelPosition(
|
||||
VertexLabel.Position.valueOf(
|
||||
displayProperties.getOrDefault(VERTEX_LABEL_POSITION, "AUTO")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import javax.swing.border.Border;
|
|||
import javax.swing.border.CompoundBorder;
|
||||
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
import ghidra.service.graph.GraphDisplay;
|
||||
|
||||
public class GhidraIconCache {
|
||||
|
||||
|
@ -43,8 +42,7 @@ public class GhidraIconCache {
|
|||
private final Map<AttributedVertex, Icon> map = new ConcurrentHashMap<>();
|
||||
|
||||
private final IconShape.Function iconShapeFunction = new IconShape.Function();
|
||||
private String preferredLabel = null;
|
||||
private int labelAlignment = GraphDisplay.ALIGN_CENTER;
|
||||
private String preferredVeretxLabelAttribute = null;
|
||||
|
||||
Icon get(AttributedVertex vertex) {
|
||||
|
||||
|
@ -65,7 +63,8 @@ public class GhidraIconCache {
|
|||
}
|
||||
|
||||
private Icon createIcon(AttributedVertex vertex) {
|
||||
rendererLabel.setText(ProgramGraphFunctions.getLabel(vertex, preferredLabel));
|
||||
rendererLabel
|
||||
.setText(ProgramGraphFunctions.getLabel(vertex, preferredVeretxLabelAttribute));
|
||||
rendererLabel.setFont(new Font(DEFAULT_FONT_NAME, Font.BOLD, DEFAULT_FONT_SIZE));
|
||||
rendererLabel.setForeground(Color.black);
|
||||
rendererLabel.setBackground(Color.white);
|
||||
|
@ -103,17 +102,21 @@ public class GhidraIconCache {
|
|||
// triangles have a non-zero +/- yoffset instead of centering the label
|
||||
case TRIANGLE:
|
||||
// scale the vertex shape
|
||||
scalex = labelSize.getWidth() / vertexShape.getBounds().getWidth() * LABEL_TO_ICON_PROPORTION;
|
||||
scaley = labelSize.getHeight() / vertexShape.getBounds().getHeight() * LABEL_TO_ICON_PROPORTION;
|
||||
scalex = labelSize.getWidth() / vertexShape.getBounds().getWidth() *
|
||||
LABEL_TO_ICON_PROPORTION;
|
||||
scaley = labelSize.getHeight() / vertexShape.getBounds().getHeight() *
|
||||
LABEL_TO_ICON_PROPORTION;
|
||||
vertexShape = AffineTransform.getScaleInstance(scalex, scaley)
|
||||
.createTransformedShape(vertexShape);
|
||||
.createTransformedShape(vertexShape);
|
||||
offset = -(int) ((vertexShape.getBounds().getHeight() - labelSize.getHeight()) / 2);
|
||||
break;
|
||||
case INVERTED_TRIANGLE:
|
||||
scalex = labelSize.getWidth() / vertexShape.getBounds().getWidth() * LABEL_TO_ICON_PROPORTION;
|
||||
scaley = labelSize.getHeight() / vertexShape.getBounds().getHeight() * LABEL_TO_ICON_PROPORTION;
|
||||
scalex = labelSize.getWidth() / vertexShape.getBounds().getWidth() *
|
||||
LABEL_TO_ICON_PROPORTION;
|
||||
scaley = labelSize.getHeight() / vertexShape.getBounds().getHeight() *
|
||||
LABEL_TO_ICON_PROPORTION;
|
||||
vertexShape = AffineTransform.getScaleInstance(scalex, scaley)
|
||||
.createTransformedShape(vertexShape);
|
||||
.createTransformedShape(vertexShape);
|
||||
offset = (int) ((vertexShape.getBounds().getHeight() - labelSize.getHeight()) / 2);
|
||||
break;
|
||||
|
||||
|
@ -122,17 +125,17 @@ public class GhidraIconCache {
|
|||
scalex = labelSize.getWidth() / vertexShape.getBounds().getWidth();
|
||||
scaley = labelSize.getHeight() / vertexShape.getBounds().getHeight();
|
||||
vertexShape = AffineTransform.getScaleInstance(scalex, scaley)
|
||||
.createTransformedShape(vertexShape);
|
||||
.createTransformedShape(vertexShape);
|
||||
break;
|
||||
|
||||
// diamonds and ellipses reduce the label size to fit
|
||||
// diamonds and ellipses reduce the label size to fit
|
||||
case DIAMOND:
|
||||
default: // ELLIPSE
|
||||
scalex =
|
||||
labelSize.getWidth() / vertexShape.getBounds().getWidth() * 1.1;
|
||||
scaley = labelSize.getHeight() / vertexShape.getBounds().getHeight() * 1.1;
|
||||
vertexShape = AffineTransform.getScaleInstance(scalex, scaley)
|
||||
.createTransformedShape(vertexShape);
|
||||
.createTransformedShape(vertexShape);
|
||||
break;
|
||||
}
|
||||
Rectangle vertexBounds = vertexShape.getBounds();
|
||||
|
@ -166,13 +169,13 @@ public class GhidraIconCache {
|
|||
label.paint(graphics);
|
||||
// draw the shape again, but lighter (on top of the label)
|
||||
offsetTransform =
|
||||
AffineTransform.getTranslateInstance(strokeThickness + vertexBounds.width / 2.0,
|
||||
strokeThickness + vertexBounds.height / 2.0);
|
||||
AffineTransform.getTranslateInstance(strokeThickness + vertexBounds.width / 2.0,
|
||||
strokeThickness + vertexBounds.height / 2.0);
|
||||
offsetTransform.preConcatenate(graphicsTransform);
|
||||
graphics.setTransform(offsetTransform);
|
||||
Paint paint = Colors.getColor(vertex);
|
||||
if (paint instanceof Color) {
|
||||
Color color = (Color)paint;
|
||||
Color color = (Color) paint;
|
||||
Color transparent = new Color(color.getRed(), color.getGreen(), color.getBlue(), 50);
|
||||
graphics.setPaint(transparent);
|
||||
graphics.setStroke(new BasicStroke(strokeThickness));
|
||||
|
@ -201,7 +204,7 @@ public class GhidraIconCache {
|
|||
* Sets the vertex label to the value of the passed attribute name
|
||||
* @param attributeName the attribute key for the vertex label value to be displayed
|
||||
*/
|
||||
public void setPreferredLabel(String attributeName) {
|
||||
this.preferredLabel = attributeName;
|
||||
public void setPreferredVertexLabelAttribute(String attributeName) {
|
||||
this.preferredVeretxLabelAttribute = attributeName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.graph.visualization;
|
||||
|
||||
import static org.jungrapht.visualization.layout.util.PropertyLoader.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -26,8 +28,6 @@ import com.google.common.base.Splitter;
|
|||
import ghidra.service.graph.Attributed;
|
||||
import ghidra.service.graph.AttributedEdge;
|
||||
|
||||
import static org.jungrapht.visualization.layout.util.PropertyLoader.PREFIX;
|
||||
|
||||
/**
|
||||
* a container for various functions used by ProgramGraph
|
||||
*/
|
||||
|
@ -125,14 +125,14 @@ abstract class ProgramGraphFunctions {
|
|||
/**
|
||||
* gets a display label from an {@link Attributed} object (vertex)
|
||||
* @param attributed the attributed object to get a label for
|
||||
* @param preferredLabelKey the attribute to use for the label, if available
|
||||
* @param preferredLabelAttribute the attribute to use for the label, if available
|
||||
* @return the label for the given {@link Attributed}
|
||||
*/
|
||||
public static String getLabel(Attributed attributed, String preferredLabelKey) {
|
||||
public static String getLabel(Attributed attributed, String preferredLabelAttribute) {
|
||||
Map<String, String> map = attributed.getAttributeMap();
|
||||
String name = StringEscapeUtils.escapeHtml4(map.get("Name"));
|
||||
if (map.containsKey(preferredLabelKey)) {
|
||||
name = StringEscapeUtils.escapeHtml4(map.get(preferredLabelKey));
|
||||
if (map.containsKey(preferredLabelAttribute)) {
|
||||
name = StringEscapeUtils.escapeHtml4(map.get(preferredLabelAttribute));
|
||||
}
|
||||
return "<html>" + String.join("<p>", Splitter.on('\n').split(name));
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ public class BlockGraphTask extends Task {
|
|||
if (showCode) {
|
||||
display.defineVertexAttribute(CODE_ATTRIBUTE);
|
||||
display.defineVertexAttribute(SYMBOLS_ATTRIBUTE);
|
||||
display.setVertexLabel(CODE_ATTRIBUTE, GraphDisplay.ALIGN_LEFT, 12, true,
|
||||
display.setVertexLabelAttribute(CODE_ATTRIBUTE, GraphDisplay.ALIGN_LEFT, 12, true,
|
||||
codeLimitPerBlock + 1);
|
||||
}
|
||||
display.setGraph(graph, graphTitle, appendGraph, monitor);
|
||||
|
|
|
@ -74,7 +74,7 @@ public class TestGraphDisplay implements GraphDisplay {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace,
|
||||
public void setVertexLabelAttribute(String attributeName, int alignment, int size, boolean monospace,
|
||||
int maxLines) {
|
||||
// nothing
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import docking.action.DockingAction;
|
||||
|
@ -115,7 +113,7 @@ public interface GraphDisplay {
|
|||
* @param monospace true if the font should be monospaced
|
||||
* @param maxLines the maximum number lines to display in the vertex labels
|
||||
*/
|
||||
public void setVertexLabel(String attributeName, int alignment, int size, boolean monospace,
|
||||
public void setVertexLabelAttribute(String attributeName, int alignment, int size, boolean monospace,
|
||||
int maxLines);
|
||||
|
||||
/**
|
||||
|
@ -154,30 +152,4 @@ public interface GraphDisplay {
|
|||
* @param action the action to add.
|
||||
*/
|
||||
public void addAction(DockingAction action);
|
||||
|
||||
/**
|
||||
* set a property key/value pair. This may be used to pass preferences to the implementation
|
||||
* @param key the property key
|
||||
* @param value the propery value
|
||||
*/
|
||||
default void setProperty(String key, String value) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key the key to fetch a value for
|
||||
* @return the value associated with the passed key
|
||||
*/
|
||||
default String getValue(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property {@code Map} Should be implemented to pass an unmodifiable or copy
|
||||
* @return the complete {@code Map} of properties.
|
||||
*/
|
||||
default Map<String, String> getProperties() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue