mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 07:30:16 +00:00
GP-2737 - Function Graph - Added support for rendering Area Markers. Added support for a breakpoint margin area in each vertex.
This commit is contained in:
parent
7e4d2bcfaa
commit
54a240f3b8
@ -30,6 +30,7 @@ dependencies {
|
||||
api project(':Base')
|
||||
api project(':ByteViewer')
|
||||
api project(':Decompiler')
|
||||
api project(':FunctionGraph')
|
||||
api project(':ProposedUtils')
|
||||
|
||||
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
||||
|
@ -41,6 +41,9 @@ import ghidra.app.plugin.core.debug.event.TraceOpenedPluginEvent;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
||||
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||
import ghidra.app.plugin.core.functiongraph.FunctionGraphMarginService;
|
||||
import ghidra.app.plugin.core.marker.MarginProviderSupplier;
|
||||
import ghidra.app.plugin.core.marker.MarkerMarginProvider;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.viewer.listingpanel.MarkerClickedListener;
|
||||
import ghidra.async.AsyncDebouncer;
|
||||
@ -501,6 +504,16 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultMarginProviderSupplier implements MarginProviderSupplier {
|
||||
@Override
|
||||
public MarkerMarginProvider createMarginProvider() {
|
||||
if (markerService != null) {
|
||||
return markerService.createMarginProvider();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static State computeState(LogicalBreakpoint breakpoint, Program programOrView) {
|
||||
if (programOrView instanceof TraceProgramView view) {
|
||||
return breakpoint.computeStateForTrace(view.getTrace());
|
||||
@ -735,6 +748,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin
|
||||
private DebuggerControlService controlService;
|
||||
// @AutoServiceConsumed via method
|
||||
DecompilerMarginService decompilerMarginService;
|
||||
// @AutoServiceConsumed via method
|
||||
private FunctionGraphMarginService functionGraphMarginService;
|
||||
@SuppressWarnings("unused")
|
||||
private final AutoService.Wiring autoServiceWiring;
|
||||
|
||||
@ -793,6 +808,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin
|
||||
DebuggerPlaceBreakpointDialog placeBreakpointDialog = new DebuggerPlaceBreakpointDialog();
|
||||
|
||||
BreakpointsDecompilerMarginProvider decompilerMarginProvider;
|
||||
private MarginProviderSupplier functionGraphMarginSupplier =
|
||||
new DefaultMarginProviderSupplier();
|
||||
|
||||
public DebuggerBreakpointMarkerPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
@ -1038,6 +1055,21 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
@AutoServiceConsumed
|
||||
private void setFunctionGraphMarginService(
|
||||
FunctionGraphMarginService functionGraphMarginService) {
|
||||
|
||||
if (this.functionGraphMarginService != null) {
|
||||
this.functionGraphMarginService
|
||||
.removeMarkerProviderSupplier(functionGraphMarginSupplier);
|
||||
}
|
||||
|
||||
this.functionGraphMarginService = functionGraphMarginService;
|
||||
if (this.functionGraphMarginService != null) {
|
||||
this.functionGraphMarginService.addMarkerProviderSupplier(functionGraphMarginSupplier);
|
||||
}
|
||||
}
|
||||
|
||||
protected void createActions() {
|
||||
actionSetSoftwareBreakpoint =
|
||||
new SetBreakpointAction(Set.of(TraceBreakpointKind.SW_EXECUTE));
|
||||
|
@ -0,0 +1,28 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.marker;
|
||||
|
||||
/**
|
||||
* Supplies {@link MarkerMarginProvider}s.
|
||||
*/
|
||||
public interface MarginProviderSupplier {
|
||||
|
||||
/**
|
||||
* Creates a new marker margin provider.
|
||||
* @return the provider.
|
||||
*/
|
||||
public MarkerMarginProvider createMarginProvider();
|
||||
}
|
@ -25,9 +25,7 @@ import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Plugin to manage marker and navigation panels.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(
|
||||
status = PluginStatus.RELEASED,
|
||||
packageName = CorePluginPackage.NAME,
|
||||
@ -43,15 +41,17 @@ import ghidra.util.HelpLocation;
|
||||
"as bookmarks.",
|
||||
servicesRequired = { CodeViewerService.class, GoToService.class },
|
||||
servicesProvided = { MarkerService.class },
|
||||
eventsConsumed = {})
|
||||
eventsConsumed = {}
|
||||
)
|
||||
//@formatter:on
|
||||
/**
|
||||
* Plugin to manage marker and navigation panels.
|
||||
*/
|
||||
public class MarkerManagerPlugin extends Plugin {
|
||||
|
||||
private CodeViewerService codeViewerService;
|
||||
private MarkerManager markerManager;
|
||||
|
||||
/**
|
||||
* @param tool
|
||||
*/
|
||||
public MarkerManagerPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
markerManager = new MarkerManager(this);
|
||||
|
@ -32,6 +32,7 @@ import ghidra.app.plugin.core.functiongraph.graph.*;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.vertex.GroupedFunctionGraphVertex;
|
||||
import ghidra.app.plugin.core.functiongraph.mvc.*;
|
||||
import ghidra.app.plugin.core.marker.MarginProviderSupplier;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.ListingHighlightProvider;
|
||||
import ghidra.framework.model.*;
|
||||
@ -129,8 +130,6 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||
new SwingUpdateManager(250, 750, () -> setPendingLocationFromUpdateManager());
|
||||
|
||||
clipboardProvider = new FGClipboardProvider(tool, controller);
|
||||
ClipboardService service = tool.getService(ClipboardService.class);
|
||||
setClipboardService(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,7 +138,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||
return !isConnected();
|
||||
}
|
||||
|
||||
public void setClipboardService(ClipboardService service) {
|
||||
void setClipboardService(ClipboardService service) {
|
||||
clipboardService = service;
|
||||
if (clipboardService != null) {
|
||||
clipboardService.registerClipboardContentProvider(clipboardProvider);
|
||||
@ -1136,6 +1135,16 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||
controller.setGraphPerspective(info);
|
||||
}
|
||||
|
||||
void addMarkerProviderSupplier(MarginProviderSupplier supplier) {
|
||||
controller.addMarkerProviderSupplier(supplier);
|
||||
refreshAndKeepPerspective();
|
||||
}
|
||||
|
||||
void removeMarkerProviderSupplier(MarginProviderSupplier supplier) {
|
||||
controller.removeMarkerProviderSupplier(supplier);
|
||||
refreshAndKeepPerspective();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Navigatable interface methods
|
||||
//==================================================================================================
|
||||
@ -1298,7 +1307,8 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeHighlightProvider(ListingHighlightProvider highlightProvider, Program program) {
|
||||
public void removeHighlightProvider(ListingHighlightProvider highlightProvider,
|
||||
Program program) {
|
||||
// currently unsupported
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,42 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.functiongraph;
|
||||
|
||||
import ghidra.app.plugin.core.functiongraph.graph.FunctionGraph;
|
||||
import ghidra.app.plugin.core.marker.MarginProviderSupplier;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* A service that allows clients to add custom margins in the {@link FunctionGraph} UI.
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = FunctionGraphPlugin.class)
|
||||
public interface FunctionGraphMarginService {
|
||||
|
||||
/**
|
||||
* Add a marker margin supplier to Function Graph's primary window. The supplier will be called
|
||||
* for each node in the graph.
|
||||
*
|
||||
* @param supplier the supplier.
|
||||
*/
|
||||
public void addMarkerProviderSupplier(MarginProviderSupplier supplier);
|
||||
|
||||
/**
|
||||
* Removes the given margin supplier from the Function Graph's UI.
|
||||
*
|
||||
* @param supplier the supplier.
|
||||
*/
|
||||
public void removeMarkerProviderSupplier(MarginProviderSupplier supplier);
|
||||
}
|
@ -33,6 +33,7 @@ import ghidra.app.plugin.core.colorizer.ColorizingService;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutOptions;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider;
|
||||
import ghidra.app.plugin.core.functiongraph.mvc.FunctionGraphOptions;
|
||||
import ghidra.app.plugin.core.marker.MarginProviderSupplier;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.viewer.format.FormatManager;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
@ -53,10 +54,13 @@ import ghidra.util.exception.AssertException;
|
||||
category = PluginCategoryNames.GRAPH,
|
||||
shortDescription = FunctionGraphPlugin.FUNCTION_GRAPH_NAME,
|
||||
description = "Plugin for show a graphical representation of the code blocks of a function",
|
||||
servicesRequired = { GoToService.class, BlockModelService.class, CodeViewerService.class, ProgramManager.class }
|
||||
servicesRequired = { GoToService.class, BlockModelService.class, CodeViewerService.class, ProgramManager.class },
|
||||
servicesProvided = { FunctionGraphMarginService.class }
|
||||
)
|
||||
//@formatter:on
|
||||
public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeListener {
|
||||
public class FunctionGraphPlugin extends ProgramPlugin
|
||||
implements OptionsChangeListener, FunctionGraphMarginService {
|
||||
|
||||
static final String FUNCTION_GRAPH_NAME = "Function Graph";
|
||||
static final String OPTIONS_NAME_PATH =
|
||||
ToolConstants.GRAPH_OPTIONS + Options.DELIMITER + FUNCTION_GRAPH_NAME;
|
||||
@ -111,20 +115,32 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
|
||||
colorProvider = new ToolBasedColorProvider(this, (ColorizingService) service);
|
||||
connectedProvider.refreshAndKeepPerspective();
|
||||
}
|
||||
else if (interfaceClass == MarkerService.class) {
|
||||
for (FGProvider disconnectedProvider : disconnectedProviders) {
|
||||
disconnectedProvider.refreshAndKeepPerspective();
|
||||
}
|
||||
connectedProvider.refreshAndKeepPerspective();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(Class<?> interfaceClass, Object service) {
|
||||
if (interfaceClass == ClipboardService.class) {
|
||||
connectedProvider.setClipboardService((ClipboardService) service);
|
||||
connectedProvider.setClipboardService(null);
|
||||
for (FGProvider disconnectedProvider : disconnectedProviders) {
|
||||
disconnectedProvider.setClipboardService((ClipboardService) service);
|
||||
disconnectedProvider.setClipboardService(null);
|
||||
}
|
||||
}
|
||||
else if (interfaceClass == ColorizingService.class) {
|
||||
colorProvider = new IndependentColorProvider(tool);
|
||||
connectedProvider.refreshAndKeepPerspective();
|
||||
}
|
||||
else if (interfaceClass == MarkerService.class) {
|
||||
for (FGProvider disconnectedProvider : disconnectedProviders) {
|
||||
disconnectedProvider.refreshAndKeepPerspective();
|
||||
}
|
||||
connectedProvider.refreshAndKeepPerspective();
|
||||
}
|
||||
}
|
||||
|
||||
private List<FGLayoutProvider> loadLayoutProviders() {
|
||||
@ -194,6 +210,22 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMarkerProviderSupplier(MarginProviderSupplier supplier) {
|
||||
for (FGProvider disconnectedProvider : disconnectedProviders) {
|
||||
disconnectedProvider.addMarkerProviderSupplier(supplier);
|
||||
}
|
||||
connectedProvider.addMarkerProviderSupplier(supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMarkerProviderSupplier(MarginProviderSupplier supplier) {
|
||||
for (FGProvider disconnectedProvider : disconnectedProviders) {
|
||||
disconnectedProvider.removeMarkerProviderSupplier(supplier);
|
||||
}
|
||||
connectedProvider.removeMarkerProviderSupplier(supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void programActivated(Program program) {
|
||||
if (connectedProvider == null) {
|
||||
@ -431,6 +463,10 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
|
||||
return colorProvider;
|
||||
}
|
||||
|
||||
public <T> T getService(Class<T> serviceClass) {
|
||||
return tool.getService(serviceClass);
|
||||
}
|
||||
|
||||
public FunctionGraphOptions getFunctionGraphOptions() {
|
||||
return functionGraphOptions;
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ public class FGVertexListingPanel extends ListingPanel {
|
||||
//
|
||||
// Unusual Code Alert!: when the data of the listing changes its preferred size
|
||||
// may also change. If we don't invalidate the containing
|
||||
// Java component, then the cached preferred size will be
|
||||
// Java component, then the cached preferred size will be
|
||||
// invalid.
|
||||
//
|
||||
//
|
||||
getFieldPanel().invalidate();
|
||||
controller.repaint();
|
||||
}
|
||||
@ -73,10 +73,9 @@ public class FGVertexListingPanel extends ListingPanel {
|
||||
Color color = options.getDefaultVertexBackgroundColor();
|
||||
setTextBackgroundColor(color);
|
||||
|
||||
// Custom colors are in use when the ColorizingService is not installed.
|
||||
FGColorProvider colorProvider = controller.getColorProvider();
|
||||
if (!colorProvider.isUsingCustomColors()) {
|
||||
enablePropertyBasedColorModel(true); // turn on user colors in the graph
|
||||
}
|
||||
enablePropertyBasedColorModel(!colorProvider.isUsingCustomColors());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -94,8 +93,8 @@ public class FGVertexListingPanel extends ListingPanel {
|
||||
* Overridden to set the view before the parent class notifies the listeners. This prevents
|
||||
* our methods that calculate preferred size from going 'out to lunch' when attempting to
|
||||
* examine the entire program instead of just the given view.
|
||||
*
|
||||
* @param model The listing model needed by the layout model *
|
||||
*
|
||||
* @param model The listing model needed by the layout model
|
||||
* @return the new model adapter
|
||||
*/
|
||||
@Override
|
||||
|
@ -23,10 +23,12 @@ import java.awt.event.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.GenericHeader;
|
||||
@ -41,16 +43,19 @@ import generic.theme.GColor;
|
||||
import generic.theme.GIcon;
|
||||
import generic.theme.GThemeDefaults.Colors;
|
||||
import generic.theme.GThemeDefaults.Colors.Tooltips;
|
||||
import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel;
|
||||
import ghidra.app.plugin.core.codebrowser.hover.ListingHoverService;
|
||||
import ghidra.app.plugin.core.functiongraph.FunctionGraphPlugin;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.FGEdge;
|
||||
import ghidra.app.plugin.core.functiongraph.mvc.FGController;
|
||||
import ghidra.app.plugin.core.functiongraph.mvc.FunctionGraphOptions;
|
||||
import ghidra.app.plugin.core.marker.MarginProviderSupplier;
|
||||
import ghidra.app.plugin.core.marker.MarkerMarginProvider;
|
||||
import ghidra.app.services.HoverService;
|
||||
import ghidra.app.services.MarkerService;
|
||||
import ghidra.app.util.AddEditDialog;
|
||||
import ghidra.app.util.viewer.format.FormatManager;
|
||||
import ghidra.app.util.viewer.listingpanel.ListingHoverProvider;
|
||||
import ghidra.app.util.viewer.listingpanel.ListingModel;
|
||||
import ghidra.app.util.viewer.listingpanel.*;
|
||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||
import ghidra.app.util.viewer.util.FieldNavigator;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
@ -105,6 +110,12 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
|
||||
}
|
||||
};
|
||||
|
||||
private final ChangeListener markerChangeListener = e -> {
|
||||
if (controller != null) {
|
||||
controller.repaint();
|
||||
}
|
||||
};
|
||||
|
||||
ListingGraphComponentPanel(final FGVertex vertex, final FGController controller,
|
||||
PluginTool tool, Program program, AddressSetView addressSet) {
|
||||
super(controller, vertex);
|
||||
@ -122,6 +133,21 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
|
||||
.addButtonPressedListener(controller.getSharedHighlighterButtonPressedListener());
|
||||
listingPanel.setStringSelectionListener(controller.getSharedStringSelectionListener());
|
||||
|
||||
MarkerService markerService = controller.getService(MarkerService.class);
|
||||
if (markerService != null) {
|
||||
ListingBackgroundColorModel colorModel = new MarkerServiceBackgroundColorModel(
|
||||
markerService, listingPanel.getAddressIndexMap());
|
||||
listingPanel.setBackgroundColorModel(colorModel);
|
||||
markerService.addChangeListener(markerChangeListener);
|
||||
}
|
||||
|
||||
// The margin providers may be installed by services other than the MarkerService
|
||||
Set<MarginProviderSupplier> marginProviders = controller.getMarginProviderSuppliers();
|
||||
for (MarginProviderSupplier supplier : marginProviders) {
|
||||
MarkerMarginProvider marginProvider = supplier.createMarginProvider();
|
||||
listingPanel.addMarginProvider(marginProvider);
|
||||
}
|
||||
|
||||
fieldPanel = listingPanel.getFieldPanel();
|
||||
fieldPanel.setCursorOn(false);
|
||||
|
||||
@ -676,6 +702,11 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
|
||||
// references and removing the data from Jung's graph
|
||||
//
|
||||
|
||||
MarkerService markerService = controller.getService(MarkerService.class);
|
||||
if (markerService != null) {
|
||||
markerService.removeChangeListener(markerChangeListener);
|
||||
}
|
||||
|
||||
removeAll();
|
||||
|
||||
listingPanel.setStringSelectionListener(null);
|
||||
|
@ -18,9 +18,8 @@ package ghidra.app.plugin.core.functiongraph.mvc;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
@ -40,6 +39,7 @@ import ghidra.app.plugin.core.functiongraph.graph.FGEdge;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.FunctionGraph;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.vertex.*;
|
||||
import ghidra.app.plugin.core.marker.MarginProviderSupplier;
|
||||
import ghidra.app.services.ButtonPressedListener;
|
||||
import ghidra.app.services.CodeViewerService;
|
||||
import ghidra.app.util.ListingHighlightProvider;
|
||||
@ -58,6 +58,8 @@ import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||
import ghidra.util.datastruct.WeakSet;
|
||||
|
||||
public class FGController implements ProgramLocationListener, ProgramSelectionListener {
|
||||
|
||||
@ -90,6 +92,9 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
||||
// dummy
|
||||
};
|
||||
|
||||
private WeakSet<MarginProviderSupplier> marginProviders =
|
||||
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
|
||||
|
||||
public FGController(FGProvider provider, FunctionGraphPlugin plugin) {
|
||||
this.provider = provider;
|
||||
this.plugin = plugin;
|
||||
@ -421,7 +426,7 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
||||
//==================================================================================================
|
||||
|
||||
//==================================================================================================
|
||||
// Methods call by the providers
|
||||
// Methods called by the providers
|
||||
//==================================================================================================
|
||||
|
||||
public void programClosed(Program program) {
|
||||
@ -830,8 +835,16 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
||||
}
|
||||
}
|
||||
|
||||
public void addMarkerProviderSupplier(MarginProviderSupplier supplier) {
|
||||
marginProviders.add(supplier);
|
||||
}
|
||||
|
||||
public void removeMarkerProviderSupplier(MarginProviderSupplier supplier) {
|
||||
marginProviders.add(supplier);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Methods call by the model
|
||||
// Methods called by the model
|
||||
//==================================================================================================
|
||||
|
||||
public void setFunctionGraphData(FGData data) {
|
||||
@ -916,7 +929,7 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Methods call by the vertices (actions and such)
|
||||
// Methods called by the vertices (actions and such)
|
||||
//==================================================================================================
|
||||
|
||||
/** Zooms so that the graph will fit completely into the size of the primary viewer */
|
||||
@ -1007,6 +1020,10 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
||||
return plugin.getColorProvider();
|
||||
}
|
||||
|
||||
public <T> T getService(Class<T> serviceClass) {
|
||||
return plugin.getService(serviceClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the graph's notion of the current location based upon that of the Tool. This method is
|
||||
* meant to be called from internal mutative operations.
|
||||
@ -1063,6 +1080,10 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
||||
};
|
||||
}
|
||||
|
||||
public Set<MarginProviderSupplier> getMarginProviderSuppliers() {
|
||||
return Collections.unmodifiableSet(marginProviders);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
@ -28,7 +28,7 @@ import ghidra.util.exception.AssertException;
|
||||
* it may depend on a service. The ServiceManager maintains a list of
|
||||
* service names and plugins that provide those services. A plugin may
|
||||
* dynamically add and remove services from the service registry. As services
|
||||
* are added and removed, all the plugins (ServiceListener)
|
||||
* are added and removed, all the plugins (ServiceListener)
|
||||
* in the tool are notified.
|
||||
*/
|
||||
|
||||
@ -93,20 +93,24 @@ public class ServiceManager {
|
||||
/**
|
||||
* Add the service to the tool. Notify the service listeners if the
|
||||
* notification indicator is true; otherwise, add the service to a list
|
||||
* that will be used to notify listeners when notifications are
|
||||
* that will be used to notify listeners when notifications are
|
||||
* turned on again.
|
||||
* @param interfaceClass class of the service interface being added
|
||||
* @param service implementation of the service; it may be a plugin or
|
||||
* may be some object created by the plugin
|
||||
*
|
||||
* @see #setServiceAddedNotificationsOn(boolean)
|
||||
*
|
||||
* @see #setServiceAddedNotificationsOn(boolean)
|
||||
*/
|
||||
public synchronized <T> void addService(Class<? extends T> interfaceClass, T service) {
|
||||
List<Object> list =
|
||||
servicesByInterface.computeIfAbsent(interfaceClass, (k) -> new ArrayList<>());
|
||||
if (list.contains(service)) {
|
||||
// Note: this can happen if a plugin implements a service it declares and also calls
|
||||
// Plugin.registerServiceProvided(), which is a mistake, since the plugin will get
|
||||
// auto-wired when it implements the service interface.
|
||||
throw new AssertException(
|
||||
"Same Service implementation cannot be " + "added more than once");
|
||||
"The same Service implementation cannot be added more than once. Interface: " +
|
||||
interfaceClass + ". Service: " + service);
|
||||
}
|
||||
|
||||
list.add(service);
|
||||
@ -120,6 +124,8 @@ public class ServiceManager {
|
||||
|
||||
/**
|
||||
* Remove the service from the tool.
|
||||
* @param interfaceClass the service interface
|
||||
* @param service the service implementation
|
||||
*/
|
||||
public void removeService(Class<?> interfaceClass, Object service) {
|
||||
List<Object> list = servicesByInterface.get(interfaceClass);
|
||||
|
Loading…
Reference in New Issue
Block a user