mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 05:32:14 +00:00
GP-310 - Graphing - Updated mouse handling to be consistent with other graph widgets.
This commit is contained in:
parent
956e8ef342
commit
d9a1c8906f
@ -443,6 +443,8 @@ src/main/help/help/topics/GhidraServer/GhidraServer.htm||GHIDRA||||END|
|
||||
src/main/help/help/topics/Glossary/glossary.htm||GHIDRA||||END|
|
||||
src/main/help/help/topics/Glossary/images/BigEndian.png||GHIDRA||reviewed||END|
|
||||
src/main/help/help/topics/Glossary/images/LittleEndian.png||GHIDRA||reviewed||END|
|
||||
src/main/help/help/topics/Graph/GraphIntro.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/Graph/GraphServicesIntro.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/HeadlessAnalyzer/HeadlessAnalyzer.htm||GHIDRA||||END|
|
||||
src/main/help/help/topics/ImporterPlugin/images/About_pdb.png||GHIDRA||reviewed||END|
|
||||
src/main/help/help/topics/ImporterPlugin/images/BatchImportDialog.png||GHIDRA||||END|
|
||||
|
@ -150,7 +150,9 @@
|
||||
|
||||
<tocdef id="FileSystem Browser" text="FileSystem Browser" target="help/topics/FileSystemBrowserPlugin/FileSystemBrowserPlugin.html" />
|
||||
|
||||
<tocdef id="Graphing" text="Graphing" />
|
||||
<tocdef id="Graphing" text="Graphing" target="help/topics/Graph/GraphIntro.html">
|
||||
<tocdef id="Graph Services" text="Graph Services" target="help/topics/Graph/GraphServicesIntro.html"/>
|
||||
</tocdef>
|
||||
|
||||
<tocdef id="Program Tree" text="Program Tree" target="help/topics/ProgramTreePlugin/program_tree.htm" >
|
||||
<tocdef id="Folders and Fragments" sortgroup="a" text="Folders and Fragments" target="help/topics/ProgramTreePlugin/program_tree.htm#FoldersAndFragments" />
|
||||
|
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE doctype PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Graphing</TITLE>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY lang="EN-US">
|
||||
|
||||
|
||||
<H1>Graphing</H1>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
This section contains all help related to the creation and display of Graphs. Content will
|
||||
appear inside of this section as plugins are added. To see the available graph features,
|
||||
see the <B>Graph</b> menu on the toolbar.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE doctype PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Graph Services</TITLE>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY lang="EN-US">
|
||||
|
||||
|
||||
<H1>Graph Services</H1>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
This section contains all help related to the graph services that provide capabilities for
|
||||
generated graphs, such as displaying and exporting. Content will appear inside of this '
|
||||
section as plugins are added. To see the available graph features,
|
||||
see the <B>Graph</b> menu on the toolbar.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
@ -50,11 +50,9 @@
|
||||
|
||||
<tocroot>
|
||||
|
||||
<tocref id="Graphing">
|
||||
<tocdef id="Graph Services" text="Graph Services">
|
||||
<tocdef id="Default Graph Display" text="Default Graph Display" target="help/topics/GraphServices/GraphDisplay.htm" />
|
||||
<tocdef id="Exporting a Graph" text="Exporting a Graph" target="help/topics/GraphServices/GraphExport.htm" />
|
||||
</tocdef>
|
||||
<tocref id="Graph Services">
|
||||
<tocdef id="Default Graph Display" text="Default Graph Display" target="help/topics/GraphServices/GraphDisplay.htm" />
|
||||
<tocdef id="Exporting a Graph" text="Exporting a Graph" target="help/topics/GraphServices/GraphExport.htm" />
|
||||
</tocref>
|
||||
|
||||
</tocroot>
|
||||
|
@ -5,103 +5,245 @@
|
||||
<META name="generator" content=
|
||||
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
|
||||
|
||||
<TITLE>Graphing</TITLE>
|
||||
<TITLE>Graph Display</TITLE>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY lang="EN-US">
|
||||
<A name="Default_Graph_Display"/>
|
||||
<A name="Default_Graph_Display">
|
||||
|
||||
|
||||
<H1>Default Graph Display</H1>
|
||||
<H2>Visualization of a Graph</H2>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>The visualization display will show the graph in a new window or in a new tab of a previously created graph window.</P>
|
||||
<BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<P align="left"><IMG src="images/DefaultGraphDisplay.png" border="1"></P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
<H2>Manipulating the Graph:</H2>
|
||||
<ul>
|
||||
<li>MouseButton1+drag will translate the display in the x and y axis</li>
|
||||
<li>Mouse Wheel will zoom in and out</li>
|
||||
<li>CTRL+Mouse Wheel will zoom in and out in the X-Axis only</li>
|
||||
<li>ALT+Mouse Wheel will zoom in and out in the Y-Axis only</li>
|
||||
<li>Ctrl+MouseButton1 will select a vertex or edge</li>
|
||||
<ul>
|
||||
<li>Shift+Ctrl+MouseButton1 over an unselected vertex will add that vertex to the selection</li>
|
||||
<li>Shift+Ctrl+MouseButton1 over a previously selected vertex will remove that vertex from the selection</li>
|
||||
</ul>
|
||||
<li>Ctrl+MouseButton1+drag on an empty area will create a rectangular area and select enclosed vertices</li>
|
||||
<li>Ctrl+MouseButton1+drag over a vertex will reposition all selected vertices</li>
|
||||
</ul>
|
||||
<H2>Toolbar Buttons</H2>
|
||||
<P><A name="Scroll_To_Selection"/> The <IMG src="images/locationIn.gif"> toggle button, when 'set' will cause a focused vertex (red arrow) to be scrolled to the center of the view</P>
|
||||
<P><A name="Free_Form_Selection"/>The <IMG src="images/Lasso.png" width="16" height="16"> toggle button, when 'set' will allow the user to draw a free-form shape that encloses the vertices they wish to select.</P>
|
||||
<P><A name="SatelliteView"/>The <IMG src="images/sat2.png" width="16" height="16"> toggle button, when 'set' will open a satellite mini view of the graph in the lower right corner. The mini-view can be manipulated with the mouse to affect the main view</P>
|
||||
<P><A name="Reset_View"/>The <IMG src="images/reload3.png"> button will reset any visual transformations on the graph and center it at a best-effort size</P>
|
||||
<P><A name="View_Magnifier"/>The <IMG src="images/magnifier.png"> toggle button, when 'set' will open a rectangular magnification lens in the graph view</P>
|
||||
<BLOCKQUOTE><BLOCKQUOTE>
|
||||
<ul>
|
||||
<li>MouseButton1 click-drag on the lens center circle to move the magnifier lens</li>
|
||||
<li>MouseButton1 click-draw on a lens edge diamond to resize the magnifier lens </li>
|
||||
<li>MouseButton1 click on the upper-right circle-cross to dispose of the magnifier lens</li>
|
||||
<li>MouseWheel will change the magnification of the lens</li>
|
||||
</ul>
|
||||
</BLOCKQUOTE></BLOCKQUOTE>
|
||||
|
||||
<P><A name="Show_Filters"/>The <IMG src="images/filter_on.png"> button will open a Filter dialog. Select buttons in the dialog to hide specific vertices or edges in the display.
|
||||
The Filter dialog buttons are created by examining the graph vertex/edge properties to discover candidates for filtering.</P></BLOCKQUOTE></BLOCKQUOTE>
|
||||
|
||||
<P><A name="Arrangement"/>The <IMG src="images/katomic.png" width="16" height="16"> Arrangement menu is used to select one of several graph layout algorithms.</P>
|
||||
<BLOCKQUOTE><BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<P>The visualization display will show the graph in a new window or in a new tab of a
|
||||
previously created graph window.</P>
|
||||
|
||||
<ul>
|
||||
<li><A name="Compact_Hierarchical"/><B>Compact Hierarchical</B> is the <b>TidierTree Layout Algorithm</b>. It builds a tree structure and attempts to reduce horizontal space.</li>
|
||||
<li><A name="Hierarchical"/><B>Hierarchical</B> is a basic Tree algorithm. It prioritizes 'important' edges while constructing the tree.</li>
|
||||
<li><A name="Compact Radial"/><B>Compact Radial</B> is the <b>TidierTree Layout Algorithm</b> with the root(s) at the center and child vertices radiating outwards.</li>
|
||||
<li><B>Hierarchical MinCross</B> is the <b>Sugiyama Layout Algorithm</b>. It attempts to route edges around vertices in order to reduce crossing.There are four layering algorithms:</li>
|
||||
<ul>
|
||||
<li><A name="Hierarchical_MinCross_Top_Down"/><B>Top Down</B> - biases the vertices to the top</li>
|
||||
<li><A name="Hierarchical_MinCross_Longest_Path"/><B>Longest Path</B> - biases the vertices to the bottom</li>
|
||||
<li><A name="Hierarchical_MinCross_Network_Simplex"/><B>Network Simplex</B> - layers after finding an 'optimal tree'</li>
|
||||
<li><A name="Hierarchical_MinCross_Coffman_Graham"/><B>Coffman Graham</B> - biases the vertices using a scheduling algorithm to minimize length</li>
|
||||
</ul>
|
||||
|
||||
<li><A name="Circle"/><B>Circle</B> will arrange vertices in a Circle. If there are not too many edges (less than specified in the jungrapht.circle.reduceEdgeCrossingMaxEdges property with a default of 200), it will attempt to reduce edge crossing by rearranging the vertices.</li>
|
||||
<li><A name="Force_Balanced"/><B>Force Balanced</B> is a <b>Force Directed Layout Algorithm</b> using the the <b>Kamada Kawai</b> approach. It attempts to balance the graph by considering vertices and edge connections.</li>
|
||||
<li><A name="Force_Directed"/><B>Force Directed</B> is a <b>Force Directed Layout Algorithm</b> using the <b>Fructermann Reingold</b> approach. It pushes unconnected vertices apart and draws connected vertices together.</li>
|
||||
<li><A name="Radial"/><B>Radial</B> is a Tree structure with the root(s) at the center and child vertices radiating outwards.</li>
|
||||
<li><A name="Balloon"/><B>Balloon</B> is a Tree structure with the root(s) at the centers of circles in a radial pattern</li>
|
||||
<li><A name="Gem__Graph_Embedder_"/><B>GEM</B> is a Force Directed layout with locally separated components </li>
|
||||
</ul>
|
||||
</BLOCKQUOTE></BLOCKQUOTE>
|
||||
<H2>Popup Actions</H2>
|
||||
<BLOCKQUOTE>
|
||||
<H3> Standard Popup Actions</H3>
|
||||
<ul>
|
||||
<li><A name="Hide Selected"/><B>Hide Selected</B> - Causes the display to not show selected vertices. </li>
|
||||
<li><A name="Hide Unselected"/><B>Hide Unselected</B> - Causes the display to not show unselected vertices.</li>
|
||||
<li><A name="Invert Selection"/><B>Invert Selection</B> - Unselects all selected nodes and selects all unselected nodes.</li>
|
||||
<li><A name="Grow Selection From Sources"/><B>Grow Selection From Sources</B> - Adds to the selection all vertices that have outgoing edges to the current selection.</li>
|
||||
<li><A name="Grow Selection To Targets"/><B>Grow Selection To Targets</B> - Adds to the selection all vertices that have incoming edges from the current selection.</li>
|
||||
<li><A name="Create Subgraph"/><B>Display Selected As New Graph</B> - Creates a new graph and display from the currently selected vertices.</li>
|
||||
</ul>
|
||||
<H3> Vertex Popup Actions</H3>
|
||||
<ul>
|
||||
<li><A name="Select Vertex"/><B>Select Vertex</B> - Selects the vertex that this action was invoked on.</li>
|
||||
<li><A name="Deselect Vertex"/><B>Deselect Vertex</B> - Deselects the vertex that this action was invoked on.</li>
|
||||
</ul>
|
||||
|
||||
<H3> Edge Popup Actions</H3>
|
||||
<ul>
|
||||
<li><A name="Edge Source"/><B>Go To Edge Source</B> - Makes this edge's source vertex be the focused vertex.</li>
|
||||
<li><A name="Edge Target"/><B>Go To Edge Target</B> - Makes this edge's destination vertex be the focused vertex.</li>
|
||||
<li><A name="Select Edge"/><B>Select Edge</B> - Add this edge and its associated vertices to the selection</li>
|
||||
<li><A name="Deselect Edge"/><B>Deselect Edge</B> - Removes this edge and its associated vertices from the selection </li>
|
||||
</ul>
|
||||
<CENTER>
|
||||
<TABLE border="0" width="100%">
|
||||
<TR>
|
||||
<TD width="100%" align="center"><IMG alt="" border="1" src=
|
||||
"images/DefaultGraphDisplay.png"></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Manipulating the Graph</H2>
|
||||
|
||||
<UL>
|
||||
<LI>Dragging in the graph or on any unselected vertices will pan the graph (translate the
|
||||
display in the x and y axis)</LI>
|
||||
|
||||
<LI>Dragging a selected vertex will reposition all selected vertices</LI>
|
||||
|
||||
<LI>Using the <CODE>Mouse Wheel</CODE> will zoom the graph in and out</LI>
|
||||
|
||||
<LI><CODE>Control+Mouse Wheel</CODE> will zoom the graph in and out on the X-Axis only</LI>
|
||||
|
||||
<LI><CODE>ALT+Mouse Wheel</CODE> will zoom the graph in and out in the Y-Axis only</LI>
|
||||
|
||||
<LI><CODE>Ctrl+Click</CODE> will select a vertex
|
||||
<UL>
|
||||
<LI><CODE>Ctrl+Click</CODE> over an unselected vertex will add that vertex to the
|
||||
selection</LI>
|
||||
|
||||
<LI><CODE>Ctrl+Click</CODE> over a previously selected vertex will remove that vertex
|
||||
from the selection</LI>
|
||||
</UL>
|
||||
</LI>
|
||||
|
||||
<LI><CODE>Ctrl+drag</CODE> on an empty area will create a rectangular area and select
|
||||
enclosed vertices</LI>
|
||||
|
||||
|
||||
</UL>
|
||||
|
||||
<H2>Toolbar Buttons</H2>
|
||||
|
||||
<P><A name="Scroll_To_Selection">
|
||||
The <IMG alt="" src="images/locationIn.gif"> toggle button, when 'set' will cause a focused
|
||||
vertex (the vertex with the red arrow) to be moved to the center of the view</P>
|
||||
|
||||
<P><A name="Free_Form_Selection">
|
||||
The <IMG alt="" src="images/Lasso.png" width="16" height="16"> toggle button, when 'set' will
|
||||
allow the user to draw a free-form shape that encloses the vertices they wish to select.</P>
|
||||
|
||||
<P><A name="SatelliteView">
|
||||
The <IMG alt="" src="images/network-wireless-16.png" width="16" height="16"> toggle button,
|
||||
when 'set' will open a satellite mini view of the graph in the lower right corner. The
|
||||
mini-view can be manipulated with the mouse to affect the main view</P>
|
||||
|
||||
<P><A name="Reset_View">
|
||||
The <IMG alt="" src="images/reload3.png"> button will reset any visual transformations on the
|
||||
graph and center it at a best-effort size</P>
|
||||
|
||||
<P><A name="View_Magnifier">
|
||||
The <IMG alt="" src="images/magnifier.png"> toggle button, when 'set' will open a rectangular
|
||||
magnification lens in the graph view</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<UL>
|
||||
<LI>MouseButton1 click-drag on the lens center circle to move the magnifier lens</LI>
|
||||
|
||||
<LI>MouseButton1 click-draw on a lens edge diamond to resize the magnifier lens</LI>
|
||||
|
||||
<LI>MouseButton1 click on the upper-right circle-cross to dispose of the magnifier
|
||||
lens</LI>
|
||||
|
||||
<LI>MouseWheel will change the magnification of the lens</LI>
|
||||
</UL>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><A name="Show_Filters">
|
||||
The <IMG alt="" src="Icons.CONFIGURE_FILTER_ICON"> button will open a Filter dialog. Select
|
||||
buttons in the dialog to hide specific vertices or edges in the display. The Filter dialog
|
||||
buttons are created by examining the graph vertex/edge properties to discover candidates for
|
||||
filtering.</P>
|
||||
|
||||
<P><A name="Arrangement">
|
||||
The <IMG alt="" src="images/katomic.png" width="16" height="16"> Arrangement menu is used to
|
||||
select one of several graph layout algorithms.</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<UL>
|
||||
<LI><A name="Compact_Hierarchical">
|
||||
<B>Compact Hierarchical</B> is the <B>TidierTree Layout Algorithm</B>. It builds a tree
|
||||
structure and attempts to reduce horizontal space.</LI>
|
||||
|
||||
<LI><A name="Hierarchical">
|
||||
<B>Hierarchical</B> is a basic Tree algorithm. It prioritizes 'important' edges while
|
||||
constructing the tree.</LI>
|
||||
|
||||
<LI><A name="Compact Radial">
|
||||
<B>Compact Radial</B> is the <B>TidierTree Layout Algorithm</B> with the root(s) at the
|
||||
center and child vertices radiating outwards.</LI>
|
||||
|
||||
<LI><B>Hierarchical MinCross</B> is the <B>Sugiyama Layout Algorithm</B>. It attempts to
|
||||
route edges around vertices in order to reduce crossing.There are four layering
|
||||
algorithms:</LI>
|
||||
|
||||
<LI style="list-style: none">
|
||||
<UL>
|
||||
<LI><A name="Hierarchical_MinCross_Top_Down">
|
||||
<B>Top Down</B> - biases the vertices to the top</LI>
|
||||
|
||||
<LI><A name="Hierarchical_MinCross_Longest_Path">
|
||||
<B>Longest Path</B> - biases the vertices to the bottom</LI>
|
||||
|
||||
<LI><A name="Hierarchical_MinCross_Network_Simplex">
|
||||
<B>Network Simplex</B> - layers after finding an 'optimal tree'</LI>
|
||||
|
||||
<LI><A name="Hierarchical_MinCross_Coffman_Graham">
|
||||
<B>Coffman Graham</B> - biases the vertices using a scheduling algorithm to minimize
|
||||
length</LI>
|
||||
</UL>
|
||||
</LI>
|
||||
|
||||
<LI><A name="Circle">
|
||||
<B>Circle</B> will arrange vertices in a Circle. If there are not too many edges (less
|
||||
than specified in the jungrapht.circle.reduceEdgeCrossingMaxEdges property with a default
|
||||
of 200), it will attempt to reduce edge crossing by rearranging the vertices.</LI>
|
||||
|
||||
<LI><A name="Force_Balanced">
|
||||
<B>Force Balanced</B> is a <B>Force Directed Layout Algorithm</B> using the the <B>Kamada
|
||||
Kawai</B> approach. It attempts to balance the graph by considering vertices and edge
|
||||
connections.</LI>
|
||||
|
||||
<LI><A name="Force_Directed">
|
||||
<B>Force Directed</B> is a <B>Force Directed Layout Algorithm</B> using the
|
||||
<B>Fructermann Reingold</B> approach. It pushes unconnected vertices apart and draws
|
||||
connected vertices together.</LI>
|
||||
|
||||
<LI><A name="Radial">
|
||||
<B>Radial</B> is a Tree structure with the root(s) at the center and child vertices
|
||||
radiating outwards.</LI>
|
||||
|
||||
<LI><A name="Balloon">
|
||||
<B>Balloon</B> is a Tree structure with the root(s) at the centers of circles in a radial
|
||||
pattern</LI>
|
||||
|
||||
<LI><A name="Gem__Graph_Embedder_">
|
||||
<B>GEM</B> is a Force Directed layout with locally separated components</LI>
|
||||
</UL>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Popup Actions</H2>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<H3>Standard Popup Actions</H3>
|
||||
|
||||
<UL>
|
||||
<LI><A name="Hide_Selected">
|
||||
<B>Hide Selected</B> - Causes the display to not show selected vertices.</LI>
|
||||
|
||||
<LI><A name="Hide_Unselected">
|
||||
<B>Hide Unselected</B> - Causes the display to not show unselected vertices.</LI>
|
||||
|
||||
<LI><A name="Invert_Selection">
|
||||
<B>Invert Selection</B> - Unselects all selected nodes and selects all unselected
|
||||
nodes.</LI>
|
||||
|
||||
<LI><A name="Grow_Selection From Sources">
|
||||
<B>Grow Selection From Sources</B> - Adds to the selection all vertices that have outgoing
|
||||
edges to the current selection.</LI>
|
||||
|
||||
<LI><A name="Grow_Selection To Targets">
|
||||
<B>Grow Selection To Targets</B> - Adds to the selection all vertices that have incoming
|
||||
edges from the current selection.</LI>
|
||||
|
||||
<LI><A name="Clear_Selection">
|
||||
<B>Clear Selection</B> - Clears all edge and vertex selection.</LI>
|
||||
|
||||
<LI><A name="Create_Subgraph">
|
||||
<B>Display Selected As New Graph</B> - Creates a new graph and display from the currently
|
||||
selected vertices.</LI>
|
||||
|
||||
<LI><A name="Display_Popup_Windows">
|
||||
<B>Display Popup Windows</B> - When toggled off no tooltip popups will be displayed.</LI>
|
||||
|
||||
</UL>
|
||||
|
||||
<H3>Vertex Popup Actions</H3>
|
||||
|
||||
<UL>
|
||||
<LI><A name="Select_Vertex">
|
||||
<B>Select Vertex</B> - Selects the vertex that this action was invoked on.</LI>
|
||||
|
||||
<LI><A name="Deselect_Vertex">
|
||||
<B>Deselect Vertex</B> - Deselects the vertex that this action was invoked on.</LI>
|
||||
</UL>
|
||||
|
||||
<H3>Edge Popup Actions</H3>
|
||||
|
||||
<UL>
|
||||
<LI><A name="Edge_Source">
|
||||
<B>Go To Edge Source</B> - Makes this edge's source vertex be the focused vertex.</LI>
|
||||
|
||||
<LI><A name="Edge_Target">
|
||||
<B>Go To Edge Target</B> - Makes this edge's destination vertex be the focused vertex.</LI>
|
||||
|
||||
<LI><A name="Select_Edge">
|
||||
<B>Select Edge</B> - Add this edge and its associated vertices to the selection</LI>
|
||||
|
||||
<LI><A name="Deselect_Edge">
|
||||
<B>Deselect Edge</B> - Removes this edge and its associated vertices from the
|
||||
selection</LI>
|
||||
</UL>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P class="providedbyplugin">Provided By: <I>GraphDisplayBrokerPlugin</I></P>
|
||||
|
||||
<P class="relatedtopic">Related Topics:</P>
|
||||
|
||||
<UL>
|
||||
<LI><A href="help/topics/GraphServices/GraphExport.htm">Graph Export</A></LI>
|
||||
</UL><BR>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
</HTML>
|
||||
|
@ -11,19 +11,22 @@
|
||||
</HEAD>
|
||||
|
||||
<BODY lang="EN-US">
|
||||
<A name="Default Graph Exporter"/>
|
||||
<A NAME="Graph_Exporter"/>
|
||||
<H1>Graph Export Service</H1>
|
||||
|
||||
<H2> Export Dialog </H2>
|
||||
<P> Whenever a graph is generated and the graph output is set to <B>Graph Export</B>, then the
|
||||
following graph export dialog is displayed: </P>
|
||||
<BR>
|
||||
<BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<P align="left"><IMG src="images/ExportDialog.png"></P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
<CENTER>
|
||||
<TABLE border="0" width="100%">
|
||||
<TR>
|
||||
<TD width="100%" align="center"><IMG alt="" border="1" src=
|
||||
"images/ExportDialog.png"></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
<BR>
|
||||
<BLOCKQUOTE>
|
||||
<P>The Export Graph dialog offers a choice of the following graph formats:</P>
|
||||
@ -49,5 +52,16 @@
|
||||
<p>The <b>Ok</b> button will marshal the graph to the selected file in the selected format and close the dialog.</p>
|
||||
<p>The <b>Cancel</b> button will close the dialog and perform no other action.</p>
|
||||
|
||||
|
||||
|
||||
<P class="providedbyplugin">Provided By: <I>GraphDisplayBrokerPlugin</I></P>
|
||||
|
||||
<P class="relatedtopic">Related Topics:</P>
|
||||
<UL>
|
||||
<LI><A href="help/topics/GraphServices/GraphDisplay.htm">Default Graph Display</A></LI>
|
||||
</UL>
|
||||
<BR>
|
||||
<BR>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
Binary file not shown.
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 8.5 KiB |
@ -73,6 +73,6 @@ public class ExportAttributedGraphDisplayProvider implements GraphDisplayProvide
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("GraphServices", "Default_Graph_Exporter");
|
||||
return new HelpLocation("GraphServices", "Graph_Exporter");
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class GraphExporterDialog extends DialogComponentProvider {
|
||||
addWorkPanel(buildWorkPanel());
|
||||
addOKButton();
|
||||
addCancelButton();
|
||||
setHelpLocation(new HelpLocation("ExporterPlugin", "Exporter_Dialog"));
|
||||
setHelpLocation(new HelpLocation("GraphServices", "Graph_Exporter"));
|
||||
validate();
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,10 @@ final class DefaultDisplayGraphIcons {
|
||||
private DefaultDisplayGraphIcons() {
|
||||
}
|
||||
|
||||
public static final Icon SATELLITE_VIEW_ICON = Icons.get("images/sat2.png");
|
||||
public static final Icon SATELLITE_VIEW_ICON = Icons.get("images/network-wireless-16.png");
|
||||
public static final Icon VIEW_MAGNIFIER_ICON = Icons.get("images/magnifier.png");
|
||||
public static final Icon PROGRAM_GRAPH_ICON = Icons.get("images/redspheregraph.png");
|
||||
public static final Icon LAYOUT_ALGORITHM_ICON = Icons.get("images/katomic.png");
|
||||
public static final Icon LASSO_ICON = Icons.get("images/Lasso.png");
|
||||
public static final Icon FILTER_ICON = Icons.get("images/filter_on.png");
|
||||
public static final Icon FILTER_ICON = Icons.CONFIGURE_FILTER_ICON;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import java.awt.event.*;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
@ -64,6 +63,8 @@ import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.graph.AttributeFilters;
|
||||
import ghidra.graph.job.GraphJobRunner;
|
||||
import ghidra.graph.viewer.popup.*;
|
||||
import ghidra.graph.visualization.mouse.JgtPluggableGraphMouse;
|
||||
import ghidra.graph.visualization.mouse.JgtUtils;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@ -76,19 +77,18 @@ import resources.Icons;
|
||||
*/
|
||||
public class DefaultGraphDisplay implements GraphDisplay {
|
||||
|
||||
public static final String FAVORED_EDGE = "Fall-Through";
|
||||
private static final int MAX_NODES = Integer.getInteger("maxNodes", 10000);
|
||||
public static final Dimension PREFERRED_VIEW_SIZE = new Dimension(1000, 1000);
|
||||
public static final Dimension PREFERRED_LAYOUT_SIZE = new Dimension(3000, 3000);
|
||||
private static final String ACTION_OWNER = "GraphServices";
|
||||
|
||||
Logger log = Logger.getLogger(DefaultGraphDisplay.class.getName());
|
||||
private static final String FAVORED_EDGE = "Fall-Through";
|
||||
private static final int MAX_NODES = Integer.getInteger("maxNodes", 10000);
|
||||
private static final Dimension PREFERRED_VIEW_SIZE = new Dimension(1000, 1000);
|
||||
private static final Dimension PREFERRED_LAYOUT_SIZE = new Dimension(3000, 3000);
|
||||
|
||||
private Logger log = Logger.getLogger(DefaultGraphDisplay.class.getName());
|
||||
|
||||
private GraphDisplayListener listener = new DummyGraphDisplayListener();
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* the {@link Graph} to visualize
|
||||
*/
|
||||
private AttributedGraph graph;
|
||||
|
||||
/**
|
||||
@ -97,91 +97,64 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
private final int displayId;
|
||||
|
||||
/**
|
||||
* the delegate viewer to display the ProgramGraph
|
||||
* The delegate viewer to display the ProgramGraph
|
||||
*/
|
||||
private final VisualizationViewer<AttributedVertex, AttributedEdge> viewer;
|
||||
|
||||
/**
|
||||
* the {@link PluginTool}
|
||||
* The {@link PluginTool}
|
||||
*/
|
||||
private final PluginTool pluginTool;
|
||||
|
||||
/**
|
||||
* the "owner name" for action - mainly affects default help location
|
||||
*/
|
||||
private final String actionOwnerName = "GraphServices";
|
||||
|
||||
/**
|
||||
* provides the component for the {@link GraphDisplay}
|
||||
*/
|
||||
private final DefaultGraphDisplayComponentProvider componentProvider;
|
||||
|
||||
/**
|
||||
* whether to ensure the focused vertex is visible, scrolling if necessary
|
||||
* Whether to ensure the focused vertex is visible, scrolling if necessary
|
||||
* the visualization in order to center the selected vertex
|
||||
* or the center of the set of selected vertices
|
||||
*/
|
||||
private boolean ensureVertexIsVisible = false;
|
||||
|
||||
/**
|
||||
* allows selection of various {@link LayoutAlgorithm} ('arrangements')
|
||||
* Allows selection of various {@link LayoutAlgorithm} ('arrangements')
|
||||
*/
|
||||
private final LayoutTransitionManager layoutTransitionManager;
|
||||
|
||||
/**
|
||||
* provides graph displays for supplied graphs
|
||||
* Provides graph displays for supplied graphs
|
||||
*/
|
||||
private final DefaultGraphDisplayProvider graphDisplayProvider;
|
||||
/**
|
||||
* the vertex that has been nominated to be 'focused' in the graph display and listing
|
||||
*/
|
||||
private AttributedVertex focusedVertex;
|
||||
|
||||
/**
|
||||
* Runs animation jobs for updating the display
|
||||
*/
|
||||
private final GraphJobRunner jobRunner = new GraphJobRunner();
|
||||
|
||||
/**
|
||||
* a satellite view that shows in the lower left corner as a birds-eye view of the graph display
|
||||
*/
|
||||
private final SatelliteVisualizationViewer<AttributedVertex, AttributedEdge> satelliteViewer;
|
||||
/**
|
||||
* generated filters on edges
|
||||
*/
|
||||
private AttributeFilters edgeFilters;
|
||||
/**
|
||||
* generated filters on vertices
|
||||
*/
|
||||
private AttributeFilters vertexFilters;
|
||||
/**
|
||||
* a dialog populated with generated vertex/edge filters
|
||||
*/
|
||||
|
||||
private FilterDialog filterDialog;
|
||||
/**
|
||||
* holds the vertex icons (instead of recomputing them)
|
||||
*/
|
||||
private AttributeFilters edgeFilters;
|
||||
private AttributeFilters vertexFilters;
|
||||
|
||||
private GhidraIconCache iconCache;
|
||||
|
||||
/**
|
||||
* multi-selection is done in a free-form traced shape instead of a rectangle
|
||||
* Multi-selection is done in a free-form traced shape instead of a rectangle
|
||||
*/
|
||||
private boolean freeFormSelection;
|
||||
|
||||
/**
|
||||
* Handles the popup
|
||||
* Handles all mouse interaction
|
||||
*/
|
||||
private GhidraGraphMouse graphMouse;
|
||||
private JgtPluggableGraphMouse graphMouse;
|
||||
|
||||
/**
|
||||
* Will accept a {@link Graph} and use it to create a new graph display in
|
||||
* a new tab or new window
|
||||
*/
|
||||
Consumer<Graph<AttributedVertex, AttributedEdge>> subgraphConsumer = g -> {
|
||||
|
||||
AttributedGraph attributedGraph = new AttributedGraph();
|
||||
g.vertexSet().forEach(attributedGraph::addVertex);
|
||||
g.edgeSet().forEach(e -> {
|
||||
AttributedVertex source = g.getEdgeSource(e);
|
||||
AttributedVertex target = g.getEdgeTarget(e);
|
||||
attributedGraph.addEdge(source, target, e);
|
||||
});
|
||||
displaySubGraph(attributedGraph);
|
||||
};
|
||||
private ToggleDockingAction hideSelectedAction;
|
||||
private ToggleDockingAction hideUnselectedAction;
|
||||
private SwitchableSelectionItemListener switchableSelectionListener;
|
||||
@ -226,7 +199,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
.builder(viewer.getRenderContext().getVertexBoundsFunction())
|
||||
.build());
|
||||
|
||||
graphMouse = new GhidraGraphMouse(componentProvider, viewer);
|
||||
graphMouse = new JgtPluggableGraphMouse(this);
|
||||
|
||||
createToolbarActions();
|
||||
createPopupActions();
|
||||
@ -302,7 +275,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
private void createToolbarActions() {
|
||||
|
||||
// create a toggle for 'scroll to selected vertex'
|
||||
new ToggleActionBuilder("Scroll To Selection", actionOwnerName)
|
||||
new ToggleActionBuilder("Scroll To Selection", ACTION_OWNER)
|
||||
.toolBarIcon(Icons.NAVIGATE_ON_INCOMING_EVENT_ICON)
|
||||
.description("Ensure that the 'focused' vertex is visible")
|
||||
.selected(true)
|
||||
@ -314,7 +287,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
|
||||
// create a toggle for enabling 'free-form' selection: selection is
|
||||
// inside of a traced shape instead of a rectangle
|
||||
new ToggleActionBuilder("Free-Form Selection", actionOwnerName)
|
||||
new ToggleActionBuilder("Free-Form Selection", ACTION_OWNER)
|
||||
.toolBarIcon(DefaultDisplayGraphIcons.LASSO_ICON)
|
||||
.description("Trace Free-Form Shape to select multiple vertices (CTRL-click-drag)")
|
||||
.selected(false)
|
||||
@ -323,14 +296,14 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
// create an icon button to display the satellite view
|
||||
new ToggleActionBuilder("SatelliteView", actionOwnerName).description("Show Satellite View")
|
||||
new ToggleActionBuilder("SatelliteView", ACTION_OWNER).description("Show Satellite View")
|
||||
.toolBarIcon(DefaultDisplayGraphIcons.SATELLITE_VIEW_ICON)
|
||||
.onAction(this::toggleSatellite)
|
||||
.selected(graphDisplayProvider.getDefaultSatelliteState())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
// create an icon button to reset the view transformations to identity (scaled to layout)
|
||||
new ActionBuilder("Reset View", actionOwnerName)
|
||||
new ActionBuilder("Reset View", ACTION_OWNER)
|
||||
.description("Reset all view transforms to center graph in display")
|
||||
.toolBarIcon(Icons.REFRESH_ICON)
|
||||
.onAction(context -> viewer.scaleToLayout())
|
||||
@ -338,7 +311,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
|
||||
// create a button to show the view magnify lens
|
||||
LensSupport<LensGraphMouse> magnifyViewSupport = createMagnifier();
|
||||
ToggleDockingAction lensToggle = new ToggleActionBuilder("View Magnifier", actionOwnerName)
|
||||
ToggleDockingAction lensToggle = new ToggleActionBuilder("View Magnifier", ACTION_OWNER)
|
||||
.description("Show View Magnifier")
|
||||
.toolBarIcon(DefaultDisplayGraphIcons.VIEW_MAGNIFIER_ICON)
|
||||
.onAction(context -> magnifyViewSupport.activate(
|
||||
@ -349,90 +322,91 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
componentProvider.addLocalAction(lensToggle);
|
||||
|
||||
// create an action button to show a dialog with generated filters
|
||||
new ActionBuilder("Show Filters", actionOwnerName).description("Show Graph Filters")
|
||||
new ActionBuilder("Show Filters", ACTION_OWNER).description("Show Graph Filters")
|
||||
.toolBarIcon(DefaultDisplayGraphIcons.FILTER_ICON)
|
||||
.onAction(context -> showFilterDialog())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
// create a menu with graph layout algorithm selections
|
||||
new MultiStateActionBuilder<String>("Arrangement", actionOwnerName)
|
||||
.description("Select Layout Arrangement Algorithm")
|
||||
List<ActionState<String>> layoutActionStates = getLayoutActionStates();
|
||||
new MultiStateActionBuilder<String>("Arrangement", ACTION_OWNER)
|
||||
.description("Arrangement: " + layoutActionStates.get(0).getName())
|
||||
.toolBarIcon(DefaultDisplayGraphIcons.LAYOUT_ALGORITHM_ICON)
|
||||
.fireFirstAction(false)
|
||||
.onActionStateChanged((s, t) -> layoutChanged(s.getName()))
|
||||
.addStates(getLayoutActionStates())
|
||||
.addStates(layoutActionStates)
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
}
|
||||
|
||||
private void createPopupActions() {
|
||||
new ActionBuilder("Select Vertex", actionOwnerName)
|
||||
new ActionBuilder("Select Vertex", ACTION_OWNER)
|
||||
.popupMenuPath("Select Vertex")
|
||||
.popupMenuGroup("selection", "1")
|
||||
.withContext(VertexGraphActionContext.class)
|
||||
.enabledWhen(c -> !viewer.getSelectedVertexState().isSelected(c.getClickedVertex()))
|
||||
.enabledWhen(c -> !isSelected(c.getClickedVertex()))
|
||||
.onAction(c -> viewer.getSelectedVertexState().select(c.getClickedVertex()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Deselect Vertex", actionOwnerName)
|
||||
new ActionBuilder("Deselect Vertex", ACTION_OWNER)
|
||||
.popupMenuPath("Deselect Vertex")
|
||||
.popupMenuGroup("selection", "2")
|
||||
.withContext(VertexGraphActionContext.class)
|
||||
.enabledWhen(c -> viewer.getSelectedVertexState().isSelected(c.getClickedVertex()))
|
||||
.enabledWhen(c -> isSelected(c.getClickedVertex()))
|
||||
.onAction(c -> viewer.getSelectedVertexState().deselect(c.getClickedVertex()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Select Edge", actionOwnerName)
|
||||
new ActionBuilder("Select Edge", ACTION_OWNER)
|
||||
.popupMenuPath("Select Edge")
|
||||
.popupMenuGroup("selection", "1")
|
||||
.withContext(EdgeGraphActionContext.class)
|
||||
.enabledWhen(c -> !viewer.getSelectedEdgeState().isSelected(c.getClickedEdge()))
|
||||
.enabledWhen(c -> !isSelected(c.getClickedEdge()))
|
||||
.onAction(c -> selectEdge(c.getClickedEdge()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Deselect Edge", actionOwnerName)
|
||||
new ActionBuilder("Deselect Edge", ACTION_OWNER)
|
||||
.popupMenuPath("Deselect Edge")
|
||||
.popupMenuGroup("selection", "2")
|
||||
.withContext(EdgeGraphActionContext.class)
|
||||
.enabledWhen(c -> viewer.getSelectedEdgeState().isSelected(c.getClickedEdge()))
|
||||
.enabledWhen(c -> isSelected(c.getClickedEdge()))
|
||||
.onAction(c -> deselectEdge(c.getClickedEdge()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Edge Source", actionOwnerName)
|
||||
new ActionBuilder("Edge Source", ACTION_OWNER)
|
||||
.popupMenuPath("Go To Edge Source")
|
||||
.popupMenuGroup("Go To")
|
||||
.withContext(EdgeGraphActionContext.class)
|
||||
.onAction(c -> setFocusedVertex(graph.getEdgeSource(c.getClickedEdge())))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Edge Target", actionOwnerName)
|
||||
new ActionBuilder("Edge Target", ACTION_OWNER)
|
||||
.popupMenuPath("Go To Edge Target")
|
||||
.popupMenuGroup("Go To")
|
||||
.withContext(EdgeGraphActionContext.class)
|
||||
.onAction(c -> setFocusedVertex(graph.getEdgeTarget(c.getClickedEdge())))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
hideSelectedAction = new ToggleActionBuilder("Hide Selected", actionOwnerName)
|
||||
hideSelectedAction = new ToggleActionBuilder("Hide Selected", ACTION_OWNER)
|
||||
.popupMenuPath("Hide Selected")
|
||||
.popupMenuGroup("z", "1")
|
||||
.description("Toggles whether or not to show selected vertices and edges")
|
||||
.onAction(c -> manageVertexDisplay())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
hideUnselectedAction = new ToggleActionBuilder("Hide Unselected", actionOwnerName)
|
||||
hideUnselectedAction = new ToggleActionBuilder("Hide Unselected", ACTION_OWNER)
|
||||
.popupMenuPath("Hide Unselected")
|
||||
.popupMenuGroup("z", "2")
|
||||
.description("Toggles whether or not to show selected vertices and edges")
|
||||
.onAction(c -> manageVertexDisplay())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Invert Selection", actionOwnerName)
|
||||
new ActionBuilder("Invert Selection", ACTION_OWNER)
|
||||
.popupMenuPath("Invert Selection")
|
||||
.popupMenuGroup("z", "3")
|
||||
.description("Inverts the current selection")
|
||||
.onAction(c -> invertSelection())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Grow Selection To Targets", actionOwnerName)
|
||||
new ActionBuilder("Grow Selection To Targets", ACTION_OWNER)
|
||||
.popupMenuPath("Grow Selection To Targets")
|
||||
.popupMenuGroup("z", "4")
|
||||
.description("Extends the current selection by including the target vertex " +
|
||||
@ -442,7 +416,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
.onAction(c -> growSelection(getTargetVerticesFromSelected()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Grow Selection From Sources", actionOwnerName)
|
||||
new ActionBuilder("Grow Selection From Sources", ACTION_OWNER)
|
||||
.popupMenuPath("Grow Selection From Sources")
|
||||
.popupMenuGroup("z", "4")
|
||||
.description("Extends the current selection by including the target vertex " +
|
||||
@ -452,15 +426,23 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
.onAction(c -> growSelection(getSourceVerticesFromSelected()))
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Create Subgraph", actionOwnerName)
|
||||
.popupMenuPath("Display Selected as New Graph")
|
||||
new ActionBuilder("Clear Selection", ACTION_OWNER)
|
||||
.popupMenuPath("Clear Selection")
|
||||
.popupMenuGroup("z", "5")
|
||||
.keyBinding("escape")
|
||||
.enabledWhen(c -> hasSelection())
|
||||
.onAction(c -> clearSelection())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
new ActionBuilder("Create Subgraph", ACTION_OWNER)
|
||||
.popupMenuPath("Display Selected as New Graph")
|
||||
.popupMenuGroup("zz", "5")
|
||||
.description("Creates a subgraph from the selected nodes")
|
||||
.enabledWhen(c -> !viewer.getSelectedVertexState().getSelected().isEmpty())
|
||||
.onAction(c -> createAndDisplaySubGraph())
|
||||
.buildAndInstallLocal(componentProvider);
|
||||
|
||||
togglePopupsAction = new ToggleActionBuilder("Display Popup Windows", actionOwnerName)
|
||||
togglePopupsAction = new ToggleActionBuilder("Display Popup Windows", ACTION_OWNER)
|
||||
.popupMenuPath("Display Popup Windows")
|
||||
.popupMenuGroup("zz", "1")
|
||||
.description("Toggles whether or not to show popup windows, such as tool tips")
|
||||
@ -471,6 +453,24 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
|
||||
}
|
||||
|
||||
private void clearSelection() {
|
||||
viewer.getSelectedVertexState().clear();
|
||||
viewer.getSelectedEdgeState().clear();
|
||||
}
|
||||
|
||||
private boolean hasSelection() {
|
||||
return !(viewer.getSelectedVertexState().getSelected().isEmpty() &&
|
||||
viewer.getSelectedEdgeState().getSelected().isEmpty());
|
||||
}
|
||||
|
||||
private boolean isSelected(AttributedVertex v) {
|
||||
return viewer.getSelectedVertexState().isSelected(v);
|
||||
}
|
||||
|
||||
private boolean isSelected(AttributedEdge e) {
|
||||
return viewer.getSelectedEdgeState().isSelected(e);
|
||||
}
|
||||
|
||||
private void createAndDisplaySubGraph() {
|
||||
GraphDisplay display = graphDisplayProvider.getGraphDisplay(false, TaskMonitor.DUMMY);
|
||||
try {
|
||||
@ -556,7 +556,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
for (String layoutName : names) {
|
||||
ActionState<String> state = new ActionState<>(layoutName,
|
||||
DefaultDisplayGraphIcons.LAYOUT_ALGORITHM_ICON, layoutName);
|
||||
state.setHelpLocation(new HelpLocation(actionOwnerName, layoutName));
|
||||
state.setHelpLocation(new HelpLocation(ACTION_OWNER, layoutName));
|
||||
actionStates.add(state);
|
||||
}
|
||||
return actionStates;
|
||||
@ -603,24 +603,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
viewer.repaint();
|
||||
}
|
||||
|
||||
private void displaySubGraph(Graph<AttributedVertex, AttributedEdge> subGraph) {
|
||||
|
||||
try {
|
||||
GraphDisplay graphDisplay =
|
||||
graphDisplayProvider.getGraphDisplay(false, TaskMonitor.DUMMY);
|
||||
graphDisplay.setGraph((AttributedGraph) subGraph, "SubGraph", false, TaskMonitor.DUMMY);
|
||||
graphDisplay.setGraphDisplayListener(listener);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// can't happen while using a dummy monitor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a SatelliteViewer for the Visualization
|
||||
* @param parentViewer the main visualization 'parent' of the satellite view
|
||||
* @return a new SatelliteVisualizationViewer
|
||||
*/
|
||||
private SatelliteVisualizationViewer<AttributedVertex, AttributedEdge> createSatelliteViewer(
|
||||
VisualizationViewer<AttributedVertex, AttributedEdge> parentViewer) {
|
||||
Dimension viewerSize = parentViewer.getSize();
|
||||
@ -649,9 +631,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
return satellite;
|
||||
}
|
||||
|
||||
/**
|
||||
* close this graph display
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
graphDisplayProvider.remove(this);
|
||||
@ -662,10 +641,6 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
componentProvider.closeComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* accept a {@code GraphDisplayListener}
|
||||
* @param listener the listener to be notified
|
||||
*/
|
||||
@Override
|
||||
public void setGraphDisplayListener(GraphDisplayListener listener) {
|
||||
if (this.listener != null) {
|
||||
@ -697,7 +672,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
viewer.getSelectedVertexState().addItemListener(switchableSelectionListener);
|
||||
}
|
||||
|
||||
protected void setFocusedVertex(AttributedVertex vertex) {
|
||||
public void setFocusedVertex(AttributedVertex vertex) {
|
||||
setFocusedVertex(vertex, EventTrigger.API_CALL);
|
||||
}
|
||||
|
||||
@ -1008,8 +983,7 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
return new Point2D.Double(p.x, p.y);
|
||||
}
|
||||
|
||||
// they did not pick a vertex to center, so
|
||||
// just center the graph
|
||||
// they did not pick a vertex to center, so just center the graph
|
||||
Point2D center = viewer.getCenter();
|
||||
Point p = Point.of(center.getX(), center.getY());
|
||||
return new Point2D.Double(p.x, p.y);
|
||||
@ -1211,13 +1185,13 @@ public class DefaultGraphDisplay implements GraphDisplay {
|
||||
|
||||
public ActionContext getActionContext(MouseEvent e) {
|
||||
|
||||
AttributedVertex pickedVertex = graphMouse.getPickedVertex(e);
|
||||
AttributedVertex pickedVertex = JgtUtils.getVertex(e, viewer);
|
||||
if (pickedVertex != null) {
|
||||
return new VertexGraphActionContext(componentProvider, graph, getSelectedVertices(),
|
||||
focusedVertex, pickedVertex);
|
||||
}
|
||||
|
||||
AttributedEdge pickedEdge = graphMouse.getPickedEdge(e);
|
||||
AttributedEdge pickedEdge = JgtUtils.getEdge(e, viewer);
|
||||
if (pickedEdge != null) {
|
||||
return new EdgeGraphActionContext(componentProvider, graph, getSelectedVertices(),
|
||||
focusedVertex, pickedEdge);
|
||||
|
@ -0,0 +1,311 @@
|
||||
/* ###
|
||||
* 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.graph.visualization.mouse;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.*;
|
||||
|
||||
import org.jungrapht.visualization.SatelliteVisualizationViewer;
|
||||
import org.jungrapht.visualization.VisualizationViewer;
|
||||
import org.jungrapht.visualization.control.AbstractGraphMousePlugin;
|
||||
import org.jungrapht.visualization.selection.MutableSelectedState;
|
||||
|
||||
/**
|
||||
* Graph mouse plugin base class.
|
||||
*
|
||||
* Usage Notes:
|
||||
* <ul>
|
||||
* <li>We clear state on mouseReleased() and mouseExited(), since we will get
|
||||
* at least one of those calls</li>
|
||||
* </ul>
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
//@formatter:off
|
||||
public abstract class AbstractJgtGraphMousePlugin<V, E>
|
||||
extends AbstractGraphMousePlugin
|
||||
implements MouseListener, MouseMotionListener {
|
||||
//@formatter:on
|
||||
|
||||
protected boolean isHandlingMouseEvents;
|
||||
|
||||
protected V selectedVertex;
|
||||
protected E selectedEdge;
|
||||
|
||||
public AbstractJgtGraphMousePlugin() {
|
||||
this(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
public AbstractJgtGraphMousePlugin(int selectionModifiers) {
|
||||
super(selectionModifiers);
|
||||
}
|
||||
|
||||
public VisualizationViewer<V, E> getViewer(MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = getGraphViewer(e);
|
||||
return viewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <b>primary/master</b> graph viewer.
|
||||
*
|
||||
* @param e the mouse event from which to get the viewer
|
||||
* @return the viewer
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public VisualizationViewer<V, E> getGraphViewer(MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = (VisualizationViewer<V, E>) e.getSource();
|
||||
|
||||
// is this the satellite viewer?
|
||||
if (viewer instanceof SatelliteVisualizationViewer) {
|
||||
return ((SatelliteVisualizationViewer<V, E>) viewer).getMaster();
|
||||
}
|
||||
|
||||
return viewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the satellite graph viewer. This assumes that the mouse event originated from
|
||||
* the satellite viewer.
|
||||
*
|
||||
* @param e the mouse event from which to get the viewer
|
||||
* @return the viewer
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public SatelliteVisualizationViewer<V, E> getSatelliteGraphViewer(MouseEvent e) {
|
||||
|
||||
VisualizationViewer<V, E> viewer = (VisualizationViewer<V, E>) e.getSource();
|
||||
|
||||
// is this the satellite viewer?
|
||||
if (viewer instanceof SatelliteVisualizationViewer) {
|
||||
return (SatelliteVisualizationViewer<V, E>) viewer;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Do not have a satellite GraphViewer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals to perform any cleanup when this plugin is going away
|
||||
*/
|
||||
public void dispose() {
|
||||
// stub
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given mouse event to see if it is a valid event for selecting a vertex at the
|
||||
* mouse location. If so, then the vertex is selected in this mouse handler and the event
|
||||
* is consumed.
|
||||
* @param e the event
|
||||
* @return true if a vertex was selected
|
||||
*/
|
||||
protected boolean checkForVertex(MouseEvent e) {
|
||||
if (!checkModifiers(e)) {
|
||||
selectedVertex = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
VisualizationViewer<V, E> vv = getViewer(e);
|
||||
selectedVertex = JgtUtils.getVertex(e, vv);
|
||||
if (selectedVertex == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.consume();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given mouse event to see if it is a valid event for selecting an edge at the
|
||||
* mouse location. If so, then the edge is selected in this mouse handler and the event
|
||||
* is consumed.
|
||||
* @param e the event
|
||||
* @return true if an edge was selected
|
||||
*/
|
||||
protected boolean checkForEdge(MouseEvent e) {
|
||||
if (!checkModifiers(e) || isOverVertex(e)) {
|
||||
selectedEdge = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
VisualizationViewer<V, E> vv = getViewer(e);
|
||||
selectedEdge = JgtUtils.getEdge(e, vv);
|
||||
if (selectedEdge == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.consume();
|
||||
isHandlingMouseEvents = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the given vertex
|
||||
* @param vertex the vertex
|
||||
* @param viewer the graph viewer
|
||||
* @return true if the vertex is selected
|
||||
*/
|
||||
protected boolean selectVertex(V vertex, VisualizationViewer<V, E> viewer) {
|
||||
MutableSelectedState<V> selectedVertexState = viewer.getSelectedVertexState();
|
||||
if (selectedVertexState == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
selectedVertexState.isSelected(vertex);
|
||||
|
||||
if (selectedVertexState.isSelected(vertex) == false) {
|
||||
selectedVertexState.clear();
|
||||
selectedVertexState.select(vertex, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the given edge
|
||||
* @param edge the edge
|
||||
* @param viewer the graph viewer
|
||||
* @return true if the edge is selected
|
||||
*/
|
||||
protected boolean selectEdge(E edge, VisualizationViewer<V, E> viewer) {
|
||||
|
||||
MutableSelectedState<E> selectedVertexState = viewer.getSelectedEdgeState();
|
||||
if (selectedVertexState == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
selectedVertexState.isSelected(edge);
|
||||
|
||||
if (selectedVertexState.isSelected(edge) == false) {
|
||||
selectedVertexState.clear();
|
||||
selectedVertexState.select(edge, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the location of the mouse event is over a vertex
|
||||
* @param e the event
|
||||
* @return true if the location of the mouse event is over a vertex
|
||||
*/
|
||||
protected boolean isOverVertex(MouseEvent e) {
|
||||
return getVertex(e) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertex if the mouse event is over a vertex
|
||||
* @param e the event
|
||||
* @return a vertex or null
|
||||
*/
|
||||
protected V getVertex(MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = getViewer(e);
|
||||
return JgtUtils.getVertex(e, viewer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the location of the mouse event is over a edge
|
||||
* @param e the event
|
||||
* @return true if the location of the mouse event is over a edge
|
||||
*/
|
||||
protected boolean isOverEdge(MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = getViewer(e);
|
||||
E edge = JgtUtils.getEdge(e, viewer);
|
||||
if (edge == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !isOverVertex(e);
|
||||
}
|
||||
|
||||
protected void installCursor(Cursor newCursor, MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = getViewer(e);
|
||||
viewer.setCursor(newCursor);
|
||||
}
|
||||
|
||||
protected boolean shouldShowCursor(MouseEvent e) {
|
||||
return isOverVertex(e); // to showing cursor over vertices
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (!checkModifiers(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// override this method to do stuff
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (!isHandlingMouseEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.consume();
|
||||
resetState();
|
||||
}
|
||||
|
||||
protected void resetState() {
|
||||
isHandlingMouseEvents = false;
|
||||
selectedVertex = null;
|
||||
selectedEdge = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (!isHandlingMouseEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.consume();
|
||||
resetState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (isHandlingMouseEvents) {
|
||||
e.consume();
|
||||
}
|
||||
|
||||
// only "turn on" the cursor; resetting is handled elsewhere (in the mouse driver)
|
||||
if (shouldShowCursor(e)) {
|
||||
installCursor(cursor, e);
|
||||
e.consume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (isHandlingMouseEvents) {
|
||||
e.consume();
|
||||
}
|
||||
|
||||
if (shouldShowCursor(e)) {
|
||||
installCursor(cursor, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (shouldShowCursor(e)) {
|
||||
installCursor(cursor, e);
|
||||
e.consume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
installCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR), e);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/* ###
|
||||
* 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.graph.visualization.mouse;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
|
||||
import org.jungrapht.visualization.VisualizationViewer;
|
||||
import org.jungrapht.visualization.control.AbstractGraphMousePlugin;
|
||||
|
||||
/**
|
||||
* Restores the cursor after other graph mouse operations.
|
||||
*
|
||||
* Future: this is copied from the Visual Graph counterpart--consolidate these
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class JgtCursorRestoringPlugin<V, E> extends AbstractGraphMousePlugin
|
||||
implements MouseMotionListener {
|
||||
|
||||
public JgtCursorRestoringPlugin() {
|
||||
super(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
// don't care
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
installCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR), e);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void installCursor(Cursor newCursor, MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = (VisualizationViewer<V, E>) e.getSource();
|
||||
viewer.setCursor(newCursor);
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/* ###
|
||||
* 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.graph.visualization.mouse;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.jgrapht.Graph;
|
||||
import org.jungrapht.visualization.VisualizationViewer;
|
||||
import org.jungrapht.visualization.layout.model.Point;
|
||||
import org.jungrapht.visualization.selection.MutableSelectedState;
|
||||
|
||||
import ghidra.graph.visualization.CenterAnimationJob;
|
||||
|
||||
/**
|
||||
* Mouse plugin to allow for edge navigation
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class JgtEdgeNavigationPlugin<V, E> extends AbstractJgtGraphMousePlugin<V, E> {
|
||||
|
||||
public JgtEdgeNavigationPlugin() {
|
||||
this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (!checkModifiers(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.getClickCount() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkForEdge(e); // this will select an edge if we can and store off the edge
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (!isHandlingMouseEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
E edge = selectedEdge; // save off before we reset
|
||||
e.consume();
|
||||
resetState();
|
||||
|
||||
// on double-clicks we go to the vertex in the current edge direction unless that vertex
|
||||
// is already selected, then we go to the other vertex
|
||||
VisualizationViewer<V, E> viewer = getViewer(e);
|
||||
MutableSelectedState<V> selectedState = viewer.getSelectedVertexState();
|
||||
|
||||
Graph<V, E> graph = viewer.getVisualizationModel().getGraph();
|
||||
V end = graph.getEdgeTarget(edge);
|
||||
if (!selectedState.isSelected(end)) {
|
||||
pickAndShowVertex(end, selectedState, viewer);
|
||||
return;
|
||||
}
|
||||
|
||||
// the destination was picked, go the other direction
|
||||
V source = graph.getEdgeSource(edge);
|
||||
pickAndShowVertex(source, selectedState, viewer);
|
||||
}
|
||||
|
||||
private void pickAndShowVertex(V vertex, MutableSelectedState<V> selectedVertexState,
|
||||
VisualizationViewer<V, E> viewer) {
|
||||
|
||||
// TODO animate; this requires a single view updater
|
||||
Point2D existingCenter = viewer.getRenderContext()
|
||||
.getMultiLayerTransformer()
|
||||
.inverseTransform(viewer.getCenter());
|
||||
Point vp = viewer.getVisualizationModel().getLayoutModel().get(vertex);
|
||||
Point2D newCenter = new Point2D.Double(vp.x, vp.y);
|
||||
CenterAnimationJob job = new CenterAnimationJob(viewer, existingCenter, newCenter);
|
||||
job.finished();
|
||||
|
||||
selectedVertexState.clear();
|
||||
selectedVertexState.select(vertex);
|
||||
|
||||
/*
|
||||
VisualGraphViewUpdater<V, E> updater = viewer.getViewUpdater();
|
||||
updater.moveVertexToCenterWithAnimation(vertex, isBusy -> {
|
||||
|
||||
// pick the vertex after the animation has run
|
||||
if (!isBusy) {
|
||||
GPickedState<V> pickedStateWrapper = (GPickedState<V>) selectedVertexState;
|
||||
pickedStateWrapper.pickToActivate(vertex);
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowCursor(MouseEvent e) {
|
||||
return isOverEdge(e);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/* ###
|
||||
* 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.graph.visualization.mouse;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
|
||||
import org.jungrapht.visualization.control.*;
|
||||
|
||||
import docking.DockingUtils;
|
||||
import ghidra.graph.visualization.DefaultGraphDisplay;
|
||||
import ghidra.service.graph.AttributedEdge;
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
|
||||
/**
|
||||
* Pluggable graph mouse for jungrapht
|
||||
*/
|
||||
public class JgtPluggableGraphMouse extends DefaultGraphMouse<AttributedVertex, AttributedEdge> {
|
||||
|
||||
private DefaultGraphDisplay graphDisplay;
|
||||
|
||||
// TODO we should not need the graph display for any mouse plugins, but the API is net yet
|
||||
// robust enough to communicate fully without it
|
||||
public JgtPluggableGraphMouse(DefaultGraphDisplay graphDisplay) {
|
||||
super(DefaultGraphMouse.<AttributedVertex, AttributedEdge> builder());
|
||||
this.graphDisplay = graphDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadPlugins() {
|
||||
|
||||
//
|
||||
// Note: the order of these additions matters, as an event will flow to each plugin until
|
||||
// it is handled.
|
||||
//
|
||||
|
||||
// edge
|
||||
add(new JgtEdgeNavigationPlugin<AttributedVertex, AttributedEdge>());
|
||||
|
||||
add(new JgtVertexFocusingPlugin<AttributedVertex, AttributedEdge>(graphDisplay));
|
||||
|
||||
// scaling
|
||||
add(new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, in, out));
|
||||
|
||||
// the grab/pan feature
|
||||
add(new JgtTranslatingPlugin<AttributedVertex, AttributedEdge>());
|
||||
|
||||
add(new SelectingGraphMousePlugin<AttributedVertex, AttributedEdge>(
|
||||
InputEvent.BUTTON1_DOWN_MASK,
|
||||
0,
|
||||
DockingUtils.CONTROL_KEY_MODIFIER_MASK));
|
||||
|
||||
// cursor cleanup
|
||||
add(new JgtCursorRestoringPlugin<AttributedVertex, AttributedEdge>());
|
||||
|
||||
setPluginsLoaded();
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
/* ###
|
||||
* 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.graph.visualization.mouse;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.jungrapht.visualization.*;
|
||||
import org.jungrapht.visualization.MultiLayerTransformer.Layer;
|
||||
import org.jungrapht.visualization.control.TranslatingGraphMousePlugin;
|
||||
import org.jungrapht.visualization.transform.MutableTransformer;
|
||||
|
||||
/**
|
||||
* Note: this class is based on {@link TranslatingGraphMousePlugin}.
|
||||
* <p>
|
||||
* TranslatingGraphMousePlugin uses a MouseButtonOne press and drag gesture to translate
|
||||
* the graph display in the x and y direction. The default MouseButtonOne modifier can be overridden
|
||||
* to cause a different mouse gesture to translate the display.
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class JgtTranslatingPlugin<V, E>
|
||||
extends AbstractJgtGraphMousePlugin<V, E> {
|
||||
|
||||
private boolean panning;
|
||||
private boolean isHandlingEvent;
|
||||
|
||||
public JgtTranslatingPlugin() {
|
||||
this(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
public JgtTranslatingPlugin(int modifiers) {
|
||||
super(modifiers);
|
||||
this.cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
boolean accepted = checkModifiers(e) && isInDraggingArea(e);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
down = e.getPoint();
|
||||
VisualizationViewer<V, E> viewer = getGraphViewer(e);
|
||||
viewer.setCursor(cursor);
|
||||
isHandlingEvent = true;
|
||||
e.consume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
boolean wasHandlingEvent = isHandlingEvent;
|
||||
isHandlingEvent = false;
|
||||
down = null;
|
||||
installCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR), e);
|
||||
|
||||
// NOTE: we are only consuming the event here if we actually did pan...this allows follow-on
|
||||
// mouse handlers to process the mouseReleased() event. This is a bit odd and not the
|
||||
// normal event processing (which is to consume all related events).
|
||||
if (wasHandlingEvent && panning) {
|
||||
e.consume();
|
||||
}
|
||||
|
||||
panning = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
boolean accepted = checkModifiers(e);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isHandlingEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
panning = true;
|
||||
|
||||
VisualizationViewer<V, E> viewer = getGraphViewer(e);
|
||||
RenderContext<V, E> context = viewer.getRenderContext();
|
||||
MultiLayerTransformer multiLayerTransformer = context.getMultiLayerTransformer();
|
||||
MutableTransformer layoutTransformer = multiLayerTransformer.getTransformer(Layer.LAYOUT);
|
||||
viewer.setCursor(cursor);
|
||||
Point2D downPoint = multiLayerTransformer.inverseTransform(down);
|
||||
Point2D p = multiLayerTransformer.inverseTransform(e.getPoint());
|
||||
float dx = (float) (p.getX() - downPoint.getX());
|
||||
float dy = (float) (p.getY() - downPoint.getY());
|
||||
|
||||
layoutTransformer.translate(dx, dy);
|
||||
down.x = e.getX();
|
||||
down.y = e.getY();
|
||||
e.consume();
|
||||
viewer.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
// don't care
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (isHandlingEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInDraggingArea(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkModifiersForCursor(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
installCursor(cursor, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
installCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (!checkModifiersForCursor(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isHandlingEvent) {
|
||||
e.consume();
|
||||
}
|
||||
|
||||
if (isInDraggingArea(e)) {
|
||||
installCursor(cursor, e);
|
||||
e.consume();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkModifiersForCursor(MouseEvent e) {
|
||||
if (e.getModifiersEx() == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Private methods
|
||||
//==================================================================================================
|
||||
|
||||
private boolean isInDraggingArea(MouseEvent e) {
|
||||
return !(isOverVertex(e) || isOverEdge(e));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installCursor(Cursor newCursor, MouseEvent e) {
|
||||
VisualizationViewer<V, E> viewer = getViewer(e);
|
||||
viewer.setCursor(newCursor);
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.graph.visualization;
|
||||
package ghidra.graph.visualization.mouse;
|
||||
|
||||
import static org.jungrapht.visualization.VisualizationServer.*;
|
||||
|
||||
@ -22,42 +22,86 @@ import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import org.jungrapht.visualization.VisualizationViewer;
|
||||
import org.jungrapht.visualization.control.*;
|
||||
import org.jungrapht.visualization.control.GraphElementAccessor;
|
||||
import org.jungrapht.visualization.control.TransformSupport;
|
||||
import org.jungrapht.visualization.layout.model.LayoutModel;
|
||||
import org.jungrapht.visualization.selection.ShapePickSupport;
|
||||
|
||||
import docking.ComponentProvider;
|
||||
import ghidra.service.graph.AttributedEdge;
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
|
||||
/**
|
||||
* An extension of the jungrapht DefaultGraphMouse. This class has references to
|
||||
* <ul>
|
||||
* <li>a {@link VisualizationViewer} (to access the Graph and LayoutModel)
|
||||
*
|
||||
* Keeper of shared logic for jungrapht handling
|
||||
*/
|
||||
public class GhidraGraphMouse extends DefaultGraphMouse<AttributedVertex, AttributedEdge> {
|
||||
public class JgtUtils {
|
||||
|
||||
private static final String PICK_AREA_SIZE_PROPERTY = PREFIX + "pickAreaSize";
|
||||
|
||||
private VisualizationViewer<AttributedVertex, AttributedEdge> viewer;
|
||||
|
||||
private int pickSize;
|
||||
|
||||
/**
|
||||
* create an instance with default values
|
||||
* @param componentProvider the graph component provider
|
||||
* @param viewer the graph viewer component
|
||||
* Returns the edge under the given mouse event
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
* @param e the event
|
||||
* @param viewer the graph viewer
|
||||
* @return the edge
|
||||
*/
|
||||
GhidraGraphMouse(ComponentProvider componentProvider,
|
||||
VisualizationViewer<AttributedVertex, AttributedEdge> viewer) {
|
||||
public static <V, E> E getEdge(MouseEvent e, VisualizationViewer<V, E> viewer) {
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
super(DefaultGraphMouse.<AttributedVertex, AttributedEdge> builder());
|
||||
this.viewer = viewer;
|
||||
pickSize = Integer.getInteger(GhidraGraphMouse.PICK_AREA_SIZE_PROPERTY, 4);
|
||||
Rectangle2D footprintRectangle = getFootprint(e);
|
||||
LayoutModel<V> layoutModel = viewer.getVisualizationModel().getLayoutModel();
|
||||
GraphElementAccessor<V, E> pickSupport = viewer.getPickSupport();
|
||||
if (pickSupport == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pickSupport instanceof ShapePickSupport) {
|
||||
ShapePickSupport<V, E> shapePickSupport =
|
||||
(ShapePickSupport<V, E>) pickSupport;
|
||||
return shapePickSupport.getEdge(layoutModel, footprintRectangle);
|
||||
}
|
||||
|
||||
TransformSupport<V, E> transformSupport =
|
||||
viewer.getTransformSupport();
|
||||
Point2D layoutPoint = transformSupport.inverseTransform(viewer, e.getPoint());
|
||||
return pickSupport.getEdge(layoutModel, layoutPoint.getX(), layoutPoint.getY());
|
||||
}
|
||||
|
||||
private Rectangle2D getFootprint(MouseEvent e) {
|
||||
/**
|
||||
* Returns the vertex under the given mouse event
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
* @param e the event
|
||||
* @param viewer the graph viewer
|
||||
* @return the vertex
|
||||
*/
|
||||
public static <V, E> V getVertex(MouseEvent e, VisualizationViewer<V, E> viewer) {
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Rectangle2D footprintRectangle = getFootprint(e);
|
||||
LayoutModel<V> layoutModel = viewer.getVisualizationModel().getLayoutModel();
|
||||
GraphElementAccessor<V, E> pickSupport = viewer.getPickSupport();
|
||||
if (pickSupport == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (pickSupport instanceof ShapePickSupport) {
|
||||
ShapePickSupport<V, E> shapePickSupport =
|
||||
(ShapePickSupport<V, E>) pickSupport;
|
||||
return shapePickSupport.getVertex(layoutModel, footprintRectangle);
|
||||
}
|
||||
|
||||
TransformSupport<V, E> transformSupport =
|
||||
viewer.getTransformSupport();
|
||||
Point2D layoutPoint = transformSupport.inverseTransform(viewer, e.getPoint());
|
||||
return pickSupport.getVertex(layoutModel, layoutPoint.getX(), layoutPoint.getY());
|
||||
}
|
||||
|
||||
private static Rectangle2D getFootprint(MouseEvent e) {
|
||||
int pickSize = Integer.getInteger(PICK_AREA_SIZE_PROPERTY, 4);
|
||||
return new Rectangle2D.Float(
|
||||
e.getPoint().x - pickSize / 2f,
|
||||
e.getPoint().y - pickSize / 2f,
|
||||
@ -65,44 +109,4 @@ public class GhidraGraphMouse extends DefaultGraphMouse<AttributedVertex, Attrib
|
||||
pickSize);
|
||||
}
|
||||
|
||||
AttributedEdge getPickedEdge(MouseEvent e) {
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
Rectangle2D footprintRectangle = getFootprint(e);
|
||||
LayoutModel<AttributedVertex> layoutModel = viewer.getVisualizationModel().getLayoutModel();
|
||||
GraphElementAccessor<AttributedVertex, AttributedEdge> pickSupport =
|
||||
viewer.getPickSupport();
|
||||
if (pickSupport instanceof ShapePickSupport) {
|
||||
ShapePickSupport<AttributedVertex, AttributedEdge> shapePickSupport =
|
||||
(ShapePickSupport<AttributedVertex, AttributedEdge>) pickSupport;
|
||||
return shapePickSupport.getEdge(layoutModel, footprintRectangle);
|
||||
}
|
||||
|
||||
TransformSupport<AttributedVertex, AttributedEdge> transformSupport =
|
||||
viewer.getTransformSupport();
|
||||
Point2D layoutPoint = transformSupport.inverseTransform(viewer, e.getPoint());
|
||||
return pickSupport.getEdge(layoutModel, layoutPoint.getX(), layoutPoint.getY());
|
||||
}
|
||||
|
||||
AttributedVertex getPickedVertex(MouseEvent e) {
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
Rectangle2D footprintRectangle = getFootprint(e);
|
||||
LayoutModel<AttributedVertex> layoutModel = viewer.getVisualizationModel().getLayoutModel();
|
||||
GraphElementAccessor<AttributedVertex, AttributedEdge> pickSupport =
|
||||
viewer.getPickSupport();
|
||||
if (pickSupport instanceof ShapePickSupport) {
|
||||
ShapePickSupport<AttributedVertex, AttributedEdge> shapePickSupport =
|
||||
(ShapePickSupport<AttributedVertex, AttributedEdge>) pickSupport;
|
||||
return shapePickSupport.getVertex(layoutModel, footprintRectangle);
|
||||
}
|
||||
|
||||
TransformSupport<AttributedVertex, AttributedEdge> transformSupport =
|
||||
viewer.getTransformSupport();
|
||||
Point2D layoutPoint = transformSupport.inverseTransform(viewer, e.getPoint());
|
||||
return pickSupport.getVertex(layoutModel, layoutPoint.getX(), layoutPoint.getY());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/* ###
|
||||
* 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.graph.visualization.mouse;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import ghidra.graph.visualization.DefaultGraphDisplay;
|
||||
import ghidra.service.graph.AttributedVertex;
|
||||
|
||||
/**
|
||||
* A mouse plugin to focus a vertex when clicked
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class JgtVertexFocusingPlugin<V, E> extends AbstractJgtGraphMousePlugin<V, E> {
|
||||
|
||||
private DefaultGraphDisplay graphDisplay;
|
||||
|
||||
public JgtVertexFocusingPlugin(DefaultGraphDisplay graphDisplay) {
|
||||
this.graphDisplay = graphDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (!checkModifiers(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedVertex = getVertex(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (selectedVertex == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
graphDisplay.setFocusedVertex((AttributedVertex) selectedVertex);
|
||||
|
||||
// Note: do not consume the event. We will just focus our vertex, regardless of further
|
||||
// mouse event processing.
|
||||
}
|
||||
}
|
@ -62,3 +62,10 @@ jungrapht.initialDimensionVertexDensity=0.3f
|
||||
|
||||
jungrapht.minScale=0.001
|
||||
jungrapht.maxScale=1.0
|
||||
|
||||
|
||||
11:45 AM
|
||||
|
||||
# not using spatial data structures for edges (fixed in versions after 1.0)
|
||||
jungrapht.edgeSpatialSupport=NONE
|
||||
jungrapht.vertexSpatialSupport=NONE
|
||||
|
@ -13,7 +13,7 @@
|
||||
<BODY lang="EN-US">
|
||||
<H1>Graphing the Program</H1>
|
||||
|
||||
<H3>Graph Output</H3>
|
||||
<H2>Graph Output</H2>
|
||||
|
||||
<P>To display or export a graph, Ghidra supports multiple graph services. Ghidra has two
|
||||
built-in graph services; one to display a graph and one to export a graph. Before invoking
|
||||
@ -21,7 +21,7 @@
|
||||
will direct the output of the graph function to the active graph service. To select a graph
|
||||
service, use the <B>Graph<IMG src="../../shared/arrow.gif">Graph Output</B></LI> menu.
|
||||
|
||||
<H3>Graph types</H3>
|
||||
<H2>Graph types</H2>
|
||||
<P>Program control flow Graphs can be created and then shown using an appropriate graph service.
|
||||
A control flow graph is a representation of the flow from one portion of the code to
|
||||
another. The nodes of the graph represent blocks of code and the edges represent flow between
|
||||
@ -49,7 +49,7 @@
|
||||
<P>Selection and Location events are synchronized between each
|
||||
graph and the other windows in the tool.
|
||||
|
||||
<H3>Selection</H3>
|
||||
<H2>Selection</H2>
|
||||
|
||||
<P>The current selection within the graph display is represented by a red box around selected
|
||||
nodes as shown below on the node labeled "00408133". A node is selected if any addresses it represents are contained within the
|
||||
@ -74,7 +74,7 @@
|
||||
from the basic blocks found within the selected subroutine.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Location</H3>
|
||||
<H2>Location</H2>
|
||||
|
||||
<P>The node containing the current address location is marked with a large red arrow as shown
|
||||
below on the graph node labeled "00408133".</P>
|
||||
@ -95,7 +95,7 @@
|
||||
current address location within Ghidra to change to the minimum address represented by the
|
||||
graph node.</P>
|
||||
|
||||
<H3>Graph Representation</H3>
|
||||
<H2>Graph Representation</H2>
|
||||
|
||||
<P>By Default, the graphs use the following icons and colors to represent the nodes and edges.</P>
|
||||
|
||||
@ -220,99 +220,7 @@
|
||||
</DIV>
|
||||
</CENTER>
|
||||
|
||||
<H2><A name="Graph_Block_Flow"></A>Block Flow Graph</H2>
|
||||
|
||||
<P>A Block Flow Graph consists of nodes that represent Basic blocks of contiguous instructions.
|
||||
Basic blocks are broken up by any instruction that causes a change in execution flow. All Jump,
|
||||
Call, Branch, and Return instructions can cause the execution flow to change. Arithmetic and
|
||||
store/load instructions do not break a Basic block because they do not change the execution
|
||||
flow. A labeled instruction will always start a block regardless of the instruction type.</P>
|
||||
|
||||
<P>For example:</P>
|
||||
|
||||
<P align="center"><IMG src="images/BasicBlockExampleCode.png"></P>
|
||||
|
||||
<P>Would generate the following graph:</P>
|
||||
|
||||
<P align="center"><IMG src="images/BasicBlockGraph.png">
|
||||
</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/note.png"> If there is a current selection, the nodes and edges
|
||||
will be restricted to blocks of code that fall within the selection.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>To Graph Block Flow Using the default model,</P>
|
||||
|
||||
<OL>
|
||||
<LI>Select <B>Graph<IMG src="../../shared/arrow.gif"> Block Flow</B></LI>
|
||||
|
||||
<LI>A new graph window is created</LI>
|
||||
</OL>
|
||||
|
||||
<H2><A name="Graph_Code_Flow"></A>Graph Code Flow</H2>
|
||||
|
||||
<P align="left">A Code Flow Graph is an extension of a <A href="#Graph_Block_Flow">Block Flow
|
||||
Graph</A> in which each graph node (i.e., vertex) contains the list of instructions contained
|
||||
within the associated block. The list of instructions are passed to the graph as the vertex
|
||||
label.</P>
|
||||
|
||||
<P align="center"><BR>
|
||||
<BR>
|
||||
<IMG src="images/CodeBlockGraph.png"></P>
|
||||
|
||||
<H2><A name="Graph_Calls_Using_Default_Model"></A>Graph Calls</H2>
|
||||
|
||||
<P>A graph of the call instruction flow from one subroutine to another can be created with
|
||||
<B>Graph<IMG src="../../shared/arrow.gif"> Calls</B>. The graph is created using the default
|
||||
Call Model. Several Subroutine Models are available. Each model provides a slightly
|
||||
different perspective on what constitutes a subroutine.</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/note.png"> If there is a current selection, the nodes and edges
|
||||
will be restricted to blocks of code that fall within the selection.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>To Graph Calls Using the default model,</P>
|
||||
|
||||
<OL>
|
||||
<LI>Select <B>Graph<IMG src="../../shared/arrow.gif"> Calls</B></LI>
|
||||
|
||||
<LI>A new graph window is created</LI>
|
||||
</OL>
|
||||
|
||||
<P><A name="Graph_Calls_Using_Model"></A>To Graph Calls Using a specific model*,</P>
|
||||
|
||||
<OL>
|
||||
<LI>Select <B>Graph<IMG src="../../shared/arrow.gif"> Calls Using Model<IMG src=
|
||||
"../../shared/arrow.gif"></B> <<I><B>a Call Model</B></I>></LI>
|
||||
|
||||
<LI>
|
||||
Select one of
|
||||
|
||||
<UL>
|
||||
<LI>Isolated Entry Model</LI>
|
||||
|
||||
<LI>Multiple Entry Model</LI>
|
||||
|
||||
<LI>Overlapped Code Model</LI>
|
||||
|
||||
<LI>Partitioned Code Model</LI>
|
||||
</UL>
|
||||
</LI>
|
||||
|
||||
<LI>A new graph window is created</LI>
|
||||
</OL>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/note.png"> *For a more thorough description of each Call Block
|
||||
Model (i.e., Subroutine Model), see <A href="help/topics/BlockModel/Block_Model.htm">Block
|
||||
Models</A>. The specific list of models presented to the user may vary depending upon the
|
||||
set of block models configured into the tool.</P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Reuse_Graph"></A>Reuse Graph</H2>
|
||||
|
||||
<P>When <I>Reuse Graph</I> is turned on, creating any new graphs will re-use the active graph
|
||||
@ -378,6 +286,123 @@
|
||||
|
||||
<P>When Show Location is turned <U><I>off</I></U>, the graph view will not change as the
|
||||
current address location changes.</P>
|
||||
|
||||
|
||||
<BR>
|
||||
<BR>
|
||||
<BR>
|
||||
<BR>
|
||||
<BR>
|
||||
<BR>
|
||||
<BR>
|
||||
<BR>
|
||||
<HR WIDTH="90%">
|
||||
<BR>
|
||||
<BR>
|
||||
|
||||
<H2><A name="Graph_Block_Flow"></A>Block Flow Graph</H2>
|
||||
|
||||
<P>A Block Flow Graph consists of nodes that represent Basic blocks of contiguous instructions.
|
||||
Basic blocks are broken up by any instruction that causes a change in execution flow. All Jump,
|
||||
Call, Branch, and Return instructions can cause the execution flow to change. Arithmetic and
|
||||
store/load instructions do not break a Basic block because they do not change the execution
|
||||
flow. A labeled instruction will always start a block regardless of the instruction type.</P>
|
||||
|
||||
<P>For example:</P>
|
||||
|
||||
<P align="center"><IMG src="images/BasicBlockExampleCode.png"></P>
|
||||
|
||||
<P>Would generate the following graph:</P>
|
||||
|
||||
<P align="center"><IMG src="images/BasicBlockGraph.png">
|
||||
</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/note.png"> If there is a current selection, the nodes and edges
|
||||
will be restricted to blocks of code that fall within the selection.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>To Graph Block Flow Using the default model,</P>
|
||||
|
||||
<OL>
|
||||
<LI>Select <B>Graph<IMG src="../../shared/arrow.gif"> Block Flow</B></LI>
|
||||
|
||||
<LI>A new graph window is created</LI>
|
||||
</OL>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<H3><A NAME="Rename_Vertex"></A>Rename Vertex</H3>
|
||||
<BLOCKQUOTE>
|
||||
<P>Allows the user to rename the symbol represented by the given vertex.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
<H2><A name="Graph_Code_Flow"></A>Graph Code Flow</H2>
|
||||
|
||||
<P align="left">A Code Flow Graph is an extension of a <A href="#Graph_Block_Flow">Block Flow
|
||||
Graph</A> in which each graph node (i.e., vertex) contains the list of instructions contained
|
||||
within the associated block. The list of instructions are passed to the graph as the vertex
|
||||
label.</P>
|
||||
|
||||
<P align="center"><BR>
|
||||
<BR>
|
||||
<IMG src="images/CodeBlockGraph.png"></P>
|
||||
|
||||
<H2><A name="Graph_Calls_Using_Default_Model"></A>Graph Calls</H2>
|
||||
|
||||
<P>A graph of the call instruction flow from one subroutine to another can be created with
|
||||
<B>Graph<IMG src="../../shared/arrow.gif"> Calls</B>. The graph is created using the default
|
||||
Call Model. Several Subroutine Models are available. Each model provides a slightly
|
||||
different perspective on what constitutes a subroutine.</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/note.png"> If there is a current selection, the nodes and edges
|
||||
will be restricted to blocks of code that fall within the selection.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>To Graph Calls Using the default model,</P>
|
||||
|
||||
<OL>
|
||||
<LI>Select <B>Graph<IMG src="../../shared/arrow.gif"> Calls</B></LI>
|
||||
|
||||
<LI>A new graph window is created</LI>
|
||||
</OL>
|
||||
|
||||
<P><A name="Graph_Calls_Using_Model"></A>To Graph Calls Using a specific model*,</P>
|
||||
|
||||
<OL>
|
||||
<LI>Select <B>Graph<IMG src="../../shared/arrow.gif"> Calls Using Model<IMG src=
|
||||
"../../shared/arrow.gif"></B> <<I><B>a Call Model</B></I>></LI>
|
||||
|
||||
<LI>
|
||||
Select one of
|
||||
|
||||
<UL>
|
||||
<LI>Isolated Entry Model</LI>
|
||||
|
||||
<LI>Multiple Entry Model</LI>
|
||||
|
||||
<LI>Overlapped Code Model</LI>
|
||||
|
||||
<LI>Partitioned Code Model</LI>
|
||||
</UL>
|
||||
</LI>
|
||||
|
||||
<LI>A new graph window is created</LI>
|
||||
</OL>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P><IMG src="../../shared/note.png"> *For a more thorough description of each Call Block
|
||||
Model (i.e., Subroutine Model), see <A href="help/topics/BlockModel/Block_Model.htm">Block
|
||||
Models</A>. The specific list of models presented to the user may vary depending upon the
|
||||
set of block models configured into the tool.</P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
<BR>
|
||||
|
@ -26,6 +26,7 @@ import ghidra.program.model.block.*;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.SymbolTable;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@ -47,6 +48,7 @@ public class BlockModelGraphDisplayListener extends AddressBasedGraphDisplayList
|
||||
display.addAction(new ActionBuilder("Rename Vertex", "Block Graph")
|
||||
.popupMenuPath("Rename Vertex")
|
||||
.withContext(VertexGraphActionContext.class)
|
||||
.helpLocation(new HelpLocation("ProgramGraphPlugin", "Rename Vertex"))
|
||||
// only enable action when vertex corresponds to an address
|
||||
.enabledWhen(c -> getAddress(c.getClickedVertex().getId()) != null)
|
||||
.onAction(this::updateVertexName)
|
||||
|
@ -1128,9 +1128,13 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
|
||||
|
||||
private V selectedVertex;
|
||||
|
||||
@SuppressWarnings("deprecation") // deprecated until we fix the checkModifiers() code
|
||||
public VertexClickMousePlugin() {
|
||||
super(InputEvent.BUTTON1_MASK);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1203,6 +1207,5 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
|
||||
public void mouseExited(MouseEvent e) {
|
||||
// stub
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,9 @@ import ghidra.graph.viewer.*;
|
||||
* <li>We clear state on mouseReleased() and mouseExited(), since we will get
|
||||
* at least one of those calls</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
//@formatter:off
|
||||
public abstract class VisualGraphAbstractGraphMousePlugin<V extends VisualVertex,
|
||||
@ -46,13 +49,18 @@ public abstract class VisualGraphAbstractGraphMousePlugin<V extends VisualVertex
|
||||
protected E selectedEdge;
|
||||
|
||||
public VisualGraphAbstractGraphMousePlugin() {
|
||||
this(InputEvent.BUTTON1_MASK);
|
||||
this(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
public VisualGraphAbstractGraphMousePlugin(int selectionModifiers) {
|
||||
super(selectionModifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
protected boolean checkForVertex(MouseEvent e) {
|
||||
if (!checkModifiers(e)) {
|
||||
selectedVertex = null;
|
||||
|
@ -24,7 +24,10 @@ import edu.uci.ics.jung.visualization.control.AnimatedPickingGraphMousePlugin;
|
||||
import ghidra.graph.viewer.*;
|
||||
|
||||
/**
|
||||
* A mouse handler to center a vertex when the header is double-clicked.
|
||||
* A mouse handler to center a vertex when the header is double-clicked
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class VisualGraphAnimatedPickingGraphMousePlugin<V extends VisualVertex, E extends VisualEdge<V>>
|
||||
extends AnimatedPickingGraphMousePlugin<V, E> implements VisualGraphMousePlugin<V, E> {
|
||||
@ -32,7 +35,7 @@ public class VisualGraphAnimatedPickingGraphMousePlugin<V extends VisualVertex,
|
||||
private boolean isHandlingMouseEvents;
|
||||
|
||||
public VisualGraphAnimatedPickingGraphMousePlugin() {
|
||||
super(InputEvent.BUTTON1_MASK);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK);
|
||||
this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,17 @@ public class VisualGraphCursorRestoringGraphMousePlugin<V, E> extends AbstractGr
|
||||
super(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
// don't care
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
installCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR), e);
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ public class VisualGraphEventForwardingGraphMousePlugin<V extends VisualVertex,
|
||||
|
||||
private boolean isHandlingEvent = false;
|
||||
|
||||
// TODO for deprecated usage note, see the VisualGraphMousePlugin interface
|
||||
public VisualGraphEventForwardingGraphMousePlugin() {
|
||||
this(InputEvent.BUTTON1_MASK | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK);
|
||||
this(InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON2_DOWN_MASK |
|
||||
InputEvent.BUTTON3_DOWN_MASK);
|
||||
}
|
||||
|
||||
public VisualGraphEventForwardingGraphMousePlugin(int modifiers) {
|
||||
@ -50,18 +50,18 @@ public class VisualGraphEventForwardingGraphMousePlugin<V extends VisualVertex,
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
int eventModifiers = e.getModifiers();
|
||||
int eventModifiers = e.getModifiersEx();
|
||||
eventModifiers = turnOffControlKey(eventModifiers);
|
||||
return ((eventModifiers & getModifiers()) == eventModifiers);
|
||||
}
|
||||
|
||||
private int turnOffControlKey(int eventModifiers) {
|
||||
return eventModifiers & (~DockingUtils.CONTROL_KEY_MODIFIER_MASK_DEPRECATED);
|
||||
return eventModifiers & (~DockingUtils.CONTROL_KEY_MODIFIER_MASK);
|
||||
}
|
||||
|
||||
private boolean isControlClick(MouseEvent e) {
|
||||
int allModifiers = e.getModifiers();
|
||||
int osSpecificMask = DockingUtils.CONTROL_KEY_MODIFIER_MASK_DEPRECATED;
|
||||
int allModifiers = e.getModifiersEx();
|
||||
int osSpecificMask = DockingUtils.CONTROL_KEY_MODIFIER_MASK;
|
||||
return (allModifiers & osSpecificMask) == osSpecificMask;
|
||||
|
||||
// can't use this until we fix the old modifiers usage
|
||||
|
@ -61,6 +61,11 @@ public class VisualGraphHoverMousePlugin<V extends VisualVertex, E extends Visua
|
||||
this.otherViewer = otherViewer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
lastMouseEvent = e;
|
||||
|
@ -28,7 +28,6 @@ import edu.uci.ics.jung.visualization.transform.MutableTransformer;
|
||||
import ghidra.graph.viewer.*;
|
||||
import ghidra.graph.viewer.renderer.*;
|
||||
|
||||
|
||||
/**
|
||||
* A simple plugin that allows clients to be notified of mouse events before any of the other
|
||||
* mouse plugins.
|
||||
@ -52,14 +51,15 @@ public class VisualGraphMouseTrackingGraphMousePlugin<V extends VisualVertex,
|
||||
private int mouseMovedCount;
|
||||
|
||||
public VisualGraphMouseTrackingGraphMousePlugin(GraphViewer<V, E> viewer) {
|
||||
super(InputEvent.BUTTON1_MASK | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON2_DOWN_MASK |
|
||||
InputEvent.BUTTON3_DOWN_MASK);
|
||||
this.viewer = Objects.requireNonNull(viewer);
|
||||
viewer.addPostRenderPaintable(paintable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
int eventModifiers = e.getModifiers();
|
||||
int eventModifiers = e.getModifiersEx();
|
||||
eventModifiers = turnOffControlKey(eventModifiers);
|
||||
return ((eventModifiers & getModifiers()) == eventModifiers);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -39,18 +38,17 @@ public class VisualGraphPickingGraphMousePlugin<V extends VisualVertex, E extend
|
||||
// ALERT: -this class was created because mouseDragged() has a bug that generates a NPE
|
||||
// -also, mousePressed() has a bug in that it does not check the modifiers when the method is entered
|
||||
|
||||
// TODO for deprecated usage note, see the VisualGraphMousePlugin interface
|
||||
public VisualGraphPickingGraphMousePlugin() {
|
||||
super(InputEvent.BUTTON1_MASK,
|
||||
InputEvent.BUTTON1_MASK | DockingUtils.CONTROL_KEY_MODIFIER_MASK_DEPRECATED);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK,
|
||||
InputEvent.BUTTON1_DOWN_MASK | DockingUtils.CONTROL_KEY_MODIFIER_MASK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
if (e.getModifiers() == addToSelectionModifiers) {
|
||||
if (e.getModifiersEx() == addToSelectionModifiers) {
|
||||
return true;
|
||||
}
|
||||
return super.checkModifiers(e);
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,7 +78,7 @@ public class VisualGraphPickingGraphMousePlugin<V extends VisualVertex, E extend
|
||||
|
||||
private void increaseDragRectangle(MouseEvent e) {
|
||||
Point2D out = e.getPoint();
|
||||
int theModifiers = e.getModifiers();
|
||||
int theModifiers = e.getModifiersEx();
|
||||
if (theModifiers == addToSelectionModifiers || theModifiers == modifiers) {
|
||||
if (down != null) {
|
||||
rect.setFrameFromDiagonal(down, out);
|
||||
|
@ -29,7 +29,7 @@ public abstract class VisualGraphSatelliteAbstractGraphMousePlugin<V extends Vis
|
||||
extends VisualGraphAbstractGraphMousePlugin<V, E> {
|
||||
|
||||
public VisualGraphSatelliteAbstractGraphMousePlugin() {
|
||||
this(InputEvent.BUTTON1_MASK);
|
||||
this(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
public VisualGraphSatelliteAbstractGraphMousePlugin(int selectionModifiers) {
|
||||
|
@ -1,25 +0,0 @@
|
||||
/* ###
|
||||
* 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.graph.viewer.event.mouse;
|
||||
|
||||
import ghidra.graph.viewer.VisualEdge;
|
||||
import ghidra.graph.viewer.VisualVertex;
|
||||
|
||||
public class VisualGraphSatelliteAnimatedPickingGraphMousePlugin<V extends VisualVertex, E extends VisualEdge<V>>
|
||||
extends VisualGraphAnimatedPickingGraphMousePlugin<V, E> {
|
||||
|
||||
// TODO - delete this class--it should not longer be needed
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/* ###
|
||||
* 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.graph.viewer.event.mouse;
|
||||
|
||||
import ghidra.graph.viewer.VisualEdge;
|
||||
import ghidra.graph.viewer.VisualVertex;
|
||||
|
||||
public class VisualGraphSatelliteEdgeSelectionGraphMousePlugin<V extends VisualVertex, E extends VisualEdge<V>>
|
||||
extends VisualGraphEdgeSelectionGraphMousePlugin<V, E> {
|
||||
|
||||
// TODO this class probably can be deleted now
|
||||
}
|
@ -25,7 +25,7 @@ public class VisualGraphSatelliteNavigationGraphMousePlugin<V extends VisualVert
|
||||
extends VisualGraphSatelliteAbstractGraphMousePlugin<V, E> {
|
||||
|
||||
public VisualGraphSatelliteNavigationGraphMousePlugin() {
|
||||
super(InputEvent.BUTTON1_MASK);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,7 @@ public class VisualGraphSatelliteScalingGraphMousePlugin<V extends VisualVertex,
|
||||
VisualGraphOptions options = viewer.getOptions();
|
||||
boolean scrollWheelPans = options.getScrollWheelPans();
|
||||
int scrollWheelModifierToggle = DockingUtils.CONTROL_KEY_MODIFIER_MASK;
|
||||
int eventModifiers = e.getModifiers();
|
||||
int eventModifiers = e.getModifiersEx();
|
||||
if (scrollWheelPans) {
|
||||
// scrolling will zoom if modified (unmodified in this case means to pan)
|
||||
return (scrollWheelModifierToggle & eventModifiers) == scrollWheelModifierToggle;
|
||||
|
@ -35,7 +35,7 @@ public class VisualGraphSatelliteTranslatingGraphMousePlugin<V extends VisualVer
|
||||
|
||||
// Note: for ideas on resizing instead of moving, see LensTranslatingGraphMousePlugin
|
||||
public VisualGraphSatelliteTranslatingGraphMousePlugin() {
|
||||
super(InputEvent.BUTTON1_MASK);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK);
|
||||
this.cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,9 @@ import ghidra.graph.viewer.options.VisualGraphOptions;
|
||||
/**
|
||||
* Overridden implementation that allows us to change scaling behavior through options. This
|
||||
* class works on the opposite modifier setup as FunctionGraphScrollWheelPanningPlugin.
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class VisualGraphScalingGraphMousePlugin<V extends VisualVertex, E extends VisualEdge<V>>
|
||||
extends ScalingGraphMousePlugin implements VisualGraphMousePlugin<V, E> {
|
||||
@ -51,8 +54,8 @@ public class VisualGraphScalingGraphMousePlugin<V extends VisualVertex, E extend
|
||||
// TODO for deprecated usage note, see the VisualGraphMousePlugin interface
|
||||
VisualGraphOptions options = viewer.getOptions();
|
||||
boolean scrollWheelPans = options.getScrollWheelPans();
|
||||
int scrollWheelModifierToggle = DockingUtils.CONTROL_KEY_MODIFIER_MASK_DEPRECATED;
|
||||
int eventModifiers = e.getModifiers();
|
||||
int scrollWheelModifierToggle = DockingUtils.CONTROL_KEY_MODIFIER_MASK;
|
||||
int eventModifiers = e.getModifiersEx();
|
||||
if (scrollWheelPans) {
|
||||
// scrolling will zoom if modified (unmodified in this case means to pan)
|
||||
return (scrollWheelModifierToggle & eventModifiers) == scrollWheelModifierToggle;
|
||||
|
@ -16,8 +16,7 @@
|
||||
package ghidra.graph.viewer.event.mouse;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.event.*;
|
||||
|
||||
import docking.DockingUtils;
|
||||
import edu.uci.ics.jung.visualization.control.AbstractGraphMousePlugin;
|
||||
@ -31,9 +30,14 @@ public class VisualGraphScreenPositioningPlugin<V extends VisualVertex, E extend
|
||||
super(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
int eventModifiers = e.getModifiers();
|
||||
int eventModifiers = e.getModifiersEx();
|
||||
boolean controlKeyDown = (eventModifiers & DockingUtils.CONTROL_KEY_MODIFIER_MASK) != 0;
|
||||
if (!controlKeyDown) {
|
||||
return;
|
||||
|
@ -16,8 +16,7 @@
|
||||
package ghidra.graph.viewer.event.mouse;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.event.*;
|
||||
|
||||
import docking.DockingUtils;
|
||||
import edu.uci.ics.jung.visualization.control.AbstractGraphMousePlugin;
|
||||
@ -35,6 +34,11 @@ public class VisualGraphScrollWheelPanningPlugin<V extends VisualVertex,
|
||||
super(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (!isScrollModifiers(e)) {
|
||||
@ -91,7 +95,7 @@ public class VisualGraphScrollWheelPanningPlugin<V extends VisualVertex,
|
||||
VisualGraphOptions options = viewer.getOptions();
|
||||
boolean scrollWheelPans = options.getScrollWheelPans();
|
||||
int scrollWheelModifierToggle = DockingUtils.CONTROL_KEY_MODIFIER_MASK;
|
||||
int eventModifiers = e.getModifiers();
|
||||
int eventModifiers = e.getModifiersEx();
|
||||
if (scrollWheelPans) {
|
||||
// scrolling will pan if *not* modified (modified in this case means to zoom)
|
||||
return !((scrollWheelModifierToggle & eventModifiers) == scrollWheelModifierToggle);
|
||||
|
@ -33,8 +33,8 @@ import ghidra.graph.viewer.*;
|
||||
* the graph display in the x and y direction. The default MouseButtonOne modifier can be overridden
|
||||
* to cause a different mouse gesture to translate the display.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class VisualGraphTranslatingGraphMousePlugin<V extends VisualVertex, E extends VisualEdge<V>>
|
||||
extends AbstractGraphMousePlugin
|
||||
@ -43,9 +43,8 @@ public class VisualGraphTranslatingGraphMousePlugin<V extends VisualVertex, E ex
|
||||
private boolean panning;
|
||||
private boolean isHandlingEvent;
|
||||
|
||||
// TODO for deprecated usage note, see the VisualGraphMousePlugin interface
|
||||
public VisualGraphTranslatingGraphMousePlugin() {
|
||||
this(InputEvent.BUTTON1_MASK);
|
||||
this(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
public VisualGraphTranslatingGraphMousePlugin(int modifiers) {
|
||||
@ -53,6 +52,11 @@ public class VisualGraphTranslatingGraphMousePlugin<V extends VisualVertex, E ex
|
||||
this.cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkModifiers(MouseEvent e) {
|
||||
return e.getModifiersEx() == modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
GraphViewer<V, E> viewer = getGraphViewer(e);
|
||||
@ -158,7 +162,7 @@ public class VisualGraphTranslatingGraphMousePlugin<V extends VisualVertex, E ex
|
||||
}
|
||||
|
||||
private boolean checkModifiersForCursor(MouseEvent e) {
|
||||
if (e.getModifiers() == 0) {
|
||||
if (e.getModifiersEx() == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -24,13 +24,15 @@ import ghidra.graph.viewer.*;
|
||||
/**
|
||||
* A handler to zoom nodes when double-clicked. If the vertex is zoomed out, then we will zoom
|
||||
* in and center. If the vertex is zoomed to full size, then we will zoom out and center.
|
||||
*
|
||||
* @param <V> the vertex type
|
||||
* @param <E> the edge type
|
||||
*/
|
||||
public class VisualGraphZoomingPickingGraphMousePlugin<V extends VisualVertex, E extends VisualEdge<V>>
|
||||
extends VisualGraphAbstractGraphMousePlugin<V, E> {
|
||||
|
||||
// TODO for deprecated usage note, see the VisualGraphMousePlugin interface
|
||||
public VisualGraphZoomingPickingGraphMousePlugin() {
|
||||
super(InputEvent.BUTTON1_MASK);
|
||||
super(InputEvent.BUTTON1_DOWN_MASK);
|
||||
this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
||||
}
|
||||
|
||||
|
@ -72,10 +72,11 @@ public class GraphServicesScreenShots extends GhidraScreenShotGenerator {
|
||||
AttributedEdge e2 = graph.addEdge(v1, v3);
|
||||
e2.setAttribute("EdgeType", "Unconditional-Call");
|
||||
|
||||
display.setGraph(graph, "test", false, TaskMonitor.DUMMY);
|
||||
display.setGraph(graph, "Program Graph", false, TaskMonitor.DUMMY);
|
||||
waitForSwing();
|
||||
setGraphWindowSize(700, 500);
|
||||
((DefaultGraphDisplay) display).centerAndScale();
|
||||
runSwing(() -> ((DefaultGraphDisplay) display).centerAndScale());
|
||||
waitForSwing();
|
||||
|
||||
captureProvider(DefaultGraphDisplayComponentProvider.class);
|
||||
}
|
||||
@ -95,7 +96,7 @@ public class GraphServicesScreenShots extends GhidraScreenShotGenerator {
|
||||
provider.getComponent().requestFocus();
|
||||
paintFix(window);
|
||||
});
|
||||
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user