GP-757 - Function Graph - added options to set background color for

graph view and for the vertices

Closes #1324
This commit is contained in:
dragonmacher 2021-03-08 18:15:27 -05:00
parent c905c203f0
commit 9e785c25ec
18 changed files with 150 additions and 30 deletions

View file

@ -578,6 +578,10 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
}
}
public void optionsChanged() {
controller.optionsChanged();
}
@Override
public void domainObjectChanged(DomainObjectChangedEvent ev) {
if (!isVisible()) {

View file

@ -172,6 +172,8 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
functionGraphOptions.loadOptions(options);
connectedProvider.optionsChanged();
if (functionGraphOptions.optionChangeRequiresRelayout(optionName)) {
connectedProvider.refreshAndKeepPerspective();
}

View file

@ -36,6 +36,7 @@ import ghidra.graph.viewer.*;
import ghidra.graph.viewer.layout.LayoutListener.ChangeType;
import ghidra.graph.viewer.layout.LayoutProvider;
import ghidra.graph.viewer.layout.VisualGraphLayout;
import ghidra.graph.viewer.options.VisualGraphOptions;
import ghidra.graph.viewer.renderer.VisualGraphEdgeLabelRenderer;
import ghidra.program.model.listing.Function;
import ghidra.program.util.ProgramLocation;
@ -65,6 +66,8 @@ public class FGComponent extends GraphComponent<FGVertex, FGEdge, FunctionGraph>
// the base class builds.
// super(data.getFunctionGraph());
setGraphOptions(functionGraphView.getController().getFunctionGraphOptions());
setGraph(data.getFunctionGraph());
this.functionGraphView = functionGraphView;
@ -217,7 +220,12 @@ public class FGComponent extends GraphComponent<FGVertex, FGEdge, FunctionGraph>
edgeLabelRenderer.setRotateEdgeLabels(false);
renderContext.setEdgeLabelRenderer(edgeLabelRenderer);
// Give user notice when seeing the graph for a non-function.
viewer.setGraphOptions(options);
Color bgColor = options.getGraphBackgroundColor();
if (bgColor.equals(VisualGraphOptions.DEFAULT_GRAPH_BACKGROUND_COLOR)) {
// Give user notice when seeing the graph for a non-function. Don't do this if the
// user has manually set the background color (this would require another option).
Function function = functionGraphData.getFunction();
if (function instanceof UndefinedFunction) {
viewer.setBackground(UNDEFINED_FUNCTION_COLOR);
@ -225,6 +233,7 @@ public class FGComponent extends GraphComponent<FGVertex, FGEdge, FunctionGraph>
else {
viewer.setBackground(Color.WHITE);
}
}
return viewer;
}
@ -248,6 +257,8 @@ public class FGComponent extends GraphComponent<FGVertex, FGEdge, FunctionGraph>
renderContext.setVertexFillPaintTransformer(new FGVertexPickableBackgroundPaintTransformer(
pickedVertexState, Color.YELLOW, START_COLOR, END_COLOR));
viewer.setGraphOptions(options);
return viewer;
}
@ -274,7 +285,7 @@ public class FGComponent extends GraphComponent<FGVertex, FGEdge, FunctionGraph>
//==================================================================================================
public FunctionGraphOptions getFucntionGraphOptions() {
return functionGraphView.getController().getFunctionGraphOptions();
return (FunctionGraphOptions) options;
}
public void ensureCursorVisible(FGVertex vertex) {

View file

@ -33,7 +33,6 @@ public class FGPrimaryViewer extends GraphViewer<FGVertex, FGEdge> {
super(layout, size);
setVertexTooltipProvider(new FGVertexTooltipProvider());
setGraphOptions(graphComponent.getFucntionGraphOptions());
}
@Override

View file

@ -140,9 +140,6 @@ public abstract class AbstractGraphComponentPanel extends JPanel {
}
Component header = getHeader();
if (clickedComponent == null) {
return false;
}
return SwingUtilities.isDescendingFrom(clickedComponent, header);
}

View file

@ -98,7 +98,7 @@ public interface FGVertex extends VisualVertex {
* grouped, but that it has been part of a group and can be put back into its group form
* again.
*
* @param groupMember True if this vertex is a associate with a group
* @param groupInfo True if this vertex is a associate with a group
*/
public void updateGroupAssociationStatus(GroupHistoryInfo groupInfo);
@ -190,8 +190,8 @@ public interface FGVertex extends VisualVertex {
public void refreshDisplay();
/**
* Refresh the vertex's display information if the given address is the entry point
* of the vertex.
* Refresh the vertex's display information if the given address is the vertex entry point
* @param address the addresses
*/
public void refreshDisplayForAddress(Address address);

View file

@ -15,6 +15,7 @@
*/
package ghidra.app.plugin.core.functiongraph.graph.vertex;
import java.awt.Color;
import java.awt.Dimension;
import java.math.BigInteger;
import java.util.ArrayList;
@ -23,6 +24,7 @@ import java.util.List;
import docking.widgets.fieldpanel.*;
import ghidra.app.plugin.core.functiongraph.FGColorProvider;
import ghidra.app.plugin.core.functiongraph.mvc.FGController;
import ghidra.app.plugin.core.functiongraph.mvc.FunctionGraphOptions;
import ghidra.app.util.viewer.format.FormatManager;
import ghidra.app.util.viewer.listingpanel.*;
import ghidra.program.model.address.AddressSetView;
@ -66,6 +68,10 @@ public class FGVertexListingPanel extends ListingPanel {
ListingModel model = getListingModel();
model.addListener(listener);
FunctionGraphOptions options = controller.getFunctionGraphOptions();
Color color = options.getDefaultVertexBackgroundColor();
setTextBackgroundColor(color);
FGColorProvider colorProvider = controller.getColorProvider();
if (!colorProvider.isUsingCustomColors()) {
enablePropertyBasedColorModel(true); // turn on user colors in the graph

View file

@ -382,6 +382,7 @@ public class GroupedFunctionGraphComponentPanel extends AbstractGraphComponentPa
}
private void doSetBackgroundColor(Color color) {
setBackground(color);
contentPanel.setBackground(color);
userTextArea.setBackground(color);
controller.removeColor(vertex);
@ -561,12 +562,26 @@ public class GroupedFunctionGraphComponentPanel extends AbstractGraphComponentPa
@Override
void refreshDisplay() {
updateDefaultBackgroundColor();
Set<FGVertex> vertices = groupVertex.getVertices();
for (FGVertex v : vertices) {
v.refreshDisplay();
}
}
private void updateDefaultBackgroundColor() {
FunctionGraphOptions options = controller.getFunctionGraphOptions();
Color newBgColor = options.getDefaultGroupBackgroundColor();
if (!defaultBackgroundColor.equals(newBgColor)) {
defaultBackgroundColor = newBgColor;
if (userDefinedColor == null) {
doSetBackgroundColor(defaultBackgroundColor);
}
}
}
@Override
void refreshDisplayForAddress(Address address) {
Set<FGVertex> vertices = groupVertex.getVertices();

View file

@ -251,6 +251,19 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
title = createTitle();
genericHeader.setTitle(title);
previewListingPanel = null;
updateDefaultBackgroundColor();
}
private void updateDefaultBackgroundColor() {
FunctionGraphOptions options = controller.getFunctionGraphOptions();
Color newBgColor = options.getDefaultVertexBackgroundColor();
if (!defaultBackgroundColor.equals(newBgColor)) {
defaultBackgroundColor = newBgColor;
if (userDefinedColor == null) {
listingPanel.setTextBackgroundColor(defaultBackgroundColor);
}
}
}
@Override
@ -522,7 +535,8 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
tooltipTitleLabel.setText("From: " + getTitle());
}
previewListingPanel.getFieldPanel().setBackgroundColorModel(
previewListingPanel.getFieldPanel()
.setBackgroundColorModel(
new HighlightingColorModel(address, getColorForEdge(edge)));
}

View file

@ -332,7 +332,8 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
}
private boolean shouldSaveVertexChanges() {
return functionGraphOptions.getNavigationHistoryChoice() == NavigationHistoryChoices.VERTEX_CHANGES;
return functionGraphOptions
.getNavigationHistoryChoice() == NavigationHistoryChoices.VERTEX_CHANGES;
}
@Override
@ -634,6 +635,10 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
viewSettings.setLocation(location);
}
public void optionsChanged() {
view.optionsChanged();
}
public void refreshDisplayWithoutRebuilding() {
view.refreshDisplayWithoutRebuilding();
}

View file

@ -73,7 +73,6 @@ public class FGView extends VisualGraphView<FGVertex, FGEdge, FunctionGraph> {
protected void installGraphViewer() {
FGComponent newFgComponent = createGraphComponent();
newFgComponent.setGraphOptions(controller.getFunctionGraphOptions());
setGraphComponent(newFgComponent);
// we must assign the variable here, as the call to setGraphComponent() will call

View file

@ -70,6 +70,10 @@ public class FunctionGraphOptions extends VisualGraphOptions {
"<li><b>Never</b> - do not automatically relayout the graph</li></ul><br><br>" +
"<b><i>See help for more</i></b>";
private static final String DEFAULT_VERTEX_BACKGROUND_COLOR_KEY = "Default Vertex Color";
private static final String DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION =
"The default background color applied to each vertex";
private static final String DEFAULT_GROUP_BACKGROUND_COLOR_KEY = "Default Group Color";
private static final String DEFAULT_GROUP_BACKGROUND_COLOR_DESCRPTION =
"The default background color applied to newly created group vertices";
@ -80,11 +84,14 @@ public class FunctionGraphOptions extends VisualGraphOptions {
"Signals that any user color changes to a group vertex will apply that same color to " +
"all grouped vertices as well.";
public static final Color DEFAULT_VERTEX_BACKGROUND_COLOR = Color.WHITE;
public static final Color DEFAULT_GROUP_BACKGROUND_COLOR = new Color(226, 255, 155);
private static final Color HOVER_HIGHLIGHT_FALL_THROUGH_COLOR = new Color(255, 127, 127);
private static final Color HOVER_HIGHLIGHT_UNCONDITIONAL_COLOR = new Color(127, 127, 255);
private static final Color HOVER_HIGHLIGHT_CONDITIONAL_COLOR = Color.GREEN;
private Color defaultVertexBackgroundColor = DEFAULT_VERTEX_BACKGROUND_COLOR;
private boolean updateGroupColorsAutomatically = true;
private Color defaultGroupBackgroundColor = DEFAULT_GROUP_BACKGROUND_COLOR;
@ -104,6 +111,10 @@ public class FunctionGraphOptions extends VisualGraphOptions {
private Map<String, FGLayoutOptions> layoutOptionsByName = new HashMap<>();
public Color getDefaultVertexBackgroundColor() {
return defaultVertexBackgroundColor;
}
public Color getDefaultGroupBackgroundColor() {
return defaultGroupBackgroundColor;
}
@ -174,6 +185,12 @@ public class FunctionGraphOptions extends VisualGraphOptions {
options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help,
SCROLL_WHEEL_PANS_DESCRIPTION);
options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR,
help, GRAPH_BACKGROUND_COLOR_DESCRPTION);
options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR,
help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION);
options.registerOption(DEFAULT_GROUP_BACKGROUND_COLOR_KEY, DEFAULT_GROUP_BACKGROUND_COLOR,
help, DEFAULT_GROUP_BACKGROUND_COLOR_DESCRPTION);
@ -242,6 +259,12 @@ public class FunctionGraphOptions extends VisualGraphOptions {
scrollWheelPans = options.getBoolean(SCROLL_WHEEL_PANS_KEY, scrollWheelPans);
graphBackgroundColor =
options.getColor(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR);
defaultVertexBackgroundColor =
options.getColor(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR);
defaultGroupBackgroundColor =
options.getColor(DEFAULT_GROUP_BACKGROUND_COLOR_KEY, DEFAULT_GROUP_BACKGROUND_COLOR);
@ -308,5 +331,4 @@ public class FunctionGraphOptions extends VisualGraphOptions {
public void setLayoutOptions(String layoutName, FGLayoutOptions options) {
layoutOptionsByName.put(layoutName, options);
}
}

View file

@ -124,7 +124,7 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
// a cache to prevent unnecessary layout calculations
private Dimension lastSize;
private VisualGraphOptions options = new VisualGraphOptions();
protected VisualGraphOptions options = new VisualGraphOptions();
public GraphComponent(G graph) {
@ -208,9 +208,7 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
renderContext.setVertexFillPaintTransformer(
new PickableVertexPaintTransformer<>(pickedVertexState, Color.WHITE, Color.YELLOW));
viewer.setBackground(Color.WHITE);
viewer.setGraphOptions(new VisualGraphOptions());
viewer.setGraphOptions(options);
return viewer;
}
@ -297,6 +295,8 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
SatelliteGraphViewer<V, E> viewer = createSatelliteGraphViewer(masterViewer, viewerSize);
viewer.setGraphOptions(options);
viewer.setMinimumSize(viewerSize);
viewer.setMaximumSize(viewerSize);
@ -525,6 +525,15 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
public void setGraphOptions(VisualGraphOptions options) {
this.options = options;
// the viewers may be null if called during initialization
if (primaryViewer != null) {
primaryViewer.setGraphOptions(options);
}
if (satelliteViewer != null) {
satelliteViewer.setGraphOptions(options);
}
}
public boolean isUninitialized() {
@ -562,6 +571,11 @@ public class GraphComponent<V extends VisualVertex, E extends VisualEdge<V>, G e
return mainPanel;
}
public void optionsChanged() {
primaryViewer.optionsChanged();
satelliteViewer.optionsChanged();
}
public void repaint() {
mainPanel.repaint();
}

View file

@ -88,7 +88,7 @@ public class GraphViewer<V extends VisualVertex, E extends VisualEdge<V>>
gPickedState = new GPickedState<>((MultiPickedState<V>) pickedState);
setPickedVertexState(gPickedState);
popupRegulator = new PopupRegulator<V, E>(new GraphViewerPopupSource());
popupRegulator = new PopupRegulator<>(new GraphViewerPopupSource());
}
private void buildUpdater() {
@ -158,6 +158,11 @@ public class GraphViewer<V extends VisualVertex, E extends VisualEdge<V>>
public void setGraphOptions(VisualGraphOptions options) {
this.options = options;
optionsChanged();
}
public void optionsChanged() {
setBackground(options.getGraphBackgroundColor());
}
public VisualGraphOptions getOptions() {

View file

@ -21,6 +21,7 @@ import edu.uci.ics.jung.visualization.control.SatelliteVisualizationViewer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import ghidra.graph.viewer.event.mouse.VisualGraphPluggableGraphMouse;
import ghidra.graph.viewer.event.mouse.VisualGraphSatelliteGraphMouse;
import ghidra.graph.viewer.options.VisualGraphOptions;
import ghidra.graph.viewer.renderer.VisualGraphRenderer;
import ghidra.graph.viewer.renderer.VisualVertexSatelliteRenderer;
@ -36,6 +37,7 @@ public class SatelliteGraphViewer<V extends VisualVertex, E extends VisualEdge<V
protected GraphViewer<V, E> graphViewer;
private boolean docked;
private VisualGraphOptions options;
public SatelliteGraphViewer(GraphViewer<V, E> master, Dimension preferredSize) {
super(master, preferredSize);
@ -73,6 +75,15 @@ public class SatelliteGraphViewer<V extends VisualVertex, E extends VisualEdge<V
return new VisualVertexSatelliteRenderer<>();
}
public void setGraphOptions(VisualGraphOptions options) {
this.options = options;
optionsChanged();
}
public void optionsChanged() {
setBackground(options.getGraphBackgroundColor());
}
@SuppressWarnings("unchecked")
@Override
public VisualGraphPluggableGraphMouse<V, E> getGraphMouse() {
@ -87,5 +98,4 @@ public class SatelliteGraphViewer<V extends VisualVertex, E extends VisualEdge<V
}
super.setGraphMouse(graphMouse);
}
}

View file

@ -31,7 +31,6 @@ import ghidra.graph.VisualGraph;
import ghidra.graph.viewer.event.mouse.VertexTooltipProvider;
import ghidra.graph.viewer.event.mouse.VisualGraphMousePlugin;
import ghidra.graph.viewer.layout.LayoutProvider;
import ghidra.graph.viewer.options.VisualGraphOptions;
import ghidra.graph.viewer.vertex.VertexClickListener;
import ghidra.graph.viewer.vertex.VertexFocusListener;
@ -159,6 +158,13 @@ public class VisualGraphView<V extends VisualVertex,
undockedSatelliteContentPanel.validate();
}
/**
* Called when the options used by this graph view have changed
*/
public void optionsChanged() {
graphComponent.optionsChanged();
}
/**
* Sets the given layout provider, <b>but does not actually perform a layout</b>.
* @param newLayoutProvider the new provider
@ -201,7 +207,6 @@ public class VisualGraphView<V extends VisualVertex,
protected void installGraphViewer() {
GraphComponent<V, E, G> newGraphComponent = new GraphComponent<>(graph);
newGraphComponent.setGraphOptions(new VisualGraphOptions());
setGraphComponent(newGraphComponent);
}
@ -522,7 +527,7 @@ public class VisualGraphView<V extends VisualVertex,
public MouseEvent translateMouseEventFromVertexToViewSpace(V v, MouseEvent e) {
Point viewerPoint = translatePointFromVertexToViewSpace(v, e.getPoint());
VisualizationViewer<V, E> newSource = getPrimaryGraphViewer();
return new MouseEvent(newSource, e.getID(), e.getWhen(), e.getModifiers(),
return new MouseEvent(newSource, e.getID(), e.getWhen(), e.getModifiersEx(),
(int) viewerPoint.getX(), (int) viewerPoint.getY(), e.getClickCount(),
e.isPopupTrigger(), e.getButton());
}

View file

@ -15,10 +15,16 @@
*/
package ghidra.graph.viewer.options;
import java.awt.Color;
import docking.DockingUtils;
public class VisualGraphOptions {
public static final String GRAPH_BACKGROUND_COLOR_KEY = "Graph Background Color";
public static final String GRAPH_BACKGROUND_COLOR_DESCRPTION =
"The graph display background color";
public static final String SHOW_ANIMATION_OPTIONS_KEY = "Use Animation";
public static final String SHOW_ANIMATION_DESCRIPTION = "Signals to the Function Graph to " +
"use animated transitions for certain operations, like navigation.";
@ -48,6 +54,9 @@ public class VisualGraphOptions {
"new graphs and already rendered graphs are zoomed and positioned. See the help for " +
"more details.";
public static final Color DEFAULT_GRAPH_BACKGROUND_COLOR = Color.WHITE;
protected Color graphBackgroundColor = DEFAULT_GRAPH_BACKGROUND_COLOR;
protected boolean useAnimation = true;
protected boolean scrollWheelPans = false;
@ -59,6 +68,10 @@ public class VisualGraphOptions {
protected ViewRestoreOption viewRestoreOption = ViewRestoreOption.START_FULLY_ZOOMED_OUT;
public Color getGraphBackgroundColor() {
return graphBackgroundColor;
}
public boolean getScrollWheelPans() {
return scrollWheelPans;
}

View file

@ -151,7 +151,6 @@ public class TestGraphAlgorithmSteppingViewerPanel<V, E extends GEdge<V>> extend
tvg.setLayout(layout);
viewer = new GraphViewer<>(layout, new Dimension(400, 400));
viewer.setBackground(Color.WHITE);
viewer.setGraphOptions(new VisualGraphOptions());
Renderer<AlgorithmTestSteppingVertex<V>, AlgorithmTestSteppingEdge<V>> renderer =