mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 12:23:50 +08:00
Merge remote-tracking branch
'origin/GP-6085-dragonmacher-flow-arrows-for-all--SQUASHED' (Closes #8601)
This commit is contained in:
+21
-11
@@ -85,7 +85,8 @@ import ghidra.util.Msg;
|
|||||||
servicesRequired = {
|
servicesRequired = {
|
||||||
DebuggerLogicalBreakpointService.class,
|
DebuggerLogicalBreakpointService.class,
|
||||||
MarkerService.class,
|
MarkerService.class,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
||||||
|
|
||||||
private static final Color COLOR_BREAKPOINT_ENABLED_MARKER =
|
private static final Color COLOR_BREAKPOINT_ENABLED_MARKER =
|
||||||
@@ -496,7 +497,7 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
new ProgramLocationActionContext(null, location.getProgram(),
|
new ProgramLocationActionContext(null, location.getProgram(),
|
||||||
new ProgramLocation(location.getProgram(), location.getAddr()), null, null);
|
new ProgramLocation(location.getProgram(), location.getAddr()), null, null);
|
||||||
if (contextCanManipulateBreakpoints(context)) {
|
if (contextCanManipulateBreakpoints(context)) {
|
||||||
doToggleBreakpointsAt(ToggleBreakpointAction.NAME, context);
|
doToggleBreakpointsAt(AbstractToggleBreakpointAction.NAME, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -753,28 +754,32 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
@AutoOptionDefined(
|
@AutoOptionDefined(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_ENABLED_BREAKPOINT_COLORING_BACKGROUND,
|
name = DebuggerResources.OPTION_NAME_COLORS_ENABLED_BREAKPOINT_COLORING_BACKGROUND,
|
||||||
description = "Whether or not to color background for memory at an enabled breakpoint",
|
description = "Whether or not to color background for memory at an enabled breakpoint",
|
||||||
help = @HelpInfo(anchor = "colors"))
|
help = @HelpInfo(anchor = "colors")
|
||||||
|
)
|
||||||
private boolean breakpointEnabledColoringBackground =
|
private boolean breakpointEnabledColoringBackground =
|
||||||
DebuggerResources.DEFAULT_COLOR_ENABLED_BREAKPOINT_COLORING_BACKGROUND;
|
DebuggerResources.DEFAULT_COLOR_ENABLED_BREAKPOINT_COLORING_BACKGROUND;
|
||||||
|
|
||||||
@AutoOptionDefined(
|
@AutoOptionDefined(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_DISABLED_BREAKPOINT_COLORING_BACKGROUND,
|
name = DebuggerResources.OPTION_NAME_COLORS_DISABLED_BREAKPOINT_COLORING_BACKGROUND,
|
||||||
description = "Whether or not to color background for memory at a disabled breakpoint",
|
description = "Whether or not to color background for memory at a disabled breakpoint",
|
||||||
help = @HelpInfo(anchor = "colors"))
|
help = @HelpInfo(anchor = "colors")
|
||||||
|
)
|
||||||
private boolean breakpointDisabledColoringBackground =
|
private boolean breakpointDisabledColoringBackground =
|
||||||
DebuggerResources.DEFAULT_COLOR_DISABLED_BREAKPOINT_COLORING_BACKGROUND;
|
DebuggerResources.DEFAULT_COLOR_DISABLED_BREAKPOINT_COLORING_BACKGROUND;
|
||||||
|
|
||||||
@AutoOptionDefined(
|
@AutoOptionDefined(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_EN_BREAKPOINT_COLORING_BACKGROUND,
|
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_EN_BREAKPOINT_COLORING_BACKGROUND,
|
||||||
description = "Whether or not to color background for memory at an enabled, but ineffective, breakpoint",
|
description = "Whether or not to color background for memory at an enabled, but ineffective, breakpoint",
|
||||||
help = @HelpInfo(anchor = "colors"))
|
help = @HelpInfo(anchor = "colors")
|
||||||
|
)
|
||||||
private boolean breakpointIneffEnColoringBackground =
|
private boolean breakpointIneffEnColoringBackground =
|
||||||
DebuggerResources.DEFAULT_COLOR_INEFF_EN_BREAKPOINT_COLORING_BACKGROUND;
|
DebuggerResources.DEFAULT_COLOR_INEFF_EN_BREAKPOINT_COLORING_BACKGROUND;
|
||||||
|
|
||||||
@AutoOptionDefined(
|
@AutoOptionDefined(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_DIS_BREAKPOINT_COLORING_BACKGROUND,
|
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_DIS_BREAKPOINT_COLORING_BACKGROUND,
|
||||||
description = "Whether or not to color background for memory at an disabled, but ineffective, breakpoint",
|
description = "Whether or not to color background for memory at an disabled, but ineffective, breakpoint",
|
||||||
help = @HelpInfo(anchor = "colors"))
|
help = @HelpInfo(anchor = "colors")
|
||||||
|
)
|
||||||
private boolean breakpointIneffDisColoringBackground =
|
private boolean breakpointIneffDisColoringBackground =
|
||||||
DebuggerResources.DEFAULT_COLOR_INEFF_DIS_BREAKPOINT_COLORING_BACKGROUND;
|
DebuggerResources.DEFAULT_COLOR_INEFF_DIS_BREAKPOINT_COLORING_BACKGROUND;
|
||||||
|
|
||||||
@@ -832,7 +837,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AutoOptionConsumed(
|
@AutoOptionConsumed(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_ENABLED_BREAKPOINT_COLORING_BACKGROUND)
|
name = DebuggerResources.OPTION_NAME_COLORS_ENABLED_BREAKPOINT_COLORING_BACKGROUND
|
||||||
|
)
|
||||||
private void setEnabledBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
private void setEnabledBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
||||||
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
||||||
markers.setEnabledColoringBackground(breakpointColoringBackground);
|
markers.setEnabledColoringBackground(breakpointColoringBackground);
|
||||||
@@ -840,7 +846,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AutoOptionConsumed(
|
@AutoOptionConsumed(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_DISABLED_BREAKPOINT_COLORING_BACKGROUND)
|
name = DebuggerResources.OPTION_NAME_COLORS_DISABLED_BREAKPOINT_COLORING_BACKGROUND
|
||||||
|
)
|
||||||
private void setDisabledBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
private void setDisabledBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
||||||
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
||||||
markers.setDisabledColoringBackground(breakpointColoringBackground);
|
markers.setDisabledColoringBackground(breakpointColoringBackground);
|
||||||
@@ -848,7 +855,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AutoOptionConsumed(
|
@AutoOptionConsumed(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_EN_BREAKPOINT_COLORING_BACKGROUND)
|
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_EN_BREAKPOINT_COLORING_BACKGROUND
|
||||||
|
)
|
||||||
private void setIneffectiveEBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
private void setIneffectiveEBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
||||||
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
||||||
markers.setIneffectiveEnabledColoringBackground(breakpointColoringBackground);
|
markers.setIneffectiveEnabledColoringBackground(breakpointColoringBackground);
|
||||||
@@ -856,7 +864,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AutoOptionConsumed(
|
@AutoOptionConsumed(
|
||||||
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_DIS_BREAKPOINT_COLORING_BACKGROUND)
|
name = DebuggerResources.OPTION_NAME_COLORS_INEFF_DIS_BREAKPOINT_COLORING_BACKGROUND
|
||||||
|
)
|
||||||
private void setIneffectiveDBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
private void setIneffectiveDBreakpointMarkerBackground(boolean breakpointColoringBackground) {
|
||||||
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
for (BreakpointMarkerSets markers : markersByProgram.values()) {
|
||||||
markers.setIneffectiveDisabledColoringBackground(breakpointColoringBackground);
|
markers.setIneffectiveDisabledColoringBackground(breakpointColoringBackground);
|
||||||
@@ -1089,7 +1098,8 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin {
|
|||||||
actionDisableBreakpoint = new DisableBreakpointAction();
|
actionDisableBreakpoint = new DisableBreakpointAction();
|
||||||
actionClearBreakpoint = new ClearBreakpointAction();
|
actionClearBreakpoint = new ClearBreakpointAction();
|
||||||
|
|
||||||
tool.setMenuGroup(new String[] { SetBreakpointAction.NAME }, SetBreakpointAction.GROUP);
|
tool.setMenuGroup(new String[] { AbstractSetBreakpointAction.NAME },
|
||||||
|
SetBreakpointAction.GROUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+3
-3
@@ -198,7 +198,7 @@ public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin<DebuggerLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void locationChanged(CodeViewerProvider provider, ProgramLocation location) {
|
public void broadcastLocationChanged(CodeViewerProvider provider, ProgramLocation location) {
|
||||||
// TODO: Fix cursor?
|
// TODO: Fix cursor?
|
||||||
// Do not fire ProgramLocationPluginEvent.
|
// Do not fire ProgramLocationPluginEvent.
|
||||||
if (provider == connectedProvider) {
|
if (provider == connectedProvider) {
|
||||||
@@ -207,7 +207,7 @@ public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin<DebuggerLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectionChanged(CodeViewerProvider provider, ProgramSelection selection) {
|
public void broadcastSelectionChanged(CodeViewerProvider provider, ProgramSelection selection) {
|
||||||
if (provider != connectedProvider) {
|
if (provider != connectedProvider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin<DebuggerLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void highlightChanged(CodeViewerProvider provider, ProgramSelection highlight) {
|
public void broadcastHighlightChanged(CodeViewerProvider provider, ProgramSelection highlight) {
|
||||||
if (provider != connectedProvider) {
|
if (provider != connectedProvider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-27
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.listing;
|
package ghidra.app.plugin.core.debug.gui.listing;
|
||||||
|
|
||||||
import static ghidra.app.plugin.core.debug.gui.DebuggerResources.ICON_REGISTER_MARKER;
|
import static ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
@@ -130,13 +130,6 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class MarkerSetChangeListener implements ChangeListener {
|
|
||||||
@Override
|
|
||||||
public void stateChanged(ChangeEvent e) {
|
|
||||||
getListingPanel().getFieldPanel().repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class ForStaticSyncMappingChangeListener
|
protected class ForStaticSyncMappingChangeListener
|
||||||
implements DebuggerStaticMappingChangeListener {
|
implements DebuggerStaticMappingChangeListener {
|
||||||
@Override
|
@Override
|
||||||
@@ -335,7 +328,6 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||||||
protected final JLabel trackingLabel = new JLabel();
|
protected final JLabel trackingLabel = new JLabel();
|
||||||
|
|
||||||
protected final MultiBlendedListingBackgroundColorModel colorModel;
|
protected final MultiBlendedListingBackgroundColorModel colorModel;
|
||||||
protected final MarkerSetChangeListener markerChangeListener = new MarkerSetChangeListener();
|
|
||||||
protected MarkerServiceBackgroundColorModel markerServiceColorModel;
|
protected MarkerServiceBackgroundColorModel markerServiceColorModel;
|
||||||
protected MarkerMarginProvider markerMarginProvider;
|
protected MarkerMarginProvider markerMarginProvider;
|
||||||
protected MarkerOverviewProvider markerOverviewProvider;
|
protected MarkerOverviewProvider markerOverviewProvider;
|
||||||
@@ -573,28 +565,13 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||||||
|
|
||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
private void setMarkerService(MarkerService markerService) {
|
private void setMarkerService(MarkerService markerService) {
|
||||||
if (this.markerService != null) {
|
ListingPanel listingPanel = getListingPanel();
|
||||||
this.markerService.removeChangeListener(markerChangeListener);
|
listingPanel.setMarkerService(markerService);
|
||||||
removeMarginProvider(markerMarginProvider);
|
|
||||||
markerMarginProvider = null;
|
|
||||||
removeOverviewProvider(markerOverviewProvider);
|
|
||||||
markerOverviewProvider = null;
|
|
||||||
}
|
|
||||||
removeOldStaticTrackingMarker();
|
removeOldStaticTrackingMarker();
|
||||||
this.markerService = markerService;
|
this.markerService = markerService;
|
||||||
createNewStaticTrackingMarker();
|
createNewStaticTrackingMarker();
|
||||||
updateMarkerServiceColorModel();
|
updateMarkerServiceColorModel();
|
||||||
|
|
||||||
if (this.markerService != null && !isMainListing()) {
|
|
||||||
// NOTE: Connected provider marker listener is taken care of by CodeBrowserPlugin
|
|
||||||
this.markerService.addChangeListener(markerChangeListener);
|
|
||||||
}
|
|
||||||
if (this.markerService != null) {
|
|
||||||
markerMarginProvider = markerService.createMarginProvider();
|
|
||||||
addMarginProvider(markerMarginProvider);
|
|
||||||
markerOverviewProvider = markerService.createOverviewProvider();
|
|
||||||
addOverviewProvider(markerOverviewProvider);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
|
|||||||
+10
-5
@@ -24,7 +24,7 @@ import javax.swing.*;
|
|||||||
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.util.viewer.listingpanel.OverviewProvider;
|
import ghidra.app.util.viewer.listingpanel.ListingOverviewProvider;
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
@@ -35,7 +35,7 @@ import ghidra.util.task.SwingUpdateManager;
|
|||||||
* Overview bar component. Uses color to indicate various snap-based properties for a program.
|
* Overview bar component. Uses color to indicate various snap-based properties for a program.
|
||||||
* Uses an {@link TimeOverviewColorService} to get the appropriate color for a snaps.
|
* Uses an {@link TimeOverviewColorService} to get the appropriate color for a snaps.
|
||||||
*/
|
*/
|
||||||
public class TimeOverviewColorComponent extends JPanel implements OverviewProvider {
|
public class TimeOverviewColorComponent extends JPanel implements ListingOverviewProvider {
|
||||||
private static final Color DEFAULT_COLOR = Color.GRAY;
|
private static final Color DEFAULT_COLOR = Color.GRAY;
|
||||||
protected TimeOverviewColorService service;
|
protected TimeOverviewColorService service;
|
||||||
private Color[] colorsByPixel = new Color[0];
|
private Color[] colorsByPixel = new Color[0];
|
||||||
@@ -101,7 +101,7 @@ public class TimeOverviewColorComponent extends JPanel implements OverviewProvid
|
|||||||
stop = start;
|
stop = start;
|
||||||
start = tmp;
|
start = tmp;
|
||||||
}
|
}
|
||||||
span = Lifespan.span(start, stop);
|
span = Lifespan.span(start, stop);
|
||||||
}
|
}
|
||||||
plugin.setLifespan(span);
|
plugin.setLifespan(span);
|
||||||
enableDrag = false;
|
enableDrag = false;
|
||||||
@@ -113,6 +113,11 @@ public class TimeOverviewColorComponent extends JPanel implements OverviewProvid
|
|||||||
actions = service.getActions();
|
actions = service.getActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
uninstallActions();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs actions for this component
|
* Installs actions for this component
|
||||||
*/
|
*/
|
||||||
@@ -233,13 +238,13 @@ public class TimeOverviewColorComponent extends JPanel implements OverviewProvid
|
|||||||
public Lifespan getLifespan() {
|
public Lifespan getLifespan() {
|
||||||
return service.getBounds();
|
return service.getBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLifespan(Lifespan bounds) {
|
public void setLifespan(Lifespan bounds) {
|
||||||
service.setBounds(bounds);
|
service.setBounds(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgram(Program program, AddressIndexMap map) {
|
public void screenDataChanged(Program program, AddressIndexMap map) {
|
||||||
// Ignored
|
// Ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -221,8 +221,8 @@ public class TimeOverviewColorPlugin extends AbstractDebuggerPlugin {
|
|||||||
|
|
||||||
private void uninstallOverview(TimeOverviewColorService overviewColorService) {
|
private void uninstallOverview(TimeOverviewColorService overviewColorService) {
|
||||||
TimeOverviewColorComponent overviewComponent = activeServices.get(overviewColorService);
|
TimeOverviewColorComponent overviewComponent = activeServices.get(overviewColorService);
|
||||||
overviewComponent.uninstallActions();
|
|
||||||
listingService.removeOverviewProvider(overviewComponent);
|
listingService.removeOverviewProvider(overviewComponent);
|
||||||
|
overviewComponent.dispose();
|
||||||
activeServices.remove(overviewColorService);
|
activeServices.remove(overviewColorService);
|
||||||
overviewColorService.setTrace(null);
|
overviewColorService.setTrace(null);
|
||||||
}
|
}
|
||||||
|
|||||||
+241
-255
File diff suppressed because it is too large
Load Diff
+22
-32
@@ -97,22 +97,21 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void highlightChanged(CodeViewerProvider provider, ProgramSelection highlight) {
|
public void broadcastHighlightChanged(CodeViewerProvider provider, ProgramSelection highlight) {
|
||||||
MarkerSet highlightMarkers = getHighlightMarkers(currentProgram);
|
|
||||||
if (highlightMarkers != null) {
|
|
||||||
highlightMarkers.clearAll();
|
|
||||||
}
|
|
||||||
if (highlight != null && currentProgram != null) {
|
|
||||||
if (highlightMarkers != null) {
|
|
||||||
highlightMarkers.add(highlight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (provider == connectedProvider) {
|
if (provider == connectedProvider) {
|
||||||
tool.firePluginEvent(new ProgramHighlightPluginEvent(getName(), highlight,
|
tool.firePluginEvent(new ProgramHighlightPluginEvent(getName(), highlight,
|
||||||
connectedProvider.getProgram()));
|
connectedProvider.getProgram()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcastLocationChanged(CodeViewerProvider provider, ProgramLocation location) {
|
||||||
|
if (provider == connectedProvider) {
|
||||||
|
tool.firePluginEvent(new ProgramLocationPluginEvent(getName(), location,
|
||||||
|
connectedProvider.getProgram()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processEvent(PluginEvent event) {
|
public void processEvent(PluginEvent event) {
|
||||||
if (event instanceof ProgramClosedPluginEvent) {
|
if (event instanceof ProgramClosedPluginEvent) {
|
||||||
@@ -125,7 +124,7 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
currentProgram.removeListener(this);
|
currentProgram.removeListener(this);
|
||||||
}
|
}
|
||||||
ProgramActivatedPluginEvent evt = (ProgramActivatedPluginEvent) event;
|
ProgramActivatedPluginEvent evt = (ProgramActivatedPluginEvent) event;
|
||||||
clearMarkers(currentProgram); // do this just before changing the program
|
connectedProvider.clearMarkers(currentProgram); // do this before changing the program
|
||||||
|
|
||||||
currentProgram = evt.getActiveProgram();
|
currentProgram = evt.getActiveProgram();
|
||||||
if (currentProgram != null) {
|
if (currentProgram != null) {
|
||||||
@@ -135,12 +134,13 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
else {
|
else {
|
||||||
currentView = new AddressSet();
|
currentView = new AddressSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedProvider.doSetProgram(currentProgram);
|
connectedProvider.doSetProgram(currentProgram);
|
||||||
|
|
||||||
updateHighlightProvider();
|
connectedProvider.updateHighlightProvider();
|
||||||
updateBackgroundColorModel();
|
updateBackgroundColorModel(connectedProvider);
|
||||||
setHighlight(new FieldSelection());
|
setConnectedProviderHighlight(new FieldSelection());
|
||||||
setSelection(new ProgramSelection());
|
setConnectedProviderSelection(new ProgramSelection());
|
||||||
}
|
}
|
||||||
else if (event instanceof ProgramLocationPluginEvent) {
|
else if (event instanceof ProgramLocationPluginEvent) {
|
||||||
ProgramLocationPluginEvent evt = (ProgramLocationPluginEvent) event;
|
ProgramLocationPluginEvent evt = (ProgramLocationPluginEvent) event;
|
||||||
@@ -156,12 +156,12 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
}
|
}
|
||||||
else if (event instanceof ProgramSelectionPluginEvent) {
|
else if (event instanceof ProgramSelectionPluginEvent) {
|
||||||
ProgramSelectionPluginEvent evt = (ProgramSelectionPluginEvent) event;
|
ProgramSelectionPluginEvent evt = (ProgramSelectionPluginEvent) event;
|
||||||
setSelection(evt.getSelection());
|
setConnectedProviderSelection(evt.getSelection());
|
||||||
}
|
}
|
||||||
else if (event instanceof ProgramHighlightPluginEvent) {
|
else if (event instanceof ProgramHighlightPluginEvent) {
|
||||||
ProgramHighlightPluginEvent evt = (ProgramHighlightPluginEvent) event;
|
ProgramHighlightPluginEvent evt = (ProgramHighlightPluginEvent) event;
|
||||||
if (evt.getProgram() == currentProgram) {
|
if (evt.getProgram() == currentProgram) {
|
||||||
setHighlight(evt.getHighlight());
|
connectedProvider.setHighlight(evt.getHighlight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event instanceof ViewChangedPluginEvent) {
|
else if (event instanceof ViewChangedPluginEvent) {
|
||||||
@@ -206,10 +206,13 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
if (location != null) {
|
if (location != null) {
|
||||||
connectedProvider.setLocation(location);
|
connectedProvider.setLocation(location);
|
||||||
}
|
}
|
||||||
setHighlight(highlight);
|
|
||||||
|
connectedProvider.setHighlight(highlight);
|
||||||
|
|
||||||
if (selection != null) {
|
if (selection != null) {
|
||||||
connectedProvider.setSelection(selection);
|
connectedProvider.setSelection(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vp != null) {
|
if (vp != null) {
|
||||||
FieldPanel fieldPanel = connectedProvider.getListingPanel().getFieldPanel();
|
FieldPanel fieldPanel = connectedProvider.getListingPanel().getFieldPanel();
|
||||||
fieldPanel.setViewerPosition(vp.getIndex(), vp.getXOffset(), vp.getYOffset());
|
fieldPanel.setViewerPosition(vp.getIndex(), vp.getXOffset(), vp.getYOffset());
|
||||||
@@ -268,7 +271,7 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
FieldSelection highlight = new FieldSelection();
|
FieldSelection highlight = new FieldSelection();
|
||||||
highlight.load(saveState);
|
highlight.load(saveState);
|
||||||
if (!highlight.isEmpty()) {
|
if (!highlight.isEmpty()) {
|
||||||
setHighlight(highlight);
|
setConnectedProviderHighlight(highlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,19 +289,6 @@ public class CodeBrowserPlugin extends AbstractCodeBrowserPlugin<CodeViewerProvi
|
|||||||
connectedProvider.readState(saveState);
|
connectedProvider.readState(saveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void locationChanged(CodeViewerProvider provider, ProgramLocation location) {
|
|
||||||
if (provider == connectedProvider) {
|
|
||||||
MarkerSet cursorMarkers = getCursorMarkers(currentProgram);
|
|
||||||
if (cursorMarkers != null) {
|
|
||||||
cursorMarkers.clearAll();
|
|
||||||
cursorMarkers.add(location.getAddress());
|
|
||||||
}
|
|
||||||
tool.firePluginEvent(new ProgramLocationPluginEvent(getName(), location,
|
|
||||||
connectedProvider.getProgram()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewManagerService getViewManager(CodeViewerProvider codeViewerProvider) {
|
public ViewManagerService getViewManager(CodeViewerProvider codeViewerProvider) {
|
||||||
if (codeViewerProvider == connectedProvider) {
|
if (codeViewerProvider == connectedProvider) {
|
||||||
|
|||||||
+11
-13
@@ -1,13 +1,12 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -23,22 +22,21 @@ import ghidra.program.util.ProgramSelection;
|
|||||||
|
|
||||||
public interface CodeBrowserPluginInterface {
|
public interface CodeBrowserPluginInterface {
|
||||||
|
|
||||||
PluginTool getTool();
|
public PluginTool getTool();
|
||||||
|
|
||||||
String getName();
|
public String getName();
|
||||||
|
|
||||||
void providerClosed(CodeViewerProvider codeViewerProvider);
|
public boolean isDisposed();
|
||||||
|
|
||||||
boolean isDisposed();
|
public void providerClosed(CodeViewerProvider provider);
|
||||||
|
|
||||||
void locationChanged(CodeViewerProvider codeViewerProvider, ProgramLocation loc);
|
public void broadcastLocationChanged(CodeViewerProvider provider, ProgramLocation loc);
|
||||||
|
|
||||||
void selectionChanged(CodeViewerProvider codeViewerProvider, ProgramSelection currentSelection);
|
public void broadcastSelectionChanged(CodeViewerProvider provider, ProgramSelection selection);
|
||||||
|
|
||||||
void highlightChanged(CodeViewerProvider codeViewerProvider, ProgramSelection highlight);
|
public void broadcastHighlightChanged(CodeViewerProvider provider, ProgramSelection highlight);
|
||||||
|
|
||||||
ViewManagerService getViewManager(CodeViewerProvider codeViewerProvider);
|
public ViewManagerService getViewManager(CodeViewerProvider provider);
|
||||||
|
|
||||||
CodeViewerProvider createNewDisconnectedProvider();
|
|
||||||
|
|
||||||
|
public CodeViewerProvider createNewDisconnectedProvider();
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-45
@@ -20,7 +20,6 @@ import java.awt.Point;
|
|||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
import java.awt.dnd.*;
|
import java.awt.dnd.*;
|
||||||
import java.awt.event.MouseAdapter;
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -112,7 +111,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
liveSelection = selection;
|
liveSelection = selection;
|
||||||
updateSubTitle();
|
updateSubTitle();
|
||||||
};
|
};
|
||||||
private FocusingMouseListener focusingMouseListener;
|
|
||||||
|
|
||||||
private CodeBrowserClipboardProvider codeViewerClipboardProvider;
|
private CodeBrowserClipboardProvider codeViewerClipboardProvider;
|
||||||
private ClipboardService clipboardService;
|
private ClipboardService clipboardService;
|
||||||
@@ -151,6 +149,11 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
setDefaultWindowPosition(WindowPosition.RIGHT);
|
setDefaultWindowPosition(WindowPosition.RIGHT);
|
||||||
|
|
||||||
listingPanel = new ListingPanel(formatMgr);
|
listingPanel = new ListingPanel(formatMgr);
|
||||||
|
if (!isConnected) {
|
||||||
|
// update the marker set names to be unique so that each listing can have its own
|
||||||
|
listingPanel.setUseMarkerNameSuffix(true);
|
||||||
|
}
|
||||||
|
|
||||||
listingPanel.enablePropertyBasedColorModel(true);
|
listingPanel.enablePropertyBasedColorModel(true);
|
||||||
|
|
||||||
decorationPanel = new ListingPanelContainer(listingPanel, isConnected);
|
decorationPanel = new ListingPanelContainer(listingPanel, isConnected);
|
||||||
@@ -253,6 +256,8 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
public void dispose() {
|
public void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
||||||
|
clearMarkers(program);
|
||||||
|
|
||||||
tool.removePopupActionProvider(this);
|
tool.removePopupActionProvider(this);
|
||||||
|
|
||||||
if (clipboardService != null) {
|
if (clipboardService != null) {
|
||||||
@@ -324,8 +329,8 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
|
|
||||||
private Object getContextForMarginPanels(ListingPanel lp, MouseEvent event) {
|
private Object getContextForMarginPanels(ListingPanel lp, MouseEvent event) {
|
||||||
Object source = event.getSource();
|
Object source = event.getSource();
|
||||||
List<MarginProvider> marginProviders = lp.getMarginProviders();
|
List<ListingMarginProvider> marginProviders = lp.getMarginProviders();
|
||||||
for (MarginProvider marginProvider : marginProviders) {
|
for (ListingMarginProvider marginProvider : marginProviders) {
|
||||||
JComponent c = marginProvider.getComponent();
|
JComponent c = marginProvider.getComponent();
|
||||||
if (c == source) {
|
if (c == source) {
|
||||||
MarkerLocation loc = marginProvider.getMarkerLocation(event.getX(), event.getY());
|
MarkerLocation loc = marginProvider.getMarkerLocation(event.getX(), event.getY());
|
||||||
@@ -337,8 +342,8 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<OverviewProvider> overviewProviders = lp.getOverviewProviders();
|
List<ListingOverviewProvider> overviewProviders = lp.getOverviewProviders();
|
||||||
for (OverviewProvider overviewProvider : overviewProviders) {
|
for (ListingOverviewProvider overviewProvider : overviewProviders) {
|
||||||
JComponent c = overviewProvider.getComponent();
|
JComponent c = overviewProvider.getComponent();
|
||||||
if (c == source) {
|
if (c == source) {
|
||||||
return source;
|
return source;
|
||||||
@@ -444,6 +449,10 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
contextChanged();
|
contextChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearMarkers(Program p) {
|
||||||
|
listingPanel.clearMarkers(p);
|
||||||
|
}
|
||||||
|
|
||||||
protected void updateTitle() {
|
protected void updateTitle() {
|
||||||
String subTitle = program == null ? "" : ' ' + program.getDomainFile().getName();
|
String subTitle = program == null ? "" : ' ' + program.getDomainFile().getName();
|
||||||
String newTitle = TITLE + subTitle;
|
String newTitle = TITLE + subTitle;
|
||||||
@@ -657,6 +666,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// events coming from the ListingPanel
|
||||||
@Override
|
@Override
|
||||||
public void programLocationChanged(ProgramLocation loc, EventTrigger trigger) {
|
public void programLocationChanged(ProgramLocation loc, EventTrigger trigger) {
|
||||||
if (plugin.isDisposed()) {
|
if (plugin.isDisposed()) {
|
||||||
@@ -665,7 +675,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
if (!loc.equals(currentLocation)) {
|
if (!loc.equals(currentLocation)) {
|
||||||
codeViewerClipboardProvider.setLocation(loc);
|
codeViewerClipboardProvider.setLocation(loc);
|
||||||
currentLocation = loc;
|
currentLocation = loc;
|
||||||
plugin.locationChanged(this, loc);
|
plugin.broadcastLocationChanged(this, loc);
|
||||||
contextChanged();
|
contextChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -696,7 +706,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
currentSelection = selection;
|
currentSelection = selection;
|
||||||
codeViewerClipboardProvider.setSelection(currentSelection);
|
codeViewerClipboardProvider.setSelection(currentSelection);
|
||||||
listingPanel.setSelection(currentSelection);
|
listingPanel.setSelection(currentSelection);
|
||||||
plugin.selectionChanged(this, currentSelection);
|
plugin.broadcastSelectionChanged(this, currentSelection);
|
||||||
contextChanged();
|
contextChanged();
|
||||||
updateSubTitle();
|
updateSubTitle();
|
||||||
}
|
}
|
||||||
@@ -792,7 +802,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
private void doSetHighlight(ProgramSelection highlight) {
|
private void doSetHighlight(ProgramSelection highlight) {
|
||||||
listingPanel.setHighlight(highlight);
|
listingPanel.setHighlight(highlight);
|
||||||
currentHighlight = highlight;
|
currentHighlight = highlight;
|
||||||
plugin.highlightChanged(this, highlight);
|
plugin.broadcastHighlightChanged(this, highlight);
|
||||||
contextChanged();
|
contextChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,45 +1171,51 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
listingPanel.removeDisplayListener(listener);
|
listingPanel.removeDisplayListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void createFocusingMouseListener() {
|
public void addOverviewProvider(ListingOverviewProvider overviewProvider) {
|
||||||
if (focusingMouseListener == null) {
|
|
||||||
focusingMouseListener = new FocusingMouseListener();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addOverviewProvider(OverviewProvider overviewProvider) {
|
|
||||||
createFocusingMouseListener();
|
|
||||||
JComponent component = overviewProvider.getComponent();
|
|
||||||
|
|
||||||
// just in case we get repeated calls
|
|
||||||
component.removeMouseListener(focusingMouseListener);
|
|
||||||
component.addMouseListener(focusingMouseListener);
|
|
||||||
overviewProvider.setNavigatable(this);
|
overviewProvider.setNavigatable(this);
|
||||||
getListingPanel().addOverviewProvider(overviewProvider);
|
getListingPanel().addOverviewProvider(overviewProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMarginProvider(MarginProvider marginProvider) {
|
public void removeOverviewProvider(ListingOverviewProvider overviewProvider) {
|
||||||
createFocusingMouseListener();
|
|
||||||
JComponent component = marginProvider.getComponent();
|
|
||||||
|
|
||||||
// just in case we get repeated calls
|
|
||||||
component.removeMouseListener(focusingMouseListener);
|
|
||||||
component.addMouseListener(focusingMouseListener);
|
|
||||||
getListingPanel().addMarginProvider(marginProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeOverviewProvider(OverviewProvider overviewProvider) {
|
|
||||||
JComponent component = overviewProvider.getComponent();
|
|
||||||
component.removeMouseListener(focusingMouseListener);
|
|
||||||
getListingPanel().removeOverviewProvider(overviewProvider);
|
getListingPanel().removeOverviewProvider(overviewProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeMarginProvider(MarginProvider marginProvider) {
|
public void addMarginProvider(ListingMarginProvider marginProvider) {
|
||||||
JComponent component = marginProvider.getComponent();
|
getListingPanel().addMarginProvider(marginProvider);
|
||||||
component.removeMouseListener(focusingMouseListener);
|
}
|
||||||
|
|
||||||
|
public void removeMarginProvider(ListingMarginProvider marginProvider) {
|
||||||
getListingPanel().removeMarginProvider(marginProvider);
|
getListingPanel().removeMarginProvider(marginProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addMarginService(ListingMarginProviderService service) {
|
||||||
|
getListingPanel().addMarginService(service, isConnected());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOverviewService(ListingOverviewProviderService service) {
|
||||||
|
getListingPanel().addOverviewService(service, this, isConnected());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOverviewService(ListingOverviewProviderService service) {
|
||||||
|
getListingPanel().removeOverviewService(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMarginService(ListingMarginProviderService service) {
|
||||||
|
getListingPanel().removeMarginService(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHoverService(ListingHoverService hoverService) {
|
||||||
|
getListingPanel().addHoverService(hoverService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeHoverService(ListingHoverService hoverService) {
|
||||||
|
getListingPanel().removeHoverService(hoverService);
|
||||||
|
|
||||||
|
if (otherPanel != null) {
|
||||||
|
otherPanel.removeHoverService(hoverService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@@ -1280,11 +1296,4 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
return list.toArray(new Highlight[list.size()]);
|
return list.toArray(new Highlight[list.size()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FocusingMouseListener extends MouseAdapter {
|
|
||||||
@Override
|
|
||||||
public void mousePressed(MouseEvent e) {
|
|
||||||
getListingPanel().getFieldPanel().requestFocus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-8
@@ -1,13 +1,12 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -16,11 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.flowarrow;
|
package ghidra.app.plugin.core.flowarrow;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
class ConditionalFlowArrow extends FlowArrow {
|
class ConditionalFlowArrow extends FlowArrow {
|
||||||
|
|
||||||
private static final Stroke CONDITIONAL_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
private static final Stroke CONDITIONAL_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
||||||
@@ -28,9 +27,9 @@ class ConditionalFlowArrow extends FlowArrow {
|
|||||||
private static final Stroke NORMAL_ACTIVE_STROKE = new BasicStroke(2, BasicStroke.CAP_SQUARE,
|
private static final Stroke NORMAL_ACTIVE_STROKE = new BasicStroke(2, BasicStroke.CAP_SQUARE,
|
||||||
BasicStroke.JOIN_MITER);
|
BasicStroke.JOIN_MITER);
|
||||||
|
|
||||||
ConditionalFlowArrow(FlowArrowPlugin plugin, Component canvas, Address start, Address end,
|
ConditionalFlowArrow(FlowArrowMarginProvider provider, Component canvas, Address start,
|
||||||
RefType referenceType) {
|
Address end, RefType referenceType) {
|
||||||
super(plugin, canvas, start, end, referenceType);
|
super(provider, canvas, start, end, referenceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+6
-7
@@ -1,13 +1,12 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -16,11 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.flowarrow;
|
package ghidra.app.plugin.core.flowarrow;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
class DefaultFlowArrow extends FlowArrow {
|
class DefaultFlowArrow extends FlowArrow {
|
||||||
|
|
||||||
private static final Stroke NORMAL_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
private static final Stroke NORMAL_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
||||||
@@ -28,9 +27,9 @@ class DefaultFlowArrow extends FlowArrow {
|
|||||||
private static final Stroke NORMAL_ACTIVE_STROKE = new BasicStroke(2, BasicStroke.CAP_SQUARE,
|
private static final Stroke NORMAL_ACTIVE_STROKE = new BasicStroke(2, BasicStroke.CAP_SQUARE,
|
||||||
BasicStroke.JOIN_MITER);
|
BasicStroke.JOIN_MITER);
|
||||||
|
|
||||||
DefaultFlowArrow(FlowArrowPlugin plugin, Component canvas, Address start, Address end,
|
DefaultFlowArrow(FlowArrowMarginProvider provider, Component canvas, Address start, Address end,
|
||||||
RefType referenceType) {
|
RefType referenceType) {
|
||||||
super(plugin, canvas, start, end, referenceType);
|
super(provider, canvas, start, end, referenceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+7
-8
@@ -1,13 +1,12 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -16,11 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.flowarrow;
|
package ghidra.app.plugin.core.flowarrow;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
class FallthroughFlowArrow extends FlowArrow {
|
class FallthroughFlowArrow extends FlowArrow {
|
||||||
|
|
||||||
private static final Stroke FALLTHROUGH_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
private static final Stroke FALLTHROUGH_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
||||||
@@ -28,9 +27,9 @@ class FallthroughFlowArrow extends FlowArrow {
|
|||||||
private static final Stroke FALLTHROUGH_ACTIVE_STROKE = new BasicStroke(2,
|
private static final Stroke FALLTHROUGH_ACTIVE_STROKE = new BasicStroke(2,
|
||||||
BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10, new float[] { 8, 3, 2, 3 }, 0);
|
BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10, new float[] { 8, 3, 2, 3 }, 0);
|
||||||
|
|
||||||
FallthroughFlowArrow(FlowArrowPlugin plugin, Component canvas, Address start, Address end,
|
FallthroughFlowArrow(FlowArrowMarginProvider provider, Component canvas, Address start,
|
||||||
RefType referenceType) {
|
Address end, RefType referenceType) {
|
||||||
super(plugin, canvas, start, end, referenceType);
|
super(provider, canvas, start, end, referenceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+33
-22
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.flowarrow;
|
package ghidra.app.plugin.core.flowarrow;
|
||||||
|
|
||||||
|
import static ghidra.util.HTMLUtilities.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.PathIterator;
|
import java.awt.geom.PathIterator;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
@@ -23,7 +25,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
import ghidra.util.HTMLUtilities;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
abstract class FlowArrow {
|
abstract class FlowArrow {
|
||||||
@@ -36,15 +37,16 @@ abstract class FlowArrow {
|
|||||||
|
|
||||||
Address start;
|
Address start;
|
||||||
Address end;
|
Address end;
|
||||||
AddressSet addressSet;
|
AddressSet addresses;
|
||||||
int depth = -1;
|
int column = -1;
|
||||||
RefType refType;
|
RefType refType;
|
||||||
|
private int maxColumn;
|
||||||
private boolean isUp;
|
private boolean isUp;
|
||||||
|
|
||||||
boolean active;
|
boolean active;
|
||||||
boolean selected;
|
boolean selected;
|
||||||
|
|
||||||
private FlowArrowPlugin plugin;
|
private FlowArrowMarginProvider provider;
|
||||||
private Component canvas;
|
private Component canvas;
|
||||||
protected Shape arrowBody;
|
protected Shape arrowBody;
|
||||||
protected Shape arrowHead;
|
protected Shape arrowHead;
|
||||||
@@ -52,15 +54,16 @@ abstract class FlowArrow {
|
|||||||
/** The shape of the arrow body, but with added size */
|
/** The shape of the arrow body, but with added size */
|
||||||
private List<Shape> clickableShapes = new ArrayList<>();
|
private List<Shape> clickableShapes = new ArrayList<>();
|
||||||
|
|
||||||
FlowArrow(FlowArrowPlugin plugin, Component canvas, Address start, Address end,
|
FlowArrow(FlowArrowMarginProvider provider, Component canvas, Address start, Address end,
|
||||||
RefType referenceType) {
|
RefType referenceType) {
|
||||||
this.plugin = plugin;
|
this.provider = provider;
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.refType = referenceType;
|
this.refType = referenceType;
|
||||||
this.addressSet = new AddressSet(new AddressRangeImpl(start, end));
|
this.maxColumn = provider.getMaxColumn();
|
||||||
isUp = start.compareTo(end) > 0;
|
this.addresses = new AddressSet(new AddressRangeImpl(start, end));
|
||||||
|
this.isUp = start.compareTo(end) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract Stroke getSelectedStroke();
|
abstract Stroke getSelectedStroke();
|
||||||
@@ -101,7 +104,7 @@ abstract class FlowArrow {
|
|||||||
g2.setStroke(oldStroke);
|
g2.setStroke(oldStroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True if this arrow points up instead of down */
|
/** {@return true if this arrow points up instead of down} */
|
||||||
boolean isUp() {
|
boolean isUp() {
|
||||||
return isUp;
|
return isUp;
|
||||||
}
|
}
|
||||||
@@ -242,20 +245,20 @@ abstract class FlowArrow {
|
|||||||
int displayWidth = canvas.getWidth();// - FlowArrowPlugin.LEFT_OFFSET;
|
int displayWidth = canvas.getWidth();// - FlowArrowPlugin.LEFT_OFFSET;
|
||||||
int lineWidth = calculateLineWidth(displayWidth);
|
int lineWidth = calculateLineWidth(displayWidth);
|
||||||
|
|
||||||
arrowBody = FlowArrowShapeFactory.createArrowBody(plugin, this, displayWidth, displayHeight,
|
arrowBody =
|
||||||
lineWidth);
|
FlowArrowShapeFactory.createArrowBody(provider, this, displayWidth, displayHeight,
|
||||||
|
lineWidth);
|
||||||
|
|
||||||
arrowHead = FlowArrowShapeFactory.createArrowHead(plugin, this, displayWidth, displayHeight,
|
arrowHead =
|
||||||
lineWidth);
|
FlowArrowShapeFactory.createArrowHead(provider, this, displayWidth, displayHeight,
|
||||||
|
lineWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateLineWidth(int displayWidth) {
|
private int calculateLineWidth(int displayWidth) {
|
||||||
// Crunch or stretch spacing depending upon width and maximum depth
|
// Crunch or stretch spacing depending upon width and maximum depth
|
||||||
int lineWidth = DEFAULT_LINE_SPACING;
|
int lineWidth = DEFAULT_LINE_SPACING;
|
||||||
int maxDepth = plugin.getMaxDepth();
|
if (maxColumn >= 0) {
|
||||||
|
int availabeWidth = displayWidth - FlowArrowMarginProvider.LEFT_OFFSET;
|
||||||
if (maxDepth >= 0) {
|
|
||||||
int availabeWidth = displayWidth - FlowArrowPlugin.LEFT_OFFSET;
|
|
||||||
lineWidth = (int) (availabeWidth * ARROW_SPACING_RATIO);
|
lineWidth = (int) (availabeWidth * ARROW_SPACING_RATIO);
|
||||||
}
|
}
|
||||||
if (lineWidth < MIN_LINE_SPACING) {
|
if (lineWidth < MIN_LINE_SPACING) {
|
||||||
@@ -321,9 +324,17 @@ abstract class FlowArrow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getDisplayString() {
|
public String getDisplayString() {
|
||||||
return "<html><table><tr><td>start</td><td>" + HTMLUtilities.escapeHTML(start.toString()) +
|
//@formatter:off
|
||||||
"</td><tr><td>end</td><td>" + HTMLUtilities.escapeHTML(end.toString()) +
|
return """
|
||||||
"</td><tr><td>ref type</td><td>" + refType + "</td></tr></table>";
|
<html><table>
|
||||||
|
<tr><td>start</td><td>%s</td></tr>
|
||||||
|
<tr><td>end</td><td>%s</td></tr>
|
||||||
|
<tr><td>ref type</td><td>%s</td></tr>
|
||||||
|
</table>
|
||||||
|
""".formatted(escapeHTML(start.toString()),
|
||||||
|
escapeHTML(end.toString()),
|
||||||
|
refType).trim();
|
||||||
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+737
File diff suppressed because it is too large
Load Diff
+25
-27
@@ -36,7 +36,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
private Cursor clickCursor;
|
private Cursor clickCursor;
|
||||||
private Cursor defaultCursor;
|
private Cursor defaultCursor;
|
||||||
|
|
||||||
private FlowArrowPlugin plugin;
|
private FlowArrowMarginProvider provider;
|
||||||
private Color foregroundColor;
|
private Color foregroundColor;
|
||||||
private Color highlightColor;
|
private Color highlightColor;
|
||||||
private Color selectedColor;
|
private Color selectedColor;
|
||||||
@@ -44,8 +44,8 @@ class FlowArrowPanel extends JPanel {
|
|||||||
private SwingUpdateManager mouseClickUpdater;
|
private SwingUpdateManager mouseClickUpdater;
|
||||||
private Point pendingMouseClickPoint;
|
private Point pendingMouseClickPoint;
|
||||||
|
|
||||||
FlowArrowPanel(FlowArrowPlugin p) {
|
FlowArrowPanel(FlowArrowMarginProvider provider) {
|
||||||
this.plugin = p;
|
this.provider = provider;
|
||||||
setMinimumSize(new Dimension(0, 0));
|
setMinimumSize(new Dimension(0, 0));
|
||||||
setPreferredSize(new Dimension(32, 1));
|
setPreferredSize(new Dimension(32, 1));
|
||||||
|
|
||||||
@@ -110,18 +110,18 @@ class FlowArrowPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private FlowArrow getArrow(Point p) {
|
private FlowArrow getArrow(Point p) {
|
||||||
FlowArrow arrow = getArrow(p, plugin.getFlowArrowIterator());
|
FlowArrow arrow = getArrow(p, provider.getFlowArrowIterator());
|
||||||
if (arrow != null) {
|
if (arrow != null) {
|
||||||
return arrow;
|
return arrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try the arrows that hang around a bit
|
// try the arrows that hang around a bit
|
||||||
arrow = getArrow(p, plugin.getSelectedFlowArrows());
|
arrow = getArrow(p, provider.getSelectedFlowArrows());
|
||||||
if (arrow != null) {
|
if (arrow != null) {
|
||||||
return arrow;
|
return arrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getArrow(p, plugin.getActiveArrows());
|
return getArrow(p, provider.getActiveArrows());
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlowArrow getArrow(Point p, Iterator<FlowArrow> it) {
|
private FlowArrow getArrow(Point p, Iterator<FlowArrow> it) {
|
||||||
@@ -139,26 +139,24 @@ class FlowArrowPanel extends JPanel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO to do this, we should probably have another concept of 'navigated'/'current' as to not
|
|
||||||
// confuse the concept of selecting arrows
|
|
||||||
// select any arrow we double-click
|
// select any arrow we double-click
|
||||||
arrow.selected = true;
|
arrow.selected = true;
|
||||||
plugin.setArrowSelected(arrow, true);
|
provider.setArrowSelected(arrow, true);
|
||||||
|
|
||||||
Address end = arrow.end;
|
Address end = arrow.end;
|
||||||
if (end.equals(plugin.getCurrentAddress())) {
|
if (end.equals(provider.getCurrentAddress())) {
|
||||||
// go back the other direction
|
// go back the other direction
|
||||||
end = arrow.start;
|
end = arrow.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin.isOnScreen(end)) {
|
if (provider.isOnScreen(end)) {
|
||||||
// don't animate arrows completely on screen
|
// don't animate arrows completely on screen
|
||||||
plugin.goTo(end);
|
provider.goTo(end);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the animation at the edge of the screen
|
// Start the animation at the edge of the screen
|
||||||
Address start = plugin.getLastAddressOnScreen(end, arrow.isUp());
|
Address start = provider.getLastAddressOnScreen(end, arrow.isUp());
|
||||||
|
|
||||||
ScrollingCallback callback = new ScrollingCallback(start, end);
|
ScrollingCallback callback = new ScrollingCallback(start, end);
|
||||||
Animator animator = AnimationUtils.executeSwingAnimationCallback(callback);
|
Animator animator = AnimationUtils.executeSwingAnimationCallback(callback);
|
||||||
@@ -169,7 +167,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
FlowArrow arrow = getArrow(point);
|
FlowArrow arrow = getArrow(point);
|
||||||
if (arrow != null) {
|
if (arrow != null) {
|
||||||
arrow.selected = !arrow.selected; // toggle
|
arrow.selected = !arrow.selected; // toggle
|
||||||
plugin.setArrowSelected(arrow, arrow.selected);
|
provider.setArrowSelected(arrow, arrow.selected);
|
||||||
repaint();
|
repaint();
|
||||||
return; // only select one line at a time
|
return; // only select one line at a time
|
||||||
}
|
}
|
||||||
@@ -179,13 +177,13 @@ class FlowArrowPanel extends JPanel {
|
|||||||
public void setBounds(int x, int y, int width, int height) {
|
public void setBounds(int x, int y, int width, int height) {
|
||||||
// note: this gets called as the user drags the divider pane
|
// note: this gets called as the user drags the divider pane
|
||||||
super.setBounds(x, y, width, height);
|
super.setBounds(x, y, width, height);
|
||||||
plugin.updateAndRepaint();
|
provider.updateAndRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getToolTipText(MouseEvent e) {
|
public String getToolTipText(MouseEvent e) {
|
||||||
Point point = e.getPoint();
|
Point point = e.getPoint();
|
||||||
Iterator<FlowArrow> it = plugin.getFlowArrowIterator();
|
Iterator<FlowArrow> it = provider.getFlowArrowIterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
FlowArrow arrow = it.next();
|
FlowArrow arrow = it.next();
|
||||||
if (arrow.intersects(point)) {
|
if (arrow.intersects(point)) {
|
||||||
@@ -223,7 +221,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
|
|
||||||
super.paintComponent(g);
|
super.paintComponent(g);
|
||||||
|
|
||||||
Address currentAddress = plugin.getCurrentAddress();
|
Address currentAddress = provider.getCurrentAddress();
|
||||||
if (currentAddress == null) {
|
if (currentAddress == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,7 +233,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
//
|
//
|
||||||
// Non-selected arrows
|
// Non-selected arrows
|
||||||
//
|
//
|
||||||
Iterator<FlowArrow> it = plugin.getFlowArrowIterator();
|
Iterator<FlowArrow> it = provider.getFlowArrowIterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
FlowArrow arrow = it.next();
|
FlowArrow arrow = it.next();
|
||||||
if (arrow.active || arrow.selected) {
|
if (arrow.active || arrow.selected) {
|
||||||
@@ -251,7 +249,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
//
|
//
|
||||||
// Active arrows--those at the selected address; paint on top of normal arrows
|
// Active arrows--those at the selected address; paint on top of normal arrows
|
||||||
//
|
//
|
||||||
it = plugin.getActiveArrows();
|
it = provider.getActiveArrows();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
FlowArrow arrow = it.next();
|
FlowArrow arrow = it.next();
|
||||||
if (arrow.selected) {
|
if (arrow.selected) {
|
||||||
@@ -266,7 +264,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
// Selected arrows
|
// Selected arrows
|
||||||
//
|
//
|
||||||
fgColor = selectedColor;
|
fgColor = selectedColor;
|
||||||
it = plugin.getSelectedFlowArrows();
|
it = provider.getSelectedFlowArrows();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
FlowArrow arrow = it.next();
|
FlowArrow arrow = it.next();
|
||||||
paintJump(g2, arrow, fgColor);
|
paintJump(g2, arrow, fgColor);
|
||||||
@@ -274,7 +272,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void paintJump(Graphics2D g2, FlowArrow arrow, Color fgColor) {
|
private void paintJump(Graphics2D g2, FlowArrow arrow, Color fgColor) {
|
||||||
if (plugin.isOffscreen(arrow)) {
|
if (provider.isOffscreen(arrow)) {
|
||||||
return; // don't paint linger arrows, such as selected or active arrows
|
return; // don't paint linger arrows, such as selected or active arrows
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,19 +327,19 @@ class FlowArrowPanel extends JPanel {
|
|||||||
// System.err.printf("%1.3f%%\t", (percentComplete * 100));
|
// System.err.printf("%1.3f%%\t", (percentComplete * 100));
|
||||||
// System.err.println("scrolling to: " + current);
|
// System.err.println("scrolling to: " + current);
|
||||||
|
|
||||||
plugin.scrollTo(current);
|
provider.scrollTo(current);
|
||||||
lastAddress = current; // let's us avoid multiple duplicate requests
|
lastAddress = current; // let's us avoid multiple duplicate requests
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done() {
|
public void done() {
|
||||||
// set the final position
|
// set the final position
|
||||||
// TODO This happens after the animation is finished, which is jarring. If we want this centered,
|
// Note: This happens after the animation is finished, which is jarring. If we want this centered,
|
||||||
// then we need an entirely different way of animating the transition so that the centering
|
// then we need an entirely different way of animating the transition so that the centering
|
||||||
// is part of the animation.
|
// is part of the animation.
|
||||||
// plugin.scrollToCenter(end);
|
// plugin.scrollToCenter(end);
|
||||||
|
|
||||||
plugin.goTo(end);
|
provider.goTo(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAnimator(Animator animator) {
|
void setAnimator(Animator animator) {
|
||||||
@@ -392,7 +390,7 @@ class FlowArrowPanel extends JPanel {
|
|||||||
private class FlowArrowPanelMouseWheelListener implements MouseWheelListener {
|
private class FlowArrowPanelMouseWheelListener implements MouseWheelListener {
|
||||||
@Override
|
@Override
|
||||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||||
plugin.forwardMouseEventToListing(e);
|
provider.forwardMouseEventToListing(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-711
File diff suppressed because it is too large
Load Diff
+17
-16
@@ -1,13 +1,12 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -28,26 +27,27 @@ class FlowArrowShapeFactory {
|
|||||||
private static final int TRIANGLE_HEIGHT = 9;
|
private static final int TRIANGLE_HEIGHT = 9;
|
||||||
private static final int TRIANGLE_WIDTH = 7;
|
private static final int TRIANGLE_WIDTH = 7;
|
||||||
|
|
||||||
static Shape createArrowBody(FlowArrowPlugin plugin, FlowArrow arrow, int width, int height,
|
static Shape createArrowBody(FlowArrowMarginProvider provider, FlowArrow arrow, int width,
|
||||||
|
int height,
|
||||||
int lineSpacing) {
|
int lineSpacing) {
|
||||||
|
|
||||||
GeneralPath linePath = new GeneralPath();
|
GeneralPath linePath = new GeneralPath();
|
||||||
|
|
||||||
// Compute the start Y coordinate (place at proper offset, fix if off screen)
|
// Compute the start Y coordinate (place at proper offset, fix if off screen)
|
||||||
Integer startTop = plugin.getStartPos(arrow.start);
|
Integer startTop = provider.getStartPos(arrow.start);
|
||||||
Integer startBottom = plugin.getEndPos(arrow.start);
|
Integer startBottom = provider.getEndPos(arrow.start);
|
||||||
int startY = 0;
|
int startY = 0;
|
||||||
if (startTop != null && startBottom != null) {
|
if (startTop != null && startBottom != null) {
|
||||||
int start = startTop;
|
int start = startTop;
|
||||||
int end = startBottom;
|
int end = startBottom;
|
||||||
startY = (start + end) / 2;// middle of line
|
startY = (start + end) / 2;// middle of line
|
||||||
}
|
}
|
||||||
else if (plugin.isBelowScreen(arrow.start)) {
|
else if (provider.isBelowScreen(arrow.start)) {
|
||||||
startY = height;
|
startY = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer endTop = plugin.getStartPos(arrow.end);
|
Integer endTop = provider.getStartPos(arrow.end);
|
||||||
Integer endBottom = plugin.getEndPos(arrow.end);
|
Integer endBottom = provider.getEndPos(arrow.end);
|
||||||
int endY = 0;
|
int endY = 0;
|
||||||
if (endTop != null && endBottom != null) {
|
if (endTop != null && endBottom != null) {
|
||||||
int start = endTop;
|
int start = endTop;
|
||||||
@@ -55,11 +55,11 @@ class FlowArrowShapeFactory {
|
|||||||
endY = (start + end) / 2;
|
endY = (start + end) / 2;
|
||||||
endY = Math.min(endY, height); // ensure on screen
|
endY = Math.min(endY, height); // ensure on screen
|
||||||
}
|
}
|
||||||
else if (plugin.isBelowScreen(arrow.end)) {
|
else if (provider.isBelowScreen(arrow.end)) {
|
||||||
endY = height;
|
endY = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = width - ((arrow.depth + 1) * lineSpacing);
|
int x = width - ((arrow.column + 1) * lineSpacing);
|
||||||
if (x < 3) {
|
if (x < 3) {
|
||||||
x = 3;
|
x = 3;
|
||||||
}
|
}
|
||||||
@@ -126,12 +126,13 @@ class FlowArrowShapeFactory {
|
|||||||
return linePath;
|
return linePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Shape createArrowHead(FlowArrowPlugin plugin, FlowArrow arrow, int width, int height,
|
static Shape createArrowHead(FlowArrowMarginProvider provider, FlowArrow arrow, int width,
|
||||||
|
int height,
|
||||||
int lineSpacing) {
|
int lineSpacing) {
|
||||||
|
|
||||||
// Compute the start Y coordinate (place at proper offset, fix if off screen)
|
// Compute the start Y coordinate (place at proper offset, fix if off screen)
|
||||||
Integer addrStartInt = plugin.getStartPos(arrow.end);
|
Integer addrStartInt = provider.getStartPos(arrow.end);
|
||||||
Integer addrEndInt = plugin.getEndPos(arrow.end);
|
Integer addrEndInt = provider.getEndPos(arrow.end);
|
||||||
int endY = 0;
|
int endY = 0;
|
||||||
if (addrStartInt != null && addrEndInt != null) {
|
if (addrStartInt != null && addrEndInt != null) {
|
||||||
int start = addrStartInt;
|
int start = addrStartInt;
|
||||||
@@ -139,11 +140,11 @@ class FlowArrowShapeFactory {
|
|||||||
endY = (start + end) / 2;
|
endY = (start + end) / 2;
|
||||||
endY = Math.min(endY, height); // ensure on screen
|
endY = Math.min(endY, height); // ensure on screen
|
||||||
}
|
}
|
||||||
else if (plugin.isBelowScreen(arrow.end)) {
|
else if (provider.isBelowScreen(arrow.end)) {
|
||||||
endY = height;
|
endY = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = width - ((arrow.depth + 1) * lineSpacing);
|
int x = width - ((arrow.column + 1) * lineSpacing);
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
x = 3;
|
x = 3;
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-22
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -40,6 +40,7 @@ import ghidra.program.model.address.AddressSet;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.util.ColorUtils.ColorBlender;
|
import ghidra.util.ColorUtils.ColorBlender;
|
||||||
|
import ghidra.util.UniversalID;
|
||||||
import ghidra.util.datastruct.*;
|
import ghidra.util.datastruct.*;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.task.SwingUpdateManager;
|
import ghidra.util.task.SwingUpdateManager;
|
||||||
@@ -70,11 +71,9 @@ public class MarkerManager implements MarkerService {
|
|||||||
private SwingUpdateManager updater;
|
private SwingUpdateManager updater;
|
||||||
private GoToService goToService;
|
private GoToService goToService;
|
||||||
|
|
||||||
private MarkerMarginProvider primaryMarginProvider;
|
|
||||||
private WeakSet<MarkerMarginProvider> marginProviders =
|
private WeakSet<MarkerMarginProvider> marginProviders =
|
||||||
WeakDataStructureFactory.createCopyOnWriteWeakSet();
|
WeakDataStructureFactory.createCopyOnWriteWeakSet();
|
||||||
|
|
||||||
private MarkerOverviewProvider primaryOverviewProvider;
|
|
||||||
private WeakSet<MarkerOverviewProvider> overviewProviders =
|
private WeakSet<MarkerOverviewProvider> overviewProviders =
|
||||||
WeakDataStructureFactory.createCopyOnWriteWeakSet();
|
WeakDataStructureFactory.createCopyOnWriteWeakSet();
|
||||||
|
|
||||||
@@ -101,9 +100,6 @@ public class MarkerManager implements MarkerService {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
|
|
||||||
primaryMarginProvider = createMarginProvider();
|
|
||||||
primaryOverviewProvider = createOverviewProvider();
|
|
||||||
|
|
||||||
Gui.addThemeListener(themeListener);
|
Gui.addThemeListener(themeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,8 +216,12 @@ public class MarkerManager implements MarkerService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarkerMarginProvider getMarginProvider() {
|
public boolean contains(ListingMarginProvider provider) {
|
||||||
return primaryMarginProvider;
|
return marginProviders.contains(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(ListingOverviewProvider provider) {
|
||||||
|
return overviewProviders.contains(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -231,8 +231,8 @@ public class MarkerManager implements MarkerService {
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OverviewProvider getOverviewProvider() {
|
public void removeProvider(MarkerMarginProvider provider) {
|
||||||
return primaryOverviewProvider;
|
marginProviders.remove(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -246,7 +246,6 @@ public class MarkerManager implements MarkerService {
|
|||||||
Gui.removeThemeListener(themeListener);
|
Gui.removeThemeListener(themeListener);
|
||||||
updater.dispose();
|
updater.dispose();
|
||||||
markerSetCache.clear();
|
markerSetCache.clear();
|
||||||
overviewProviders.forEach(provider -> provider.dispose());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void navigateTo(Navigatable navigatable, Program program, int x, int y, int viewHeight,
|
void navigateTo(Navigatable navigatable, Program program, int x, int y, int viewHeight,
|
||||||
@@ -276,13 +275,13 @@ public class MarkerManager implements MarkerService {
|
|||||||
entry.paintNavigation(g, panel.getViewHeight(), panel.getWidth(), addrMap);
|
entry.paintNavigation(g, panel.getViewHeight(), panel.getWidth(), addrMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void paintMarkers(Program program, Graphics g, VerticalPixelAddressMap pixmap,
|
void paintMarkers(UniversalID ownerId, Program program, Graphics g,
|
||||||
AddressIndexMap addrMap) {
|
VerticalPixelAddressMap pixMap, AddressIndexMap addrMap) {
|
||||||
MarkerSetCacheEntry entry = markerSetCache.get(program);
|
MarkerSetCacheEntry entry = markerSetCache.get(program);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entry.paintMarkers(g, pixmap, addrMap);
|
entry.paintMarkers(ownerId, g, pixMap, addrMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showToolTipPopup(MouseEvent event, String tip) {
|
void showToolTipPopup(MouseEvent event, String tip) {
|
||||||
@@ -301,10 +300,6 @@ public class MarkerManager implements MarkerService {
|
|||||||
popupWindow.showPopup(event);
|
popupWindow.showPopup(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*testing*/ String generateToolTip(MouseEvent event) {
|
|
||||||
return primaryMarginProvider.generateToolTip(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> getMarkerTooltipLines(Program program, int y, int x, Address minAddr,
|
List<String> getMarkerTooltipLines(Program program, int y, int x, Address minAddr,
|
||||||
Address maxAddr) {
|
Address maxAddr) {
|
||||||
MarkerSetCacheEntry entry = markerSetCache.get(program);
|
MarkerSetCacheEntry entry = markerSetCache.get(program);
|
||||||
@@ -484,6 +479,7 @@ public class MarkerManager implements MarkerService {
|
|||||||
if (program == null || program.isClosed()) {
|
if (program == null || program.isClosed()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkerSetCacheEntry entry = map.computeIfAbsent(program, this::newEntry);
|
MarkerSetCacheEntry entry = map.computeIfAbsent(program, this::newEntry);
|
||||||
if (program.isClosed()) {
|
if (program.isClosed()) {
|
||||||
map.remove(program);
|
map.remove(program);
|
||||||
@@ -571,13 +567,22 @@ public class MarkerManager implements MarkerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void paintMarkers(Graphics g, VerticalPixelAddressMap pixmap, AddressIndexMap addrMap) {
|
void paintMarkers(UniversalID ownerId, Graphics g, VerticalPixelAddressMap pixMap,
|
||||||
|
AddressIndexMap addrMap) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (MarkerSetImpl markers : markerSets) {
|
for (MarkerSetImpl markers : markerSets) {
|
||||||
count++;
|
count++;
|
||||||
if (markers.active) {
|
if (!markers.active) {
|
||||||
markers.paintMarkers(g, count++, pixmap, addrMap);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniversalID markerId = markers.getOwnerId();
|
||||||
|
if (markerId != null && markerId != ownerId) {
|
||||||
|
// a non-global marker that does not match the owner being painted
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
markers.paintMarkers(g, count++, pixMap, addrMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,4 +643,5 @@ public class MarkerManager implements MarkerService {
|
|||||||
return new ArrayList<>(markerSets);
|
return new ArrayList<>(markerSets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-14
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -20,6 +20,8 @@ import ghidra.app.CorePluginPackage;
|
|||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
|
import ghidra.app.util.viewer.listingpanel.ListingMarginProvider;
|
||||||
|
import ghidra.app.util.viewer.listingpanel.ListingOverviewProvider;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
import ghidra.framework.plugintool.util.PluginStatus;
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
@@ -39,17 +41,17 @@ import ghidra.util.HelpLocation;
|
|||||||
"supported; point markers and area markers. Area markers are used to indicate a range " +
|
"supported; point markers and area markers. Area markers are used to indicate a range " +
|
||||||
"value such as selection. Point markers are used to represent individual addresses such " +
|
"value such as selection. Point markers are used to represent individual addresses such " +
|
||||||
"as bookmarks.",
|
"as bookmarks.",
|
||||||
servicesRequired = { CodeViewerService.class, GoToService.class },
|
servicesRequired = { GoToService.class },
|
||||||
servicesProvided = { MarkerService.class },
|
servicesProvided = { MarkerService.class, ListingMarginProviderService.class, ListingOverviewProviderService.class },
|
||||||
eventsConsumed = {}
|
eventsConsumed = {}
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
/**
|
/**
|
||||||
* Plugin to manage marker and navigation panels.
|
* Plugin to manage marker and navigation panels.
|
||||||
*/
|
*/
|
||||||
public class MarkerManagerPlugin extends Plugin {
|
public class MarkerManagerPlugin extends Plugin
|
||||||
|
implements ListingMarginProviderService, ListingOverviewProviderService {
|
||||||
|
|
||||||
private CodeViewerService codeViewerService;
|
|
||||||
private MarkerManager markerManager;
|
private MarkerManager markerManager;
|
||||||
|
|
||||||
public MarkerManagerPlugin(PluginTool tool) {
|
public MarkerManagerPlugin(PluginTool tool) {
|
||||||
@@ -65,17 +67,26 @@ public class MarkerManagerPlugin extends Plugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dispose() {
|
protected void dispose() {
|
||||||
if (codeViewerService != null) {
|
|
||||||
codeViewerService.removeMarginProvider(markerManager.getMarginProvider());
|
|
||||||
codeViewerService.removeOverviewProvider(markerManager.getOverviewProvider());
|
|
||||||
}
|
|
||||||
markerManager.dispose();
|
markerManager.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
public ListingMarginProvider createMarginProvider() {
|
||||||
codeViewerService = tool.getService(CodeViewerService.class);
|
return markerManager.createMarginProvider();
|
||||||
codeViewerService.addMarginProvider(markerManager.getMarginProvider());
|
}
|
||||||
codeViewerService.addOverviewProvider(markerManager.getOverviewProvider());
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwner(ListingMarginProvider provider) {
|
||||||
|
return markerManager.contains(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListingOverviewProvider createOverviewProvider() {
|
||||||
|
return markerManager.createOverviewProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwner(ListingOverviewProvider provider) {
|
||||||
|
return markerManager.contains(provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-9
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -28,6 +28,8 @@ import ghidra.app.util.viewer.util.AddressIndexMap;
|
|||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.MarkerLocation;
|
import ghidra.program.util.MarkerLocation;
|
||||||
|
import ghidra.program.util.ProgramLocation;
|
||||||
|
import ghidra.util.UniversalID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The provider which renders the marker margin, usually placed to the left of listing
|
* The provider which renders the marker margin, usually placed to the left of listing
|
||||||
@@ -37,7 +39,7 @@ import ghidra.program.util.MarkerLocation;
|
|||||||
* These are managed by a {@link MarkerManager}. Obtain one via
|
* These are managed by a {@link MarkerManager}. Obtain one via
|
||||||
* {@link MarkerService#createMarginProvider()}.
|
* {@link MarkerService#createMarginProvider()}.
|
||||||
*/
|
*/
|
||||||
public class MarkerMarginProvider implements MarginProvider {
|
public class MarkerMarginProvider implements ListingMarginProvider {
|
||||||
private final MarkerManager markerManager;
|
private final MarkerManager markerManager;
|
||||||
private final MarkerPanel markerPanel;
|
private final MarkerPanel markerPanel;
|
||||||
|
|
||||||
@@ -62,6 +64,22 @@ public class MarkerMarginProvider implements MarginProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOwnerId(UniversalID ownerId) {
|
||||||
|
markerPanel.setOwnerId(ownerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLocation(ProgramLocation location) {
|
||||||
|
// we don't use locations
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
markerManager.removeProvider(this);
|
||||||
|
markerPanel.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
void repaintPanel() {
|
void repaintPanel() {
|
||||||
markerPanel.repaint();
|
markerPanel.repaint();
|
||||||
}
|
}
|
||||||
@@ -95,12 +113,11 @@ public class MarkerMarginProvider implements MarginProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgram(Program program, AddressIndexMap addrMap,
|
public void screenDataChanged(ListingPanel listing, AddressIndexMap addrMap,
|
||||||
VerticalPixelAddressMap pixmap) {
|
VerticalPixelAddressMap pixMap) {
|
||||||
this.program = program;
|
this.program = listing.getProgram();
|
||||||
this.pixmap = pixmap;
|
this.pixmap = pixMap;
|
||||||
|
this.markerPanel.listingUpdated(listing, addrMap, pixMap);
|
||||||
this.markerPanel.setProgram(program, addrMap, pixmap);
|
|
||||||
|
|
||||||
markerManager.updateMarkerSets(program, true, false, true);
|
markerManager.updateMarkerSets(program, true, false, true);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-7
@@ -30,7 +30,7 @@ import ghidra.GhidraOptions;
|
|||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.services.MarkerService;
|
import ghidra.app.services.MarkerService;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.app.util.viewer.listingpanel.OverviewProvider;
|
import ghidra.app.util.viewer.listingpanel.ListingOverviewProvider;
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
import ghidra.framework.options.*;
|
import ghidra.framework.options.*;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@@ -46,7 +46,7 @@ import ghidra.util.Swing;
|
|||||||
* These are managed by a {@link MarkerManager}. Obtain one via
|
* These are managed by a {@link MarkerManager}. Obtain one via
|
||||||
* {@link MarkerService#createOverviewProvider()}.
|
* {@link MarkerService#createOverviewProvider()}.
|
||||||
*/
|
*/
|
||||||
public class MarkerOverviewProvider implements OverviewProvider {
|
public class MarkerOverviewProvider implements ListingOverviewProvider {
|
||||||
private final PluginTool tool;
|
private final PluginTool tool;
|
||||||
private final String owner;
|
private final String owner;
|
||||||
|
|
||||||
@@ -74,7 +74,8 @@ public class MarkerOverviewProvider implements OverviewProvider {
|
|||||||
actionList = new MarkerActionList();
|
actionList = new MarkerActionList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
@Override
|
||||||
|
public void dispose() {
|
||||||
actionList.dispose();
|
actionList.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,11 +89,11 @@ public class MarkerOverviewProvider implements OverviewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgram(Program program, AddressIndexMap map) {
|
public void screenDataChanged(Program p, AddressIndexMap addressMap) {
|
||||||
this.program = program;
|
this.program = p;
|
||||||
|
|
||||||
navigationPanel.setProgram(program, map);
|
navigationPanel.setProgram(p, addressMap);
|
||||||
markerManager.updateMarkerSets(program, true, true, false);
|
markerManager.updateMarkerSets(p, true, true, false);
|
||||||
actionList.refresh();
|
actionList.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -24,10 +24,12 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.ToolTipManager;
|
import javax.swing.ToolTipManager;
|
||||||
|
|
||||||
import docking.widgets.fieldpanel.FieldPanel;
|
import docking.widgets.fieldpanel.FieldPanel;
|
||||||
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.app.util.viewer.listingpanel.VerticalPixelAddressMap;
|
import ghidra.app.util.viewer.listingpanel.VerticalPixelAddressMap;
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.util.UniversalID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel to display markers. Normally placed to the left hand side of the scrolled
|
* Panel to display markers. Normally placed to the left hand side of the scrolled
|
||||||
@@ -36,29 +38,40 @@ import ghidra.program.model.listing.Program;
|
|||||||
public class MarkerPanel extends JPanel {
|
public class MarkerPanel extends JPanel {
|
||||||
|
|
||||||
private MarkerManager manager;
|
private MarkerManager manager;
|
||||||
|
|
||||||
private Program program;
|
private Program program;
|
||||||
private AddressIndexMap addrMap;
|
private AddressIndexMap addrMap;
|
||||||
private VerticalPixelAddressMap pixmap;
|
private VerticalPixelAddressMap pixMap;
|
||||||
|
private UniversalID ownerId;
|
||||||
|
|
||||||
MarkerPanel(MarkerManager manager) {
|
MarkerPanel(MarkerManager manager) {
|
||||||
super();
|
super();
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
|
||||||
this.setPreferredSize(new Dimension(16, 1));
|
this.setPreferredSize(new Dimension(16, 1));
|
||||||
ToolTipManager.sharedInstance().registerComponent(this);
|
ToolTipManager.sharedInstance().registerComponent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setProgram(Program program, AddressIndexMap addrMap, VerticalPixelAddressMap pixmap) {
|
void setOwnerId(UniversalID ownerId) {
|
||||||
this.program = program;
|
this.ownerId = ownerId;
|
||||||
this.addrMap = addrMap;
|
}
|
||||||
this.pixmap = pixmap;
|
|
||||||
|
void dispose() {
|
||||||
|
this.program = null;
|
||||||
|
this.addrMap = null;
|
||||||
|
this.pixMap = null;
|
||||||
|
ToolTipManager.sharedInstance().unregisterComponent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void listingUpdated(ListingPanel listingPanel, AddressIndexMap addressMap,
|
||||||
|
VerticalPixelAddressMap pixelMap) {
|
||||||
|
this.program = listingPanel.getProgram();
|
||||||
|
this.addrMap = addressMap;
|
||||||
|
this.pixMap = pixelMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintComponent(Graphics g) {
|
protected void paintComponent(Graphics g) {
|
||||||
super.paintComponent(g);
|
super.paintComponent(g);
|
||||||
manager.paintMarkers(program, g, pixmap, addrMap);
|
manager.paintMarkers(ownerId, program, g, pixMap, addrMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,14 +94,14 @@ public class MarkerPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String generateToolTip(MouseEvent event) {
|
String generateToolTip(MouseEvent event) {
|
||||||
if (pixmap == null) {
|
if (pixMap == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int y = event.getY();
|
int y = event.getY();
|
||||||
int x = event.getX();
|
int x = event.getX();
|
||||||
int layoutIndex = pixmap.findLayoutAt(y);
|
int layoutIndex = pixMap.findLayoutAt(y);
|
||||||
Address layoutAddress = pixmap.getLayoutAddress(layoutIndex);
|
Address layoutAddress = pixMap.getLayoutAddress(layoutIndex);
|
||||||
if (layoutAddress == null) {
|
if (layoutAddress == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -99,7 +112,8 @@ public class MarkerPanel extends JPanel {
|
|||||||
|
|
||||||
private List<String> getMarkerTooltipLines(int y, int x, int layoutIndex,
|
private List<String> getMarkerTooltipLines(int y, int x, int layoutIndex,
|
||||||
Address layoutAddress) {
|
Address layoutAddress) {
|
||||||
Address endAddr = pixmap.getLayoutEndAddress(layoutIndex);
|
Address endAddr = pixMap.getLayoutEndAddress(layoutIndex);
|
||||||
return manager.getMarkerTooltipLines(program, y, layoutIndex, layoutAddress, endAddr);
|
return manager.getMarkerTooltipLines(program, y, layoutIndex, layoutAddress, endAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-18
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -35,8 +35,7 @@ import ghidra.program.model.address.*;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.MarkerLocation;
|
import ghidra.program.util.MarkerLocation;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.util.ColorUtils;
|
import ghidra.util.*;
|
||||||
import ghidra.util.Swing;
|
|
||||||
import ghidra.util.datastruct.SortedRangeList;
|
import ghidra.util.datastruct.SortedRangeList;
|
||||||
|
|
||||||
abstract class MarkerSetImpl implements MarkerSet {
|
abstract class MarkerSetImpl implements MarkerSet {
|
||||||
@@ -52,7 +51,7 @@ abstract class MarkerSetImpl implements MarkerSet {
|
|||||||
protected AddressSetCollection markers;
|
protected AddressSetCollection markers;
|
||||||
protected SortedRangeList overview = null;
|
protected SortedRangeList overview = null;
|
||||||
|
|
||||||
protected VerticalPixelAddressMap activePixmap = null;
|
protected VerticalPixelAddressMap activePixMap = null;
|
||||||
protected List<Integer> activeLayouts = null;
|
protected List<Integer> activeLayouts = null;
|
||||||
|
|
||||||
protected Color markerColor;
|
protected Color markerColor;
|
||||||
@@ -72,9 +71,11 @@ abstract class MarkerSetImpl implements MarkerSet {
|
|||||||
private boolean colorBackground;
|
private boolean colorBackground;
|
||||||
private boolean isPreferred;
|
private boolean isPreferred;
|
||||||
|
|
||||||
|
/** Optional owner ID. A null ID implies a global marker set. */
|
||||||
|
private UniversalID ownerId;
|
||||||
|
|
||||||
MarkerSetImpl(MarkerManager mgr, Program program, String name, String desc, int priority,
|
MarkerSetImpl(MarkerManager mgr, Program program, String name, String desc, int priority,
|
||||||
boolean showMarkers,
|
boolean showMarkers, boolean showNavigation, boolean colorBackground, Color markerColor,
|
||||||
boolean showNavigation, boolean colorBackground, Color markerColor,
|
|
||||||
boolean isPreferred) {
|
boolean isPreferred) {
|
||||||
|
|
||||||
this.mgr = mgr;
|
this.mgr = mgr;
|
||||||
@@ -93,6 +94,16 @@ abstract class MarkerSetImpl implements MarkerSet {
|
|||||||
markers = new ModifiableAddressSetCollection();
|
markers = new ModifiableAddressSetCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOwnerId(UniversalID ownerId) {
|
||||||
|
this.ownerId = ownerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UniversalID getOwnerId() {
|
||||||
|
return ownerId;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void doPaintMarkers(Graphics g, VerticalPixelAddressMap pixmap, int index,
|
protected abstract void doPaintMarkers(Graphics g, VerticalPixelAddressMap pixmap, int index,
|
||||||
AddressIndexMap map, List<Integer> layouts);
|
AddressIndexMap map, List<Integer> layouts);
|
||||||
|
|
||||||
@@ -244,11 +255,11 @@ abstract class MarkerSetImpl implements MarkerSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void paintMarkers(Graphics g, int index, VerticalPixelAddressMap pixmap,
|
public final void paintMarkers(Graphics g, int index, VerticalPixelAddressMap pixMap,
|
||||||
AddressIndexMap map) {
|
AddressIndexMap map) {
|
||||||
if (showMarkers) {
|
if (showMarkers) {
|
||||||
List<Integer> layouts = computeActiveLayouts(pixmap, map);
|
List<Integer> layouts = computeActiveLayouts(pixMap, map);
|
||||||
doPaintMarkers(g, pixmap, index, map, layouts);
|
doPaintMarkers(g, pixMap, index, map, layouts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,32 +300,32 @@ abstract class MarkerSetImpl implements MarkerSet {
|
|||||||
return markers.contains(addr);
|
return markers.contains(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Integer> computeActiveLayouts(VerticalPixelAddressMap pixmap,
|
private List<Integer> computeActiveLayouts(VerticalPixelAddressMap pixMap,
|
||||||
AddressIndexMap map) {
|
AddressIndexMap map) {
|
||||||
|
|
||||||
if (pixmap == null) {
|
if (pixMap == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeLayouts != null && activePixmap == pixmap) {
|
if (activeLayouts != null && activePixMap == pixMap) {
|
||||||
return activeLayouts; // use cache
|
return activeLayouts; // use cache
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Integer> newLayouts = new ArrayList<>();
|
List<Integer> newLayouts = new ArrayList<>();
|
||||||
int n = pixmap.getNumLayouts();
|
int n = pixMap.getNumLayouts();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
Address addr = pixmap.getLayoutAddress(i);
|
Address addr = pixMap.getLayoutAddress(i);
|
||||||
if (addr == null) {
|
if (addr == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address end = pixmap.getLayoutEndAddress(i);
|
Address end = pixMap.getLayoutEndAddress(i);
|
||||||
if (markers.intersects(addr, end)) {
|
if (markers.intersects(addr, end)) {
|
||||||
newLayouts.add(i);
|
newLayouts.add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activePixmap = pixmap;
|
activePixMap = pixMap;
|
||||||
activeLayouts = newLayouts;
|
activeLayouts = newLayouts;
|
||||||
return newLayouts;
|
return newLayouts;
|
||||||
}
|
}
|
||||||
@@ -536,6 +547,6 @@ abstract class MarkerSetImpl implements MarkerSet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Json.toString(this, "active", "colorBackground", "markers");
|
return Json.toString(this, "name", "active", "colorBackground", "markers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -95,7 +95,7 @@ class PointMarkerSet extends MarkerSetImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPaintMarkers(Graphics g, VerticalPixelAddressMap pixmap, int index,
|
protected void doPaintMarkers(Graphics g, VerticalPixelAddressMap pixMap, int index,
|
||||||
AddressIndexMap map, List<Integer> layouts) {
|
AddressIndexMap map, List<Integer> layouts) {
|
||||||
|
|
||||||
if (layouts == null) {
|
if (layouts == null) {
|
||||||
@@ -105,20 +105,20 @@ class PointMarkerSet extends MarkerSetImpl {
|
|||||||
Iterator<Integer> it = layouts.iterator();
|
Iterator<Integer> it = layouts.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
int i = it.next().intValue();
|
int i = it.next().intValue();
|
||||||
int yStart = pixmap.getMarkPosition(i);
|
int yStart = pixMap.getMarkPosition(i);
|
||||||
|
|
||||||
Image curImage = getMarkerImage(pixmap, i, yStart);
|
Image curImage = getMarkerImage(pixMap, i, yStart);
|
||||||
|
|
||||||
g.drawImage(curImage, 0, yStart, imageObserver);
|
g.drawImage(curImage, 0, yStart, imageObserver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image getMarkerImage(VerticalPixelAddressMap pixmap, int i, int yStart) {
|
private Image getMarkerImage(VerticalPixelAddressMap pixMap, int i, int yStart) {
|
||||||
if (markerDescriptor == null) {
|
if (markerDescriptor == null) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address address = pixmap.getLayoutAddress(i);
|
Address address = pixMap.getLayoutAddress(i);
|
||||||
MarkerLocation loc = new MarkerLocation(this, program, address, 0, yStart);
|
MarkerLocation loc = new MarkerLocation(this, program, address, 0, yStart);
|
||||||
ImageIcon icon = markerDescriptor.getIcon(loc);
|
ImageIcon icon = markerDescriptor.getIcon(loc);
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
|
|||||||
+22
-17
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -28,7 +28,7 @@ import docking.action.DockingActionIf;
|
|||||||
import generic.theme.GColor;
|
import generic.theme.GColor;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
import ghidra.app.util.viewer.listingpanel.OverviewProvider;
|
import ghidra.app.util.viewer.listingpanel.ListingOverviewProvider;
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
@@ -40,13 +40,13 @@ import help.Help;
|
|||||||
* Overview bar component. Uses color to indicate various address based properties for a program.
|
* Overview bar component. Uses color to indicate various address based properties for a program.
|
||||||
* Uses an {@link OverviewColorService} to get the appropriate color for an address.
|
* Uses an {@link OverviewColorService} to get the appropriate color for an address.
|
||||||
*/
|
*/
|
||||||
public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
public class OverviewColorComponent extends JPanel implements ListingOverviewProvider {
|
||||||
private static final Color DEFAULT_COLOR = new GColor("color.bg.plugin.overview.defalt");
|
private static final Color DEFAULT_COLOR = new GColor("color.bg.plugin.overview.defalt");
|
||||||
private OverviewColorService service;
|
private OverviewColorService service;
|
||||||
private Color[] colors = new Color[0];
|
private Color[] colors = new Color[0];
|
||||||
private final SwingUpdateManager refreshUpdater =
|
private final SwingUpdateManager refreshUpdater =
|
||||||
new SwingUpdateManager(100, 15000, () -> doRefresh());
|
new SwingUpdateManager(100, 15000, () -> doRefresh());
|
||||||
private AddressIndexMap map;
|
private AddressIndexMap addressMap;
|
||||||
private Navigatable navigatable;
|
private Navigatable navigatable;
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
private List<DockingActionIf> actions;
|
private List<DockingActionIf> actions;
|
||||||
@@ -76,6 +76,12 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
|||||||
actions = service.getActions();
|
actions = service.getActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
service = null;
|
||||||
|
ToolTipManager.sharedInstance().unregisterComponent(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs actions for this component
|
* Installs actions for this component
|
||||||
*/
|
*/
|
||||||
@@ -154,10 +160,10 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doRefresh() {
|
private void doRefresh() {
|
||||||
if (map == null) {
|
if (addressMap == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BigInteger indexCount = map.getIndexCount();
|
BigInteger indexCount = addressMap.getIndexCount();
|
||||||
if (indexCount.equals(BigInteger.ZERO)) {
|
if (indexCount.equals(BigInteger.ZERO)) {
|
||||||
Arrays.fill(colors, DEFAULT_COLOR);
|
Arrays.fill(colors, DEFAULT_COLOR);
|
||||||
repaint();
|
repaint();
|
||||||
@@ -168,7 +174,7 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
|||||||
for (int i = 0; i < colors.length; i++) {
|
for (int i = 0; i < colors.length; i++) {
|
||||||
if (colors[i] == null) {
|
if (colors[i] == null) {
|
||||||
BigInteger index = indexCount.multiply(BigInteger.valueOf(i)).divide(bigTotal);
|
BigInteger index = indexCount.multiply(BigInteger.valueOf(i)).divide(bigTotal);
|
||||||
Address address = map.getAddress(index);
|
Address address = addressMap.getAddress(index);
|
||||||
colors[i] = service.getColor(address);
|
colors[i] = service.getColor(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,17 +184,17 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
|||||||
private Address getAddress(int pixelIndex) {
|
private Address getAddress(int pixelIndex) {
|
||||||
BigInteger bigHeight = BigInteger.valueOf(getOverviewPixelCount());
|
BigInteger bigHeight = BigInteger.valueOf(getOverviewPixelCount());
|
||||||
BigInteger bigPixelIndex = BigInteger.valueOf(pixelIndex);
|
BigInteger bigPixelIndex = BigInteger.valueOf(pixelIndex);
|
||||||
BigInteger bigIndex = map.getIndexCount().multiply(bigPixelIndex).divide(bigHeight);
|
BigInteger bigIndex = addressMap.getIndexCount().multiply(bigPixelIndex).divide(bigHeight);
|
||||||
return map.getAddress(bigIndex);
|
return addressMap.getAddress(bigIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPixelIndex(Address address) {
|
private int getPixelIndex(Address address) {
|
||||||
BigInteger addressIndex = map.getIndex(address);
|
BigInteger addressIndex = addressMap.getIndex(address);
|
||||||
if (addressIndex == null) {
|
if (addressIndex == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
BigInteger bigHeight = BigInteger.valueOf(getOverviewPixelCount());
|
BigInteger bigHeight = BigInteger.valueOf(getOverviewPixelCount());
|
||||||
BigInteger indexCount = map.getIndexCount();
|
BigInteger indexCount = addressMap.getIndexCount();
|
||||||
return addressIndex.multiply(bigHeight).divide(indexCount).intValue();
|
return addressIndex.multiply(bigHeight).divide(indexCount).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,10 +204,10 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgram(Program program, AddressIndexMap map) {
|
public void screenDataChanged(Program program, AddressIndexMap map) {
|
||||||
this.map = map;
|
this.addressMap = map;
|
||||||
colors = new Color[getOverviewPixelCount()];
|
this.colors = new Color[getOverviewPixelCount()];
|
||||||
refreshUpdater.updateLater();
|
this.refreshUpdater.updateLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -248,5 +254,4 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider {
|
|||||||
public PluginTool getTool() {
|
public PluginTool getTool() {
|
||||||
return tool;
|
return tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -92,5 +92,4 @@ public interface OverviewColorService extends ExtensionPoint {
|
|||||||
* @return the current program used by the service.
|
* @return the current program used by the service.
|
||||||
*/
|
*/
|
||||||
public Program getProgram();
|
public Program getProgram();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -143,6 +143,8 @@ public class AddressTypeOverviewColorService
|
|||||||
@Override
|
@Override
|
||||||
public void setOverviewComponent(OverviewColorComponent component) {
|
public void setOverviewComponent(OverviewColorComponent component) {
|
||||||
this.overviewComponent = component;
|
this.overviewComponent = component;
|
||||||
|
this.overviewComponent.getAccessibleContext()
|
||||||
|
.setAccessibleName("Address Type Overview Component");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+9
-4
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -33,6 +33,7 @@ import ghidra.app.CorePluginPackage;
|
|||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.plugin.ProgramPlugin;
|
import ghidra.app.plugin.ProgramPlugin;
|
||||||
import ghidra.app.services.CodeViewerService;
|
import ghidra.app.services.CodeViewerService;
|
||||||
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
import ghidra.framework.plugintool.PluginInfo;
|
import ghidra.framework.plugintool.PluginInfo;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@@ -147,7 +148,10 @@ public class PrintingPlugin extends ProgramPlugin {
|
|||||||
format = job.defaultPage();
|
format = job.defaultPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutModel lm = cvService.getFieldPanel().getLayoutModel();
|
ListingPanel listingPanel = cvService.getListingPanel();
|
||||||
|
FieldPanel fp = listingPanel.getFieldPanel();
|
||||||
|
LayoutModel lm = fp.getLayoutModel();
|
||||||
|
|
||||||
//Scale everything down if appropriate to fit on the page
|
//Scale everything down if appropriate to fit on the page
|
||||||
double scaleAmount =
|
double scaleAmount =
|
||||||
format.getImageableWidth() / lm.getPreferredViewSize().width;
|
format.getImageableWidth() / lm.getPreferredViewSize().width;
|
||||||
@@ -316,7 +320,8 @@ public class PrintingPlugin extends ProgramPlugin {
|
|||||||
private void printVisibleContent(TaskMonitor monitor, Date startDate,
|
private void printVisibleContent(TaskMonitor monitor, Date startDate,
|
||||||
PrinterJob job, Book book, LayoutModel lm, double scaleAmount,
|
PrinterJob job, Book book, LayoutModel lm, double scaleAmount,
|
||||||
int maxPageHeight) {
|
int maxPageHeight) {
|
||||||
FieldPanel fp = cvService.getFieldPanel();
|
ListingPanel listingPanel = cvService.getListingPanel();
|
||||||
|
FieldPanel fp = listingPanel.getFieldPanel();
|
||||||
List<AnchoredLayout> visibleLayouts = fp.getVisibleLayouts();
|
List<AnchoredLayout> visibleLayouts = fp.getVisibleLayouts();
|
||||||
BigInteger startIndex = visibleLayouts.get(0).getIndex();
|
BigInteger startIndex = visibleLayouts.get(0).getIndex();
|
||||||
BigInteger endIndex = visibleLayouts.get(visibleLayouts.size() - 1).getIndex();
|
BigInteger endIndex = visibleLayouts.get(visibleLayouts.size() - 1).getIndex();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -34,39 +34,48 @@ import ghidra.program.util.ProgramLocation;
|
|||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service provided by a plugin that shows the listing from a Program, i.e., a
|
* Service provided by a plugin that shows the Code Viewer listing for a Program. The service
|
||||||
* Code Viewer. The service allows other plugins to add components and
|
* allows other plugins to add components and actions local to the Code Viewer.
|
||||||
* actions local to the Code Viewer.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@ServiceInfo(defaultProvider = CodeBrowserPlugin.class)
|
@ServiceInfo(defaultProvider = CodeBrowserPlugin.class)
|
||||||
public interface CodeViewerService {
|
public interface CodeViewerService {
|
||||||
/**
|
/**
|
||||||
* Add a provider that shows an overview of the program.
|
* Add a provider that shows an overview of the program.
|
||||||
|
* <p>
|
||||||
|
* Note: the provider passed here will only appear in the primary code viewer, not in any of the
|
||||||
|
* snapshot windows. to have an overview provider appear in all windows, you must create a
|
||||||
|
* {@link ListingOverviewProviderService} implementation instead of using this method.
|
||||||
|
*
|
||||||
* @param overviewProvider provider to add
|
* @param overviewProvider provider to add
|
||||||
*/
|
*/
|
||||||
public void addOverviewProvider(OverviewProvider overviewProvider);
|
public void addOverviewProvider(ListingOverviewProvider overviewProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a provider that shows an overview of the program.
|
* Remove a provider that shows an overview of the program.
|
||||||
* @param overviewProvider provider to remove
|
* @param overviewProvider provider to remove
|
||||||
|
* @see CodeViewerService#addOverviewProvider(ListingOverviewProvider)
|
||||||
*/
|
*/
|
||||||
public void removeOverviewProvider(OverviewProvider overviewProvider);
|
public void removeOverviewProvider(ListingOverviewProvider overviewProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a provider that shows markers in a program for the portion
|
* Add a provider that shows markers in a program for the portion
|
||||||
* that is visible.
|
* that is visible.
|
||||||
* @param marginProvider provider to add
|
* @param marginProvider provider to add
|
||||||
|
* @deprecated clients that wish to be margin providers should now create a
|
||||||
|
* {@link ListingMarginProviderService}.
|
||||||
*/
|
*/
|
||||||
public void addMarginProvider(MarginProvider marginProvider);
|
@Deprecated(since = "12.1", forRemoval = true)
|
||||||
|
public void addMarginProvider(ListingMarginProvider marginProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a provider that shows markers in a program for the portion
|
* Remove a provider that shows markers in a program for the portion
|
||||||
* that is visible.
|
* that is visible.
|
||||||
* @param marginProvider provider to remove
|
* @param marginProvider provider to remove
|
||||||
|
* @deprecated clients that wish to be margin providers should now create a
|
||||||
|
* {@link ListingMarginProviderService}.
|
||||||
*/
|
*/
|
||||||
public void removeMarginProvider(MarginProvider marginProvider);
|
@Deprecated(since = "12.1", forRemoval = true)
|
||||||
|
public void removeMarginProvider(ListingMarginProvider marginProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an action that is local to the Code Viewer.
|
* Add an action that is local to the Code Viewer.
|
||||||
@@ -88,13 +97,13 @@ public interface CodeViewerService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a listener that is notified when a mouse button is pressed.
|
* Add a listener that is notified when a mouse button is pressed.
|
||||||
* @param listener
|
* @param listener the listener
|
||||||
*/
|
*/
|
||||||
public void addButtonPressedListener(ButtonPressedListener listener);
|
public void addButtonPressedListener(ButtonPressedListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the button pressed listener.
|
* Remove the button pressed listener.
|
||||||
* @param listener
|
* @param listener the listener
|
||||||
*/
|
*/
|
||||||
public void removeButtonPressedListener(ButtonPressedListener listener);
|
public void removeButtonPressedListener(ButtonPressedListener listener);
|
||||||
|
|
||||||
@@ -114,7 +123,8 @@ public interface CodeViewerService {
|
|||||||
public void removeHighlightProvider(ListingHighlightProvider provider, Program program);
|
public void removeHighlightProvider(ListingHighlightProvider provider, Program program);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a listing panel on the code viewer.
|
* Set a listing panel on the code viewer. The given listing panel is a secondary listing panel
|
||||||
|
* to be displayed along with the primary listing panel.
|
||||||
* @param listingPanel the panel to add.
|
* @param listingPanel the panel to add.
|
||||||
*/
|
*/
|
||||||
public void setListingPanel(ListingPanel listingPanel);
|
public void setListingPanel(ListingPanel listingPanel);
|
||||||
@@ -127,11 +137,12 @@ public interface CodeViewerService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the given listing panel from the code viewer.
|
* Remove the given listing panel from the code viewer.
|
||||||
|
* @param listingPanel the listing panel
|
||||||
*/
|
*/
|
||||||
public void removeListingPanel(ListingPanel listingPanel);
|
public void removeListingPanel(ListingPanel listingPanel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Current view that the CodeViewer is showing.
|
* @return the current set of addresses that the CodeViewer is showing.}
|
||||||
*/
|
*/
|
||||||
public AddressSetView getView();
|
public AddressSetView getView();
|
||||||
|
|
||||||
@@ -145,15 +156,21 @@ public interface CodeViewerService {
|
|||||||
public boolean goTo(ProgramLocation loc, boolean centerOnScreen);
|
public boolean goTo(ProgramLocation loc, boolean centerOnScreen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the fieldPanel.
|
* Returns the current field panel.
|
||||||
|
* @return the current field panel.
|
||||||
|
* @deprecated use {@link #getListingPanel()} to get the field panel
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "12.1", forRemoval = true)
|
||||||
public FieldPanel getFieldPanel();
|
public FieldPanel getFieldPanel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current address-index-map
|
* {@return the current address index map.}
|
||||||
*/
|
*/
|
||||||
public AddressIndexMap getAddressIndexMap();
|
public AddressIndexMap getAddressIndexMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the format manager.}
|
||||||
|
*/
|
||||||
public FormatManager getFormatManager();
|
public FormatManager getFormatManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.services;
|
||||||
|
|
||||||
|
import ghidra.app.util.viewer.listingpanel.ListingMarginProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A service to provide a widget that is designed to appear on the left-hand side of the Code Viewer
|
||||||
|
*/
|
||||||
|
public interface ListingMarginProviderService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new margin provider.
|
||||||
|
* @return the provider
|
||||||
|
*/
|
||||||
|
public ListingMarginProvider createMarginProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this service is the owner of the given provider.
|
||||||
|
* @param provider the provider to check
|
||||||
|
* @return true if the owner
|
||||||
|
*/
|
||||||
|
public boolean isOwner(ListingMarginProvider provider);
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.services;
|
||||||
|
|
||||||
|
import ghidra.app.util.viewer.listingpanel.ListingOverviewProvider;
|
||||||
|
|
||||||
|
public interface ListingOverviewProviderService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new overview provider.
|
||||||
|
* @return the provider
|
||||||
|
*/
|
||||||
|
public ListingOverviewProvider createOverviewProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this service is the owner of the given provider.
|
||||||
|
* @param provider the provider to check
|
||||||
|
* @return true if the owner
|
||||||
|
*/
|
||||||
|
public boolean isOwner(ListingOverviewProvider provider);
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ package ghidra.app.services;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.util.UniversalID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines methods for working with a set of addresses that correspond to markers.
|
* Defines methods for working with a set of addresses that correspond to markers.
|
||||||
@@ -25,6 +26,19 @@ import ghidra.program.model.address.*;
|
|||||||
*/
|
*/
|
||||||
public interface MarkerSet extends Comparable<MarkerSet> {
|
public interface MarkerSet extends Comparable<MarkerSet> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an optional owner ID that signals when this marker set should be painted. A null ID
|
||||||
|
* means that this marker set is global and should always be painted. Otherwise, this marker
|
||||||
|
* set will be painted when its owner ID matches the owner ID being painted.
|
||||||
|
* @param ownerId the ID
|
||||||
|
*/
|
||||||
|
public void setOwnerId(UniversalID ownerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the owner ID. See #setOwner(UniversalID).}
|
||||||
|
*/
|
||||||
|
public UniversalID getOwnerId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a marker at the address
|
* Add a marker at the address
|
||||||
* @param addr the address
|
* @param addr the address
|
||||||
@@ -151,8 +165,9 @@ public interface MarkerSet extends Comparable<MarkerSet> {
|
|||||||
public void setMarkerColor(Color color);
|
public void setMarkerColor(Color color);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the marker manager listener to use for user interaction
|
* Set the marker set descriptor. This allows clients to control tooltip text and program
|
||||||
* with markers owned by this manager.
|
* location generation for individual markers on-the-fly.
|
||||||
|
*
|
||||||
* @param markerDescriptor the descriptor
|
* @param markerDescriptor the descriptor
|
||||||
*/
|
*/
|
||||||
public void setMarkerDescriptor(MarkerDescriptor markerDescriptor);
|
public void setMarkerDescriptor(MarkerDescriptor markerDescriptor);
|
||||||
|
|||||||
+1
-1
@@ -965,7 +965,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
* A library that has not been processed by the loader yet
|
* A library that has not been processed by the loader yet
|
||||||
*
|
*
|
||||||
* @param name The name of the library
|
* @param name The name of the library
|
||||||
* @param depth The recursive load depth of the library (based on the original binary being
|
* @param column The recursive load depth of the library (based on the original binary being
|
||||||
* loaded)
|
* loaded)
|
||||||
* @param temporary True if the library is temporary and should be discarded prior to returning
|
* @param temporary True if the library is temporary and should be discarded prior to returning
|
||||||
* from the load
|
* from the load
|
||||||
|
|||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.util.viewer.listingpanel;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
|
import ghidra.program.util.MarkerLocation;
|
||||||
|
import ghidra.program.util.ProgramLocation;
|
||||||
|
import ghidra.util.UniversalID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for objects that want to add a component to the listing's left margin.
|
||||||
|
*/
|
||||||
|
public interface ListingMarginProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the optional owner ID to be used with this margin provider. Implementations may use
|
||||||
|
* this ID to determine when they should paint.
|
||||||
|
* @param ownerId the ID
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an optional owner ID that signals when the markers for this provider should be painted.
|
||||||
|
* A null ID means that this provider is a non-snapshot provider and should paint all markers.
|
||||||
|
* A non-null ID means this provider's markers will be painted when the marker's owner ID
|
||||||
|
* this provider's ID
|
||||||
|
* .
|
||||||
|
* @param ownerId the ID
|
||||||
|
*/
|
||||||
|
public void setOwnerId(UniversalID ownerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the component to show the margin markers.
|
||||||
|
* @return the component
|
||||||
|
*/
|
||||||
|
public JComponent getComponent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if can be resized.
|
||||||
|
* @return true if can be resized.
|
||||||
|
*/
|
||||||
|
public boolean isResizeable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to notify this margin provider that the current screen information has changed.
|
||||||
|
*
|
||||||
|
* @param listingPanel the listing panel.
|
||||||
|
* @param addressIndexMap the address index map to use.
|
||||||
|
* @param pixelMap the vertical pixel map to use.
|
||||||
|
*/
|
||||||
|
public void screenDataChanged(ListingPanel listingPanel, AddressIndexMap addressIndexMap,
|
||||||
|
VerticalPixelAddressMap pixelMap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the client when their location changes internally. This is different from a tool
|
||||||
|
* location event, which is considered a global event.
|
||||||
|
* @param location the location
|
||||||
|
*/
|
||||||
|
public void setLocation(ProgramLocation location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the marker location for the given x, y point.
|
||||||
|
*
|
||||||
|
* @param x the horizontal coordinate.
|
||||||
|
* @param y the vertical coordinate.
|
||||||
|
* @return the location
|
||||||
|
*/
|
||||||
|
public MarkerLocation getMarkerLocation(int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the client is done with this provider.
|
||||||
|
*/
|
||||||
|
public void dispose();
|
||||||
|
}
|
||||||
+15
-11
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -22,28 +22,32 @@ import ghidra.app.util.viewer.util.AddressIndexMap;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by classes that provide overview components to the right side of the
|
* An overview component that will be placed to the right side of the listing.
|
||||||
* listing.
|
|
||||||
*/
|
*/
|
||||||
public interface OverviewProvider {
|
public interface ListingOverviewProvider {
|
||||||
/**
|
/**
|
||||||
* Returns the component to display in the right margin of the listing.
|
* Returns the component to display in the right margin of the listing.
|
||||||
* @return the component
|
* @return the component
|
||||||
*/
|
*/
|
||||||
JComponent getComponent();
|
public JComponent getComponent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current program and associated address-index map
|
* Called to notify this margin provider that the current screen information has changed.
|
||||||
*
|
*
|
||||||
* @param program the program to use.
|
* @param program the program to use
|
||||||
* @param map the address-index map to use.
|
* @param map the address index map to use
|
||||||
*/
|
*/
|
||||||
void setProgram(Program program, AddressIndexMap map);
|
public void screenDataChanged(Program program, AddressIndexMap map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the component provider that this overview navigates
|
* Set the component provider that this overview navigates
|
||||||
*
|
*
|
||||||
* @param navigatable the navigatable provider
|
* @param navigatable the navigatable provider
|
||||||
*/
|
*/
|
||||||
void setNavigatable(Navigatable navigatable);
|
public void setNavigatable(Navigatable navigatable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clients call this when they are done with this provider.
|
||||||
|
*/
|
||||||
|
public void dispose();
|
||||||
}
|
}
|
||||||
+373
-44
File diff suppressed because it is too large
Load Diff
-60
@@ -1,60 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.app.util.viewer.listingpanel;
|
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
|
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.util.MarkerLocation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for objects that want to add a component to the listing's left margin.
|
|
||||||
*/
|
|
||||||
public interface MarginProvider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the component to show the margin markers.
|
|
||||||
* @return the component
|
|
||||||
*/
|
|
||||||
JComponent getComponent();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if can be resized.
|
|
||||||
* @return true if can be resized.
|
|
||||||
*/
|
|
||||||
boolean isResizeable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the program and associated maps.
|
|
||||||
*
|
|
||||||
* @param program the program to use.
|
|
||||||
* @param addressIndexMap the address-index map to use.
|
|
||||||
* @param pixelMap the vertical pixel map to use.
|
|
||||||
*/
|
|
||||||
void setProgram(Program program, AddressIndexMap addressIndexMap,
|
|
||||||
VerticalPixelAddressMap pixelMap);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the marker location for the given x, y point.
|
|
||||||
*
|
|
||||||
* @param x the horizontal coordinate.
|
|
||||||
* @param y the vertical coordinate.
|
|
||||||
* @return the location
|
|
||||||
*/
|
|
||||||
public MarkerLocation getMarkerLocation(int x, int y);
|
|
||||||
|
|
||||||
}
|
|
||||||
+8
-8
@@ -394,8 +394,8 @@ public class ListingCodeComparisonView
|
|||||||
public Object getContextObjectForMarginPanels(ListingPanel panel, MouseEvent event) {
|
public Object getContextObjectForMarginPanels(ListingPanel panel, MouseEvent event) {
|
||||||
Object source = event.getSource();
|
Object source = event.getSource();
|
||||||
// Is event source a marker margin provider on the left side of the listing?
|
// Is event source a marker margin provider on the left side of the listing?
|
||||||
List<MarginProvider> marginProviders = panel.getMarginProviders();
|
List<ListingMarginProvider> marginProviders = panel.getMarginProviders();
|
||||||
for (MarginProvider marginProvider : marginProviders) {
|
for (ListingMarginProvider marginProvider : marginProviders) {
|
||||||
JComponent c = marginProvider.getComponent();
|
JComponent c = marginProvider.getComponent();
|
||||||
if (c == source) {
|
if (c == source) {
|
||||||
MarkerLocation loc = marginProvider.getMarkerLocation(event.getX(), event.getY());
|
MarkerLocation loc = marginProvider.getMarkerLocation(event.getX(), event.getY());
|
||||||
@@ -406,8 +406,8 @@ public class ListingCodeComparisonView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Is event source an overview provider on the right side of the listing?
|
// Is event source an overview provider on the right side of the listing?
|
||||||
List<OverviewProvider> overviewProviders = panel.getOverviewProviders();
|
List<ListingOverviewProvider> overviewProviders = panel.getOverviewProviders();
|
||||||
for (OverviewProvider overviewProvider : overviewProviders) {
|
for (ListingOverviewProvider overviewProvider : overviewProviders) {
|
||||||
JComponent c = overviewProvider.getComponent();
|
JComponent c = overviewProvider.getComponent();
|
||||||
if (c == source) {
|
if (c == source) {
|
||||||
return source; // Return the overview provider that was clicked.
|
return source; // Return the overview provider that was clicked.
|
||||||
@@ -623,8 +623,8 @@ public class ListingCodeComparisonView
|
|||||||
|
|
||||||
private Object getContextForMarginPanels(ListingPanel lp, MouseEvent event) {
|
private Object getContextForMarginPanels(ListingPanel lp, MouseEvent event) {
|
||||||
Object source = event.getSource();
|
Object source = event.getSource();
|
||||||
List<MarginProvider> marginProvidersForLP = lp.getMarginProviders();
|
List<ListingMarginProvider> marginProvidersForLP = lp.getMarginProviders();
|
||||||
for (MarginProvider marginProvider : marginProvidersForLP) {
|
for (ListingMarginProvider marginProvider : marginProvidersForLP) {
|
||||||
JComponent c = marginProvider.getComponent();
|
JComponent c = marginProvider.getComponent();
|
||||||
if (c == source) {
|
if (c == source) {
|
||||||
MarkerLocation loc = marginProvider.getMarkerLocation(event.getX(), event.getY());
|
MarkerLocation loc = marginProvider.getMarkerLocation(event.getX(), event.getY());
|
||||||
@@ -634,8 +634,8 @@ public class ListingCodeComparisonView
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<OverviewProvider> overviewProvidersForLP = lp.getOverviewProviders();
|
List<ListingOverviewProvider> overviewProvidersForLP = lp.getOverviewProviders();
|
||||||
for (OverviewProvider overviewProvider : overviewProvidersForLP) {
|
for (ListingOverviewProvider overviewProvider : overviewProvidersForLP) {
|
||||||
JComponent c = overviewProvider.getComponent();
|
JComponent c = overviewProvider.getComponent();
|
||||||
if (c == source) {
|
if (c == source) {
|
||||||
return source;
|
return source;
|
||||||
|
|||||||
+12
-3
@@ -18,6 +18,7 @@ package ghidra.features.base.codecompare.listing;
|
|||||||
import static ghidra.GhidraOptions.*;
|
import static ghidra.GhidraOptions.*;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
@@ -94,9 +95,12 @@ public class ListingDisplay implements ListingDiffChangeListener {
|
|||||||
private void createMarkerManager(String owner) {
|
private void createMarkerManager(String owner) {
|
||||||
markerManager = new ListingDisplayMarkerManager(tool, owner);
|
markerManager = new ListingDisplayMarkerManager(tool, owner);
|
||||||
markerManager.addChangeListener(e -> listingPanel.repaint());
|
markerManager.addChangeListener(e -> listingPanel.repaint());
|
||||||
MarginProvider marginProvider = markerManager.getMarginProvider();
|
|
||||||
|
// Manually install our custom margin provider. We are not calling setMarginService(),
|
||||||
|
// which means that many of the listing markers will not work in the compare view.
|
||||||
|
ListingMarginProvider marginProvider = markerManager.createMarginProvider();
|
||||||
listingPanel.addMarginProvider(marginProvider);
|
listingPanel.addMarginProvider(marginProvider);
|
||||||
OverviewProvider overviewProvider = markerManager.getOverviewProvider();
|
ListingOverviewProvider overviewProvider = markerManager.createOverviewProvider();
|
||||||
listingPanel.addOverviewProvider(overviewProvider);
|
listingPanel.addOverviewProvider(overviewProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +175,12 @@ public class ListingDisplay implements ListingDiffChangeListener {
|
|||||||
markerManager.clearAll();
|
markerManager.clearAll();
|
||||||
listingPanel.setView(view);
|
listingPanel.setView(view);
|
||||||
AddressIndexMap indexMap = listingPanel.getAddressIndexMap();
|
AddressIndexMap indexMap = listingPanel.getAddressIndexMap();
|
||||||
markerManager.getOverviewProvider().setProgram(program, indexMap);
|
|
||||||
|
List<ListingOverviewProvider> providers = listingPanel.getOverviewProviders();
|
||||||
|
for (ListingOverviewProvider provider : providers) {
|
||||||
|
provider.screenDataChanged(program, indexMap);
|
||||||
|
}
|
||||||
|
|
||||||
listingPanel.setBackgroundColorModel(
|
listingPanel.setBackgroundColorModel(
|
||||||
new MarkerServiceBackgroundColorModel(markerManager, program, indexMap));
|
new MarkerServiceBackgroundColorModel(markerManager, program, indexMap));
|
||||||
setUpAreaMarkerSets(program, name);
|
setUpAreaMarkerSets(program, name);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -68,11 +68,11 @@ public class MarkerLocation implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Marker Manager.
|
* Returns the marker set.
|
||||||
*
|
*
|
||||||
* @return the marker manager
|
* @return the marker set
|
||||||
*/
|
*/
|
||||||
public MarkerSet getMarkerManager() {
|
public MarkerSet getMarkerSet() {
|
||||||
return markers;
|
return markers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ import ghidra.app.util.viewer.field.FieldFactory;
|
|||||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||||
import ghidra.app.util.viewer.format.FormatManager;
|
import ghidra.app.util.viewer.format.FormatManager;
|
||||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.app.util.viewer.listingpanel.MarginProvider;
|
import ghidra.app.util.viewer.listingpanel.ListingMarginProvider;
|
||||||
import ghidra.docking.settings.SettingsDefinition;
|
import ghidra.docking.settings.SettingsDefinition;
|
||||||
import ghidra.framework.ToolUtils;
|
import ghidra.framework.ToolUtils;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
@@ -1247,9 +1247,9 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
|
|||||||
CodeBrowserPlugin plugin = getPlugin(tool, CodeBrowserPlugin.class);
|
CodeBrowserPlugin plugin = getPlugin(tool, CodeBrowserPlugin.class);
|
||||||
ListingPanel listingPanel = plugin.getListingPanel();
|
ListingPanel listingPanel = plugin.getListingPanel();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<MarginProvider> list =
|
List<ListingMarginProvider> list =
|
||||||
(List<MarginProvider>) getInstanceField("marginProviders", listingPanel);
|
(List<ListingMarginProvider>) getInstanceField("marginProviders", listingPanel);
|
||||||
for (MarginProvider marginProvider : list) {
|
for (ListingMarginProvider marginProvider : list) {
|
||||||
listingPanel.removeMarginProvider(marginProvider);
|
listingPanel.removeMarginProvider(marginProvider);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+2
@@ -669,6 +669,8 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
addReference(0x1001020, 0x1008294, RefType.DATA);
|
addReference(0x1001020, 0x1008294, RefType.DATA);
|
||||||
addReference(0x1001030, 0x1008394, RefType.DATA);
|
addReference(0x1001030, 0x1008394, RefType.DATA);
|
||||||
|
|
||||||
|
waitForProgram(program);
|
||||||
|
|
||||||
Address srcAddr = addr(0x01006990);
|
Address srcAddr = addr(0x01006990);
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(srcAddr);
|
CodeUnit cu = program.getListing().getCodeUnitAt(srcAddr);
|
||||||
|
|
||||||
|
|||||||
+26
-13
@@ -44,17 +44,15 @@ import ghidra.app.plugin.core.clear.ClearPlugin;
|
|||||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
import ghidra.app.plugin.core.highlight.SetHighlightPlugin;
|
import ghidra.app.plugin.core.highlight.SetHighlightPlugin;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.util.viewer.listingpanel.OverviewProvider;
|
|
||||||
import ghidra.app.util.viewer.util.AddressIndexMap;
|
import ghidra.app.util.viewer.util.AddressIndexMap;
|
||||||
import ghidra.framework.cmd.CompoundCmd;
|
import ghidra.framework.cmd.CompoundCmd;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.BookmarkType;
|
import ghidra.program.model.listing.BookmarkType;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.ProgramLocation;
|
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.test.*;
|
import ghidra.test.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.datastruct.WeakSet;
|
||||||
|
|
||||||
public class MarkerTest extends AbstractGhidraHeadedIntegrationTest {
|
public class MarkerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
@@ -162,8 +160,13 @@ public class MarkerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
setSelection(fp, sel);
|
setSelection(fp, sel);
|
||||||
|
|
||||||
MarkerManager mm = (MarkerManager) markerService;
|
MarkerManager mm = (MarkerManager) markerService;
|
||||||
OverviewProvider op = mm.getOverviewProvider();
|
|
||||||
JPanel navPanel = (JPanel) op.getComponent();
|
@SuppressWarnings("unchecked")
|
||||||
|
WeakSet<MarkerOverviewProvider> overviewProviders =
|
||||||
|
(WeakSet<MarkerOverviewProvider>) getInstanceField("overviewProviders", mm);
|
||||||
|
MarkerOverviewProvider provider = overviewProviders.iterator().next();
|
||||||
|
|
||||||
|
JPanel navPanel = (JPanel) provider.getComponent();
|
||||||
|
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
@@ -224,8 +227,13 @@ public class MarkerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertTrue(addrSet.contains(addr("0xf000131b")));
|
assertTrue(addrSet.contains(addr("0xf000131b")));
|
||||||
|
|
||||||
MarkerManager mm = (MarkerManager) markerService;
|
MarkerManager mm = (MarkerManager) markerService;
|
||||||
OverviewProvider op = mm.getOverviewProvider();
|
|
||||||
JPanel navPanel = (JPanel) op.getComponent();
|
@SuppressWarnings("unchecked")
|
||||||
|
WeakSet<MarkerOverviewProvider> overviewProviders =
|
||||||
|
(WeakSet<MarkerOverviewProvider>) getInstanceField("overviewProviders", mm);
|
||||||
|
MarkerOverviewProvider provider = overviewProviders.iterator().next();
|
||||||
|
|
||||||
|
JPanel navPanel = (JPanel) provider.getComponent();
|
||||||
|
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
@@ -278,7 +286,12 @@ public class MarkerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
MouseEvent dummyEvent =
|
MouseEvent dummyEvent =
|
||||||
new MouseEvent(cb.getFieldPanel(), (int) time, time, 0, x, y, 1, false);
|
new MouseEvent(cb.getFieldPanel(), (int) time, time, 0, x, y, 1, false);
|
||||||
MarkerManager mm = (MarkerManager) markerService;
|
MarkerManager mm = (MarkerManager) markerService;
|
||||||
String tooltip = runSwing(() -> mm.generateToolTip(dummyEvent));
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
WeakSet<MarkerMarginProvider> marginProviders =
|
||||||
|
(WeakSet<MarkerMarginProvider>) getInstanceField("marginProviders", mm);
|
||||||
|
MarkerMarginProvider provider = marginProviders.iterator().next();
|
||||||
|
String tooltip = runSwing(() -> provider.generateToolTip(dummyEvent));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"<html><font size=\"4\">Cursor<BR>Note [TEST]: comment<BR>Changes: Unsaved<BR>",
|
"<html><font size=\"4\">Cursor<BR>Note [TEST]: comment<BR>Changes: Unsaved<BR>",
|
||||||
tooltip);
|
tooltip);
|
||||||
@@ -316,11 +329,11 @@ public class MarkerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
MouseEvent dummyEvent = new MouseEvent(cb.getFieldPanel(), (int) System.currentTimeMillis(),
|
MouseEvent dummyEvent = new MouseEvent(cb.getFieldPanel(), (int) System.currentTimeMillis(),
|
||||||
System.currentTimeMillis(), 0, x, y, 1, false);
|
System.currentTimeMillis(), 0, x, y, 1, false);
|
||||||
|
|
||||||
// debug
|
@SuppressWarnings("unchecked")
|
||||||
ProgramLocation location = cb.getListingPanel().getProgramLocation(dummyEvent.getPoint());
|
WeakSet<MarkerMarginProvider> marginProviders =
|
||||||
Msg.debug(this, "location for point: " + location + "; at " + location.getAddress());
|
(WeakSet<MarkerMarginProvider>) getInstanceField("marginProviders", mm);
|
||||||
|
MarkerMarginProvider provider = marginProviders.iterator().next();
|
||||||
String tooltip = runSwing(() -> mm.generateToolTip(dummyEvent));
|
String tooltip = runSwing(() -> provider.generateToolTip(dummyEvent));
|
||||||
assertNotNull("No tooltip for field: " + cb.getCurrentField() + "\n\tat address: " +
|
assertNotNull("No tooltip for field: " + cb.getCurrentField() + "\n\tat address: " +
|
||||||
cb.getCurrentAddress(), tooltip);
|
cb.getCurrentAddress(), tooltip);
|
||||||
|
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void cleanup() {
|
protected void dispose() {
|
||||||
fidFileManager.removeChangeListener(this);
|
fidFileManager.removeChangeListener(this);
|
||||||
super.cleanup();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+50
-50
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -133,7 +133,6 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
private DiffController diffControl;
|
private DiffController diffControl;
|
||||||
private Program primaryProgram;
|
private Program primaryProgram;
|
||||||
private Program secondaryDiffProgram;
|
private Program secondaryDiffProgram;
|
||||||
private AddressFactory p2AddressFactory;
|
|
||||||
private ProgramDiffDetails diffDetails;
|
private ProgramDiffDetails diffDetails;
|
||||||
|
|
||||||
private ProgramSelection p2DiffHighlight;
|
private ProgramSelection p2DiffHighlight;
|
||||||
@@ -286,33 +285,39 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
if (primaryProgram != null && !showingSecondProgram) {
|
if (primaryProgram != null && !showingSecondProgram) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
p1ViewAddrSet = p1AddressSet;
|
p1ViewAddrSet = p1AddressSet;
|
||||||
|
if (!showingSecondProgram) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (showingSecondProgram) {
|
ProgramSelection previousP1Selection = currentSelection;
|
||||||
ProgramSelection previousP1Selection = currentSelection;
|
ProgramSelection previousP2DiffHighlight = p2DiffHighlight;
|
||||||
ProgramSelection previousP2DiffHighlight = p2DiffHighlight;
|
ProgramSelection previousP2Selection = p2Selection;
|
||||||
ProgramSelection previousP2Selection = p2Selection;
|
|
||||||
|
|
||||||
AddressSet p2ViewAddrSet =
|
AddressSet p2ViewAddrSet =
|
||||||
DiffUtility.getCompatibleAddressSet(p1ViewAddrSet, secondaryDiffProgram);
|
DiffUtility.getCompatibleAddressSet(p1ViewAddrSet, secondaryDiffProgram);
|
||||||
diffListingPanel.setView(p2ViewAddrSet);
|
diffListingPanel.setView(p2ViewAddrSet);
|
||||||
FieldPanel fp = diffListingPanel.getFieldPanel();
|
FieldPanel fp = diffListingPanel.getFieldPanel();
|
||||||
|
|
||||||
AddressSet p1AddressSetAsP2 =
|
AddressSet p1AddressSetAsP2 =
|
||||||
DiffUtility.getCompatibleAddressSet(p1AddressSet, secondaryDiffProgram);
|
DiffUtility.getCompatibleAddressSet(p1AddressSet, secondaryDiffProgram);
|
||||||
AddressIndexMap p2IndexMap = new AddressIndexMap(p1AddressSetAsP2);
|
AddressIndexMap p2IndexMap = new AddressIndexMap(p1AddressSetAsP2);
|
||||||
markerManager.getOverviewProvider().setProgram(secondaryDiffProgram, p2IndexMap);
|
List<ListingOverviewProvider> providers = diffListingPanel.getOverviewProviders();
|
||||||
fp.setBackgroundColorModel(new MarkerServiceBackgroundColorModel(markerManager,
|
for (ListingOverviewProvider provider : providers) {
|
||||||
secondaryDiffProgram, p2IndexMap));
|
provider.screenDataChanged(secondaryDiffProgram, p2IndexMap);
|
||||||
|
}
|
||||||
|
|
||||||
currentSelection = previousP1Selection;
|
fp.setBackgroundColorModel(new MarkerServiceBackgroundColorModel(markerManager,
|
||||||
p2DiffHighlight = previousP2DiffHighlight;
|
secondaryDiffProgram, p2IndexMap));
|
||||||
|
|
||||||
p2Selection = previousP2Selection;
|
currentSelection = previousP1Selection;
|
||||||
setProgram2Selection(p2Selection);
|
p2DiffHighlight = previousP2DiffHighlight;
|
||||||
if (p2DiffHighlight != null) {
|
|
||||||
setDiffHighlight(p2DiffHighlight);
|
p2Selection = previousP2Selection;
|
||||||
}
|
setProgram2Selection(p2Selection);
|
||||||
|
if (p2DiffHighlight != null) {
|
||||||
|
setDiffHighlight(p2DiffHighlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,9 +561,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (currentSelection == null) {
|
if (currentSelection == null) {
|
||||||
AddressFactory p1AddressFactory =
|
currentSelection = new ProgramSelection();
|
||||||
(primaryProgram != null) ? primaryProgram.getAddressFactory() : null;
|
|
||||||
currentSelection = new ProgramSelection(p1AddressFactory);
|
|
||||||
}
|
}
|
||||||
actionManager.setP1SelectToP2ActionEnabled(
|
actionManager.setP1SelectToP2ActionEnabled(
|
||||||
secondaryDiffProgram != null && !currentSelection.isEmpty());
|
secondaryDiffProgram != null && !currentSelection.isEmpty());
|
||||||
@@ -605,8 +608,13 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
diffListingPanel.setProgramLocationListener(this);
|
diffListingPanel.setProgramLocationListener(this);
|
||||||
diffListingPanel.setProgramSelectionListener(this);
|
diffListingPanel.setProgramSelectionListener(this);
|
||||||
diffListingPanel.getFieldPanel().addFieldMouseListener(new MyFieldMouseListener());
|
diffListingPanel.getFieldPanel().addFieldMouseListener(new MyFieldMouseListener());
|
||||||
diffListingPanel.addMarginProvider(markerManager.getMarginProvider());
|
|
||||||
diffListingPanel.addOverviewProvider(markerManager.getOverviewProvider());
|
// Manually install our custom margin provider. We are not calling setMarginService(),
|
||||||
|
// which means that many of the listing markers will not work in the diff view.
|
||||||
|
MarkerService markerService = tool.getService(MarkerService.class);
|
||||||
|
diffListingPanel.addMarginProvider(markerService.createMarginProvider());
|
||||||
|
diffListingPanel.addOverviewProvider(markerService.createOverviewProvider());
|
||||||
|
|
||||||
diffNavigatable = new DiffNavigatable(this, codeViewerService.getNavigatable());
|
diffNavigatable = new DiffNavigatable(this, codeViewerService.getNavigatable());
|
||||||
diffFieldNavigator = new FieldNavigator(diffServiceProvider, diffNavigatable);
|
diffFieldNavigator = new FieldNavigator(diffServiceProvider, diffNavigatable);
|
||||||
diffListingPanel.addButtonPressedListener(diffFieldNavigator);
|
diffListingPanel.addButtonPressedListener(diffFieldNavigator);
|
||||||
@@ -678,9 +686,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
|
|
||||||
ProgramSelection getCurrentSelection() {
|
ProgramSelection getCurrentSelection() {
|
||||||
if (currentSelection == null) {
|
if (currentSelection == null) {
|
||||||
AddressFactory p1AddressFactory =
|
currentSelection = new ProgramSelection();
|
||||||
(primaryProgram != null) ? primaryProgram.getAddressFactory() : null;
|
|
||||||
currentSelection = new ProgramSelection(p1AddressFactory);
|
|
||||||
}
|
}
|
||||||
return currentSelection;
|
return currentSelection;
|
||||||
}
|
}
|
||||||
@@ -753,10 +759,8 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
// Make sure that the Diff selection is to the code unit boundary.
|
// Make sure that the Diff selection is to the code unit boundary.
|
||||||
ProgramSelection p2CodeUnitSelection =
|
ProgramSelection p2CodeUnitSelection =
|
||||||
new ProgramSelection(DiffUtility.getCodeUnitSet(newP2Selection, secondaryDiffProgram));
|
new ProgramSelection(DiffUtility.getCodeUnitSet(newP2Selection, secondaryDiffProgram));
|
||||||
AddressFactory p1AddressFactory =
|
|
||||||
(primaryProgram != null) ? primaryProgram.getAddressFactory() : null;
|
|
||||||
ProgramSelection intersection =
|
ProgramSelection intersection =
|
||||||
new ProgramSelection(p2AddressFactory, p2CodeUnitSelection.intersect(p2DiffHighlight));
|
new ProgramSelection(p2CodeUnitSelection.intersect(p2DiffHighlight));
|
||||||
|
|
||||||
p2Selection = intersection;
|
p2Selection = intersection;
|
||||||
AddressSet p2SelectionAsP1Set =
|
AddressSet p2SelectionAsP1Set =
|
||||||
@@ -767,8 +771,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
// of the MultiListing Layout being used.
|
// of the MultiListing Layout being used.
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
ProgramSelection p2SelectionAsP1 =
|
ProgramSelection p2SelectionAsP1 = new ProgramSelection(p2SelectionAsP1Set);
|
||||||
new ProgramSelection(p1AddressFactory, p2SelectionAsP1Set);
|
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
MarkerSet selectionMarkers = getSelectionMarkers();
|
MarkerSet selectionMarkers = getSelectionMarkers();
|
||||||
selectionMarkers.clearAll();
|
selectionMarkers.clearAll();
|
||||||
@@ -783,7 +786,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
actionManager.setP1SelectToP2ActionEnabled(
|
actionManager.setP1SelectToP2ActionEnabled(
|
||||||
(secondaryDiffProgram != null) && !currentSelection.isEmpty());
|
(secondaryDiffProgram != null) && !currentSelection.isEmpty());
|
||||||
firePluginEvent(new ProgramSelectionPluginEvent(this.getName(),
|
firePluginEvent(new ProgramSelectionPluginEvent(this.getName(),
|
||||||
new ProgramSelection(p1AddressFactory, currentSelection), primaryProgram));
|
new ProgramSelection(currentSelection), primaryProgram));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -873,7 +876,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddressSet p2DiffSet = DiffUtility.getCompatibleAddressSet(p1DiffSet, secondaryDiffProgram);
|
AddressSet p2DiffSet = DiffUtility.getCompatibleAddressSet(p1DiffSet, secondaryDiffProgram);
|
||||||
ProgramSelection p2DiffSelection = new ProgramSelection(p2AddressFactory, p2DiffSet);
|
ProgramSelection p2DiffSelection = new ProgramSelection(p2DiffSet);
|
||||||
p2DiffHighlight = p2DiffSelection;
|
p2DiffHighlight = p2DiffSelection;
|
||||||
AddressSet p2DiffSetAsP1 = DiffUtility.getCompatibleAddressSet(p2DiffSet, primaryProgram);
|
AddressSet p2DiffSetAsP1 = DiffUtility.getCompatibleAddressSet(p2DiffSet, primaryProgram);
|
||||||
|
|
||||||
@@ -918,7 +921,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
if (diffControl.hasNext()) {
|
if (diffControl.hasNext()) {
|
||||||
diffControl.next();
|
diffControl.next();
|
||||||
}
|
}
|
||||||
setProgram2Selection(new ProgramSelection(p2AddressFactory, getDiffHighlightBlock()));
|
setProgram2Selection(new ProgramSelection(getDiffHighlightBlock()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void previousDiff() {
|
void previousDiff() {
|
||||||
@@ -926,7 +929,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
if (diffControl.hasPrevious()) {
|
if (diffControl.hasPrevious()) {
|
||||||
diffControl.previous();
|
diffControl.previous();
|
||||||
}
|
}
|
||||||
setProgram2Selection(new ProgramSelection(p2AddressFactory, getDiffHighlightBlock()));
|
setProgram2Selection(new ProgramSelection(getDiffHighlightBlock()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearDiff() {
|
private void clearDiff() {
|
||||||
@@ -992,8 +995,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
AddressSet p1IgnoreSet =
|
AddressSet p1IgnoreSet =
|
||||||
DiffUtility.getCompatibleAddressSet(p2IgnoreSet, primaryProgram);
|
DiffUtility.getCompatibleAddressSet(p2IgnoreSet, primaryProgram);
|
||||||
diffControl.ignore(p1IgnoreSet, null);
|
diffControl.ignore(p1IgnoreSet, null);
|
||||||
p2DiffHighlight =
|
p2DiffHighlight = new ProgramSelection(p2DiffHighlight.subtract(p2IgnoreSet));
|
||||||
new ProgramSelection(p2AddressFactory, p2DiffHighlight.subtract(p2IgnoreSet));
|
|
||||||
|
|
||||||
adjustDiffDisplay();
|
adjustDiffDisplay();
|
||||||
|
|
||||||
@@ -1047,7 +1049,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
}
|
}
|
||||||
AddressSetView p2ViewAddrSet =
|
AddressSetView p2ViewAddrSet =
|
||||||
DiffUtility.getCompatibleAddressSet(adjustedView, secondaryDiffProgram);
|
DiffUtility.getCompatibleAddressSet(adjustedView, secondaryDiffProgram);
|
||||||
setProgram2Selection(new ProgramSelection(p2AddressFactory, p2ViewAddrSet));
|
setProgram2Selection(new ProgramSelection(p2ViewAddrSet));
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
diffListingPanel.getFieldPanel().requestFocus();
|
diffListingPanel.getFieldPanel().requestFocus();
|
||||||
@@ -1078,7 +1080,6 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
primaryProgram.removeListener(this);
|
primaryProgram.removeListener(this);
|
||||||
primaryProgram = null;
|
primaryProgram = null;
|
||||||
secondaryDiffProgram = null;
|
secondaryDiffProgram = null;
|
||||||
p2AddressFactory = null;
|
|
||||||
}
|
}
|
||||||
sameProgramContext = false;
|
sameProgramContext = false;
|
||||||
updatePgm2Enablement();
|
updatePgm2Enablement();
|
||||||
@@ -1221,7 +1222,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
if (!currentSelection.isEmpty()) {
|
if (!currentSelection.isEmpty()) {
|
||||||
AddressSet p2SelectionSet =
|
AddressSet p2SelectionSet =
|
||||||
DiffUtility.getCompatibleAddressSet(currentSelection, secondaryDiffProgram);
|
DiffUtility.getCompatibleAddressSet(currentSelection, secondaryDiffProgram);
|
||||||
setProgram2Selection(new ProgramSelection(p2AddressFactory,
|
setProgram2Selection(new ProgramSelection(
|
||||||
DiffUtility.getCodeUnitSet(p2SelectionSet, secondaryDiffProgram)));
|
DiffUtility.getCodeUnitSet(p2SelectionSet, secondaryDiffProgram)));
|
||||||
}
|
}
|
||||||
if (p2Selection.isEmpty()) {
|
if (p2Selection.isEmpty()) {
|
||||||
@@ -1630,7 +1631,6 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
|
|
||||||
primaryProgram = currentProgram;
|
primaryProgram = currentProgram;
|
||||||
secondaryDiffProgram = newProgram;
|
secondaryDiffProgram = newProgram;
|
||||||
p2AddressFactory = secondaryDiffProgram.getAddressFactory();
|
|
||||||
applyFilter = applySettingsMgr.getDefaultApplyFilter();
|
applyFilter = applySettingsMgr.getDefaultApplyFilter();
|
||||||
diffDetails = new ProgramDiffDetails(primaryProgram, secondaryDiffProgram);
|
diffDetails = new ProgramDiffDetails(primaryProgram, secondaryDiffProgram);
|
||||||
primaryProgram.addListener(this);
|
primaryProgram.addListener(this);
|
||||||
@@ -1884,14 +1884,14 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set.equals(p2Selection)) {
|
AddressSetView asView = p2Selection;
|
||||||
|
if (set.equals(asView)) {
|
||||||
return; // Selection is unchanged so do nothing.
|
return; // Selection is unchanged so do nothing.
|
||||||
}
|
}
|
||||||
MarkerSet selectionMarkers = getSelectionMarkers();
|
MarkerSet selectionMarkers = getSelectionMarkers();
|
||||||
selectionMarkers.clearAll();
|
selectionMarkers.clearAll();
|
||||||
|
|
||||||
programSelectionChanged(new ProgramSelection(p2AddressFactory, set),
|
programSelectionChanged(new ProgramSelection(set), EventTrigger.GUI_ACTION);
|
||||||
EventTrigger.GUI_ACTION);
|
|
||||||
updatePgm2Enablement();
|
updatePgm2Enablement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-10
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -762,7 +762,8 @@ public class VTSubToolManager implements VTControllerListener, OptionsChangeList
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCursorOnScreen(CodeViewerService service) {
|
private boolean isCursorOnScreen(CodeViewerService service) {
|
||||||
FieldPanel fieldPanel = service.getFieldPanel();
|
ListingPanel listingPanel = service.getListingPanel();
|
||||||
|
FieldPanel fieldPanel = listingPanel.getFieldPanel();
|
||||||
int cursorOffset = fieldPanel.getCursorOffset();
|
int cursorOffset = fieldPanel.getCursorOffset();
|
||||||
return cursorOffset >= 0; // negative offset means offscreen
|
return cursorOffset >= 0; // negative offset means offscreen
|
||||||
}
|
}
|
||||||
@@ -779,7 +780,10 @@ public class VTSubToolManager implements VTControllerListener, OptionsChangeList
|
|||||||
if (service == null) {
|
if (service == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
FieldSelection selection = service.getFieldPanel().getSelection();
|
|
||||||
|
ListingPanel listingPanel = service.getListingPanel();
|
||||||
|
FieldPanel fieldPanel = listingPanel.getFieldPanel();
|
||||||
|
FieldSelection selection = fieldPanel.getSelection();
|
||||||
AddressIndexMap addressIndexMap = service.getListingPanel().getAddressIndexMap();
|
AddressIndexMap addressIndexMap = service.getListingPanel().getAddressIndexMap();
|
||||||
AddressSet addressSet = addressIndexMap.getAddressSet(selection);
|
AddressSet addressSet = addressIndexMap.getAddressSet(selection);
|
||||||
return addressSet;
|
return addressSet;
|
||||||
@@ -788,13 +792,11 @@ public class VTSubToolManager implements VTControllerListener, OptionsChangeList
|
|||||||
/**
|
/**
|
||||||
* Sets the address set to be the selection in the tool.
|
* Sets the address set to be the selection in the tool.
|
||||||
*
|
*
|
||||||
* @param tool
|
* @param tool the tool
|
||||||
* the tool
|
* @param addresses the addressSet to use for the selection
|
||||||
* @param set
|
|
||||||
* the addressSet to use for the selection
|
|
||||||
*/
|
*/
|
||||||
private void setSelectionInTool(PluginTool tool, AddressSetView addressSet) {
|
private void setSelectionInTool(PluginTool tool, AddressSetView addresses) {
|
||||||
ProgramSelection programSelection = new ProgramSelection(addressSet);
|
ProgramSelection programSelection = new ProgramSelection(addresses);
|
||||||
CodeViewerService service = tool.getService(CodeViewerService.class);
|
CodeViewerService service = tool.getService(CodeViewerService.class);
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -268,6 +268,10 @@ public abstract class Plugin implements ExtensionPoint, PluginEventListener, Ser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the framework to dispose of this plugin and unregister for events and services.
|
||||||
|
* Subclasses should not override this method, but should instead override {@link #dispose()}.
|
||||||
|
*/
|
||||||
protected void cleanup() {
|
protected void cleanup() {
|
||||||
if (!disposed) {
|
if (!disposed) {
|
||||||
Throwable thr = null;
|
Throwable thr = null;
|
||||||
|
|||||||
+3
-1
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.control;
|
package ghidra.app.plugin.core.debug.gui.control;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -26,6 +26,7 @@ import org.junit.Test;
|
|||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import ghidra.app.context.ProgramLocationActionContext;
|
import ghidra.app.context.ProgramLocationActionContext;
|
||||||
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerIntegrationTest;
|
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerIntegrationTest;
|
||||||
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
|
||||||
@@ -50,6 +51,7 @@ public class DebuggerMethodActionsPluginTest extends AbstractGhidraHeadedDebugge
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUpMethodActionsTest() throws Exception {
|
public void setUpMethodActionsTest() throws Exception {
|
||||||
|
addPlugin(tool, CodeBrowserPlugin.class);
|
||||||
listingPlugin = addPlugin(tool, DebuggerListingPlugin.class);
|
listingPlugin = addPlugin(tool, DebuggerListingPlugin.class);
|
||||||
mappingService = addPlugin(tool, DebuggerStaticMappingServicePlugin.class);
|
mappingService = addPlugin(tool, DebuggerStaticMappingServicePlugin.class);
|
||||||
methodsPlugin = addPlugin(tool, DebuggerMethodActionsPlugin.class);
|
methodsPlugin = addPlugin(tool, DebuggerMethodActionsPlugin.class);
|
||||||
|
|||||||
+6
-6
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -31,7 +31,7 @@ import ghidra.app.util.viewer.field.*;
|
|||||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||||
import ghidra.app.util.viewer.format.FormatManager;
|
import ghidra.app.util.viewer.format.FormatManager;
|
||||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.app.util.viewer.listingpanel.MarginProvider;
|
import ghidra.app.util.viewer.listingpanel.ListingMarginProvider;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
@@ -138,11 +138,11 @@ public class BlockModelScreenShots extends GhidraScreenShotGenerator {
|
|||||||
final ListingPanel lp = cb.getListingPanel();
|
final ListingPanel lp = cb.getListingPanel();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final List<MarginProvider> list =
|
final List<ListingMarginProvider> list =
|
||||||
new ArrayList<>((List<MarginProvider>) getInstanceField("marginProviders", lp));
|
new ArrayList<>((List<ListingMarginProvider>) getInstanceField("marginProviders", lp));
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
invokeInstanceMethod("buildPanels", lp);
|
invokeInstanceMethod("buildPanels", lp);
|
||||||
for (MarginProvider marginProvider : list) {
|
for (ListingMarginProvider marginProvider : list) {
|
||||||
lp.removeMarginProvider(marginProvider);
|
lp.removeMarginProvider(marginProvider);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-3
@@ -39,7 +39,7 @@ import ghidra.app.plugin.core.datamgr.DataTypesProvider;
|
|||||||
import ghidra.app.plugin.core.programtree.ViewManagerComponentProvider;
|
import ghidra.app.plugin.core.programtree.ViewManagerComponentProvider;
|
||||||
import ghidra.app.util.viewer.field.*;
|
import ghidra.app.util.viewer.field.*;
|
||||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.app.util.viewer.listingpanel.OverviewProvider;
|
import ghidra.app.util.viewer.listingpanel.ListingOverviewProvider;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.CommentType;
|
import ghidra.program.model.listing.CommentType;
|
||||||
|
|
||||||
@@ -265,10 +265,10 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator {
|
|||||||
public void testCaptureMarkerPopup() {
|
public void testCaptureMarkerPopup() {
|
||||||
setToolSize(1400, 1200);
|
setToolSize(1400, 1200);
|
||||||
ListingPanel listingPanel = plugin.getListingPanel();
|
ListingPanel listingPanel = plugin.getListingPanel();
|
||||||
List<OverviewProvider> overviewProviders = listingPanel.getOverviewProviders();
|
List<ListingOverviewProvider> overviewProviders = listingPanel.getOverviewProviders();
|
||||||
assertEquals(1, overviewProviders.size());
|
assertEquals(1, overviewProviders.size());
|
||||||
|
|
||||||
OverviewProvider provider = overviewProviders.get(0);
|
ListingOverviewProvider provider = overviewProviders.get(0);
|
||||||
rightClick(provider.getComponent(), 1, 1);
|
rightClick(provider.getComponent(), 1, 1);
|
||||||
|
|
||||||
captureMenu();
|
captureMenu();
|
||||||
|
|||||||
Reference in New Issue
Block a user