From bc6613141dc8363b9cff5dad00869b2adb8ab552 Mon Sep 17 00:00:00 2001 From: ghidravore Date: Tue, 24 Nov 2020 10:40:28 -0500 Subject: [PATCH] added dialog for user to change name of group vertices as they are created --- .../visualization/DefaultGraphDisplay.java | 57 ++++++------------- .../graph/visualization/GroupVertex.java | 7 +-- .../visualization/ProgramGraphFunctions.java | 11 +--- .../java/ghidra/service/graph/Attributed.java | 34 +++++++++++ .../ghidra/service/graph/AttributedEdge.java | 46 --------------- .../service/graph/AttributedVertex.java | 46 --------------- .../java/ghidra/graph/GraphActionTest.java | 5 +- 7 files changed, 60 insertions(+), 146 deletions(-) diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 24fae771ba..5669b9503b 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -58,6 +58,7 @@ import docking.action.ToggleDockingAction; import docking.action.builder.*; import docking.menu.ActionState; import docking.widgets.EventTrigger; +import docking.widgets.OptionDialog; import generic.util.WindowUtilities; import ghidra.framework.plugintool.PluginTool; import ghidra.graph.AttributeFilters; @@ -471,11 +472,20 @@ public class DefaultGraphDisplay implements GraphDisplay { private void groupSelectedVertices() { AttributedVertex vertex = graphCollapser.groupSelectedVertices(); if (vertex != null) { + askToNameGroupVertex(vertex); focusedVertex = vertex; scrollToSelected(vertex); } } + private void askToNameGroupVertex(AttributedVertex vertex) { + String name = vertex.getName(); + String userName = OptionDialog.showInputMultilineDialog(null, "Enter Group Vertex Text", + "Text", name); + + updateVertexName(vertex, userName != null ? userName : name); + } + /** * Ungroup the selected vertices. If the focusedVertex is no longer * in the graph, null it. This will happen if the focusedVertex was @@ -488,7 +498,6 @@ public class DefaultGraphDisplay implements GraphDisplay { } } - private void clearSelection() { viewer.getSelectedVertexState().clear(); viewer.getSelectedEdgeState().clear(); @@ -1316,17 +1325,17 @@ public class DefaultGraphDisplay implements GraphDisplay { // center point of a vertex AttributedVertex vertex = getVertex(event); if (vertex != null) { - return new VertexToolTipInfo(vertex, event); + return new AttributedToolTipInfo(vertex, event); } AttributedEdge edge = getEdge(event); if (edge != null) { - return new EdgeToolTipInfo(edge, event); + return new AttributedToolTipInfo(edge, event); } // no vertex or edge hit; just create a basic info that is essentially a null-object // placeholder to prevent NPEs - return new VertexToolTipInfo(vertex, event); + return new AttributedToolTipInfo(vertex, event); } @Override @@ -1365,10 +1374,10 @@ public class DefaultGraphDisplay implements GraphDisplay { } } - private class VertexToolTipInfo extends ToolTipInfo { + private class AttributedToolTipInfo extends ToolTipInfo { - VertexToolTipInfo(AttributedVertex vertex, MouseEvent event) { - super(event, vertex); + AttributedToolTipInfo(Attributed graphObject, MouseEvent event) { + super(event, graphObject); } @Override @@ -1397,38 +1406,4 @@ public class DefaultGraphDisplay implements GraphDisplay { // this graph display does not have a notion of emphasizing } } - - private class EdgeToolTipInfo extends ToolTipInfo { - - EdgeToolTipInfo(AttributedEdge edge, MouseEvent event) { - super(event, edge); - } - - @Override - protected JComponent createToolTipComponent() { - if (graphObject == null) { - return null; - } - - String toolTip = graphObject.getHtmlString(); - if (StringUtils.isBlank(toolTip)) { - return null; - } - - JToolTip jToolTip = new JToolTip(); - jToolTip.setTipText(toolTip); - return jToolTip; - } - - @Override - protected void emphasize() { - // this graph display does not have a notion of emphasizing - } - - @Override - protected void deEmphasize() { - // this graph display does not have a notion of emphasizing - } - } - } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/GroupVertex.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/GroupVertex.java index 012b482c17..ffb8f027f9 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/GroupVertex.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/GroupVertex.java @@ -74,15 +74,14 @@ public class GroupVertex extends AttributedVertex { private static String getUniqueId(List vertexList) { if (vertexList.size() > MAX_IDS_TO_COMBINE) { int idsNotShownCount = vertexList.size() - MAX_IDS_TO_COMBINE; - return combineIds(vertexList.subList(0, MAX_IDS_TO_COMBINE)) + ",..., + " + - idsNotShownCount + - " Others"; + return combineIds(vertexList.subList(0, MAX_IDS_TO_COMBINE)) + "\n...\n + " + + idsNotShownCount + " Others"; } return combineIds(vertexList); } private static String combineIds(Collection vertices) { - return vertices.stream().map(AttributedVertex::getName).collect(Collectors.joining(",")); + return vertices.stream().map(AttributedVertex::getName).collect(Collectors.joining("\n")); } /** diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/ProgramGraphFunctions.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/ProgramGraphFunctions.java index f82e685117..650780d2d7 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/ProgramGraphFunctions.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/ProgramGraphFunctions.java @@ -129,15 +129,10 @@ abstract class ProgramGraphFunctions { */ public static String getLabel(Attributed attributed) { Map map = attributed.getAttributeMap(); + String name = StringEscapeUtils.escapeHtml4(map.get("Name")); if (map.containsKey("Code")) { - String code = StringEscapeUtils.escapeHtml4(map.get("Code")); - return "" + String.join("

", Splitter.on('\n').split(code)); + name = StringEscapeUtils.escapeHtml4(map.get("Code")); } - if ("Collapsed".equals(map.get("VertexType"))) { - String name = StringEscapeUtils.escapeHtml4(map.get("Name")); - return "" + String.join("

", - Splitter.on(',').split(name)); - } - return map.get("Name"); + return "" + String.join("

", Splitter.on('\n').split(name)); } } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java index 9b408496d2..af8962e0a1 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/Attributed.java @@ -16,8 +16,15 @@ package ghidra.service.graph; import java.util.*; +import java.util.Map.Entry; + +import org.apache.commons.text.StringEscapeUtils; public class Attributed { + /** + * cache of the html rendering of the vertex attributes + */ + private String htmlString; /** * the {@link HashMap} to contain attribute mappings @@ -41,6 +48,7 @@ public class Attributed { * @return the previous value of the attribute */ public String setAttribute(String key, String value) { + htmlString = null; return attributes.put(key, value); } @@ -135,4 +143,30 @@ public class Attributed { return attributes.entrySet(); } + /** + * parse (one time) then cache the attributes to html + * @return the html string + */ + public String getHtmlString() { + + if (htmlString != null) { + return htmlString; + } + + Set> entries = entrySet(); + if (entries.isEmpty()) { + return ""; // empty so tooltip clients can handle empty data + } + + StringBuilder buf = new StringBuilder(""); + for (Map.Entry entry : entries) { + buf.append(entry.getKey()); + buf.append(":"); + buf.append(StringEscapeUtils.escapeHtml4(entry.getValue())); + buf.append("
"); + } + htmlString = buf.toString(); + return htmlString; + } + } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedEdge.java b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedEdge.java index bdb0671aec..3b5a92482c 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedEdge.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedEdge.java @@ -15,23 +15,12 @@ */ package ghidra.service.graph; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.apache.commons.text.StringEscapeUtils; - /** * Generic directed graph edge implementation */ public class AttributedEdge extends Attributed { private final String id; - /** - * Cache of the edge label parsed as html - */ - private String htmlString; - /** * Constructs a new GhidraEdge * @param id the unique id for the edge @@ -45,31 +34,6 @@ public class AttributedEdge extends Attributed { return id; } - /** - * The html representation of the key/values for this edge - * @return html formatted label for the edge - */ - public String getHtmlString() { - if (htmlString != null) { - return htmlString; - } - - Set> entries = entrySet(); - if (entries.isEmpty()) { - return ""; // empty so tooltip clients can handle empty data - } - - StringBuilder buf = new StringBuilder(""); - for (Map.Entry entry : entries) { - buf.append(entry.getKey()); - buf.append(":"); - buf.append(StringEscapeUtils.escapeHtml4(entry.getValue())); - buf.append("
"); - } - htmlString = buf.toString(); - return htmlString; - } - /** * Returns the id for this edge * @return the id for this edge @@ -78,12 +42,6 @@ public class AttributedEdge extends Attributed { return id; } - @Override - public String setAttribute(String key, String value) { - clearCache(); - return super.setAttribute(key, value); - } - @Override public int hashCode() { return id.hashCode(); @@ -104,8 +62,4 @@ public class AttributedEdge extends Attributed { return id.equals(other.id); } - private void clearCache() { - this.htmlString = null; - } - } diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedVertex.java b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedVertex.java index dded3d3fa0..529be98249 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedVertex.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/AttributedVertex.java @@ -15,22 +15,12 @@ */ package ghidra.service.graph; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.apache.commons.text.StringEscapeUtils; - /** * Graph vertex with attributes */ public class AttributedVertex extends Attributed { private final String id; - /** - * cache of the html rendering of the vertex attributes - */ - private String htmlString; /** * Constructs a new GhidraVertex with the given id and name @@ -56,12 +46,6 @@ public class AttributedVertex extends Attributed { setAttribute("Name", name); } - @Override - public String setAttribute(String key, String value) { - clearCache(); - return super.setAttribute(key, value); - } - /** * Returns the id for this vertex * @return the id for this vertex @@ -84,36 +68,6 @@ public class AttributedVertex extends Attributed { return getName() + " (" + id + ")"; } - private void clearCache() { - this.htmlString = null; - } - - /** - * parse (one time) then cache the attributes to html - * @return the html string - */ - public String getHtmlString() { - - if (htmlString != null) { - return htmlString; - } - - Set> entries = entrySet(); - if (entries.isEmpty()) { - return ""; // empty so tooltip clients can handle empty data - } - - StringBuilder buf = new StringBuilder(""); - for (Map.Entry entry : entries) { - buf.append(entry.getKey()); - buf.append(":"); - buf.append(StringEscapeUtils.escapeHtml4(entry.getValue())); - buf.append("
"); - } - htmlString = buf.toString(); - return htmlString; - } - @Override public int hashCode() { return id.hashCode(); diff --git a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java index ff22139d45..20953d54d2 100644 --- a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java +++ b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java @@ -24,6 +24,7 @@ import org.junit.*; import docking.ComponentProvider; import docking.action.DockingActionIf; import docking.widgets.EventTrigger; +import docking.widgets.dialogs.MultiLineInputDialog; import ghidra.app.plugin.core.graph.GraphDisplayBrokerPlugin; import ghidra.app.services.GraphDisplayBroker; import ghidra.framework.plugintool.PluginTool; @@ -415,7 +416,9 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { DockingActionIf action = getAction(tool, "Collapse Selected"); GraphActionContext context = new GraphActionContext(graphComponentProvider, graph, null, null); - performAction(action, context, true); + performAction(action, context, false); + MultiLineInputDialog dialog = waitForDialogComponent(MultiLineInputDialog.class); + pressButtonByText(dialog, "OK", true); } private void expand() {