added dialog for user to change name of group vertices as they are created

This commit is contained in:
ghidravore
2020-11-24 10:40:28 -05:00
parent 14d4c87ef4
commit bc6613141d
7 changed files with 60 additions and 146 deletions

View File

@@ -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<AttributedVertex> {
private class AttributedToolTipInfo extends ToolTipInfo<Attributed> {
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<AttributedEdge> {
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
}
}
}

View File

@@ -74,15 +74,14 @@ public class GroupVertex extends AttributedVertex {
private static String getUniqueId(List<AttributedVertex> 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<AttributedVertex> vertices) {
return vertices.stream().map(AttributedVertex::getName).collect(Collectors.joining(","));
return vertices.stream().map(AttributedVertex::getName).collect(Collectors.joining("\n"));
}
/**

View File

@@ -129,15 +129,10 @@ abstract class ProgramGraphFunctions {
*/
public static String getLabel(Attributed attributed) {
Map<String, String> map = attributed.getAttributeMap();
String name = StringEscapeUtils.escapeHtml4(map.get("Name"));
if (map.containsKey("Code")) {
String code = StringEscapeUtils.escapeHtml4(map.get("Code"));
return "<html>" + String.join("<p>", 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 "<html>" + String.join("<p>",
Splitter.on(',').split(name));
}
return map.get("Name");
return "<html>" + String.join("<p>", Splitter.on('\n').split(name));
}
}

View File

@@ -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<Entry<String, String>> entries = entrySet();
if (entries.isEmpty()) {
return ""; // empty so tooltip clients can handle empty data
}
StringBuilder buf = new StringBuilder("<html>");
for (Map.Entry<String, String> entry : entries) {
buf.append(entry.getKey());
buf.append(":");
buf.append(StringEscapeUtils.escapeHtml4(entry.getValue()));
buf.append("<br>");
}
htmlString = buf.toString();
return htmlString;
}
}

View File

@@ -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<Entry<String, String>> entries = entrySet();
if (entries.isEmpty()) {
return ""; // empty so tooltip clients can handle empty data
}
StringBuilder buf = new StringBuilder("<html>");
for (Map.Entry<String, String> entry : entries) {
buf.append(entry.getKey());
buf.append(":");
buf.append(StringEscapeUtils.escapeHtml4(entry.getValue()));
buf.append("<br>");
}
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;
}
}

View File

@@ -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<Entry<String, String>> entries = entrySet();
if (entries.isEmpty()) {
return ""; // empty so tooltip clients can handle empty data
}
StringBuilder buf = new StringBuilder("<html>");
for (Map.Entry<String, String> entry : entries) {
buf.append(entry.getKey());
buf.append(":");
buf.append(StringEscapeUtils.escapeHtml4(entry.getValue()));
buf.append("<br>");
}
htmlString = buf.toString();
return htmlString;
}
@Override
public int hashCode() {
return id.hashCode();

View File

@@ -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() {