mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
added dialog for user to change name of group vertices as they are created
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user