diff --git a/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java b/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java index 4c3ca57cc3..476d3c14c1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java @@ -35,8 +35,6 @@ public interface GhidraOptions { * Category name for the Browser options that affect the display. */ final String CATEGORY_BROWSER_DISPLAY = "Listing Display"; - @Deprecated //remove a few versions after 8.0 - final String OLD_CATEGORY_BROWSER_DISPLAY = "Browser Display"; /** * Category name for the Browser Navigation Marker options. @@ -101,8 +99,6 @@ public interface GhidraOptions { * Options name for Browser fields */ final String CATEGORY_BROWSER_FIELDS = "Listing Fields"; - @Deprecated //remove a few versions after 8.0 - final String OLD_CATEGORY_BROWSER_FIELDS = "Browser Fields"; /** * Options title for Mnemonic group. @@ -125,8 +121,6 @@ public interface GhidraOptions { * Category name for Browser Popup options */ final String CATEGORY_BROWSER_POPUPS = "Listing Popups"; - @Deprecated //remove a few versions after 8.0 - final String OLD_CATEGORY_BROWSER_POPUPS = "Browser Popups"; /** * Category name for Decompiler Popup options diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java index de7032c04c..e58c3d4a4c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java @@ -131,12 +131,7 @@ public class CodeBrowserPlugin extends Plugin public CodeBrowserPlugin(PluginTool tool) { super(tool); - tool.registerOptionsNameChange(GhidraOptions.OLD_CATEGORY_BROWSER_FIELDS, - GhidraOptions.CATEGORY_BROWSER_FIELDS); - tool.registerOptionsNameChange(GhidraOptions.OLD_CATEGORY_BROWSER_DISPLAY, - GhidraOptions.CATEGORY_BROWSER_DISPLAY); - tool.registerOptionsNameChange(GhidraOptions.OLD_CATEGORY_BROWSER_POPUPS, - GhidraOptions.CATEGORY_BROWSER_POPUPS); + ToolOptions displayOptions = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY); ToolOptions fieldOptions = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS); displayOptions.registerOptionsEditor(new ListingDisplayOptionsEditor(displayOptions)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/GraphDisplayBrokerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/GraphDisplayBrokerPlugin.java index dd3d6e7a42..251002d61e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/GraphDisplayBrokerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/GraphDisplayBrokerPlugin.java @@ -20,6 +20,7 @@ import java.util.*; import docking.ActionContext; import docking.action.MenuData; import docking.action.ToggleDockingAction; +import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.services.GraphDisplayBroker; @@ -39,7 +40,7 @@ import ghidra.util.task.TaskMonitor; shortDescription = "Manages the active Graph Display Service", description = "This plugin searches for available graph display providers and if it finds more" + "than one, it provides menu options for the user to choose the active provider.", - servicesProvided = { GraphDisplayBroker.class } + servicesProvided = { GraphDisplayBroker.class } ) //@formatter:on public class GraphDisplayBrokerPlugin extends Plugin @@ -90,7 +91,7 @@ public class GraphDisplayBrokerPlugin extends Plugin private void initializeServices() { for (GraphDisplayProvider service : graphDisplayProviders) { - ToolOptions options = tool.getOptions("Graph"); + ToolOptions options = tool.getOptions(ToolConstants.GRAPH_OPTIONS); options.addOptionsChangeListener(this); service.initialize(tool, options); } @@ -148,7 +149,7 @@ public class GraphDisplayBrokerPlugin extends Plugin @Override public GraphDisplay getDefaultGraphDisplay(boolean reuseGraph, Map properties, - TaskMonitor monitor) throws GraphException { + TaskMonitor monitor) throws GraphException { if (defaultGraphDisplayProvider != null) { return defaultGraphDisplayProvider.getGraphDisplay(reuseGraph, properties, monitor); } diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGActionManager.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGActionManager.java index f6b77414f3..3c58dc4885 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGActionManager.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGActionManager.java @@ -665,7 +665,7 @@ class FGActionManager { @Override public void actionPerformed(ActionContext context) { OptionsService service = tool.getService(OptionsService.class); - service.showOptionsDialog(FunctionGraphPlugin.PLUGIN_OPTIONS_NAME, + service.showOptionsDialog(FunctionGraphPlugin.OPTIONS_NAME_PATH, "Function Graph"); } diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java index 982c26efc0..c519a0a3ae 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java @@ -21,6 +21,7 @@ import javax.swing.ImageIcon; import org.jdom.Element; +import docking.tool.ToolConstants; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; import ghidra.app.events.*; @@ -57,7 +58,8 @@ import resources.ResourceManager; //@formatter:on public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeListener { static final String FUNCTION_GRAPH_NAME = "Function Graph"; - static final String PLUGIN_OPTIONS_NAME = FUNCTION_GRAPH_NAME; + static final String OPTIONS_NAME_PATH = + ToolConstants.GRAPH_OPTIONS + Options.DELIMITER + FUNCTION_GRAPH_NAME; static final ImageIcon ICON = ResourceManager.loadImage("images/function_graph.png"); @@ -147,14 +149,20 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL } private void initializeOptions() { - ToolOptions options = tool.getOptions(PLUGIN_OPTIONS_NAME); + ToolOptions options = tool.getOptions(ToolConstants.GRAPH_OPTIONS); options.addOptionsChangeListener(this); - functionGraphOptions.registerOptions(options); - functionGraphOptions.loadOptions(options); + + // Graph -> Function Graph + Options fgOptions = options.getOptions(FUNCTION_GRAPH_NAME); + + functionGraphOptions.registerOptions(fgOptions); + functionGraphOptions.loadOptions(fgOptions); for (FGLayoutProvider layoutProvider : layoutProviders) { + + // Graph -> Function Graph -> Layout Name String layoutName = layoutProvider.getLayoutName(); - Options layoutToolOptions = options.getOptions(layoutName); + Options layoutToolOptions = fgOptions.getOptions(layoutName); FGLayoutOptions layoutOptions = layoutProvider.createLayoutOptions(layoutToolOptions); if (layoutOptions == null) { continue; // many layouts do not have options @@ -170,7 +178,9 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL public void optionsChanged(ToolOptions options, String optionName, Object oldValue, Object newValue) { - functionGraphOptions.loadOptions(options); + // Graph -> Function Graph + Options fgOptions = options.getOptions(FUNCTION_GRAPH_NAME); + functionGraphOptions.loadOptions(fgOptions); connectedProvider.optionsChanged(); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java index 5ff8fb5e7d..ba23771b28 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/FGComponent.java @@ -220,8 +220,8 @@ public class FGComponent extends GraphComponent edgeLabelRenderer.setRotateEdgeLabels(false); renderContext.setEdgeLabelRenderer(edgeLabelRenderer); - viewer.setGraphOptions(options); - Color bgColor = options.getGraphBackgroundColor(); + viewer.setGraphOptions(vgOptions); + Color bgColor = vgOptions.getGraphBackgroundColor(); if (bgColor.equals(VisualGraphOptions.DEFAULT_GRAPH_BACKGROUND_COLOR)) { // Give user notice when seeing the graph for a non-function (such as an undefined @@ -259,7 +259,7 @@ public class FGComponent extends GraphComponent renderContext.setVertexFillPaintTransformer(new FGVertexPickableBackgroundPaintTransformer( pickedVertexState, Color.YELLOW, START_COLOR, END_COLOR)); - viewer.setGraphOptions(options); + viewer.setGraphOptions(vgOptions); return viewer; } @@ -287,7 +287,7 @@ public class FGComponent extends GraphComponent //================================================================================================== public FunctionGraphOptions getFucntionGraphOptions() { - return (FunctionGraphOptions) options; + return (FunctionGraphOptions) vgOptions; } public void ensureCursorVisible(FGVertex vertex) { diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java index ea22f1cf44..4012f68efd 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FunctionGraphOptions.java @@ -22,7 +22,8 @@ import java.util.Map.Entry; import ghidra.app.plugin.core.functiongraph.FunctionGraphPlugin; import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutOptions; import ghidra.framework.options.Options; -import ghidra.graph.viewer.options.*; +import ghidra.graph.viewer.options.RelayoutOption; +import ghidra.graph.viewer.options.VisualGraphOptions; import ghidra.program.model.symbol.FlowType; import ghidra.util.HelpLocation; @@ -162,7 +163,7 @@ public class FunctionGraphOptions extends VisualGraphOptions { public void registerOptions(Options options) { HelpLocation help = new HelpLocation(OWNER, "Options"); - options.setOptionsHelpLocation(help); + super.registerOptions(options, help); options.registerOption(RELAYOUT_OPTIONS_KEY, relayoutOption, help, RELAYOUT_OPTIONS_DESCRIPTION); @@ -170,24 +171,9 @@ public class FunctionGraphOptions extends VisualGraphOptions { options.registerOption(NAVIGATION_HISTORY_KEY, navigationHistoryChoice, help, NAVIGATION_HISTORY_DESCRIPTION); - options.registerOption(SHOW_ANIMATION_OPTIONS_KEY, useAnimation(), help, - SHOW_ANIMATION_DESCRIPTION); - - options.registerOption(USE_MOUSE_RELATIVE_ZOOM_KEY, useMouseRelativeZoom(), help, - USE_MOUSE_RELATIVE_ZOOM_DESCRIPTION); - options.registerOption(USE_CONDENSED_LAYOUT_KEY, useCondensedLayout(), new HelpLocation(OWNER, "Layout_Compressing"), USE_CONDENSED_LAYOUT_DESCRIPTION); - options.registerOption(VIEW_RESTORE_OPTIONS_KEY, ViewRestoreOption.START_FULLY_ZOOMED_OUT, - help, VIEW_RESTORE_OPTIONS_DESCRIPTION); - - 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); @@ -222,7 +208,11 @@ public class FunctionGraphOptions extends VisualGraphOptions { } + @Override public void loadOptions(Options options) { + + super.loadOptions(options); + conditionalJumpEdgeColor = options.getColor(EDGE_COLOR_CONDITIONAL_JUMP_KEY, conditionalJumpEdgeColor); @@ -245,23 +235,8 @@ public class FunctionGraphOptions extends VisualGraphOptions { navigationHistoryChoice = options.getEnum(NAVIGATION_HISTORY_KEY, NavigationHistoryChoices.VERTEX_CHANGES); - useAnimation = options.getBoolean(SHOW_ANIMATION_OPTIONS_KEY, useAnimation); - - useMouseRelativeZoom = - options.getBoolean(USE_MOUSE_RELATIVE_ZOOM_KEY, useMouseRelativeZoom); - - useCondensedLayout = options.getBoolean(USE_CONDENSED_LAYOUT_KEY, useCondensedLayout); - useFullSizeTooltip = options.getBoolean(USE_FULL_SIZE_TOOLTIP_KEY, useFullSizeTooltip); - viewRestoreOption = - options.getEnum(VIEW_RESTORE_OPTIONS_KEY, ViewRestoreOption.START_FULLY_ZOOMED_OUT); - - 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); diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/help/help/topics/FunctionCallGraphPlugin/Function_Call_Graph.html b/Ghidra/Features/GraphFunctionCalls/src/main/help/help/topics/FunctionCallGraphPlugin/Function_Call_Graph.html index 0544e44289..8697cf287d 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/help/help/topics/FunctionCallGraphPlugin/Function_Call_Graph.html +++ b/Ghidra/Features/GraphFunctionCalls/src/main/help/help/topics/FunctionCallGraphPlugin/Function_Call_Graph.html @@ -232,6 +232,15 @@

+

Options

+ +
+

The Function Call Graph options are currently a subset of the + + Function Graph's Options. +

+
+ @@ -240,8 +249,7 @@

Related Topics:



diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgView.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgView.java index 1175b63f12..c4e78bffdb 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgView.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgView.java @@ -25,11 +25,17 @@ import ghidra.graph.viewer.options.VisualGraphOptions; */ public class FcgView extends VisualGraphView { + private VisualGraphOptions options; + + public FcgView(VisualGraphOptions options) { + this.options = options; + } + @Override protected void installGraphViewer() { FcgComponent component = createGraphComponent(); - component.setGraphOptions(new VisualGraphOptions()); + component.setGraphOptions(options); setGraphComponent(component); } diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FcgProvider.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FcgProvider.java index 95dd6487b5..02516013f8 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FcgProvider.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FcgProvider.java @@ -15,8 +15,7 @@ */ package functioncalls.plugin; -import static functioncalls.graph.FcgDirection.IN; -import static functioncalls.graph.FcgDirection.OUT; +import static functioncalls.graph.FcgDirection.*; import java.awt.*; import java.awt.event.MouseEvent; @@ -60,7 +59,7 @@ import resources.Icons; import util.CollectionUtils; /** - * The primary component provider for the {@link FunctionCallGraphPlugin} + * The primary component provider for the {@link FunctionCallGraphPlugin} */ public class FcgProvider extends VisualGraphComponentProvider { @@ -133,6 +132,10 @@ public class FcgProvider installGraph(); } + void optionsChanged() { + view.optionsChanged(); + } + void locationChanged(ProgramLocation loc) { if (!navigateIncomingToggleAction.isSelected()) { return; @@ -277,7 +280,7 @@ public class FcgProvider private void buildComponent() { - view = new FcgView(); + view = new FcgView(plugin.getOptions()); view.setVertexClickListener((v, info) -> { @@ -519,7 +522,7 @@ public class FcgProvider addLocalAction(resetGraphAction); MultiStateDockingAction> layoutAction = - new MultiStateDockingAction>( + new MultiStateDockingAction<>( RELAYOUT_GRAPH_ACTION_NAME, plugin.getName()) { @Override @@ -627,7 +630,7 @@ public class FcgProvider //================================================================================================== // Expand/Collapse Methods -//================================================================================================== +//================================================================================================== /* * Notes @@ -660,8 +663,8 @@ public class FcgProvider Set newEdges = getModelEdges(sources, expandingLevel, edgeNotInGraphFilter); - // Need all vertices from the source level, as well as their edges. - // This is used to correctly layout the vertices we are adding. This way, if we + // Need all vertices from the source level, as well as their edges. + // This is used to correctly layout the vertices we are adding. This way, if we // later add the sibling vertices, they will be in the correct spot, without clipping. Iterable sourceSiblings = getVerticesByLevel(sourceLevel); Set parentLevelEdges = getModelEdges(sourceSiblings, expandingLevel, unfiltered); @@ -756,7 +759,7 @@ public class FcgProvider FcgLevel parentLevel = parent.getLevel(); FcgLevel otherLevel = other.getLevel(); if (!parentLevel.isParentOf(otherLevel)) { - // the other vertex must be in the child level to be a dependent + // the other vertex must be in the child level to be a dependent return false; } @@ -864,7 +867,7 @@ public class FcgProvider } private Set toStartVertices(Iterable edges, Predicate filter) { - //@formatter:off + //@formatter:off return CollectionUtils .asStream(edges) .map(e -> e.getStart()) @@ -921,7 +924,7 @@ public class FcgProvider currentLevel = currentLevel.child(); } - // hand out from greatest to least so that we can close the extremities first + // hand out from greatest to least so that we can close the extremities first Collections.reverse(result); @SuppressWarnings("unchecked") @@ -931,8 +934,8 @@ public class FcgProvider private void doExpand(FcgExpandingVertexCollection collection) { - // note: we must do this before adding edges, as that will also add vertices and - // we will filter vertices later by those that are not already in the graph + // note: we must do this before adding edges, as that will also add vertices and + // we will filter vertices later by those that are not already in the graph Set newVertices = collection.getNewVertices(); FunctionCallGraph graph = graphData.getGraph(); @@ -979,13 +982,13 @@ public class FcgProvider /** * Called when new vertices are added to the graph to ensure that known edges between any - * level of the graph get added as the associated vertices are added to the graph. This - * is needed because we don't add all known edges for a single vertex when it is added, as + * level of the graph get added as the associated vertices are added to the graph. This + * is needed because we don't add all known edges for a single vertex when it is added, as * its associated vertex may not yet be in the graph. Calling this method ensures that as * vertices appear, the edges are added. * * @param newVertices the vertices being added to the graph - * @param newEdges the set to which should be added any new edges being added to the graph + * @param newEdges the set to which should be added any new edges being added to the graph */ private void addEdgesToExistingVertices(Iterable newVertices, Set newEdges) { @@ -1018,7 +1021,7 @@ public class FcgProvider // // Unusual Code Alert - // We wish to always use the same vertex *instance* across edges that we are + // We wish to always use the same vertex *instance* across edges that we are // creating. If the vertex is already in the graph, then that will happen as we get it // from the graph. However, if the function does not have a vertex in the graph, then // it must be created. Cache the vertices we retrieve here, whether exiting or created, @@ -1026,7 +1029,7 @@ public class FcgProvider // //@formatter:off - return CollectionUtils.asStream(callees) + return CollectionUtils.asStream(callees) .map(f -> { if (newVertexCache.containsKey(f)) { diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java index 7d10066fbf..a6bc2a0ffb 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java @@ -17,18 +17,21 @@ package functioncalls.plugin; import docking.ActionContext; import docking.action.DockingAction; +import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.ProgramPlugin; import ghidra.app.services.GoToService; -import ghidra.framework.options.SaveState; +import ghidra.framework.options.*; import ghidra.framework.plugintool.PluginInfo; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginStatus; +import ghidra.graph.viewer.options.VisualGraphOptions; import ghidra.program.model.address.Address; import ghidra.program.util.ProgramLocation; import ghidra.util.HelpLocation; import ghidra.util.SystemUtilities; +import ghidra.util.bean.opteditor.OptionsVetoException; import ghidra.util.task.SwingUpdateManager; /** @@ -43,7 +46,7 @@ import ghidra.util.task.SwingUpdateManager; description = "Displays a graph of incoming and outgoing calls for a given function." ) //@formatter:on -public class FunctionCallGraphPlugin extends ProgramPlugin { +public class FunctionCallGraphPlugin extends ProgramPlugin implements OptionsChangeListener { /*package*/ static final String NAME = "Function Call Graph"; /*package*/ static final String SHOW_PROVIDER_ACTION_NAME = "Display Function Call Graph"; @@ -52,6 +55,7 @@ public class FunctionCallGraphPlugin extends ProgramPlugin { FunctionCallGraphPlugin.class.getSimpleName()); private FcgProvider provider; + private VisualGraphOptions vgOptions = new VisualGraphOptions(); // enough time for users to click around without the graph starting its work private static final int MIN_UPDATE_DELAY = 750; @@ -65,8 +69,32 @@ public class FunctionCallGraphPlugin extends ProgramPlugin { @Override protected void init() { + provider = new FcgProvider(tool, this); createActions(); + + initializeOptions(); + } + + private void initializeOptions() { + ToolOptions options = tool.getOptions(ToolConstants.GRAPH_OPTIONS); + options.addOptionsChangeListener(this); + + HelpLocation help = new HelpLocation(getName(), "Options"); + + Options callGraphOptions = options.getOptions(NAME); + vgOptions.registerOptions(callGraphOptions, help); + vgOptions.loadOptions(callGraphOptions); + provider.optionsChanged(); + } + + @Override + public void optionsChanged(ToolOptions options, String optionName, Object oldValue, + Object newValue) throws OptionsVetoException { + + Options callGraphOptions = options.getOptions(NAME); + vgOptions.loadOptions(callGraphOptions); + provider.optionsChanged(); } @Override @@ -118,7 +146,7 @@ public class FunctionCallGraphPlugin extends ProgramPlugin { } }; -// TODO create icon from scratch: bow-tie +// TODO create icon from scratch: bow-tie // ImageIcon icon = ResourceManager.loadImage("images/applications-development.png"); // showProviderAction.setToolBarData(new ToolBarData(icon, "View")); tool.addAction(showProviderAction); @@ -142,4 +170,8 @@ public class FunctionCallGraphPlugin extends ProgramPlugin { ProgramLocation getCurrentLocation() { return currentLocation; } + + VisualGraphOptions getOptions() { + return vgOptions; + } } diff --git a/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/ProgramGraphPlugin.java b/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/ProgramGraphPlugin.java index d9fac4b83b..0cc1d5eb79 100644 --- a/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/ProgramGraphPlugin.java +++ b/Ghidra/Features/ProgramGraph/src/main/java/ghidra/graph/program/ProgramGraphPlugin.java @@ -4,9 +4,9 @@ * 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. @@ -23,6 +23,7 @@ import docking.action.DockingAction; import docking.action.ToggleDockingAction; import docking.action.builder.ActionBuilder; import docking.action.builder.ToggleActionBuilder; +import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; import ghidra.app.events.ProgramLocationPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent; @@ -69,11 +70,18 @@ import ghidra.util.task.TaskLauncher; //@formatter:on public class ProgramGraphPlugin extends ProgramPlugin implements OptionsChangeListener, BlockModelServiceListener, GraphDisplayBrokerListener { - private static final String MAX_CODE_LINES_DISPLAYED = "Max Code Lines Displayed"; - private static final String REUSE_GRAPH = "Reuse Graph"; - private static final String GRAPH_ENTRY_POINT_NEXUS = "Graph Entry Point Nexus"; - private static final String FORCE_LOCATION_DISPLAY_OPTION = "Force Location Visible on Graph"; - private static final String MAX_DEPTH_OPTION = "Max Reference Depth"; + + private static final String PLUGIN_NAME = "Program Graph"; + + private static final String OPTIONS_PREFIX = PLUGIN_NAME + Options.DELIMITER; + private static final String MAX_CODE_LINES_DISPLAYED = + OPTIONS_PREFIX + "Max Code Lines Displayed"; + private static final String REUSE_GRAPH = OPTIONS_PREFIX + "Reuse Graph"; + private static final String GRAPH_ENTRY_POINT_NEXUS = + OPTIONS_PREFIX + "Graph Entry Point Nexus"; + private static final String FORCE_LOCATION_DISPLAY_OPTION = + OPTIONS_PREFIX + "Force Location Visible on Graph"; + private static final String MAX_DEPTH_OPTION = OPTIONS_PREFIX + "Max Reference Depth"; public static final String MENU_GRAPH = "&Graph"; private BlockModelService blockModelService; @@ -102,23 +110,23 @@ public class ProgramGraphPlugin extends ProgramPlugin private void intializeOptions() { HelpLocation help = new HelpLocation(getName(), "Graph_Option"); - ToolOptions options = tool.getOptions("Graph"); + ToolOptions options = tool.getOptions(ToolConstants.GRAPH_OPTIONS); options.registerOption(MAX_CODE_LINES_DISPLAYED, codeLimitPerBlock, help, "Specifies the maximum number of instructions to display in each graph " + "node in a Code Flow Graph."); options.registerOption(REUSE_GRAPH, false, help, - "Determines whether the graph will reuse the active graph window when displaying graphs."); + "Determines whether the graph will reuse the active graph window when displaying " + + "graphs."); options.registerOption(GRAPH_ENTRY_POINT_NEXUS, false, help, - "Add a dummy node at the root of the graph and adds dummy edges to each node that has " + - "no incoming edges."); + "Add a dummy node at the root of the graph and adds dummy edges to each node that " + + "has no incoming edges."); options.registerOption(FORCE_LOCATION_DISPLAY_OPTION, false, help, - "Specifies whether or not " + - "graph displays should force the visible graph to pan and/or scale to ensure that focused " + - "locations are visible."); + "Specifies whether or not graph displays should force the visible graph to pan " + + "and/or scale to ensure that focused locations are visible."); options.registerOption(MAX_DEPTH_OPTION, 1, help, "Specifies max depth of data references to graph (0 for no limit)"); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/Tool.java b/Ghidra/Framework/Docking/src/main/java/docking/Tool.java index 8965180ac5..cb7f5cb014 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/Tool.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/Tool.java @@ -27,7 +27,7 @@ import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.ServiceProvider; /** - * Generic tool interface for managing {@link ComponentProvider}s and + * Generic tool interface for managing {@link ComponentProvider}s and * {@link DockingActionIf actions} */ public interface Tool extends ServiceProvider { @@ -74,7 +74,7 @@ public interface Tool extends ServiceProvider { public void addComponentProvider(ComponentProvider componentProvider, boolean show); /** - * Removes the given ComponentProvider from the tool. When a provider has been removed + * Removes the given ComponentProvider from the tool. When a provider has been removed * from the tool it is considered disposed and should not be reused. * * @param componentProvider the provider to remove from the tool @@ -165,7 +165,7 @@ public interface Tool extends ServiceProvider { * Return a set of all actions in the tool. * *

Note: the result may contain conceptually duplicate actions, which is when multiple - * actions exist that share the same full name (the full name is the action name with the + * actions exist that share the same full name (the full name is the action name with the * owner name, such as "My Action (MyPlugin)". * * @return set of all actions @@ -176,7 +176,7 @@ public interface Tool extends ServiceProvider { * Returns all actions for the given owner * *

Note: the result may contain conceptually duplicate actions, which is when multiple - * actions exist that share the same full name (the full name is the action name with the + * actions exist that share the same full name (the full name is the action name with the * owner name, such as "My Action (MyPlugin)". * * @param owner the action owner's name @@ -239,8 +239,8 @@ public interface Tool extends ServiceProvider { public void updateTitle(ComponentProvider componentProvider); /** - * Signals to the tool that the provider's context has changed. This lets toolbar and - * menu actions update enablement based on current context. + * Signals to the tool that the provider's context has changed. This lets toolbar and + * menu actions update enablement based on current context. * *

Pass null to signal that the entire tool's context has changed * @@ -290,7 +290,7 @@ public interface Tool extends ServiceProvider { * Returns the class that manages actions for the tool. * *

Most clients will not need to use this methods. Instead, actions should be added to - * the tool via {@link #addAction(DockingActionIf)} and + * the tool via {@link #addAction(DockingActionIf)} and * {@link #addLocalAction(ComponentProvider, DockingActionIf)}. * * @return the action manager diff --git a/Ghidra/Framework/Docking/src/main/java/docking/tool/ToolConstants.java b/Ghidra/Framework/Docking/src/main/java/docking/tool/ToolConstants.java index f5712c2c07..1c539f3511 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/tool/ToolConstants.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/tool/ToolConstants.java @@ -92,17 +92,22 @@ public interface ToolConstants extends DockingToolConstants { public static final String TOOL_OWNER = "Tool"; /** - * This is used when many actions wish to share a key binding. + * This is used when many actions wish to share a key binding. * * @see KeyBindingType#SHARED */ public static final String SHARED_OWNER = "Shared"; /** - * Name of options for a tool + * Tool options name */ public static final String TOOL_OPTIONS = "Tool"; + /** + * Graph options name + */ + public static final String GRAPH_OPTIONS = "Graph"; + /** * Name of the help topic for "About" domain objects and Ghidra */ diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Options.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Options.java index ef8432abfe..41f22e3cc8 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Options.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Options.java @@ -40,7 +40,7 @@ public interface Options { /** * Returns a unique id for option in this options with the given name. This will be the full - * path name to the root options object. + * path name to the root options object. * @param optionName the name of the option for which to get an ID; * @return the unique ID for the given option. */ @@ -56,6 +56,7 @@ public interface Options { /** * Get the property editor for the option with the given name. Note: This method must be called * from the swing thread. + * @param optionName the option name * @return either the PropertyEditor that was registered for this option or a default editor * for the property type if one can be found; otherwise null. * @throws IllegalStateException if not called from the swing thread. @@ -65,6 +66,7 @@ public interface Options { /** * Get the property editor that was registered for the specific option with the given name. Unlike * the getPropertyEditor() method, this method does not have to be called from the swing thread + * @param optionName the option name * @return the PropertyEditor that was registered for this option. */ @@ -79,7 +81,7 @@ public interface Options { /** * Returns a list of option names that immediately fall under this options. For example, if this options * object had the following options named ("a", "b", "c.d"), only "a" and "b" would be returned. The - * "c.d" leaf option name could be returned by getOptions("c").getLeafOptionNames() + * "c.d" leaf option name could be returned by getOptions("c").getLeafOptionNames() * @return the list of the names of the options that are immediate children of this options object. */ public List getLeafOptionNames(); @@ -163,6 +165,8 @@ public interface Options { /** * Put the object value. If the option exists, the type must match the type of the existing * object. + * @param optionName the option name + * @param obj the option value * @throws IllegalStateException if the object does not match the existing type of the option. * @throws IllegalArgumentException if the object is null or not a supported type. */ @@ -268,7 +272,7 @@ public interface Options { * @param pName the property name * @param date the default date that is stored and returned if there is no * option with the given name - * @return the Date for the option + * @return the Date for the option * @throws IllegalArgumentException is a option exists with the given * name but it is not a Date options */ @@ -352,21 +356,21 @@ public interface Options { /** * Sets the Custom option value for the option. * @param optionName name of the option - * @param value + * @param value the value */ public abstract void setCustomOption(String optionName, CustomOption value); /** * Sets the byte[] value for the given option name. * @param optionName the name of the option on which to save bytes. - * @param value + * @param value the value */ public abstract void setByteArray(String optionName, byte[] value); /** * Sets the File value for the option. * @param optionName name of the option - * @param value + * @param value the value */ public abstract void setFile(String optionName, File value); @@ -426,7 +430,7 @@ public interface Options { /** * Get the list of option names. This method will return the names (paths) of all options contained - * in this options object or below. For example, if the options has ("aaa", "bbb", "ccc.ddd"), + * in this options object or below. For example, if the options has ("aaa", "bbb", "ccc.ddd"), * all three will be returned. the {@link Options#getLeafOptionNames()} method will return only * the "aaa" and "bbb" names. * @return the list of all option names(paths) under this options. @@ -436,6 +440,7 @@ public interface Options { /** * Return true if a option exists with the given name. * @param optionName option name + * @return true if there exists an option with the given name */ public abstract boolean contains(String optionName); @@ -449,6 +454,8 @@ public interface Options { /** * Returns true if the specified option has been registered. Only registered names * are saved. + * @param optionName the option name + * @return true if registered */ public abstract boolean isRegistered(String optionName); @@ -476,14 +483,20 @@ public interface Options { /** * Returns a Options object that is a sub-options of this options. - * @param path the path for the sub-options object. - * @return a Options object that is a sub-options of this options. + * + *

Note: the option path can have {@link Options#DELIMITER} characters which will be + * used to create a hierarchy with each element in the path resulting in sub-option of the + * previous path element. + * + * @param path the path for the sub-options object + * @return an Options object that is a sub-options of this options */ public Options getOptions(String path); /** * Create an alias in this options for an existing option in some other options object. - * @param aliasName the name within this options object that will acutally refer to some other options object. + * @param aliasName the name within this options object that will actually refer to some other + * options object. * @param options the options object that has the actual option. * @param optionsName the name within the given options object of the actual option. */ diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java index ebaf483e2b..7f8effa08d 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java @@ -32,13 +32,17 @@ import ghidra.util.exception.AssertException; /** * Class to manage a set of option name/value pairs for a category. - * The values may be primitives or - * WrappedObjects that are containers for its primitive components. - * The option may be associated with a particular group. - *

The name/value pair has a owner so that the option name - * can be removed from the Options object when it is no longer being used. - *

NOTE: Property Names can have DELIMITER characters to create a hierarchy. - * The Options Dialog shows the hierarchy in tree format. + * + *

The values may be primitives or {@link WrappedOption}s that are containers for primitive + * components. + * + *

The name/value pair has an owner so that the option name can be removed from the Options + * object when it is no longer being used. + * + *

Note: Property Names can have {@link Options#DELIMITER} characters to create a hierarchy. + * So too can sub-options accessed via {@link #getOptions(String)}. + * + *

The Options Dialog shows the delimited hierarchy in tree format. */ public class ToolOptions extends AbstractOptions { private static final String CLASS_ATTRIBUTE = "CLASS"; @@ -145,7 +149,7 @@ public class ToolOptions extends AbstractOptions { * Note: only those options which have been explicitly set * will be included. * - * @param includeDefaultBindings true to include default key binding values in the xml + * @param includeDefaultBindings true to include default key binding values in the xml * @return the xml root element */ public Element getXmlRoot(boolean includeDefaultBindings) { @@ -194,7 +198,7 @@ public class ToolOptions extends AbstractOptions { SaveState ss = new SaveState(WRAPPED_OPTION_NAME); Element elem = null; if (value == null) { - // Handle the null case ourselves, not using the wrapped option (and when + // Handle the null case ourselves, not using the wrapped option (and when // reading from xml) so that the logic does not need to in each wrapped option elem = ss.saveToXml(); elem.addContent(new Element(CLEARED_VALUE_ELEMENT_NAME)); diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java index 4c8ca78c84..5b368651a8 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java @@ -63,13 +63,13 @@ import resources.ResourceManager; import util.CollectionUtils; /** - * A component that contains primary and satellite graph views. This viewer provides + * A component that contains primary and satellite graph views. This viewer provides * methods for manipulating the graph using the mouse. * - *

To gain the full functionality offered by this class, clients will need to subclass - * this class and override {@link #createPrimaryGraphViewer(VisualGraphLayout, Dimension)} - * and {@link #createSatelliteGraphViewer(GraphViewer, Dimension)} as needed. This allows - * them to customize renderers and other viewer attributes. To use the subclass, see the + *

To gain the full functionality offered by this class, clients will need to subclass + * this class and override {@link #createPrimaryGraphViewer(VisualGraphLayout, Dimension)} + * and {@link #createSatelliteGraphViewer(GraphViewer, Dimension)} as needed. This allows + * them to customize renderers and other viewer attributes. To use the subclass, see the * {@link VisualGraphView} and its installGraphViewer() method. * * @param the vertex type @@ -83,7 +83,7 @@ public class GraphComponent, G e private static final double PARENT_TO_SATELLITE_RATIO = 4;// 2.5 smaller view seems better private static final int MINIMUM_SATELLITE_WIDTH = 150; - // TODO this is arbitrary right now; perform testing for a generic number value; + // TODO this is arbitrary right now; perform testing for a generic number value; // subclasses can override private static final int REALLY_BIG_GRAPH_VERTEX_COUNT = 500; @@ -124,7 +124,7 @@ public class GraphComponent, G e // a cache to prevent unnecessary layout calculations private Dimension lastSize; - protected VisualGraphOptions options = new VisualGraphOptions(); + protected VisualGraphOptions vgOptions = new VisualGraphOptions(); public GraphComponent(G graph) { @@ -187,7 +187,7 @@ public class GraphComponent, G e // // This method can be overridden by subclasses to perform custom creation and setup. // Any setup, like renderers, that this class should not override must be put in this - // method so that subclasses can override. Common setup items should be in the + // method so that subclasses can override. Common setup items should be in the // method that calls this one. // @@ -208,7 +208,7 @@ public class GraphComponent, G e renderContext.setVertexFillPaintTransformer( new PickableVertexPaintTransformer<>(pickedVertexState, Color.WHITE, Color.YELLOW)); - viewer.setGraphOptions(options); + viewer.setGraphOptions(vgOptions); return viewer; } @@ -295,7 +295,7 @@ public class GraphComponent, G e SatelliteGraphViewer viewer = createSatelliteGraphViewer(masterViewer, viewerSize); - viewer.setGraphOptions(options); + viewer.setGraphOptions(vgOptions); viewer.setMinimumSize(viewerSize); viewer.setMaximumSize(viewerSize); @@ -434,7 +434,7 @@ public class GraphComponent, G e /* - TODO fix when the help module is created + TODO fix when the Generic Visual Graph help module is created HelpService helpService = DockingWindowManager.getHelpService(); helpService.registerHelp(button, @@ -506,7 +506,7 @@ public class GraphComponent, G e } /** - * This method is used to determine caching strategy. For example, large graph will + * This method is used to determine caching strategy. For example, large graph will * trigger the us of a cached satellite view, for performance reasons. * * @return true if the data is considered 'really big' @@ -524,7 +524,7 @@ public class GraphComponent, G e } public void setGraphOptions(VisualGraphOptions options) { - this.options = options; + this.vgOptions = options; // the viewers may be null if called during initialization if (primaryViewer != null) { @@ -536,6 +536,10 @@ public class GraphComponent, G e } } + public VisualGraphOptions getGraphOptions() { + return vgOptions; + } + public boolean isUninitialized() { return isUninitialized; } @@ -592,7 +596,7 @@ public class GraphComponent, G e return primaryViewer.getViewUpdater(); } - /** + /** * Returns an empty rectangle if the satellite is not visible * @return the bounds */ @@ -611,10 +615,10 @@ public class GraphComponent, G e applyGraphPerspective(graphPerspectiveInfo); } else { - // + // // Default Zoom - Zoomed-out or Zoomed-in? // - ViewRestoreOption viewOption = options.getViewRestoreOption(); + ViewRestoreOption viewOption = vgOptions.getViewRestoreOption(); if (viewOption == ViewRestoreOption.START_FULLY_ZOOMED_IN) { zoomInCompletely(getInitialVertex()); } @@ -883,7 +887,7 @@ public class GraphComponent, G e } // - // Let's go a bit overboard and help the garbage collector cleanup by nulling out + // Let's go a bit overboard and help the garbage collector cleanup by nulling out // references and removing the data from Jung's graph // @@ -1204,7 +1208,7 @@ public class GraphComponent, G e @Override public void mouseClicked(MouseEvent e) { - // stub + // stub } @Override @@ -1214,7 +1218,7 @@ public class GraphComponent, G e @Override public void mouseEntered(MouseEvent e) { - // stub + // stub } @Override diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java index b205417372..a83a63c728 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphViewer.java @@ -66,7 +66,7 @@ public class GraphViewer> private PopupRegulator popupRegulator; private VertexTooltipProvider vertexTooltipProvider = new DummyTooltipProvider(); - protected VisualGraphOptions options; + protected VisualGraphOptions vgOptions; private VisualGraphViewUpdater viewUpdater; private VisualGraphPathHighlighter pathHighlighter; @@ -157,16 +157,16 @@ public class GraphViewer> } public void setGraphOptions(VisualGraphOptions options) { - this.options = options; + this.vgOptions = options; optionsChanged(); } public void optionsChanged() { - setBackground(options.getGraphBackgroundColor()); + setBackground(vgOptions.getGraphBackgroundColor()); } public VisualGraphOptions getOptions() { - return options; + return vgOptions; } public void setVertexHoverPathHighlightMode(PathHighlightMode hoverMode) { @@ -221,7 +221,7 @@ public class GraphViewer> * @return true if using mouse-relative zoom */ public boolean useMouseRelativeZoom() { - return options.useMouseRelativeZoom(); + return vgOptions.useMouseRelativeZoom(); } /** diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java index ef7aab20bd..b054d7731b 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/options/VisualGraphOptions.java @@ -18,6 +18,8 @@ package ghidra.graph.viewer.options; import java.awt.Color; import docking.DockingUtils; +import ghidra.framework.options.Options; +import ghidra.util.HelpLocation; public class VisualGraphOptions { @@ -96,4 +98,41 @@ public class VisualGraphOptions { return useCondensedLayout; } + public void registerOptions(Options options, HelpLocation help) { + + options.setOptionsHelpLocation(help); + + options.registerOption(SHOW_ANIMATION_OPTIONS_KEY, useAnimation(), help, + SHOW_ANIMATION_DESCRIPTION); + + options.registerOption(USE_MOUSE_RELATIVE_ZOOM_KEY, useMouseRelativeZoom(), help, + USE_MOUSE_RELATIVE_ZOOM_DESCRIPTION); + + options.registerOption(VIEW_RESTORE_OPTIONS_KEY, ViewRestoreOption.START_FULLY_ZOOMED_OUT, + help, VIEW_RESTORE_OPTIONS_DESCRIPTION); + + 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); + } + + public void loadOptions(Options options) { + + useAnimation = options.getBoolean(SHOW_ANIMATION_OPTIONS_KEY, useAnimation); + + useMouseRelativeZoom = + options.getBoolean(USE_MOUSE_RELATIVE_ZOOM_KEY, useMouseRelativeZoom); + + useCondensedLayout = options.getBoolean(USE_CONDENSED_LAYOUT_KEY, useCondensedLayout); + + viewRestoreOption = + options.getEnum(VIEW_RESTORE_OPTIONS_KEY, ViewRestoreOption.START_FULLY_ZOOMED_OUT); + + scrollWheelPans = options.getBoolean(SCROLL_WHEEL_PANS_KEY, scrollWheelPans); + + graphBackgroundColor = + options.getColor(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR); + } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java index 1ae78a4a8f..a1abf45f6b 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java @@ -60,12 +60,12 @@ import ghidra.util.*; import ghidra.util.task.*; /** - * Base class that is a container to manage plugins and their actions, and to coordinate the + * Base class that is a container to manage plugins and their actions, and to coordinate the * firing of plugin events and tool events. A PluginTool may have visible components supplied by - *

ComponentProviders 
. These components may be docked within the tool, or moved + *
ComponentProviders 
. These components may be docked within the tool, or moved * out into their own windows. * - *

Plugins normally add actions via {@link #addAction(DockingActionIf)}. There is also + *

Plugins normally add actions via {@link #addAction(DockingActionIf)}. There is also * an alternate method for getting actions to appear in the popup context menu (see * {@link #addPopupActionProvider(PopupActionProvider)}). The popup listener mechanism is generally not * needed and should only be used in special circumstances (see {@link PopupActionProvider}). @@ -710,11 +710,6 @@ public abstract class PluginTool extends AbstractDockingTool { new TaskLauncher(task, winMgr.getActiveWindow()); } - /** - * Get the options for the given category name; if no options exist with - * the given name, then one is created. - */ - @Override public ToolOptions getOptions(String categoryName) { return optionsMgr.getOptions(categoryName); @@ -1103,7 +1098,7 @@ public abstract class PluginTool extends AbstractDockingTool { return configChangedFlag; // ignore the window layout changes } - /** + /** * Called when it is time to save the tool. Handles auto-saving logic. * @return true if a save happened */ diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java index 909043b0b2..41cf86845c 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java @@ -58,12 +58,9 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { optionsMap.values().forEach(options -> options.dispose()); } - /** - * Get the options for the given category name. - * @param category name of category - */ @Override public ToolOptions getOptions(String category) { + ToolOptions opt = optionsMap.get(category); if (opt == null) { opt = new ToolOptions(category); @@ -87,20 +84,11 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { } } - /** - * Return whether an Options object exists for the given category. - * @param category name of the category - * @return true if an Options object exists - */ @Override public boolean hasOptions(String category) { return optionsMap.containsKey(category); } - /** - * Shows Options Dialog with the section called 'category' being displayed - * @param category The category of options to have displayed - */ @Override public void showOptionsDialog(String category, String filterText) { if (optionsDialog != null && optionsDialog.isVisible()) { @@ -112,9 +100,6 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { tool.showDialog(optionsDialog); } - /** - * Get the list of options for all categories. - */ @Override public ToolOptions[] getOptions() { ToolOptions[] opt = new ToolOptions[optionsMap.size()]; @@ -134,7 +119,6 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { * remove the options from the map. * @param ownerPlugin the owner plugin */ - //TODO anyone using this Or should they be? public void deregisterOwner(Plugin ownerPlugin) { List deleteList = new ArrayList<>(); Iterator iter = optionsMap.keySet().iterator(); @@ -211,9 +195,6 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { } } - /** - * Show the dialog to edit options. - */ public void editOptions() { if (optionsMap.isEmpty()) { Msg.showInfo(getClass(), tool.getToolFrame(), "No Options", @@ -234,9 +215,6 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { } } - /** - * Create the options dialog. - */ private OptionsDialog createOptionsDialog() { OptionsDialog dialog = null; if (optionsMap.size() == 0) { @@ -275,37 +253,20 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { } private class OptionsComparator implements Comparator { - /** - * Compares its two arguments for order. Returns a negative integer, - * zero, or a positive integer as the first argument is less than, equal - * to, or greater than the second.

- * - * @param o1 the first object to be compared. - * @param o2 the second object to be compared. - * @return a negative integer, zero, or a positive integer as the - * first argument is less than, equal to, or greater than the - * second. - * @throws ClassCastException if the arguments' types prevent them from - * being compared by this Comparator. - */ @Override public int compare(ToolOptions o1, ToolOptions o2) { return o1.getName().compareTo(o2.getName()); } } - ///////////////////////////////////////////////////////////////////// private class KeyBindingOptionsEditor implements OptionsEditor { private KeyBindingsPanel panel; KeyBindingOptionsEditor() { - panel = new KeyBindingsPanel(tool, getOptions(ToolConstants.KEY_BINDINGS)); + panel = new KeyBindingsPanel(tool, getOptions(DockingToolConstants.KEY_BINDINGS)); } - /** - * Apply the changes. - */ @Override public void apply() { panel.apply(); @@ -326,9 +287,6 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { panel.dispose(); } - /** - * Get the editor component. - */ @Override public JComponent getEditorComponent(Options options, EditorStateFactory editorStateFactory) { @@ -339,12 +297,10 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { public void setOptionsPropertyChangeListener(PropertyChangeListener listener) { panel.setOptionsPropertyChangeListener(listener); } - } @Override public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) { tool.setConfigChanged(true); } - } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/util/OptionsService.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/util/OptionsService.java index 7628d0453d..8d3d73ee72 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/util/OptionsService.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/util/OptionsService.java @@ -19,53 +19,59 @@ import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; /** - * Provides a service interface that allows the user to get Options and to check for the + * Provides a service interface that allows the user to get Options and to check for the * existence of options. */ public interface OptionsService { - /** - * Get the list of options for all categories. - * @return the list of options for all categories. - */ - public Options[] getOptions(); - - /** - * Get the options for the given category name. - * @param category name of category - * @return the options for the given category name. - */ - public ToolOptions getOptions(String category); - - /** - * Return whether an Options object exists for the given category. - * @param category name of the category - * @return true if an Options object exists - */ - public boolean hasOptions(String category); - - /** - * Shows Options Dialog with the node denoted by "category" being displayed. The value is - * expected to be the name of a node in the options tree, residing under the root node. You - * may also provide the name of such a node, followed by the options delimiter, followed by - * the name of a child node under that node. For example, suppose in the options tree exists - * a node {@literal Root->Foo} You may pass the value "Foo" to get that node. Or, suppose - * in the options tree exists a node {@literal Root->Foo->childNode1} In this case, you may - * pass the value "Foo.childNode1", where the '.' character is the delimiter of the - * {@link ToolOptions} class (this is the value at the time of writing this documentation). - * - *

- * The filter text parameter is used to set the contents filter text of the options. You may - * use this parameter to filter the tree; for example, to show only the node in the tree that - * you want the user to see. - * - * @param category The category of options to have displayed - * @param filterText An optional value used to filter the nodes visible in the options tree. - * You may pass null or the empty string "" here if you - * do not desire filtering. - * @throws IllegalArgumentException if the given category value does not exist in - * the tree of options. - */ - public void showOptionsDialog(String category, String filterText); + /** + * Get the list of options for all categories. + * @return the list of options for all categories. + */ + public Options[] getOptions(); + + /** + * Get the options for the given category name. If no options exist with the given name, + * then a new options object is created. + * + *

Note: the given name should not contains options path separator characters. Any + * sub-options needed must be retrieved from the ToolOptions object returned from this + * method. + * + * @param category name of category + * @return the options for the given category name. + */ + public ToolOptions getOptions(String category); + + /** + * Return whether an Options object exists for the given category. + * @param category name of the category + * @return true if an Options object exists + */ + public boolean hasOptions(String category); + + /** + * Shows Options Dialog with the node denoted by "category" being displayed. The value is + * expected to be the name of a node in the options tree, residing under the root node. You + * may also provide the name of such a node, followed by the options delimiter, followed by + * the name of a child node under that node. For example, suppose in the options tree exists + * a node {@literal Root->Foo} You may pass the value "Foo" to get that node. Or, suppose + * in the options tree exists a node {@literal Root->Foo->childNode1} In this case, you may + * pass the value "Foo.childNode1", where the '.' character is the delimiter of the + * {@link ToolOptions} class (this is the value at the time of writing this documentation). + * + *

+ * The filter text parameter is used to set the contents filter text of the options. You may + * use this parameter to filter the tree; for example, to show only the node in the tree that + * you want the user to see. + * + * @param category The category of options to have displayed + * @param filterText An optional value used to filter the nodes visible in the options tree. + * You may pass null or the empty string "" here if you + * do not desire filtering. + * @throws IllegalArgumentException if the given category value does not exist in + * the tree of options. + */ + public void showOptionsDialog(String category, String filterText); }