From 2cc6e2633e76a7d1376e20aa7db2ba0262432606 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:41:08 -0500 Subject: [PATCH 1/4] GP-430 - Graph - fixed broken 'drag to select nodes' --- .../mouse/JungPickingGraphMousePlugin.java | 24 +++++++++++-------- .../VisualGraphPickingGraphMousePlugin.java | 3 --- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/JungPickingGraphMousePlugin.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/JungPickingGraphMousePlugin.java index 7b0b165b0c..aa7887d232 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/JungPickingGraphMousePlugin.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/JungPickingGraphMousePlugin.java @@ -257,16 +257,7 @@ public class JungPickingGraphMousePlugin extends AbstractGraphMousePlugin @SuppressWarnings("unchecked") public void mouseReleased(MouseEvent e) { VisualizationViewer vv = (VisualizationViewer) e.getSource(); - if (e.getModifiersEx() == modifiers) { - if (down != null) { - Point2D out = e.getPoint(); - - if (vertex == null && heyThatsTooClose(down, out, 5) == false) { - pickContainedVertices(vv, down, out, true); - } - } - } - else if (e.getModifiersEx() == this.addToSelectionModifiers) { + if (e.getModifiersEx() == this.addToSelectionModifiers) { if (down != null) { Point2D out = e.getPoint(); @@ -275,6 +266,19 @@ public class JungPickingGraphMousePlugin extends AbstractGraphMousePlugin } } } + else { + + // Mouse released without the 'add to selection' modifiers. See if we have been dragging + if (down != null) { + // check to see if we were dragging (no vertex picked and a large enough rectangle) + Point2D out = e.getPoint(); + if (vertex == null && heyThatsTooClose(down, out, 5) == false) { + pickContainedVertices(vv, down, out, true); + } + } + + } + down = null; vertex = null; edge = null; diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/VisualGraphPickingGraphMousePlugin.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/VisualGraphPickingGraphMousePlugin.java index d1a71e2348..d05fcb040b 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/VisualGraphPickingGraphMousePlugin.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/event/mouse/VisualGraphPickingGraphMousePlugin.java @@ -151,9 +151,6 @@ public class VisualGraphPickingGraphMousePlugin Date: Tue, 24 Nov 2020 14:18:24 -0500 Subject: [PATCH 2/4] Fixed slightly broken animation option referenced in #2519 --- .../src/main/java/docking/DockableHeader.java | 4 ++++ .../src/main/java/docking/GenericHeader.java | 14 ++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java index 335d7abb5f..0ede2ee5ca 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java @@ -167,6 +167,10 @@ public class DockableHeader extends GenericHeader private Animator emphasizeDockableComponent() { + if (!AnimationUtils.isAnimationEnabled()) { + return null; + } + ComponentPlaceholder placeholder = dockComp.getComponentWindowingPlaceholder(); ComponentNode node = placeholder.getNode(); WindowNode windowNode = node.getTopLevelNode(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java b/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java index 7ec1df35b6..ab224f95fb 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java @@ -26,6 +26,7 @@ import org.jdesktop.animation.timing.TimingTargetAdapter; import org.jdesktop.animation.timing.interpolation.PropertySetter; import docking.action.DockingActionIf; +import docking.util.AnimationUtils; import docking.widgets.VariableHeightPanel; import docking.widgets.label.GDLabel; @@ -100,6 +101,7 @@ public class GenericHeader extends JPanel { /** * Signals whether or not to break the toolbar actions into multiple rows. The default is * to wrap as necessary. + * @param noWrap true signals not to break the actions into multiple rows */ public void setNoWrapToolbar(boolean noWrap) { useSingleLineLayoutOverride = noWrap; @@ -254,6 +256,10 @@ public class GenericHeader extends JPanel { } protected Animator createEmphasizingAnimator() { + if (!AnimationUtils.isAnimationEnabled()) { + return null; + } + TitleFlasher titleFlasher = new TitleFlasher(); return titleFlasher.animator; } @@ -262,10 +268,6 @@ public class GenericHeader extends JPanel { return titlePanel.isSelected(); } - /** - * Sets the title displayed within the header - * @param title - */ public void setTitle(String title) { titlePanel.setTitle(title); } @@ -389,10 +391,6 @@ public class GenericHeader extends JPanel { titleLabel.setToolTipText(s); } - /** - * Sets the Icon for this header - * @param icon - */ void setIcon(Icon icon) { icon = DockingUtils.scaleIconAsNeeded(icon); From 1259632113cd042d228ea58ac5bef3f326f60894 Mon Sep 17 00:00:00 2001 From: ghidravore Date: Wed, 25 Nov 2020 13:11:16 -0500 Subject: [PATCH 3/4] fixed stack trace when exporting --- .../core/graph/AddressBasedGraphDisplayListener.java | 3 ++- .../graph/export/ExportAttributedGraphDisplay.java | 11 +++++++---- .../service/graph/DummyGraphDisplayListener.java | 5 +++++ .../ghidra/service/graph/GraphDisplayListener.java | 5 +++++ .../src/test/java/ghidra/graph/GraphActionTest.java | 5 +++++ 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java index 0e6b40ca8b..71447e37b4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java @@ -222,7 +222,8 @@ public abstract class AddressBasedGraphDisplayListener graphDisplay.updateVertexName(vertex, displayName); } - private void dispose() { + @Override + public void dispose() { Swing.runLater(() -> tool.removeListenerForAllPluginEvents(this)); program.removeListener(this); } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java index 51cbca873b..c75c8caa67 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/ExportAttributedGraphDisplay.java @@ -39,6 +39,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay { private final PluginTool pluginTool; private String title; + private AttributedGraph graph; /** * Create the initial display, the graph-less visualization viewer, and its controls @@ -55,7 +56,8 @@ class ExportAttributedGraphDisplay implements GraphDisplay { @Override public void setGraphDisplayListener(GraphDisplayListener listener) { - // This display is not interactive, so N/A + // This display is not interactive, so just dispose the listener + listener.dispose(); } @@ -86,10 +88,11 @@ class ExportAttributedGraphDisplay implements GraphDisplay { } @Override - public void setGraph(AttributedGraph graphData, String title, boolean append, + public void setGraph(AttributedGraph graph, String title, boolean append, TaskMonitor monitor) { this.title = title; - doSetGraphData(graphData); + this.graph = graph; + doSetGraphData(graph); } /** @@ -132,7 +135,7 @@ class ExportAttributedGraphDisplay implements GraphDisplay { @Override public AttributedGraph getGraph() { - return null; + return graph; } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java index 11b056fcbb..22ad336d75 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/DummyGraphDisplayListener.java @@ -39,4 +39,9 @@ public class DummyGraphDisplayListener implements GraphDisplayListener { // I'm a dummy } + @Override + public void dispose() { + // I'm a dummy + } + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java index c763ea3977..0902fe8ca0 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/service/graph/GraphDisplayListener.java @@ -49,4 +49,9 @@ public interface GraphDisplayListener { */ public GraphDisplayListener cloneWith(GraphDisplay graphDisplay); + /** + * Tells the listener that it is no longer needed and it can release any listeners/resources + */ + public void dispose(); + } 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 39584dd51d..1bdfe9d870 100644 --- a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java +++ b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/graph/GraphActionTest.java @@ -303,6 +303,11 @@ public class GraphActionTest extends AbstractGhidraHeadedIntegrationTest { return new TestGraphDisplayListener("clone"); } + @Override + public void dispose() { + // do nothing + } + } private AttributedGraph createGraph() { From 7758c069b7c44e38909d455cf9ff848ec001c9b6 Mon Sep 17 00:00:00 2001 From: ghidravore Date: Mon, 30 Nov 2020 16:30:53 -0500 Subject: [PATCH 4/4] GP-280 fixed issue preventing exporting a graph to DOT format. --- .../graph/export/AbstractGraphExporterFactory.java | 9 ++++++++- .../java/ghidra/graph/export/GraphExporterDialog.java | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/AbstractGraphExporterFactory.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/AbstractGraphExporterFactory.java index c6608ec4e2..bd65e9db6c 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/AbstractGraphExporterFactory.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/AbstractGraphExporterFactory.java @@ -125,8 +125,15 @@ public abstract class AbstractGraphExporterFactory { return exporter; } + String getQuotedId(V vertex) { + String id = vertexIdProvider.apply(vertex); + return "\"" + id + "\""; + } + private GraphExporter createDotExporter() { - DOTExporter exporter = new DOTExporter<>(vertexIdProvider); + // DOT format is picky about its identifiers, so pass in a vertex id supplier + // that wraps the vertex ids in quotes + DOTExporter exporter = new DOTExporter<>(this::getQuotedId); setupExporter(exporter); return exporter; } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/GraphExporterDialog.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/GraphExporterDialog.java index 15c282c8a9..6bc87c1035 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/GraphExporterDialog.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/export/GraphExporterDialog.java @@ -276,14 +276,14 @@ public class GraphExporterDialog extends DialogComponentProvider { GraphExportFormat exporterFormat = getSelectedExporter(); File outputFile = getSelectedOutputFile(); - try { - if (outputFile.exists() && + if (outputFile.exists() && OptionDialog.showOptionDialog(getComponent(), "Overwrite Existing File?", "The file " + outputFile + " already exists.\nDo you want to overwrite it?", "Overwrite", OptionDialog.QUESTION_MESSAGE) != OptionDialog.OPTION_ONE) { return false; - } - Writer writer = new FileWriter(outputFile); + } + + try (Writer writer = new FileWriter(outputFile)) { GraphExporter exporter = AttributedGraphExporterFactory.getExporter(exporterFormat);