mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-769 - Function Graph - added option to not used dimming for return flow edges
This commit is contained in:
parent
f2e702d1b2
commit
e19d59cac7
5 changed files with 103 additions and 62 deletions
|
@ -840,6 +840,22 @@
|
||||||
location when zooming from the middle-mouse. The default for this option is off, which
|
location when zooming from the middle-mouse. The default for this option is off, which
|
||||||
triggers zoom to work from the center of the graph, regardless of the mouse location.</P>
|
triggers zoom to work from the center of the graph, regardless of the mouse location.</P>
|
||||||
|
|
||||||
|
<P>The <B>View Settings</B> option describes how the graph will be zoomed when it is first
|
||||||
|
loaded. The values are:</P>
|
||||||
|
|
||||||
|
<UL>
|
||||||
|
<LI><B>Start Fully Zoomed Out</B> - always start fully zoomed out so that the entire
|
||||||
|
graph can be seen.</LI>
|
||||||
|
|
||||||
|
<LI><B>Start Fully Zoomed In/B> - always start fully zoomed in on the vertex containing
|
||||||
|
the current location.</LI>
|
||||||
|
|
||||||
|
<LI><B>Remember User Settings</B> - keep the zoom level where the user previously left
|
||||||
|
it.</LI>
|
||||||
|
</UL>
|
||||||
|
<BR>
|
||||||
|
<BR>
|
||||||
|
|
||||||
<P>There are various edge color and highlight color options available to change. The
|
<P>There are various edge color and highlight color options available to change. The
|
||||||
highlight colors are those to be used when the flow animations take place.</P>
|
highlight colors are those to be used when the flow animations take place.</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
|
@ -49,6 +49,13 @@
|
||||||
notes on how edges are routed for this layout.)
|
notes on how edges are routed for this layout.)
|
||||||
</P>
|
</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>The <B>Use Dim Return Edges</B> option makes default code block return flow edges
|
||||||
|
lighter than conditional edges. This makes it easier for users to scan the
|
||||||
|
graph and ignore return flows.
|
||||||
|
</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class FunctionGraphOptions extends VisualGraphOptions {
|
||||||
private static final String EDGE_COLOR_CONDITIONAL_JUMP_KEY = "Edge Color - Conditional Jump ";
|
private static final String EDGE_COLOR_CONDITIONAL_JUMP_KEY = "Edge Color - Conditional Jump ";
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
private static final String NAVIGATION_HISTORY_KEY = "Navigation History";
|
private static final String NAVIGATION_HISTORY_KEY = "Navigation History";
|
||||||
private static final String NAVIGATION_HISTORY_DESCRIPTION =
|
private static final String NAVIGATION_HISTORY_DESCRIPTION =
|
||||||
"Determines how the navigation history will be updated when using the Function Graph. " +
|
"Determines how the navigation history will be updated when using the Function Graph. " +
|
||||||
"The basic options are:" +
|
"The basic options are:" +
|
||||||
|
@ -185,8 +185,8 @@ public class FunctionGraphOptions extends VisualGraphOptions {
|
||||||
options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help,
|
options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help,
|
||||||
SCROLL_WHEEL_PANS_DESCRIPTION);
|
SCROLL_WHEEL_PANS_DESCRIPTION);
|
||||||
|
|
||||||
options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR,
|
options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, help,
|
||||||
help, GRAPH_BACKGROUND_COLOR_DESCRPTION);
|
GRAPH_BACKGROUND_COLOR_DESCRPTION);
|
||||||
|
|
||||||
options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR,
|
options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR,
|
||||||
help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION);
|
help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION);
|
||||||
|
|
|
@ -31,7 +31,12 @@ public class DNLayoutOptions implements FGLayoutOptions {
|
||||||
"edges should be routed around any intersecting vertex. When toggled off, edges will " +
|
"edges should be routed around any intersecting vertex. When toggled off, edges will " +
|
||||||
"pass through any intersecting vertices.";
|
"pass through any intersecting vertices.";
|
||||||
|
|
||||||
|
private static final String DIM_RETURN_EDGES_KEY = "Use Dim Return Edges";
|
||||||
|
private static final String DIM_RETURN_EDGES_DESCRIPTION =
|
||||||
|
"Signals to lighten the default return edges.";
|
||||||
|
|
||||||
private boolean useEdgeRoutingAroundVertices;
|
private boolean useEdgeRoutingAroundVertices;
|
||||||
|
private boolean useDimmedReturnEdges = true;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerOptions(Options options) {
|
public void registerOptions(Options options) {
|
||||||
|
@ -40,21 +45,32 @@ public class DNLayoutOptions implements FGLayoutOptions {
|
||||||
|
|
||||||
options.registerOption(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices,
|
options.registerOption(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices,
|
||||||
help, USE_EDGE_ROUTING_AROUND_VERTICES_DESCRIPTION);
|
help, USE_EDGE_ROUTING_AROUND_VERTICES_DESCRIPTION);
|
||||||
|
|
||||||
|
options.registerOption(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges, help,
|
||||||
|
DIM_RETURN_EDGES_DESCRIPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadOptions(Options options) {
|
public void loadOptions(Options options) {
|
||||||
useEdgeRoutingAroundVertices =
|
useEdgeRoutingAroundVertices =
|
||||||
options.getBoolean(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices);
|
options.getBoolean(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices);
|
||||||
|
|
||||||
|
useDimmedReturnEdges = options.getBoolean(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean useEdgeRoutingAroundVertices() {
|
public boolean useEdgeRoutingAroundVertices() {
|
||||||
return useEdgeRoutingAroundVertices;
|
return useEdgeRoutingAroundVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean useDimmedReturnEdges() {
|
||||||
|
return useDimmedReturnEdges;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean optionChangeRequiresRelayout(String optionName) {
|
public boolean optionChangeRequiresRelayout(String optionName) {
|
||||||
// format: 'Nested Code Layout.Route Edges....'
|
// format: 'Nested Code Layout.Route Edges....'
|
||||||
return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY);
|
return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY) ||
|
||||||
|
optionName.endsWith(DIM_RETURN_EDGES_KEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,19 +52,19 @@ import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A layout that uses the decompiler to show code nesting based upon conditional logic.
|
* A layout that uses the decompiler to show code nesting based upon conditional logic.
|
||||||
*
|
*
|
||||||
* <p>Edges returning to the default code flow are painted lighter to de-emphasize them. This
|
* <p>Edges returning to the default code flow are painted lighter to de-emphasize them. This
|
||||||
* could be made into an option.
|
* could be made into an option.
|
||||||
*
|
*
|
||||||
* <p>Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option.
|
* <p>Edge routing herein defaults to 'simple routing'; 'complex routing' is a user option.
|
||||||
* Simple routing will reduce edge noise as much as possible by combining/overlapping edges that
|
* Simple routing will reduce edge noise as much as possible by combining/overlapping edges that
|
||||||
* flow towards the bottom of the function (returning code flow). Also, edges may fall behind
|
* flow towards the bottom of the function (returning code flow). Also, edges may fall behind
|
||||||
* vertices for some functions. Complex routing allows the user to visually follow the flow
|
* vertices for some functions. Complex routing allows the user to visually follow the flow
|
||||||
* of an individual edge. Complex routing will prevent edges from overlapping and will route
|
* of an individual edge. Complex routing will prevent edges from overlapping and will route
|
||||||
* edges around vertices. Simple routing is better when the layout of the vertices is
|
* edges around vertices. Simple routing is better when the layout of the vertices is
|
||||||
* important to the user; complex routing is better when edges/relationships are more
|
* important to the user; complex routing is better when edges/relationships are more
|
||||||
* important to the user.
|
* important to the user.
|
||||||
*
|
*
|
||||||
* TODO ideas:
|
* TODO ideas:
|
||||||
* -paint fallthrough differently for all, or just for those returning to the baseline
|
* -paint fallthrough differently for all, or just for those returning to the baseline
|
||||||
*/
|
*/
|
||||||
|
@ -113,7 +113,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected double getCondenseFactor() {
|
protected double getCondenseFactor() {
|
||||||
// our layout needs more spacing because we have custom edge routing that we want to
|
// our layout needs more spacing because we have custom edge routing that we want to
|
||||||
// stand out
|
// stand out
|
||||||
return .3;
|
return .3;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Special case: fallthrough--don't label this...not sure how to tell fallthrough. For
|
// Special case: fallthrough--don't label this...not sure how to tell fallthrough. For
|
||||||
// now assume that any column below or backwards is fallthrough. However,
|
// now assume that any column below or backwards is fallthrough. However,
|
||||||
// do label fallthrough if it is the only edge.
|
// do label fallthrough if it is the only edge.
|
||||||
|
@ -231,10 +231,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
Map<FGEdge, List<Point2D>> newEdgeArticulations = new HashMap<>();
|
Map<FGEdge, List<Point2D>> newEdgeArticulations = new HashMap<>();
|
||||||
|
|
||||||
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
||||||
// vertices and edges towards the center of the graph after we calculate positions.
|
// vertices and edges towards the center of the graph after we calculate positions.
|
||||||
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
||||||
// bit for that effect using this offset value. The getEdgeOffset() method below is
|
// bit for that effect using this offset value. The getEdgeOffset() method below is
|
||||||
// updated for the condense factor.
|
// updated for the condense factor.
|
||||||
int edgeOffset = isCondensedLayout()
|
int edgeOffset = isCondensedLayout()
|
||||||
? (int) (VERTEX_TO_EDGE_ARTICULATION_PADDING * (1 - getCondenseFactor()))
|
? (int) (VERTEX_TO_EDGE_ARTICULATION_PADDING * (1 - getCondenseFactor()))
|
||||||
|
@ -242,7 +242,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
Vertex2dFactory vertex2dFactory =
|
Vertex2dFactory vertex2dFactory =
|
||||||
new Vertex2dFactory(transformer, vertexLayoutLocations, layoutToGridMap, edgeOffset);
|
new Vertex2dFactory(transformer, vertexLayoutLocations, layoutToGridMap, edgeOffset);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Route our edges!
|
// Route our edges!
|
||||||
//
|
//
|
||||||
for (FGEdge e : edges) {
|
for (FGEdge e : edges) {
|
||||||
|
@ -275,31 +275,31 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
List<Point2D> articulations = new ArrayList<>();
|
List<Point2D> articulations = new ArrayList<>();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Basic routing:
|
// Basic routing:
|
||||||
// -leave the bottom of the start vertex
|
// -leave the bottom of the start vertex
|
||||||
// -first bend at some constant offset
|
// -first bend at some constant offset
|
||||||
// -move to right or left, to above the end vertex
|
// -move to right or left, to above the end vertex
|
||||||
// -second bend above the end vertex at previous constant offset
|
// -second bend above the end vertex at previous constant offset
|
||||||
//
|
//
|
||||||
// Edges start/end on the vertex center. If we offset them to avoid
|
// Edges start/end on the vertex center. If we offset them to avoid
|
||||||
// overlapping, then they produce angles when only using two articulations.
|
// overlapping, then they produce angles when only using two articulations.
|
||||||
// Thus, we create articulations that are behind the vertices to remove
|
// Thus, we create articulations that are behind the vertices to remove
|
||||||
// the angles. This points will not be seen.
|
// the angles. This points will not be seen.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Complex routing:
|
// Complex routing:
|
||||||
// -this mode will route edges around vertices
|
// -this mode will route edges around vertices
|
||||||
//
|
//
|
||||||
// One goal for complex edge routing is to prevent overlapping (simple edge routing
|
// One goal for complex edge routing is to prevent overlapping (simple edge routing
|
||||||
// prefers overlapping to reduce lines). To prevent overlapping we will use different
|
// prefers overlapping to reduce lines). To prevent overlapping we will use different
|
||||||
// offset x and y values, depending upon the start and end vertex row and column
|
// offset x and y values, depending upon the start and end vertex row and column
|
||||||
// locations. Specifically, for a given edge direction there will be a bias:
|
// locations. Specifically, for a given edge direction there will be a bias:
|
||||||
// -Edge to the right - leave from the right; arrive to the left
|
// -Edge to the right - leave from the right; arrive to the left
|
||||||
// -Edge to the left - leave from the left; arrive to the right
|
// -Edge to the left - leave from the left; arrive to the right
|
||||||
// -Edge straight down - go straight down
|
// -Edge straight down - go straight down
|
||||||
//
|
//
|
||||||
// For each of the above offsets, there will be an amplifier based upon row/column
|
// For each of the above offsets, there will be an amplifier based upon row/column
|
||||||
// distance from start to end vertex. This has the effect that larger vertex
|
// distance from start to end vertex. This has the effect that larger vertex
|
||||||
// distances will have a larger offset/spacing.
|
// distances will have a larger offset/spacing.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -335,10 +335,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
Vertex2dFactory vertex2dFactory, List<Point2D> articulations) {
|
Vertex2dFactory vertex2dFactory, List<Point2D> articulations) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// For routing to the right and back up we will leave the start vertex from the right side
|
// For routing to the right and back up we will leave the start vertex from the right side
|
||||||
// and enter the end vertex on the right side. As the vertices get further apart, we will
|
// and enter the end vertex on the right side. As the vertices get further apart, we will
|
||||||
// space them further in towards the center.
|
// space them further in towards the center.
|
||||||
//
|
//
|
||||||
|
|
||||||
int delta = start.rowIndex - end.rowIndex;
|
int delta = start.rowIndex - end.rowIndex;
|
||||||
int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER;
|
int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER;
|
||||||
|
@ -347,10 +347,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
}
|
}
|
||||||
int distanceSpacing = delta * multiplier;
|
int distanceSpacing = delta * multiplier;
|
||||||
|
|
||||||
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
||||||
// vertices and edges towards the center of the graph after we calculate positions.
|
// vertices and edges towards the center of the graph after we calculate positions.
|
||||||
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
||||||
// bit for that effect using this offset value. The getEdgeOffset() method is
|
// bit for that effect using this offset value. The getEdgeOffset() method is
|
||||||
// updated for the condense factor.
|
// updated for the condense factor.
|
||||||
int exaggerationFactor = 1;
|
int exaggerationFactor = 1;
|
||||||
if (isCondensedLayout()) {
|
if (isCondensedLayout()) {
|
||||||
|
@ -369,7 +369,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
y1 = Math.min(y1, startCenterY);
|
y1 = Math.min(y1, startCenterY);
|
||||||
articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex
|
articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex
|
||||||
|
|
||||||
// Use the spacing to move the y value towards the top of the vertex. Just like with
|
// Use the spacing to move the y value towards the top of the vertex. Just like with
|
||||||
// the x value, restrict the y to the range between the edge and the center.
|
// the x value, restrict the y to the range between the edge and the center.
|
||||||
double startRightX = start.getRight();
|
double startRightX = start.getRight();
|
||||||
double x2 = startRightX + VERTEX_BORDER_THICKNESS; // start at the end
|
double x2 = startRightX + VERTEX_BORDER_THICKNESS; // start at the end
|
||||||
|
@ -434,10 +434,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
//
|
//
|
||||||
// For routing to the left we will leave the start vertex from just left of center and
|
// For routing to the left we will leave the start vertex from just left of center and
|
||||||
// enter the end vertex on the top, towards the right. As the vertices get further apart,
|
// enter the end vertex on the top, towards the right. As the vertices get further apart,
|
||||||
// we will space them further in towards the center of the end vertex. This will keep
|
// we will space them further in towards the center of the end vertex. This will keep
|
||||||
// edges with close endpoints from intersecting edges with distant endpoints.
|
// edges with close endpoints from intersecting edges with distant endpoints.
|
||||||
//
|
//
|
||||||
|
|
||||||
int delta = end.rowIndex - start.rowIndex;
|
int delta = end.rowIndex - start.rowIndex;
|
||||||
int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER;
|
int multiplier = EDGE_ENDPOINT_DISTANCE_MULTIPLIER;
|
||||||
|
@ -499,7 +499,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
// enter the end vertex on the left side. As the vertices get further apart, we will
|
// enter the end vertex on the left side. As the vertices get further apart, we will
|
||||||
// space them further in towards the center. This will keep edges with close endpoints
|
// space them further in towards the center. This will keep edges with close endpoints
|
||||||
// from intersecting edges with distant endpoints.
|
// from intersecting edges with distant endpoints.
|
||||||
//
|
//
|
||||||
|
|
||||||
int delta = end.rowIndex - start.rowIndex;
|
int delta = end.rowIndex - start.rowIndex;
|
||||||
if (delta < 0) {
|
if (delta < 0) {
|
||||||
|
@ -529,7 +529,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
double y1 = start.getY();
|
double y1 = start.getY();
|
||||||
articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex
|
articulations.add(new Point2D.Double(x1, y1)); // point is hidden behind the vertex
|
||||||
|
|
||||||
// Use the spacing to move the y value towards the top of the vertex. Just like with
|
// Use the spacing to move the y value towards the top of the vertex. Just like with
|
||||||
// the x value, restrict the y to the range between the edge and the center.
|
// the x value, restrict the y to the range between the edge and the center.
|
||||||
double x2 = x1;
|
double x2 = x1;
|
||||||
double y2 = end.getTop() + VERTEX_BORDER_THICKNESS;
|
double y2 = end.getTop() + VERTEX_BORDER_THICKNESS;
|
||||||
|
@ -605,10 +605,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
int padding = VERTEX_TO_EDGE_AVOIDANCE_PADDING;
|
int padding = VERTEX_TO_EDGE_AVOIDANCE_PADDING;
|
||||||
int distanceSpacing = padding + delta; // adding the delta makes overlap less likely
|
int distanceSpacing = padding + delta; // adding the delta makes overlap less likely
|
||||||
|
|
||||||
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
||||||
// vertices and edges towards the center of the graph after we calculate positions.
|
// vertices and edges towards the center of the graph after we calculate positions.
|
||||||
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
||||||
// bit for that effect using this offset value. The getEdgeOffset() method is
|
// bit for that effect using this offset value. The getEdgeOffset() method is
|
||||||
// updated for the condense factor.
|
// updated for the condense factor.
|
||||||
int vertexToEdgeOffset = otherVertex.getEdgeOffset();
|
int vertexToEdgeOffset = otherVertex.getEdgeOffset();
|
||||||
int exaggerationFactor = 1;
|
int exaggerationFactor = 1;
|
||||||
|
@ -629,20 +629,20 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
// no need to check the 'y' value, as the end vertex is above/below this one
|
// no need to check the 'y' value, as the end vertex is above/below this one
|
||||||
if (vertexClipper.isClippingX(otherVertex, edgeX)) {
|
if (vertexClipper.isClippingX(otherVertex, edgeX)) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Must route around this vertex - new points:
|
Must route around this vertex - new points:
|
||||||
-p1 - just above the intersection point
|
-p1 - just above the intersection point
|
||||||
-p2 - just past the left edge
|
-p2 - just past the left edge
|
||||||
-p3 - just past the bottom of the vertex
|
-p3 - just past the bottom of the vertex
|
||||||
-p4 - back at the original x value
|
-p4 - back at the original x value
|
||||||
|
|
||||||
|
|
|
|
||||||
.___|
|
.___|
|
||||||
| .-----.
|
| .-----.
|
||||||
| | |
|
| | |
|
||||||
| '-----'
|
| '-----'
|
||||||
'---.
|
'---.
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// p1 - same x; y just above vertex
|
// p1 - same x; y just above vertex
|
||||||
|
@ -650,19 +650,19 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
double y = vertexClipper.getTopOffset(otherVertex, vertexToEdgeOffset);
|
double y = vertexClipper.getTopOffset(otherVertex, vertexToEdgeOffset);
|
||||||
articulations.add(new Point2D.Double(x, y));
|
articulations.add(new Point2D.Double(x, y));
|
||||||
|
|
||||||
// Maybe merge points if they are too close together. Visually, many lines
|
// Maybe merge points if they are too close together. Visually, many lines
|
||||||
// moving around intersecting vertices looks busy. When the intersecting
|
// moving around intersecting vertices looks busy. When the intersecting
|
||||||
// vertices are close together, we remove some of the articulations in order to
|
// vertices are close together, we remove some of the articulations in order to
|
||||||
// smooth out the edges.
|
// smooth out the edges.
|
||||||
if (articulations.size() > 2) {
|
if (articulations.size() > 2) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The last articulation is the one added before this method was called, which
|
The last articulation is the one added before this method was called, which
|
||||||
lies just below the intersecting vertex. The articulation before that is
|
lies just below the intersecting vertex. The articulation before that is
|
||||||
the one that is the one that is sending the x value straight into the
|
the one that is the one that is sending the x value straight into the
|
||||||
intersecting vertex. Delete that point as well so that the entire edge is
|
intersecting vertex. Delete that point as well so that the entire edge is
|
||||||
shifted to the outside of the intersecting vertex. This will get repeated
|
shifted to the outside of the intersecting vertex. This will get repeated
|
||||||
for each vertex that is intersecting.
|
for each vertex that is intersecting.
|
||||||
*/
|
*/
|
||||||
Point2D previousArticulation = articulations.get(articulations.size() - 2);
|
Point2D previousArticulation = articulations.get(articulations.size() - 2);
|
||||||
int closenessHeight = 50;
|
int closenessHeight = 50;
|
||||||
|
@ -720,7 +720,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
Point2D first = new Point2D.Double(x, y1);
|
Point2D first = new Point2D.Double(x, y1);
|
||||||
articulations.add(first);
|
articulations.add(first);
|
||||||
|
|
||||||
// loop second point - same y coord as destination;
|
// loop second point - same y coord as destination;
|
||||||
// x is the col after the outermost dominated vertex
|
// x is the col after the outermost dominated vertex
|
||||||
|
|
||||||
Point2D endVertexPoint = end.center;
|
Point2D endVertexPoint = end.center;
|
||||||
|
@ -733,6 +733,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
private void lighten(FGEdge e) {
|
private void lighten(FGEdge e) {
|
||||||
|
|
||||||
|
if (!getLayoutOptions().useDimmedReturnEdges()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// assumption: edges that move to the left in this layout are return flows that happen
|
// assumption: edges that move to the left in this layout are return flows that happen
|
||||||
// after the code block has been executed. We dim those a bit so that they
|
// after the code block has been executed. We dim those a bit so that they
|
||||||
// produce less clutter.
|
// produce less clutter.
|
||||||
|
@ -840,8 +844,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
BlockCopy copy = (BlockCopy) child;
|
BlockCopy copy = (BlockCopy) child;
|
||||||
|
|
||||||
StringBuilder buffy = new StringBuilder();
|
StringBuilder buffy = new StringBuilder();
|
||||||
buffy.append(printDepth(depth, depth + 1)).append(' ').append(ID).append(
|
buffy.append(printDepth(depth, depth + 1))
|
||||||
" plain - ").append(copy.getRef());
|
.append(' ')
|
||||||
|
.append(ID)
|
||||||
|
.append(" plain - ")
|
||||||
|
.append(copy.getRef());
|
||||||
|
|
||||||
debug(buffy.toString());
|
debug(buffy.toString());
|
||||||
}
|
}
|
||||||
|
@ -958,7 +965,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates knowledge of edge direction (up/down, left/right) and uses that knowledge
|
* Encapsulates knowledge of edge direction (up/down, left/right) and uses that knowledge
|
||||||
|
@ -1060,7 +1067,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that represents 2D information about the contained vertex, such as location,
|
* A class that represents 2D information about the contained vertex, such as location,
|
||||||
* bounds, row and column of the layout grid.
|
* bounds, row and column of the layout grid.
|
||||||
*/
|
*/
|
||||||
private class Vertex2d {
|
private class Vertex2d {
|
||||||
|
@ -1207,8 +1214,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
int row = startRow;
|
int row = startRow;
|
||||||
|
|
||||||
for (int i = 0; i < allChildren.size(); i++) {
|
for (DecompilerBlock block : allChildren) {
|
||||||
DecompilerBlock block = allChildren.get(i);
|
|
||||||
if (block instanceof DecompilerBlockGraph) {
|
if (block instanceof DecompilerBlockGraph) {
|
||||||
row = ((DecompilerBlockGraph) block).setRows(row);
|
row = ((DecompilerBlockGraph) block).setRows(row);
|
||||||
}
|
}
|
||||||
|
@ -1229,8 +1235,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
String getChildrenString(int depth) {
|
String getChildrenString(int depth) {
|
||||||
StringBuilder buffy = new StringBuilder();
|
StringBuilder buffy = new StringBuilder();
|
||||||
int childCount = 0;
|
int childCount = 0;
|
||||||
for (int i = 0; i < allChildren.size(); i++) {
|
for (DecompilerBlock block : allChildren) {
|
||||||
DecompilerBlock block = allChildren.get(i);
|
|
||||||
if (block instanceof DecompilerBlockGraph) {
|
if (block instanceof DecompilerBlockGraph) {
|
||||||
|
|
||||||
String blockName = block.getName();
|
String blockName = block.getName();
|
||||||
|
@ -1315,8 +1320,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
@Override
|
@Override
|
||||||
DecompilerBlock getBlock(FGVertex vertex) {
|
DecompilerBlock getBlock(FGVertex vertex) {
|
||||||
//
|
//
|
||||||
// Note: we currently allow grouping in this layout. When we search for a vertex,
|
// Note: we currently allow grouping in this layout. When we search for a vertex,
|
||||||
// we have to check each vertex inside of the given group *and* each vertex
|
// we have to check each vertex inside of the given group *and* each vertex
|
||||||
// inside of the vertex that belongs to this decompiler block.
|
// inside of the vertex that belongs to this decompiler block.
|
||||||
//
|
//
|
||||||
if (vertex instanceof GroupedFunctionGraphVertex) {
|
if (vertex instanceof GroupedFunctionGraphVertex) {
|
||||||
|
@ -1447,9 +1452,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
// The 'list' structure for children's nesting:
|
// The 'list' structure for children's nesting:
|
||||||
// -all nodes are at the same level
|
// -all nodes are at the same level
|
||||||
//
|
//
|
||||||
for (int i = 0; i < allChildren.size(); i++) {
|
for (DecompilerBlock block : allChildren) {
|
||||||
int column = col;
|
int column = col;
|
||||||
DecompilerBlock block = allChildren.get(i);
|
|
||||||
block.setCol(column);
|
block.setCol(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1477,8 +1481,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
// -each successive condition is another level nested
|
// -each successive condition is another level nested
|
||||||
//
|
//
|
||||||
int column = col;
|
int column = col;
|
||||||
for (int i = 0; i < allChildren.size(); i++) {
|
for (DecompilerBlock block : allChildren) {
|
||||||
DecompilerBlock block = allChildren.get(i);
|
|
||||||
block.setCol(column);
|
block.setCol(column);
|
||||||
column++;
|
column++;
|
||||||
}
|
}
|
||||||
|
@ -1515,11 +1518,10 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
||||||
|
|
||||||
//
|
//
|
||||||
// The 'do' structure for children's nesting:
|
// The 'do' structure for children's nesting:
|
||||||
// -all blocks nested
|
// -all blocks nested
|
||||||
//
|
//
|
||||||
int column = col + 1;
|
int column = col + 1;
|
||||||
for (int i = 0; i < allChildren.size(); i++) {
|
for (DecompilerBlock block : allChildren) {
|
||||||
DecompilerBlock block = allChildren.get(i);
|
|
||||||
block.setCol(column);
|
block.setCol(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue