mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/GP-773_ghidravore_graph_visualization_options--SQUASHED'
This commit is contained in:
commit
69e8119211
84 changed files with 4102 additions and 1822 deletions
|
@ -16,17 +16,8 @@
|
|||
package ghidra.service.graph;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
public class Attributed {
|
||||
/**
|
||||
* cache of the html rendering of the vertex attributes
|
||||
*/
|
||||
private String htmlString;
|
||||
private static final String DESCRIPTION = "Description";
|
||||
|
||||
/**
|
||||
|
@ -39,7 +30,7 @@ public class Attributed {
|
|||
* @return an unmodifiable view of the attribute map
|
||||
*/
|
||||
|
||||
public Map<String, String> getAttributeMap() {
|
||||
public Map<String, String> getAttributes() {
|
||||
return Collections.unmodifiableMap(attributes);
|
||||
}
|
||||
|
||||
|
@ -51,7 +42,6 @@ public class Attributed {
|
|||
* @return the previous value of the attribute
|
||||
*/
|
||||
public String setAttribute(String key, String value) {
|
||||
htmlString = null;
|
||||
return attributes.put(key, value);
|
||||
}
|
||||
|
||||
|
@ -154,7 +144,6 @@ public class Attributed {
|
|||
* @return the previously set description
|
||||
*/
|
||||
public String setDescription(String value) {
|
||||
htmlString = null;
|
||||
return attributes.put(DESCRIPTION, value);
|
||||
}
|
||||
|
||||
|
@ -167,35 +156,4 @@ public class Attributed {
|
|||
return getAttribute(DESCRIPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse (one time) then cache the attributes to html
|
||||
* @return the html string
|
||||
*/
|
||||
public String getHtmlString() {
|
||||
|
||||
if (htmlString != null) {
|
||||
return htmlString;
|
||||
}
|
||||
|
||||
htmlString = getDescription();
|
||||
if (htmlString == null) { // if no description is set, create a default one
|
||||
Set<Entry<String, String>> entries = entrySet();
|
||||
if (entries.isEmpty()) {
|
||||
return ""; // empty so tooltip clients can handle empty data
|
||||
}
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
buf.append(entry.getKey());
|
||||
buf.append(":");
|
||||
String value = entry.getValue();
|
||||
value = StringEscapeUtils.escapeHtml4(value);
|
||||
String split = String.join("<br>", Splitter.on('\n').split(value));
|
||||
split = split.replaceAll("\\s", " ");
|
||||
buf.append(split);
|
||||
buf.append("<br>");
|
||||
}
|
||||
htmlString = buf.toString();
|
||||
}
|
||||
return htmlString;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package ghidra.service.graph;
|
|||
* Generic directed graph edge implementation
|
||||
*/
|
||||
public class AttributedEdge extends Attributed {
|
||||
public static final String EDGE_TYPE_KEY = "EdgeType";
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
|
@ -62,4 +63,21 @@ public class AttributedEdge extends Attributed {
|
|||
return id.equals(other.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the edge type for this edge
|
||||
* @return the edge type for this edge
|
||||
*/
|
||||
public String getEdgeType() {
|
||||
return getAttribute(EDGE_TYPE_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the edge type for this edge. Should be a value defined by the {@link GraphType} for
|
||||
* this graph, but there is no enforcement for this. If the value is not defined in GraphType,
|
||||
* it will be rendered using the default edge color for {@link GraphType}
|
||||
* @param edgeType the edge type for this edge
|
||||
*/
|
||||
public void setEdgeType(String edgeType) {
|
||||
setAttribute(EDGE_TYPE_KEY, edgeType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,29 +33,80 @@ import org.jgrapht.graph.DefaultGraphType;
|
|||
* to the same source/destination vertex pair.
|
||||
*/
|
||||
public class AttributedGraph extends AbstractBaseGraph<AttributedVertex, AttributedEdge> {
|
||||
private static final String WEIGHT = "Weight";
|
||||
public static final String WEIGHT = "Weight";
|
||||
|
||||
private Map<String, AttributedVertex> vertexMap = new HashMap<>();
|
||||
private final boolean collapseDuplicateEdges;
|
||||
|
||||
private String name;
|
||||
|
||||
private GraphType type;
|
||||
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Create a new empty AttributedGraph that automatically collapses duplicate edges
|
||||
*
|
||||
* @param name the name of the graph
|
||||
* @param type the {@link GraphType} which defines valid vertex and edge types.
|
||||
*/
|
||||
public AttributedGraph() {
|
||||
this(true);
|
||||
public AttributedGraph(String name, GraphType type) {
|
||||
this(name, type, name, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty AttributedGraph that automatically collapses duplicate edges
|
||||
*
|
||||
* @param name the name of the graph
|
||||
* @param type the {@link GraphType} which defines valid vertex and edge types.
|
||||
* @param description a description of the graph
|
||||
*/
|
||||
public AttributedGraph(String name, GraphType type, String description) {
|
||||
this(name, type, description, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty AttributedGraph.
|
||||
*
|
||||
*
|
||||
* @param name the name of the graph
|
||||
* @param type the {@link GraphType} which defines valid vertex and edge types.
|
||||
* @param description a description of the graph
|
||||
* @param collapseDuplicateEdges if true, duplicate edges will be collapsed into a single
|
||||
* edge with a "Weight" attribute whose value is the number of edges between those vertices.
|
||||
*/
|
||||
public AttributedGraph(boolean collapseDuplicateEdges) {
|
||||
public AttributedGraph(String name, GraphType type, String description,
|
||||
boolean collapseDuplicateEdges) {
|
||||
super(new VertexSupplier(), new EdgeSupplier(), DefaultGraphType.directedPseudograph());
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
this.collapseDuplicateEdges = collapseDuplicateEdges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the graph
|
||||
* @return the name of the graph
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the graph
|
||||
* @return a description of the graph
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link GraphType} for this graph
|
||||
* @return the {@link GraphType} for this graph
|
||||
*/
|
||||
public GraphType getGraphType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new vertex with the given id. The vertex's name will be the same as the id.
|
||||
* If a vertex already exists with that id,
|
||||
|
|
|
@ -20,6 +20,8 @@ package ghidra.service.graph;
|
|||
*/
|
||||
public class AttributedVertex extends Attributed {
|
||||
|
||||
public static final String NAME_KEY = "Name";
|
||||
public static final String VERTEX_TYPE_KEY = "VertexType";
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
|
@ -43,7 +45,7 @@ public class AttributedVertex extends Attributed {
|
|||
* @param name the new name for the vertex
|
||||
*/
|
||||
public void setName(String name) {
|
||||
setAttribute("Name", name);
|
||||
setAttribute(NAME_KEY, name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +62,7 @@ public class AttributedVertex extends Attributed {
|
|||
* @return the name of the vertex
|
||||
*/
|
||||
public String getName() {
|
||||
return getAttribute("Name");
|
||||
return getAttribute(NAME_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,4 +90,22 @@ public class AttributedVertex extends Attributed {
|
|||
return id.equals(other.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertex type for this vertex
|
||||
* @return the vertex type for this vertex
|
||||
*/
|
||||
public String getVertexType() {
|
||||
return getAttribute(VERTEX_TYPE_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vertex type for this vertex. Should be a value defined by the {@link GraphType} for
|
||||
* this graph, but there is no enforcement for this. If the value is not defined in GraphType,
|
||||
* it will be rendered using the default vertex shape and color for the {@link GraphType}
|
||||
* @param vertexType the vertex type for this vertex
|
||||
*/
|
||||
public void setVertexType(String vertexType) {
|
||||
setAttribute(VERTEX_TYPE_KEY, vertexType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
/**
|
||||
* Empty implementation of GraphDiaplayOptions. Used as an initial default to avoid null
|
||||
* checks
|
||||
*/
|
||||
public class DefaultGraphDisplayOptions extends GraphDisplayOptions {
|
||||
|
||||
public DefaultGraphDisplayOptions() {
|
||||
super(new EmptyGraphType());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Default GraphType implementation that has no vertex or edge types defined
|
||||
*/
|
||||
public class EmptyGraphType extends GraphType {
|
||||
|
||||
public EmptyGraphType() {
|
||||
super("Empty Graph Type", "Graph type with no defined vertex or edge types",
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,831 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import docking.Tool;
|
||||
import docking.options.editor.*;
|
||||
import ghidra.framework.options.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.WebColors;
|
||||
import ghidra.util.bean.opteditor.OptionsVetoException;
|
||||
|
||||
/**
|
||||
* Class for managing graph display options. This includes color options for each vertex
|
||||
* and edge type and shapes for vertex types.
|
||||
*/
|
||||
public class GraphDisplayOptions implements OptionsChangeListener {
|
||||
|
||||
public static final GraphDisplayOptions DEFAULT =
|
||||
new GraphDisplayOptions(new EmptyGraphType());
|
||||
|
||||
private static final String FONT = "Font";
|
||||
private static final String LABEL_POSITION = "Label Position";
|
||||
private static final String USE_ICONS = "Use Icons";
|
||||
private static final String DEFAULT_LAYOUT_ALGORITHM = "Default Layout Algorithm";
|
||||
private static final String EDGE_COLORS = "Edge Colors";
|
||||
private static final String VERTEX_COLORS = "Vertex Colors";
|
||||
private static final String VERTEX_SHAPES = "Vertex Shapes";
|
||||
private static final String MISCELLANIOUS_OPTIONS = "Miscellanious";
|
||||
private static final String DEFAULT_VERTEX_COLOR = "Default Vertex Color";
|
||||
private static final String DEFAULT_EDGE_COLOR = "Default Edge Color";
|
||||
private static final String DEFAULT_VERTEX_SHAPE = "Default Vertex Shape";
|
||||
private static final String FAVORED_EDGE_TYPE = "Favored Edge Type";
|
||||
private static final String VERTEX_SELECTION_COLOR = "Selected Vertex Color";
|
||||
private static final String EDGE_SELECTION_COLOR = "Selected Edge Color";
|
||||
|
||||
private GraphType graphType;
|
||||
|
||||
private Map<String, Color> vertexColorMap = new HashMap<>();
|
||||
private Map<String, Color> edgeColorMap = new HashMap<>();
|
||||
private Map<String, VertexShape> vertexShapeMap = new HashMap<>();
|
||||
private Map<String, Integer> edgePriorityMap = new HashMap<>();
|
||||
private List<ChangeListener> changeListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private Color vertexSelectionColor = Color.green;
|
||||
private Color edgeSelectionColor = Color.green;
|
||||
private Color defaultVertexColor = Color.blue;
|
||||
private Color defaultEdgeColor = Color.blue;
|
||||
private String favoredEdgeType;
|
||||
|
||||
private VertexShape defaultVertexShape = VertexShape.RECTANGLE;
|
||||
private String vertexLabelOverride = null;
|
||||
private String vertexColorOverride = null;
|
||||
private String vertexShapeOverride = null;
|
||||
private String edgeColorOverride = null;
|
||||
private final String rootOptionsName;
|
||||
private boolean registeredWithTool = false;
|
||||
private String defaultLayoutAlgorithmName = LayoutAlgorithmNames.MIN_CROSS_COFFMAN_GRAHAM;
|
||||
private boolean useIcons = true;
|
||||
private GraphLabelPosition labelPosition = GraphLabelPosition.SOUTH;
|
||||
private Font font = new Font("Dialog", Font.BOLD, 18);
|
||||
private int arrowLength = 15;
|
||||
|
||||
/**
|
||||
* Constructs a new GraphTypeDisplayOptions for the given {@link GraphType}
|
||||
* @param graphType The {@link GraphType} for which to define display options
|
||||
*/
|
||||
public GraphDisplayOptions(GraphType graphType) {
|
||||
this(graphType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new GraphTypeDisplayOptions for the given {@link GraphType} and initializes
|
||||
* from tool options. Note this form should only be used for display options on
|
||||
* {@link GraphType}s that have options registered in the tool.
|
||||
* @param graphType The {@link GraphType} for which to define display options
|
||||
* @param tool the tool from which to initialize from {@link ToolOptions}
|
||||
*/
|
||||
public GraphDisplayOptions(GraphType graphType, Tool tool) {
|
||||
this.graphType = graphType;
|
||||
rootOptionsName = graphType.getOptionsName();
|
||||
List<String> edgeTypes = graphType.getEdgeTypes();
|
||||
if (!edgeTypes.isEmpty()) {
|
||||
favoredEdgeType = edgeTypes.iterator().next();
|
||||
}
|
||||
initializeEdgePriorities();
|
||||
initializeDefaults();
|
||||
initializeFromOptions(tool);
|
||||
}
|
||||
|
||||
private void initializeEdgePriorities() {
|
||||
// initialize priorities based on the order they were defined
|
||||
for (String edgeType : graphType.getEdgeTypes()) {
|
||||
edgePriorityMap.put(edgeType, edgePriorityMap.size());
|
||||
}
|
||||
}
|
||||
|
||||
protected void initializeDefaults() {
|
||||
// Overridden by subclass to define defaultValues
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ChangeListener to be notified when display options change
|
||||
* @param listener the listener to be notified.
|
||||
*/
|
||||
public void addChangeListener(ChangeListener listener) {
|
||||
changeListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener so that it won't be notified of changes any longer
|
||||
* @param listener the listener to be removed
|
||||
*/
|
||||
public void removeChangeListener(ChangeListener listener) {
|
||||
changeListeners.remove(listener);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets the default shape to be used by vertices that don't have a vertex type set
|
||||
* @param shape the default vertex shape
|
||||
*/
|
||||
public void setDefaultVertexShape(VertexShape shape) {
|
||||
this.defaultVertexShape = Objects.requireNonNull(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default color to be used by vertices that don't have a vertex type set
|
||||
* @param color the default vertex shape
|
||||
*/
|
||||
public void setDefaultVertexColor(Color color) {
|
||||
this.defaultVertexColor = Objects.requireNonNull(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default color to be used by edges that don't have a edge type set
|
||||
* @param color the default edge shape
|
||||
*/
|
||||
public void setDefaultEdgeColor(Color color) {
|
||||
this.defaultEdgeColor = Objects.requireNonNull(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default color for edges that don't have an edge type set
|
||||
* @return the default color for edges that don't have an edge type set
|
||||
*/
|
||||
public Color getDefaultEdgeColor() {
|
||||
return defaultEdgeColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default color for vertices that don't have an vertex type set
|
||||
* @return the default color for vertices that don't have an vertex type set
|
||||
*/
|
||||
public Color getDefaultVertexColor() {
|
||||
return defaultVertexColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute key that can be used to override the label text shown for the vertex.
|
||||
* Normally, the vertex's name is shown as the label.
|
||||
* @param attributeKey the attribute key that, if set, will be used to define the vertice's label
|
||||
*/
|
||||
public void setVertexLabelOverrideAttributeKey(String attributeKey) {
|
||||
vertexLabelOverride = attributeKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute key that can override the vertices label text
|
||||
* @return the attribute key that can override the vertices label text
|
||||
*/
|
||||
public String getVertexLabelOverride() {
|
||||
return vertexLabelOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute key that can be used to override the color for a vertex. Normally, the
|
||||
* color is determined by the vertex type, which will be mapped to a color
|
||||
* @param attributeKey the attribute key that, if set, will be used to define the vertice's color
|
||||
*/
|
||||
public void setVertexColorOverrideAttributeKey(String attributeKey) {
|
||||
vertexColorOverride = attributeKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute key that can be used to override the color for an edge. Normally, the
|
||||
* color is determined by the edge type, which will be mapped to a color
|
||||
* @param attributeKey the attribute key that, if set, will be used to define the edge's color
|
||||
*/
|
||||
public void setEdgeColorOverrideAttributeKey(String attributeKey) {
|
||||
edgeColorOverride = attributeKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute key that can be used to override the color of an edge
|
||||
* @return the attribute key that can be used to override the color of an edge
|
||||
*/
|
||||
public String getEdgeColorOverrideAttributeKey() {
|
||||
return edgeColorOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute key that can be used to override the shape for a vertex. Normally, the
|
||||
* shape is determined by the vertex type, which will be mapped to a shape
|
||||
* @param attributeKey the attribute key that, if set, will be used to define the vertice's shape
|
||||
*/
|
||||
public void setVertexShapeOverrideAttributeKey(String attributeKey) {
|
||||
vertexShapeOverride = attributeKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text that will be displayed as the label for the given vertex
|
||||
* @param vertex the vertex for which to get label text
|
||||
* @return the text that will be displayed as the label for the given vertex
|
||||
*/
|
||||
public String getVertexLabel(AttributedVertex vertex) {
|
||||
String vertexLabel = null;
|
||||
|
||||
if (vertexLabelOverride != null) {
|
||||
vertexLabel = vertex.getAttribute(vertexLabelOverride);
|
||||
}
|
||||
|
||||
if (vertexLabel == null) {
|
||||
vertexLabel = vertex.getName();
|
||||
}
|
||||
|
||||
if (vertexLabel.contains("\n")) {
|
||||
vertexLabel = StringEscapeUtils.escapeHtml4(vertexLabel);
|
||||
return "<html>" + String.join("<p>", Splitter.on('\n').split(vertexLabel));
|
||||
}
|
||||
return vertexLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link VertexShape} that will be used to draw the vertex's shape
|
||||
* @param vertex the vertex for which to get the shape
|
||||
* @return the {@link VertexShape} that will be used to draw the vertex's shape
|
||||
*/
|
||||
public VertexShape getVertexShape(AttributedVertex vertex) {
|
||||
if (vertexShapeOverride != null) {
|
||||
String shapeName = vertex.getAttribute(vertexShapeOverride);
|
||||
if (shapeName != null) {
|
||||
VertexShape shape = VertexShape.getShape(shapeName);
|
||||
if (shape != null) {
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
}
|
||||
String vertexType = vertex.getVertexType();
|
||||
return vertexShapeMap.getOrDefault(vertexType, defaultVertexShape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color that will be used to draw the vertex
|
||||
* @param vertex the vertex for which to get the color
|
||||
* @return the color that will be used to draw the vertex
|
||||
*/
|
||||
public Color getVertexColor(AttributedVertex vertex) {
|
||||
if (vertexColorOverride != null) {
|
||||
String colorValue = vertex.getAttribute(vertexColorOverride);
|
||||
if (colorValue != null) {
|
||||
Color color = WebColors.getColor(colorValue);
|
||||
if (color != null) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String vertexType = vertex.getVertexType();
|
||||
return vertexColorMap.getOrDefault(vertexType, defaultVertexColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color that will be used to draw the edge
|
||||
* @param edge the edge for which to get the color
|
||||
* @return the color that will be used to draw the edge
|
||||
*/
|
||||
public Color getEdgeColor(AttributedEdge edge) {
|
||||
if (edgeColorOverride != null) {
|
||||
String colorValue = edge.getAttribute(edgeColorOverride);
|
||||
if (colorValue != null) {
|
||||
Color color = WebColors.getColor(colorValue);
|
||||
if (color != null) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String edgeType = edge.getEdgeType();
|
||||
return edgeColorMap.getOrDefault(edgeType, defaultEdgeColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the priority for the given edge type. This is used by layout algorithms to
|
||||
* determine which edges should have more influence on the layout.
|
||||
* @param edgeType the edge type for which to get it's priority
|
||||
* @return the priority for the given edge type
|
||||
*/
|
||||
public Integer getEdgePriority(String edgeType) {
|
||||
return edgePriorityMap.getOrDefault(edgeType, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the edge type that is the preferred edge for layout purposes
|
||||
* @return the edge type that is the preferred edge for layout purposes
|
||||
*/
|
||||
public String getFavoredEdgeType() {
|
||||
return favoredEdgeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the favored edge type. The favored edge type is used to influence layout algorithms
|
||||
* @param favoredEdgeType the edge type that is to be favored by layout algorithms
|
||||
*/
|
||||
public void setFavoredEdgeType(String favoredEdgeType) {
|
||||
checkEdgeType(favoredEdgeType);
|
||||
this.favoredEdgeType = favoredEdgeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link GraphType} that this object provides display options for
|
||||
* @return the {@link GraphType} that this object provides display options for
|
||||
*/
|
||||
public GraphType getGraphType() {
|
||||
return graphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color for the given vertex type
|
||||
* @param vertexType the vertex type to get the color for
|
||||
* @return the color for the given vertex type
|
||||
*/
|
||||
public Color getVertexColor(String vertexType) {
|
||||
return vertexColorMap.getOrDefault(vertexType, defaultVertexColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color for vertices with the given vertex type
|
||||
* @param vertexType the vertex type for which to set its color
|
||||
* @param color the color to use for vertices with the given vertex type
|
||||
*/
|
||||
public void setVertexColor(String vertexType, Color color) {
|
||||
checkVertexType(vertexType);
|
||||
vertexColorMap.put(vertexType, Objects.requireNonNull(color));
|
||||
}
|
||||
|
||||
private String getVertexShapeName(String vertexType) {
|
||||
VertexShape vertexShape = vertexShapeMap.getOrDefault(vertexType, defaultVertexShape);
|
||||
return vertexShape.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link VertexShape} to use for vertices with the given vertex type
|
||||
* @param vertexType the vertex type for which to set its shape
|
||||
* @param vertexShape the {@link VertexShape} to use for vertices with the given vertex type
|
||||
*/
|
||||
public void setVertexShape(String vertexType, VertexShape vertexShape) {
|
||||
checkVertexType(vertexType);
|
||||
vertexShapeMap.put(vertexType, Objects.requireNonNull(vertexShape));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the color for the given edge type
|
||||
* @param edgeType the edge type whose color is to be determined.
|
||||
* @return the color for the given edge type.
|
||||
*/
|
||||
public Color getEdgeColor(String edgeType) {
|
||||
return edgeColorMap.getOrDefault(edgeType, defaultEdgeColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color for edges with the given edge type
|
||||
* @param edgeType the edge type for which to set its color
|
||||
* @param color the new color for edges with the given edge type
|
||||
*/
|
||||
public void setEdgeColor(String edgeType, Color color) {
|
||||
checkEdgeType(edgeType);
|
||||
edgeColorMap.put(edgeType, Objects.requireNonNull(color));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||
Object newValue) throws OptionsVetoException {
|
||||
if (optionName.startsWith(rootOptionsName)) {
|
||||
updateOptions(options.getOptions(rootOptionsName));
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name for the root Options name for this {@link GraphDisplayOptions}
|
||||
* @return the name for the root Options name for this {@link GraphDisplayOptions}
|
||||
*/
|
||||
public String getRootOptionsName() {
|
||||
return rootOptionsName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute key that can be used to override the color of a vertex. Normally,
|
||||
* a vertex is colored based on its vertex type. However, if this value is non-null, a vertex
|
||||
* can override its color by setting an attribute using this key name.
|
||||
* @return the attribute key that can be used to override the color of a vertex
|
||||
*/
|
||||
public String getVertexColorOverrideAttributeKey() {
|
||||
return vertexColorOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute key that can be used to override the shape of a vertex. Normally,
|
||||
* a vertex has a shape based on its vertex type. However, if this value is non-null, a vertex
|
||||
* can override its shape by setting an attribute using this key name.
|
||||
* @return the attribute key that can be used to override the shape of a vertex
|
||||
*/
|
||||
public String getVertexShapeOverrideAttributeKey() {
|
||||
return vertexShapeOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the {@link VertexShape} for any vertex that has not vertex type defined
|
||||
* @return the {@link VertexShape} for any vertex that has not vertex type defined
|
||||
*/
|
||||
public VertexShape getDefaultVertexShape() {
|
||||
return defaultVertexShape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link VertexShape} for vertices that have the given vertex type
|
||||
* @param vertexType the vertex type for which to get its asigned shape
|
||||
* @return the {@link VertexShape} for vertices that have the given vertex type
|
||||
*/
|
||||
public VertexShape getVertexShape(String vertexType) {
|
||||
return vertexShapeMap.getOrDefault(vertexType, defaultVertexShape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertex selection color
|
||||
* @return the vertex selection color
|
||||
*/
|
||||
public Color getVertexSelectionColor() {
|
||||
return vertexSelectionColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vertex selection color
|
||||
* @param vertexSelectionColor the color to use for highlighting selected vertices
|
||||
*/
|
||||
public void setVertexSelectionColor(Color vertexSelectionColor) {
|
||||
this.vertexSelectionColor = vertexSelectionColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color for edge selections
|
||||
* @return the color fore edge selections
|
||||
*/
|
||||
public Color getEdgeSelectionColor() {
|
||||
return edgeSelectionColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the edge selection color
|
||||
* @param edgeSelectionColor color to use for highlighting selected edges
|
||||
*/
|
||||
public void setEdgeSelectionColor(Color edgeSelectionColor) {
|
||||
this.edgeSelectionColor = edgeSelectionColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the default graph layout algorithm
|
||||
* @return the name of the default graph layout algorithms
|
||||
*/
|
||||
public String getDefaultLayoutAlgorithmNameLayout() {
|
||||
return defaultLayoutAlgorithmName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the default layout algorithm
|
||||
* @param defaultLayout the name of the layout algorithm to use by default
|
||||
*/
|
||||
public void setDefaultLayoutAlgorithmName(String defaultLayout) {
|
||||
this.defaultLayoutAlgorithmName = defaultLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the rendering mode is to use icons for the vertices. If using
|
||||
* icons, the label is drawn inside the shape.
|
||||
* @return true if the rendering mode is to use icons.
|
||||
*/
|
||||
public boolean usesIcons() {
|
||||
return useIcons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the graph rendering mode is to use icons or not. If using icons, the label and
|
||||
* shape are drawn together into a cached icon. Otherwise, the shapes are drawn on the fly and
|
||||
* labeled separately.
|
||||
* @param b true to render in icon mode.
|
||||
*/
|
||||
public void setUsesIcons(boolean b) {
|
||||
this.useIcons = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label position relative to the vertex. Note this is only relevant
|
||||
* if {@link #usesIcons()} is false
|
||||
* @return the label position relative to the vertex
|
||||
*/
|
||||
public GraphLabelPosition getLabelPosition() {
|
||||
return labelPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label position relative to the vertex. Note this is only relevant
|
||||
* if {@link #usesIcons()} is false.
|
||||
* @param labelPosition the {@link GraphLabelPosition} to use for rendering vertex labels
|
||||
*/
|
||||
public void setLabelPosition(GraphLabelPosition labelPosition) {
|
||||
this.labelPosition = labelPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the font to use for drawing vertex labels
|
||||
* @param font the font to use for drawing vertex labels
|
||||
*/
|
||||
public void setFont(Font font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font being used to render vertex labels
|
||||
* @return the font being used to render vertex labels
|
||||
*/
|
||||
public Font getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the arrow. The width will be proportional to the length.
|
||||
* Note: this option is not exposed in the Options because it is too specific to a graph
|
||||
* instance and wouldn't be appropriate to apply to shared options.
|
||||
* @return the size if the arrow
|
||||
*/
|
||||
public int getArrowLength() {
|
||||
return arrowLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the length of the arrow. The width will be proportional to the length.
|
||||
* Note: this option is not exposed in the Options because it is too specific to a graph
|
||||
* instance and wouldn't be appropriate to apply to shared options.
|
||||
* @param length the size of the arrow
|
||||
*/
|
||||
public void setArrowLength(int length) {
|
||||
this.arrowLength = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this {@link GraphDisplayOptions} instance has been constructed with
|
||||
* a tool for getting/saving option values in the tool options
|
||||
* @return true if this {@link GraphDisplayOptions} instance is connected to tool options
|
||||
*/
|
||||
public boolean isRegisteredWithTool() {
|
||||
return registeredWithTool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this GraphTypeDisplayOptions with {@link ToolOptions}. Note: this should only
|
||||
* be used by plugins or other objects that get instantiated immediately when the tool is
|
||||
* constructed. Otherwise, if the tool exits and this hasn't been called, any saved option
|
||||
* values will be lost.
|
||||
* <P>
|
||||
* @param toolOptions the {@link ToolOptions} to register these options with
|
||||
* @param help the help location to be used by the {@link OptionsDialog} for display/editing
|
||||
* these options
|
||||
*/
|
||||
public void registerOptions(ToolOptions toolOptions, HelpLocation help) {
|
||||
Options rootOptions = toolOptions.getOptions(graphType.getOptionsName());
|
||||
registerVertexColorOptions(rootOptions, help);
|
||||
registerVertexShapeOptions(rootOptions, help);
|
||||
registerEdgeColorOptions(rootOptions, help);
|
||||
registerMiscellaniousOptions(rootOptions, help);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default values for vertex types
|
||||
* @param vertexType the vertex type whose default color and shape are being defined
|
||||
* @param vertexShape the default vertex shape for the given vertex type
|
||||
* @param color the default color for the given vertex type
|
||||
*/
|
||||
protected void configureVertexType(String vertexType, VertexShape vertexShape, Color color) {
|
||||
checkVertexType(vertexType);
|
||||
vertexShapeMap.put(vertexType, vertexShape);
|
||||
vertexColorMap.put(vertexType, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default values for edge types
|
||||
* @param edgeType the edge type whose default color and shape are being defined
|
||||
* @param color the default color for the given edge type
|
||||
*/
|
||||
protected void configureEdgeType(String edgeType, Color color) {
|
||||
checkEdgeType(edgeType);
|
||||
edgeColorMap.put(edgeType, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads values from tool options
|
||||
*
|
||||
* @param tool the tool from which to update values.
|
||||
*/
|
||||
public void initializeFromOptions(Tool tool) {
|
||||
if (tool == null) {
|
||||
return;
|
||||
}
|
||||
ToolOptions toolOptions = tool.getOptions("Graph");
|
||||
toolOptions.addOptionsChangeListener(this);
|
||||
updateOptions(toolOptions.getOptions(rootOptionsName));
|
||||
registeredWithTool = true;
|
||||
}
|
||||
|
||||
|
||||
private void updateOptions(Options rootOptions) {
|
||||
updateVertexColorsFromOptions(rootOptions);
|
||||
updateEdgeColorsFromOptions(rootOptions);
|
||||
updateVertexShapesFromOptions(rootOptions);
|
||||
updateMiscellaniousOptions(rootOptions);
|
||||
}
|
||||
|
||||
private void updateMiscellaniousOptions(Options rootOptions) {
|
||||
Options options = rootOptions.getOptions(MISCELLANIOUS_OPTIONS);
|
||||
String shapeName = options.getString(DEFAULT_VERTEX_SHAPE, defaultVertexShape.getName());
|
||||
defaultVertexShape = VertexShape.getShape(shapeName);
|
||||
|
||||
defaultVertexColor = options.getColor(DEFAULT_VERTEX_COLOR, defaultVertexColor);
|
||||
defaultEdgeColor = options.getColor(DEFAULT_EDGE_COLOR, defaultEdgeColor);
|
||||
favoredEdgeType = options.getString(FAVORED_EDGE_TYPE, favoredEdgeType);
|
||||
|
||||
vertexSelectionColor = options.getColor(VERTEX_SELECTION_COLOR, vertexSelectionColor);
|
||||
edgeSelectionColor = options.getColor(EDGE_SELECTION_COLOR, edgeSelectionColor);
|
||||
|
||||
defaultLayoutAlgorithmName =
|
||||
options.getString(DEFAULT_LAYOUT_ALGORITHM, defaultLayoutAlgorithmName);
|
||||
|
||||
useIcons = options.getBoolean(USE_ICONS, useIcons);
|
||||
labelPosition = options.getEnum(LABEL_POSITION, labelPosition);
|
||||
font = options.getFont(FONT, font);
|
||||
}
|
||||
|
||||
private void updateVertexShapesFromOptions(Options rootOptions) {
|
||||
Options options = rootOptions.getOptions(VERTEX_SHAPES);
|
||||
for (String vertexType : graphType.getVertexTypes()) {
|
||||
String current = getVertexShapeName(vertexType);
|
||||
String shapeName = options.getString(vertexType, current);
|
||||
if (shapeName != null && !shapeName.equals(current)) {
|
||||
VertexShape shape = VertexShape.getShape(shapeName);
|
||||
if (shape != null) {
|
||||
setVertexShape(vertexType, VertexShape.getShape(shapeName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEdgeColorsFromOptions(Options rootOptions) {
|
||||
Options options = rootOptions.getOptions(EDGE_COLORS);
|
||||
for (String edgeType : graphType.getEdgeTypes()) {
|
||||
Color current = getEdgeColor(edgeType);
|
||||
Color color = options.getColor(edgeType, current);
|
||||
if (color != null && !color.equals(current)) {
|
||||
setEdgeColor(edgeType, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (ChangeListener changeListener : changeListeners) {
|
||||
changeListener.stateChanged(new ChangeEvent(this));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVertexColorsFromOptions(Options rootOptions) {
|
||||
Options options = rootOptions.getOptions(VERTEX_COLORS);
|
||||
for (String vertexType : graphType.getVertexTypes()) {
|
||||
Color current = getVertexColor(vertexType);
|
||||
Color color = options.getColor(vertexType, current);
|
||||
if (color != null && !color.equals(current)) {
|
||||
setVertexColor(vertexType, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerVertexColorOptions(Options rootOptions, HelpLocation help) {
|
||||
Options options = rootOptions.getOptions(VERTEX_COLORS);
|
||||
|
||||
for (String vertexType : graphType.getVertexTypes()) {
|
||||
options.registerOption(vertexType, OptionType.COLOR_TYPE,
|
||||
getVertexColor(vertexType), help,
|
||||
"Choose the color for this vertex type");
|
||||
}
|
||||
List<String> list = new ArrayList<>(graphType.getVertexTypes());
|
||||
OptionsEditor editor = new ScrollableOptionsEditor(VERTEX_COLORS, list);
|
||||
options.registerOptionsEditor(editor);
|
||||
}
|
||||
|
||||
private void registerVertexShapeOptions(Options rootOptions, HelpLocation help) {
|
||||
Options options = rootOptions.getOptions(VERTEX_SHAPES);
|
||||
|
||||
List<String> shapeNames = VertexShape.getShapeNames();
|
||||
|
||||
for (String vertexType : graphType.getVertexTypes()) {
|
||||
StringWithChoicesEditor editor = new StringWithChoicesEditor(shapeNames);
|
||||
options.registerOption(vertexType, OptionType.STRING_TYPE,
|
||||
getVertexShapeName(vertexType), help,
|
||||
"Choose the shape for this vertex type", editor);
|
||||
}
|
||||
List<String> list = new ArrayList<>(graphType.getVertexTypes());
|
||||
OptionsEditor editor = new ScrollableOptionsEditor(VERTEX_SHAPES, list);
|
||||
options.registerOptionsEditor(editor);
|
||||
}
|
||||
|
||||
private void registerEdgeColorOptions(Options rootOptions, HelpLocation help) {
|
||||
Options options = rootOptions.getOptions(EDGE_COLORS);
|
||||
|
||||
for (String edgeType : graphType.getEdgeTypes()) {
|
||||
options.registerOption(edgeType, OptionType.COLOR_TYPE,
|
||||
getEdgeColor(edgeType), help, "Choose the color for this edge type");
|
||||
}
|
||||
List<String> list = new ArrayList<>(graphType.getEdgeTypes());
|
||||
OptionsEditor editor = new ScrollableOptionsEditor(EDGE_COLORS, list);
|
||||
options.registerOptionsEditor(editor);
|
||||
}
|
||||
|
||||
private void registerMiscellaniousOptions(Options rootOptions, HelpLocation help) {
|
||||
|
||||
Options options = rootOptions.getOptions(MISCELLANIOUS_OPTIONS);
|
||||
|
||||
StringWithChoicesEditor editor = new StringWithChoicesEditor(VertexShape.getShapeNames());
|
||||
|
||||
options.registerOption(VERTEX_SELECTION_COLOR, OptionType.COLOR_TYPE, vertexSelectionColor,
|
||||
help, "Color for highlighting selected vertices");
|
||||
|
||||
options.registerOption(EDGE_SELECTION_COLOR, OptionType.COLOR_TYPE, edgeSelectionColor,
|
||||
help, "Color for highlighting selected edge");
|
||||
|
||||
options.registerOption(DEFAULT_VERTEX_SHAPE, OptionType.STRING_TYPE,
|
||||
defaultVertexShape.getName(),
|
||||
help, "Shape for vertices that have no vertex type defined", editor);
|
||||
|
||||
options.registerOption(DEFAULT_VERTEX_COLOR, OptionType.COLOR_TYPE, defaultVertexColor,
|
||||
help, "Color for vertices that have no vertex type defined");
|
||||
|
||||
options.registerOption(DEFAULT_EDGE_COLOR, OptionType.COLOR_TYPE, defaultEdgeColor,
|
||||
help, "Color for edge that have no edge type defined");
|
||||
|
||||
editor = new StringWithChoicesEditor(graphType.getEdgeTypes());
|
||||
options.registerOption(FAVORED_EDGE_TYPE, OptionType.STRING_TYPE, favoredEdgeType, help,
|
||||
"Favored edge is used to influence layout algorithms", editor);
|
||||
|
||||
editor = new StringWithChoicesEditor(LayoutAlgorithmNames.getLayoutAlgorithmNames());
|
||||
options.registerOption(DEFAULT_LAYOUT_ALGORITHM, OptionType.STRING_TYPE,
|
||||
defaultLayoutAlgorithmName, help, "Initial layout algorithm", editor);
|
||||
|
||||
options.registerOption(USE_ICONS, OptionType.BOOLEAN_TYPE, useIcons, help,
|
||||
"If true, vertices are drawn using pre-rendered images versus compact shapes");
|
||||
|
||||
options.registerOption(LABEL_POSITION, OptionType.ENUM_TYPE, labelPosition, help,
|
||||
"Relative postion of labels to vertex shape (Only applicable if \"Use Icons\" is true");
|
||||
|
||||
options.registerOption(FONT, OptionType.FONT_TYPE, font, help,
|
||||
"Font to use for vertex labels");
|
||||
|
||||
List<String> optionNamesInDisplayOrder = new ArrayList<>();
|
||||
|
||||
optionNamesInDisplayOrder.add(VERTEX_SELECTION_COLOR);
|
||||
optionNamesInDisplayOrder.add(EDGE_SELECTION_COLOR);
|
||||
optionNamesInDisplayOrder.add(DEFAULT_VERTEX_COLOR);
|
||||
optionNamesInDisplayOrder.add(DEFAULT_EDGE_COLOR);
|
||||
optionNamesInDisplayOrder.add(DEFAULT_VERTEX_SHAPE);
|
||||
optionNamesInDisplayOrder.add(FAVORED_EDGE_TYPE);
|
||||
optionNamesInDisplayOrder.add(DEFAULT_LAYOUT_ALGORITHM);
|
||||
optionNamesInDisplayOrder.add(LABEL_POSITION);
|
||||
optionNamesInDisplayOrder.add(FONT);
|
||||
optionNamesInDisplayOrder.add(USE_ICONS);
|
||||
|
||||
|
||||
OptionsEditor optionsEditor =
|
||||
new ScrollableOptionsEditor(MISCELLANIOUS_OPTIONS, optionNamesInDisplayOrder);
|
||||
options.registerOptionsEditor(optionsEditor);
|
||||
|
||||
}
|
||||
|
||||
private void checkVertexType(String vertexType) {
|
||||
if (!getGraphType().containsVertexType(vertexType)) {
|
||||
throw new IllegalArgumentException("VertexType \"" + vertexType +
|
||||
"\" not defined in GraphType \"" + getGraphType().getName() + "\".");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkEdgeType(String edgeType) {
|
||||
if (!getGraphType().containsEdgeType(edgeType)) {
|
||||
throw new IllegalArgumentException("EdgeType \"" + edgeType +
|
||||
"\" not defined in GraphType \"" + getGraphType().getName() + "\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Builder for building {@link GraphDisplayOptions}
|
||||
*/
|
||||
public class GraphDisplayOptionsBuilder {
|
||||
|
||||
private GraphDisplayOptions displayOptions;
|
||||
|
||||
/**
|
||||
* Create a new {@link GraphDisplayOptionsBuilder}
|
||||
* @param graphType the {@link GraphType} of graphs that this instance configures.
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder(GraphType graphType) {
|
||||
displayOptions = new GraphDisplayOptions(graphType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default vertex color for vertexes that don't have a registered vertex type
|
||||
* @param c the default vertex color
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder defaultVertexColor(Color c) {
|
||||
displayOptions.setDefaultVertexColor(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default edge color for edges that don't have a registered edge type
|
||||
* @param c the default edge color
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder defaultEdgeColor(Color c) {
|
||||
Objects.requireNonNull(c);
|
||||
displayOptions.setDefaultEdgeColor(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vertex selection color
|
||||
* @param color the vertex selection color
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder vertexSelectionColor(Color color) {
|
||||
displayOptions.setVertexSelectionColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the edge selection color
|
||||
* @param color the edge selection color
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder edgeSelectionColor(Color color) {
|
||||
displayOptions.setEdgeSelectionColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default vertex shape for vertices that don't have a registered vertex type
|
||||
* @param vertexShape the {@link VertexShape} to use as a default
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder defaultVertexShape(VertexShape vertexShape) {
|
||||
Objects.requireNonNull(vertexShape);
|
||||
displayOptions.setDefaultVertexShape(vertexShape);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the shape and color for vertices of the given type
|
||||
* @param vertexType the vertex type to assign shape and color
|
||||
* @param vertexShape the shape to use for the named vertex type
|
||||
* @param color the color to use for the named vertex type
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder vertex(String vertexType, VertexShape vertexShape,
|
||||
Color color) {
|
||||
displayOptions.configureVertexType(vertexType, vertexShape, color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color for edges of the given type
|
||||
* @param edgeType the edge type to assign color
|
||||
* @param color the color to use for the named edge type
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder edge(String edgeType, Color color) {
|
||||
displayOptions.configureEdgeType(edgeType, color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute used to override the color for a vertex
|
||||
* @param colorAttributeKey the attribute key to use for overriding a vertex color
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder vertexColorOverrideAttribute(String colorAttributeKey) {
|
||||
displayOptions.setVertexColorOverrideAttributeKey(colorAttributeKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute used to override the color for a edge
|
||||
* @param colorAttributeKey the attribute key to use for overriding an edge color
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder edgeColorOverrideAttribute(String colorAttributeKey) {
|
||||
displayOptions.setEdgeColorOverrideAttributeKey(colorAttributeKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute used to override the shape for a vertex
|
||||
* @param shapeAttributeKey the attribute key to use of shape override
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder shapeOverrideAttribute(String shapeAttributeKey) {
|
||||
displayOptions.setVertexShapeOverrideAttributeKey(shapeAttributeKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the layout algorithm that will be used to initially layout the graph
|
||||
* @param string the name of the layout algoritm to use to initially layout the graph
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder defaultLayoutAlgorithm(String string) {
|
||||
displayOptions.setDefaultLayoutAlgorithmName(string);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets drawing "mode" for the graph display. If true, vertices are drawn as scaled
|
||||
* cached images with the label inside the shapes. If false, vertices are drawn as smaller
|
||||
* shapes with labels drawn near the shapes.
|
||||
* @param b true to use pre-rendered icon images
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder useIcons(boolean b) {
|
||||
displayOptions.setUsesIcons(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the length of the arrows to display in the graph. The width will be sized proportionately.
|
||||
* @param length the length the arrows to display in the graph
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder arrowLength(int length) {
|
||||
displayOptions.setArrowLength(length);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vertex label position relative to vertex shape. This is only applicable if the
|
||||
* {@link #useIcons(boolean)} is set to true.
|
||||
* @param labelPosition the relative position to place the vertex label
|
||||
* @return this {@link GraphDisplayOptionsBuilder}
|
||||
*/
|
||||
public GraphDisplayOptionsBuilder labelPosition(GraphLabelPosition labelPosition) {
|
||||
displayOptions.setLabelPosition(labelPosition);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a GraphTypeDisplayOptions as configured by this builder
|
||||
* @return a GraphTypeDisplayOptions as configured by this builder
|
||||
*/
|
||||
public GraphDisplayOptions build() {
|
||||
return displayOptions;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
/**
|
||||
* Specification for the vertex label position relative to the vertex shape.
|
||||
*/
|
||||
public enum GraphLabelPosition {
|
||||
NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST, CENTER
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class that defines a new graph type. It defines the set of valid vertex and edge types
|
||||
*/
|
||||
public class GraphType {
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private final Set<String> vertexTypes;
|
||||
private final Set<String> edgeTypes;
|
||||
|
||||
/**
|
||||
* Constructs a new GraphType
|
||||
*
|
||||
* @param name the name of this GraphType instance
|
||||
* @param description a brief description for graphs of this type
|
||||
* @param vertexTypes a list of all valid vertex types for graphs of this type
|
||||
* @param edgeTypes a list of all valid edge types for graphs of this type
|
||||
*/
|
||||
public GraphType(String name, String description, List<String> vertexTypes,
|
||||
List<String> edgeTypes) {
|
||||
this.name = Objects.requireNonNull(name);
|
||||
this.description = Objects.requireNonNull(description);
|
||||
|
||||
this.vertexTypes = Collections.unmodifiableSet(new LinkedHashSet<String>(vertexTypes));
|
||||
this.edgeTypes = Collections.unmodifiableSet(new LinkedHashSet<String>(edgeTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name for this type of graph
|
||||
* @return a name of this type of graph
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description for this type of graph
|
||||
* @return a description for this type of graph
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of valid vertex types for graphs of this type
|
||||
* @return a list of valid vertex types for graphs of this type
|
||||
*/
|
||||
public List<String> getVertexTypes() {
|
||||
return new ArrayList<>(vertexTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of valid edge types for graphs of this type
|
||||
* @return a list of valid edge types for graphs of this type
|
||||
*/
|
||||
public List<String> getEdgeTypes() {
|
||||
return new ArrayList<>(edgeTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the given string is a valid vertex type
|
||||
* @param vertexType the string to test for being a valid vertex type
|
||||
* @return true if the given string is a valid vertex type
|
||||
*/
|
||||
public boolean containsVertexType(String vertexType) {
|
||||
return vertexTypes.contains(vertexType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the given string is a valid edge type
|
||||
* @param edgeType the string to test for being a valid edge type
|
||||
* @return true if the given string is a valid edge type
|
||||
*/
|
||||
public boolean containsEdgeType(String edgeType) {
|
||||
return edgeTypes.contains(edgeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||
result = prime * result + ((edgeTypes == null) ? 0 : edgeTypes.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((vertexTypes == null) ? 0 : vertexTypes.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
GraphType other = (GraphType) obj;
|
||||
|
||||
if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
if (!description.equals(other.description)) {
|
||||
return false;
|
||||
}
|
||||
if (!edgeTypes.equals(other.edgeTypes)) {
|
||||
return false;
|
||||
}
|
||||
if (!vertexTypes.equals(other.vertexTypes)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getOptionsName() {
|
||||
return getName() + " Graph Type";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Builder class for building new {@link GraphType}s
|
||||
*/
|
||||
public class GraphTypeBuilder {
|
||||
private List<String> vertexTypes = new ArrayList<>();
|
||||
private List<String> edgeTypes = new ArrayList<>();
|
||||
private final String name;
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Create a new builder
|
||||
* @param name the name of the new {@link GraphType}
|
||||
*/
|
||||
public GraphTypeBuilder(String name) {
|
||||
this.name = name;
|
||||
this.description = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description for the {@link GraphType}
|
||||
* @param text the description
|
||||
* @return this GraphTypeBuilder
|
||||
*/
|
||||
public GraphTypeBuilder description(String text) {
|
||||
this.description = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a new vertex type
|
||||
* @param type a string that names a new vertex type
|
||||
* @return this GraphTypeBuilder
|
||||
*/
|
||||
public GraphTypeBuilder vertexType(String type) {
|
||||
vertexTypes.add(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a new edge type
|
||||
* @param type a string that names a new edge type
|
||||
* @return this GraphTypeBuilder
|
||||
*/
|
||||
public GraphTypeBuilder edgeType(String type) {
|
||||
edgeTypes.add(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new GraphType
|
||||
* @return a new GraphType
|
||||
*/
|
||||
public GraphType build() {
|
||||
return new GraphType(name, description, vertexTypes, edgeTypes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Just a static list of graph layout algorithm names
|
||||
*/
|
||||
public class LayoutAlgorithmNames {
|
||||
//@formatter:off
|
||||
public static final String FORCED_BALANCED = "Force Balanced";
|
||||
public static final String FORCE_DIRECTED = "Force Directed";
|
||||
public static final String CIRCLE = "Circle";
|
||||
public static final String COMPACT_HIERACHICAL = "Compact Hierarchical";
|
||||
public static final String COMPACT_RADIAL = "Compact Radial";
|
||||
public static final String MIN_CROSS_TOP_DOWN = "Hierarchical MinCross Top Down";
|
||||
public static final String MIN_CROSS_LONGEST_PATH = "Hierarchical MinCross Longest Path";
|
||||
public static final String MIN_CROSS_NETWORK_SIMPLEX = "Hierarchical MinCross Network Simplex";
|
||||
public static final String MIN_CROSS_COFFMAN_GRAHAM = "Hierarchical MinCross Coffman Graham";
|
||||
public static final String VERT_MIN_CROSS_TOP_DOWN = "Vertical Hierarchical MinCross Top Down";
|
||||
public static final String VERT_MIN_CROSS_LONGEST_PATH ="Vertical Hierarchical MinCross Longest Path";
|
||||
public static final String VERT_MIN_CROSS_NETWORK_SIMPLEX ="Vertical Hierarchical MinCross Network Simplex";
|
||||
public static final String VERT_MIN_CROSS_COFFMAN_GRAHAM ="Vertical Hierarchical MinCross Coffman Graham";
|
||||
public static final String HIERACHICAL = "Hierarchical";
|
||||
public static final String RADIAL = "Radial";
|
||||
public static final String BALLOON = "Balloon";
|
||||
public static final String GEM = "GEM";
|
||||
|
||||
//@formatter:on
|
||||
|
||||
public static List<String> getLayoutAlgorithmNames() {
|
||||
return Arrays.asList(COMPACT_HIERACHICAL, HIERACHICAL,
|
||||
COMPACT_RADIAL, MIN_CROSS_TOP_DOWN, MIN_CROSS_LONGEST_PATH,
|
||||
MIN_CROSS_NETWORK_SIMPLEX, MIN_CROSS_COFFMAN_GRAHAM, CIRCLE,
|
||||
VERT_MIN_CROSS_TOP_DOWN,
|
||||
VERT_MIN_CROSS_LONGEST_PATH,
|
||||
VERT_MIN_CROSS_NETWORK_SIMPLEX,
|
||||
VERT_MIN_CROSS_COFFMAN_GRAHAM,
|
||||
FORCED_BALANCED, FORCE_DIRECTED, RADIAL, BALLOON, GEM);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,339 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class for defining shapes to use for rendering vertices in a graph
|
||||
*/
|
||||
public abstract class VertexShape {
|
||||
private static Map<String, VertexShape> registeredShapes = new HashMap<>();
|
||||
private static int SIZE = 50;
|
||||
|
||||
public static VertexShape RECTANGLE = new RectangleVertexShape(SIZE);
|
||||
public static VertexShape ELLIPSE = new EllipseVertexShape(SIZE);
|
||||
public static VertexShape TRIANGLE_UP = new TriangleUpVertexShape(SIZE);
|
||||
public static VertexShape TRIANGLE_DOWN = new TriangleDownVertexShape(SIZE);
|
||||
public static VertexShape STAR = new StarVertexShape(SIZE);
|
||||
public static VertexShape DIAMOND = new DiamondVertexShape(SIZE);
|
||||
public static VertexShape PENTAGON = new PentagonVertexShape(SIZE);
|
||||
public static VertexShape HEXAGON = new HexagonVertexShape(SIZE);
|
||||
public static VertexShape OCTAGON = new OctagonVertexShape(SIZE);
|
||||
|
||||
|
||||
private Shape cachedShape;
|
||||
private String name;
|
||||
private int size;
|
||||
|
||||
VertexShape(String name, int size) {
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
registeredShapes.put(name, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the shape
|
||||
* @return the name of the shape
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Shape} for this {@link VertexShape} instance
|
||||
* @return the {@link Shape} for this {@link VertexShape} instance
|
||||
*/
|
||||
public Shape getShape() {
|
||||
if (cachedShape == null) {
|
||||
cachedShape = size(createShape());
|
||||
}
|
||||
return cachedShape;
|
||||
}
|
||||
|
||||
private Shape size(Shape shape) {
|
||||
AffineTransform transform = new AffineTransform();
|
||||
Rectangle bounds = shape.getBounds();
|
||||
double scale = size / bounds.getWidth();
|
||||
transform.scale(scale, scale);
|
||||
return transform.createTransformedShape(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relative amount of margin space to allocate above the label. The default is
|
||||
* 0.5 which will center the label in the associated shape. A value closer to 0 will move
|
||||
* the label closer to the top and a value closer to 1 will move the label closer to the
|
||||
* bottom.
|
||||
* @return the relative amount of margin space to allocate obove the label.s
|
||||
*/
|
||||
public double getLabelPosition() {
|
||||
return .5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size factor for a shape relative to its label. Shapes are sized based on the
|
||||
* label of a vertex so that the label can fit inside the shape (mostly). Some subclasses
|
||||
* will need to override this value to some value > 1 to fit the label in the shape. For
|
||||
* example, a rectangle shape does not need to be extended because text naturally fits. But
|
||||
* for a shape like a triangle, its bounding box needs to be bigger so that text doesn't
|
||||
* "stick out" in the narrow part of the triangle.
|
||||
* @return the size factor for a shape relatvie to its label
|
||||
*/
|
||||
public double getShapeToLabelRatio() {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a factor to keep some shapes from being so distorted by very long labels that they
|
||||
* effectively lose their shape when seen by the user
|
||||
* @return the max width to height ratio
|
||||
*/
|
||||
public int getMaxWidthToHeightRatio() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
protected abstract Shape createShape();
|
||||
|
||||
/**
|
||||
* Returns the {@link VertexShape} for the given shape name
|
||||
* @param shapeName the name of the shape for which to get the {@link VertexShape}
|
||||
* @return the {@link VertexShape} for the given shape name
|
||||
*/
|
||||
public static VertexShape getShape(String shapeName) {
|
||||
return registeredShapes.get(shapeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of names for all the supported {@link VertexShape}s
|
||||
* @return a list of names for all the supported {@link VertexShape}s
|
||||
*/
|
||||
public static List<String> getShapeNames() {
|
||||
ArrayList<String> list = new ArrayList<String>(registeredShapes.keySet());
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
VertexShape other = (VertexShape) obj;
|
||||
return Objects.equals(name, other.name) && size == other.size;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Vertex Shape Classes
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static class RectangleVertexShape extends VertexShape {
|
||||
private RectangleVertexShape(int size) {
|
||||
super("Rectangle", size);
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
return new Rectangle2D.Double(-1.0, -1.0, 2.0, 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
static class EllipseVertexShape extends VertexShape {
|
||||
|
||||
private EllipseVertexShape(int size) {
|
||||
super("Ellipse", size);
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
return new Ellipse2D.Double(-1.0, 1.0, 2.0, 2.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getShapeToLabelRatio() {
|
||||
return 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
static class TriangleUpVertexShape extends VertexShape {
|
||||
|
||||
private TriangleUpVertexShape(int size) {
|
||||
super("Triangle Up", size);
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(-1.0, 1.0);
|
||||
path.lineTo(1.0, 1.0);
|
||||
path.lineTo(0.0, -1.0);
|
||||
path.closePath();
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getShapeToLabelRatio() {
|
||||
return 1.6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLabelPosition() {
|
||||
return 0.90;
|
||||
}
|
||||
}
|
||||
|
||||
static class TriangleDownVertexShape extends VertexShape {
|
||||
private TriangleDownVertexShape(int size) {
|
||||
super("Triangle Down", size);
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(-1.0, -1.0);
|
||||
path.lineTo(1.0, -1.0);
|
||||
path.lineTo(0.0, 1.0);
|
||||
path.closePath();
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getShapeToLabelRatio() {
|
||||
return 1.6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLabelPosition() {
|
||||
return 0.10;
|
||||
}
|
||||
}
|
||||
|
||||
static class StarVertexShape extends VertexShape {
|
||||
|
||||
private StarVertexShape(int size) {
|
||||
super("Star", size);
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
int numPoints = 7;
|
||||
Path2D path = new Path2D.Double();
|
||||
double outerRadius = 2;
|
||||
double innerRadius = 1;
|
||||
double deltaAngle = Math.PI / numPoints;
|
||||
double angle = 3 * Math.PI / 2; // start such that star points up.
|
||||
path.moveTo(outerRadius * Math.cos(angle), outerRadius * Math.sin(angle));
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
angle += deltaAngle;
|
||||
path.lineTo(innerRadius * Math.cos(angle), innerRadius * Math.sin(angle));
|
||||
angle += deltaAngle;
|
||||
path.lineTo(outerRadius * Math.cos(angle), outerRadius * Math.sin(angle));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getShapeToLabelRatio() {
|
||||
return 2.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DiamondVertexShape extends VertexShape {
|
||||
private DiamondVertexShape(int size) {
|
||||
super("Diamond", size);
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(0.0, -1.0);
|
||||
path.lineTo(-1.0, 0.0);
|
||||
path.lineTo(0.0, 1.0);
|
||||
path.lineTo(1.0, 0.0);
|
||||
path.closePath();
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getShapeToLabelRatio() {
|
||||
return 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
static class EquilateralPolygonVertexShape extends VertexShape {
|
||||
private int numSides;
|
||||
private double startAngle;
|
||||
|
||||
protected EquilateralPolygonVertexShape(String name, int numSides, double startAngle,
|
||||
int size) {
|
||||
super(name, size);
|
||||
this.numSides = numSides;
|
||||
this.startAngle = startAngle;
|
||||
}
|
||||
|
||||
protected Shape createShape() {
|
||||
Path2D path = new Path2D.Double();
|
||||
|
||||
double deltaAngle = Math.PI * 2 / numSides;
|
||||
double angle = startAngle;
|
||||
|
||||
path.moveTo(Math.cos(angle), Math.sin(angle));
|
||||
for (int i = 0; i < numSides; i++) {
|
||||
angle += deltaAngle;
|
||||
path.lineTo(Math.cos(angle), Math.sin(angle));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWidthToHeightRatio() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getShapeToLabelRatio() {
|
||||
return 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
static class PentagonVertexShape extends EquilateralPolygonVertexShape {
|
||||
|
||||
private PentagonVertexShape(int size) {
|
||||
super("Pentaon", 5, Math.PI + Math.PI / 10, size);
|
||||
}
|
||||
}
|
||||
|
||||
static class HexagonVertexShape extends EquilateralPolygonVertexShape {
|
||||
|
||||
private HexagonVertexShape(int size) {
|
||||
super("Hexagon", 6, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
static class OctagonVertexShape extends EquilateralPolygonVertexShape {
|
||||
|
||||
private OctagonVertexShape(int size) {
|
||||
super("Octagon", 8, 0, size);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ public class AttributedGraphTest {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
graph = new AttributedGraph();
|
||||
graph = new AttributedGraph("Test", new EmptyGraphType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -192,7 +192,7 @@ public class AttributedGraphTest {
|
|||
|
||||
@Test
|
||||
public void testNonCollapsingEdges() {
|
||||
graph = new AttributedGraph(false);
|
||||
graph = new AttributedGraph("Test", new EmptyGraphType(), "Test", false);
|
||||
|
||||
AttributedVertex v1 = graph.addVertex("A");
|
||||
AttributedVertex v2 = graph.addVertex("B");
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import docking.FakeDockingTool;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.WebColors;
|
||||
|
||||
public class GraphDisplayOptionsTest {
|
||||
|
||||
private GraphType graphType;
|
||||
private GraphDisplayOptions options;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
List<String> vertexTypes = Arrays.asList("V1", "V2", "V3" );
|
||||
List<String> edgeTypes = Arrays.asList("E1", "E2", "E3" );
|
||||
graphType = new GraphType("Test", "Test Description", vertexTypes, edgeTypes);
|
||||
options = new GraphDisplayOptions(graphType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetDefaultVertexShape() {
|
||||
options.setDefaultVertexShape(VertexShape.STAR);
|
||||
assertEquals(VertexShape.STAR, options.getDefaultVertexShape());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetDefaultVertexColor() {
|
||||
options.setDefaultVertexColor(Color.MAGENTA);
|
||||
assertEquals(Color.MAGENTA, options.getDefaultVertexColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetDefaultEdgeColor() {
|
||||
options.setDefaultEdgeColor(Color.MAGENTA);
|
||||
assertEquals(Color.MAGENTA, options.getDefaultEdgeColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetVertexLabelOverride() {
|
||||
assertEquals(null, options.getVertexLabelOverride());
|
||||
options.setVertexLabelOverrideAttributeKey("LABEL");
|
||||
assertEquals("LABEL", options.getVertexLabelOverride());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetVertexColorOverrideAttributeKey() {
|
||||
assertEquals(null, options.getVertexColorOverrideAttributeKey());
|
||||
options.setVertexColorOverrideAttributeKey("COLOR");
|
||||
assertEquals("COLOR", options.getVertexColorOverrideAttributeKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetEdgeColorOverrideAttributeKey() {
|
||||
assertEquals(null, options.getEdgeColorOverrideAttributeKey());
|
||||
options.setEdgeColorOverrideAttributeKey("COLOR");
|
||||
assertEquals("COLOR", options.getEdgeColorOverrideAttributeKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAndGetVertexShapeOverrideAttributeKey() {
|
||||
assertEquals(null, options.getVertexShapeOverrideAttributeKey());
|
||||
options.setVertexColorOverrideAttributeKey("SHAPE");
|
||||
assertEquals("SHAPE", options.getVertexColorOverrideAttributeKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexLabel() {
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
assertEquals("Foo", options.getVertexLabel(vertex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexLabelWithLableOverride() {
|
||||
options.setVertexLabelOverrideAttributeKey("Label");
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
vertex.setAttribute("Label", "Bar");
|
||||
assertEquals("Bar", options.getVertexLabel(vertex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexShape() {
|
||||
options.setVertexShape("V1", VertexShape.DIAMOND);
|
||||
options.setVertexShape("V2", VertexShape.PENTAGON);
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
|
||||
vertex.setVertexType("V1");
|
||||
assertEquals(VertexShape.DIAMOND, options.getVertexShape(vertex));
|
||||
|
||||
vertex.setVertexType("V2");
|
||||
assertEquals(VertexShape.PENTAGON, options.getVertexShape(vertex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexShapeWithOverride() {
|
||||
options.setVertexShape("V1", VertexShape.DIAMOND);
|
||||
options.setVertexShapeOverrideAttributeKey("Shape");
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
|
||||
vertex.setVertexType("V1");
|
||||
assertEquals(VertexShape.DIAMOND, options.getVertexShape(vertex));
|
||||
|
||||
vertex.setAttribute("Shape", VertexShape.ELLIPSE.getName());
|
||||
assertEquals(VertexShape.ELLIPSE, options.getVertexShape(vertex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexColor() {
|
||||
options.setVertexColor("V1", Color.RED);
|
||||
options.setVertexColor("V2", Color.GREEN);
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
|
||||
assertEquals(options.getDefaultVertexColor(), options.getVertexColor(vertex));
|
||||
|
||||
vertex.setVertexType("V1");
|
||||
assertEquals(Color.RED, options.getVertexColor(vertex));
|
||||
|
||||
vertex.setVertexType("V2");
|
||||
assertEquals(Color.GREEN, options.getVertexColor(vertex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexColorWithOverride() {
|
||||
options.setVertexColor("V1", Color.RED);
|
||||
options.setVertexColor("V2", Color.GREEN);
|
||||
options.setVertexColorOverrideAttributeKey("Color");
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
|
||||
vertex.setVertexType("V1");
|
||||
assertEquals(Color.RED, options.getVertexColor(vertex));
|
||||
|
||||
vertex.setAttribute("Color", WebColors.toString(Color.BLUE));
|
||||
|
||||
assertEquals(Color.BLUE, options.getVertexColor(vertex));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEdgeColor() {
|
||||
options.setEdgeColor("E1", Color.RED);
|
||||
options.setEdgeColor("E2", Color.GREEN);
|
||||
AttributedEdge edge = new AttributedEdge("1");
|
||||
assertEquals(options.getDefaultEdgeColor(), options.getEdgeColor(edge));
|
||||
|
||||
edge.setEdgeType("E1");
|
||||
assertEquals(Color.RED, options.getEdgeColor(edge));
|
||||
|
||||
edge.setEdgeType("E2");
|
||||
assertEquals(Color.GREEN, options.getEdgeColor(edge));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEdgeColorWithOverride() {
|
||||
options.setEdgeColor("E1", Color.RED);
|
||||
options.setEdgeColor("E2", Color.GREEN);
|
||||
options.setEdgeColorOverrideAttributeKey("Color");
|
||||
AttributedEdge edge = new AttributedEdge("1");
|
||||
assertEquals(options.getDefaultEdgeColor(), options.getEdgeColor(edge));
|
||||
|
||||
edge.setEdgeType("E1");
|
||||
assertEquals(Color.RED, options.getEdgeColor(edge));
|
||||
|
||||
edge.setAttribute("Color", WebColors.toString(Color.BLUE));
|
||||
|
||||
assertEquals(Color.BLUE, options.getEdgeColor(edge));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEdgePriority() {
|
||||
assertEquals(0, options.getEdgePriority("E1").intValue());
|
||||
assertEquals(1, options.getEdgePriority("E2").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFavoredEdgeType() {
|
||||
// favored edge defaults to first edge defined
|
||||
assertEquals("E1", options.getFavoredEdgeType());
|
||||
options.setFavoredEdgeType("E2");
|
||||
assertEquals("E2", options.getFavoredEdgeType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexColorForType() {
|
||||
assertEquals(options.getDefaultVertexColor(), options.getVertexColor("V1"));
|
||||
options.setVertexColor("V1", Color.RED);
|
||||
assertEquals(Color.RED, options.getVertexColor("V1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexShapeForType() {
|
||||
assertEquals(options.getDefaultVertexShape(), options.getVertexShape("V1"));
|
||||
options.setVertexShape("V1", VertexShape.STAR);
|
||||
assertEquals(VertexShape.STAR, options.getVertexShape("V1"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetEdgeColorForType() {
|
||||
assertEquals(options.getDefaultEdgeColor(), options.getEdgeColor("V1"));
|
||||
options.setEdgeColor("E1", Color.RED);
|
||||
assertEquals(Color.RED, options.getEdgeColor("E1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterOptions() {
|
||||
ToolOptions toolOptions = new ToolOptions("Test");
|
||||
HelpLocation help = new HelpLocation("Topic", "anchor");
|
||||
options.registerOptions(toolOptions, help);
|
||||
|
||||
Options graphDisplayOptions = toolOptions.getOptions(options.getRootOptionsName());
|
||||
assertNotNull(graphDisplayOptions);
|
||||
|
||||
Options vertexColorOptions = graphDisplayOptions.getOptions("Vertex Colors");
|
||||
List<String> leafOptionNames = vertexColorOptions.getLeafOptionNames();
|
||||
assertEquals(Arrays.asList("V1", "V2", "V3"), leafOptionNames);
|
||||
assertEquals(options.getDefaultVertexColor(),
|
||||
vertexColorOptions.getColor("V1", Color.WHITE));
|
||||
|
||||
Options vertexShapeOptions = graphDisplayOptions.getOptions("Vertex Shapes");
|
||||
leafOptionNames = vertexShapeOptions.getLeafOptionNames();
|
||||
assertEquals(Arrays.asList("V1", "V2", "V3"), leafOptionNames);
|
||||
assertEquals(options.getDefaultVertexShape().getName(),
|
||||
vertexShapeOptions.getString("V1", "Bob"));
|
||||
|
||||
Options edgeColorOptions = graphDisplayOptions.getOptions("Edge Colors");
|
||||
leafOptionNames = edgeColorOptions.getLeafOptionNames();
|
||||
assertEquals(Arrays.asList("E1", "E2", "E3"), leafOptionNames);
|
||||
assertEquals(options.getDefaultEdgeColor(),
|
||||
edgeColorOptions.getColor("E1", Color.WHITE));
|
||||
|
||||
Options miscellaniousOptions = graphDisplayOptions.getOptions("Miscellanious");
|
||||
leafOptionNames = miscellaniousOptions.getLeafOptionNames();
|
||||
assertEquals(Arrays.asList("Use Icons", "Selected Vertex Color", "Default Layout Algorithm",
|
||||
"Default Vertex Color", "Default Vertex Shape", "Selected Edge Color", "Label Position",
|
||||
"Default Edge Color", "Font", "Favored Edge Type"), leafOptionNames);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangingToolOptionsAffectsGraph() {
|
||||
FakeDockingTool tool = new FakeDockingTool();
|
||||
ToolOptions toolOptions = tool.getOptions("Graph");
|
||||
options.registerOptions(toolOptions, null);
|
||||
options.initializeFromOptions(tool);
|
||||
|
||||
AttributedVertex vertex = new AttributedVertex("Foo");
|
||||
vertex.setVertexType("V1");
|
||||
assertEquals(Color.BLUE, options.getVertexColor(vertex));
|
||||
|
||||
Options graphDisplayOptions = toolOptions.getOptions(options.getRootOptionsName());
|
||||
Options vertexColorOptions = graphDisplayOptions.getOptions("Vertex Colors");
|
||||
vertexColorOptions.setColor("V1", Color.CYAN);
|
||||
|
||||
assertEquals(Color.CYAN, options.getVertexColor(vertex));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class GraphTypeBuilderTest {
|
||||
|
||||
@Test
|
||||
public void testName() {
|
||||
GraphType graphType = new GraphTypeBuilder("Test").build();
|
||||
assertEquals("Test", graphType.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescription() {
|
||||
GraphType graphType = new GraphTypeBuilder("Test")
|
||||
.description("abc")
|
||||
.build();
|
||||
assertEquals("abc", graphType.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoDescriptionUsesName() {
|
||||
GraphType graphType = new GraphTypeBuilder("Test").build();
|
||||
assertEquals("Test", graphType.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVertexType() {
|
||||
GraphType graphType = new GraphTypeBuilder("Test")
|
||||
.vertexType("V1")
|
||||
.vertexType("V2")
|
||||
.build();
|
||||
|
||||
List<String> vertexTypes = graphType.getVertexTypes();
|
||||
assertEquals(2, vertexTypes.size());
|
||||
assertEquals("V1", vertexTypes.get(0));
|
||||
assertEquals("V2", vertexTypes.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEdgeType() {
|
||||
GraphType graphType = new GraphTypeBuilder("Test")
|
||||
.edgeType("E1")
|
||||
.edgeType("E2")
|
||||
.build();
|
||||
|
||||
List<String> edgeTypes = graphType.getEdgeTypes();
|
||||
assertEquals(2, edgeTypes.size());
|
||||
assertEquals("E1", edgeTypes.get(0));
|
||||
assertEquals("E2", edgeTypes.get(1));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.service.graph;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class GraphTypeTest {
|
||||
private GraphType graphType;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
List<String> vertexTypes = Arrays.asList("V1", "V2", "V3" );
|
||||
List<String> edgeTypes = Arrays.asList("E1", "E2", "E3" );
|
||||
graphType = new GraphType("Test", "Test Description", vertexTypes, edgeTypes);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testName() {
|
||||
assertEquals("Test", graphType.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescription() {
|
||||
assertEquals("Test Description", graphType.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVertexTypes() {
|
||||
List<String> types = graphType.getVertexTypes();
|
||||
assertEquals(3, types.size());
|
||||
assertEquals("V1", types.get(0));
|
||||
assertEquals("V2", types.get(1));
|
||||
assertEquals("V3", types.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEdgeTypes() {
|
||||
List<String> types = graphType.getEdgeTypes();
|
||||
assertEquals(3, types.size());
|
||||
assertEquals("E1", types.get(0));
|
||||
assertEquals("E2", types.get(1));
|
||||
assertEquals("E3", types.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsVertexType() {
|
||||
assertTrue(graphType.containsVertexType("V1"));
|
||||
assertTrue(graphType.containsVertexType("V2"));
|
||||
assertTrue(graphType.containsVertexType("V3"));
|
||||
assertFalse(graphType.containsVertexType("E1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsEdgeType() {
|
||||
assertTrue(graphType.containsEdgeType("E1"));
|
||||
assertTrue(graphType.containsEdgeType("E2"));
|
||||
assertTrue(graphType.containsEdgeType("E3"));
|
||||
assertFalse(graphType.containsEdgeType("V2"));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue