mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1625: Improve consistency of DebuggerMemoryBytesProvider
This commit is contained in:
parent
7d189001d6
commit
8e3f97056b
9 changed files with 131 additions and 29 deletions
|
@ -19,6 +19,7 @@ import static ghidra.app.plugin.core.debug.gui.DebuggerResources.ICON_REGISTER_M
|
|||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
@ -26,8 +27,7 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
|
@ -62,6 +62,7 @@ import ghidra.app.plugin.core.debug.utils.ProgramURLUtils;
|
|||
import ghidra.app.plugin.core.marker.MarkerMarginProvider;
|
||||
import ghidra.app.plugin.core.marker.MarkerOverviewProvider;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.services.DebuggerControlService.ControlModeChangeListener;
|
||||
import ghidra.app.services.DebuggerListingService.LocationTrackingSpecChangeListener;
|
||||
import ghidra.app.util.viewer.format.FormatManager;
|
||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||
|
@ -293,7 +294,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||
private DebuggerStaticMappingService mappingService;
|
||||
@AutoServiceConsumed
|
||||
private DebuggerConsoleService consoleService;
|
||||
@AutoServiceConsumed
|
||||
//@AutoServiceConsumed via method
|
||||
private DebuggerControlService controlService;
|
||||
@AutoServiceConsumed
|
||||
private ProgramManager programManager;
|
||||
|
@ -354,6 +355,12 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||
|
||||
protected final ForStaticSyncMappingChangeListener mappingChangeListener =
|
||||
new ForStaticSyncMappingChangeListener();
|
||||
private final ControlModeChangeListener controlModeChangeListener = (trace, mode) -> {
|
||||
if (trace == current.getTrace()) {
|
||||
// for Paste action
|
||||
contextChanged();
|
||||
}
|
||||
};
|
||||
|
||||
protected final boolean isMainListing;
|
||||
|
||||
|
@ -597,6 +604,17 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@AutoServiceConsumed
|
||||
private void setControlService(DebuggerControlService controlService) {
|
||||
if (this.controlService != null) {
|
||||
this.controlService.removeModeChangeListener(controlModeChangeListener);
|
||||
}
|
||||
this.controlService = controlService;
|
||||
if (this.controlService != null) {
|
||||
this.controlService.addModeChangeListener(controlModeChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@AutoServiceConsumed
|
||||
private void setConsoleService(DebuggerConsoleService consoleService) {
|
||||
if (consoleService != null) {
|
||||
|
@ -725,6 +743,14 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||
return DateUtils.formatDateTimestamp(new Date(snapshot.getRealTime()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
if (isMainListing()) {
|
||||
return getBaseIcon();
|
||||
}
|
||||
return super.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListingActionContext newListingActionContext() {
|
||||
return new DebuggerListingActionContext(this);
|
||||
|
@ -740,6 +766,21 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
|||
}
|
||||
return context.getComponentProvider() == componentProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPaste(DataFlavor[] availableFlavors) {
|
||||
if (controlService == null) {
|
||||
return false;
|
||||
}
|
||||
Trace trace = current.getTrace();
|
||||
if (trace == null) {
|
||||
return false;
|
||||
}
|
||||
if (!controlService.getCurrentMode(trace).canEdit(current)) {
|
||||
return false;
|
||||
}
|
||||
return super.canPaste(availableFlavors);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ public class DebuggerMemoryBytesPlugin
|
|||
private void createActions() {
|
||||
actionNewMemory = NewMemoryAction.builder(this)
|
||||
.enabled(true)
|
||||
.onAction(c -> createNewDisconnectedProvider())
|
||||
.onAction(c -> connectedProvider.cloneWindow())
|
||||
.buildAndInstall(tool);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,14 @@
|
|||
package ghidra.app.plugin.core.debug.gui.memory;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
@ -40,6 +40,8 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources.FollowsCurrentThreadAc
|
|||
import ghidra.app.plugin.core.debug.gui.action.*;
|
||||
import ghidra.app.plugin.core.debug.gui.action.AutoReadMemorySpec.AutoReadMemorySpecConfigFieldCodec;
|
||||
import ghidra.app.plugin.core.format.ByteBlock;
|
||||
import ghidra.app.services.DebuggerControlService;
|
||||
import ghidra.app.services.DebuggerControlService.ControlModeChangeListener;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.debug.api.action.GoToInput;
|
||||
import ghidra.debug.api.action.LocationTrackingSpec;
|
||||
|
@ -168,6 +170,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
|
||||
@AutoServiceConsumed
|
||||
private DebuggerTraceManagerService traceManager;
|
||||
//@AutoServiceConsumed via method
|
||||
private DebuggerControlService controlService;
|
||||
@SuppressWarnings("unused")
|
||||
private final AutoService.Wiring autoServiceWiring;
|
||||
|
||||
|
@ -191,6 +195,12 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
// TODO: followsCurrentSnap?
|
||||
|
||||
private final ListenerForChanges listenerForChanges = new ListenerForChanges();
|
||||
private final ControlModeChangeListener controlModeChangeListener = (trace, mode) -> {
|
||||
if (trace == getCurrent().getTrace()) {
|
||||
// for Paste action
|
||||
contextChanged();
|
||||
}
|
||||
};
|
||||
|
||||
DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
||||
private DebuggerCoordinates previous = DebuggerCoordinates.NOWHERE;
|
||||
|
@ -220,6 +230,13 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
readsMemTrait.goToCoordinates(current);
|
||||
locationLabel.goToCoordinates(current);
|
||||
|
||||
if (isConnected) {
|
||||
setTitle(DebuggerResources.TITLE_PROVIDER_MEMORY_BYTES);
|
||||
}
|
||||
else {
|
||||
setTitle("[" + DebuggerResources.TITLE_PROVIDER_MEMORY_BYTES + "]");
|
||||
}
|
||||
updateTitle(); // Actually, the subtitle
|
||||
setHelpLocation(DebuggerResources.HELP_PROVIDER_MEMORY_BYTES);
|
||||
|
||||
trackingLabel.addMouseListener(new MouseAdapter() {
|
||||
|
@ -339,11 +356,50 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
setSubTitle(computeSubTitle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
if (isMainViewer()) {
|
||||
return getBaseIcon();
|
||||
}
|
||||
return super.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteViewerActionContext newByteViewerActionContext() {
|
||||
return new DebuggerMemoryBytesActionContext(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteViewerClipboardProvider newClipboardProvider() {
|
||||
return new ByteViewerClipboardProvider(this, tool) {
|
||||
@Override
|
||||
public boolean canPaste(DataFlavor[] availableFlavors) {
|
||||
if (controlService == null) {
|
||||
return false;
|
||||
}
|
||||
Trace trace = current.getTrace();
|
||||
if (trace == null) {
|
||||
return false;
|
||||
}
|
||||
if (!controlService.getCurrentMode(trace).canEdit(current)) {
|
||||
return false;
|
||||
}
|
||||
return super.canPaste(availableFlavors);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@AutoServiceConsumed
|
||||
private void setControlService(DebuggerControlService controlService) {
|
||||
if (this.controlService != null) {
|
||||
this.controlService.removeModeChangeListener(controlModeChangeListener);
|
||||
}
|
||||
this.controlService = controlService;
|
||||
if (this.controlService != null) {
|
||||
this.controlService.addModeChangeListener(controlModeChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
protected void createActions() {
|
||||
initTraits();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.memory;
|
||||
|
||||
import static ghidra.lifecycle.Unfinished.*;
|
||||
import static ghidra.lifecycle.Unfinished.TODO;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
|
@ -49,7 +49,7 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources.FollowsCurrentThreadAc
|
|||
import ghidra.app.plugin.core.debug.gui.action.*;
|
||||
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
||||
import ghidra.app.plugin.core.debug.service.control.DebuggerControlServicePlugin;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.services.DebuggerControlService;
|
||||
import ghidra.async.SwingExecutorService;
|
||||
import ghidra.debug.api.control.ControlMode;
|
||||
import ghidra.debug.api.model.TraceRecorder;
|
||||
|
|
|
@ -79,7 +79,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||
|
||||
private static final String DIVIDER_LOCATION = "DividerLocation";
|
||||
|
||||
private ImageIcon navigatableIcon;
|
||||
private Map<Program, ListingHighlightProvider> programHighlighterMap = new HashMap<>();
|
||||
private ProgramHighlighterProvider highlighterAdapter;
|
||||
|
||||
|
@ -845,19 +844,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||
return currentStringSelection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
if (isConnected()) {
|
||||
return super.getIcon();
|
||||
}
|
||||
|
||||
if (navigatableIcon == null) {
|
||||
Icon primaryIcon = super.getIcon();
|
||||
navigatableIcon = NavigatableIconFactory.createSnapshotOverlayIcon(primaryIcon);
|
||||
}
|
||||
return navigatableIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getNavigatableIcon() {
|
||||
return getIcon();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -45,11 +44,11 @@ public abstract class NavigatableComponentProviderAdapter extends ComponentProvi
|
|||
@Override
|
||||
public Icon getIcon() {
|
||||
if (isConnected()) {
|
||||
return super.getIcon();
|
||||
return getBaseIcon();
|
||||
}
|
||||
|
||||
if (navigatableIcon == null) {
|
||||
Icon primaryIcon = super.getIcon();
|
||||
Icon primaryIcon = getBaseIcon();
|
||||
navigatableIcon = NavigatableIconFactory.createSnapshotOverlayIcon(primaryIcon);
|
||||
}
|
||||
return navigatableIcon;
|
||||
|
|
|
@ -57,7 +57,7 @@ public abstract class AbstractByteViewerPlugin<P extends ProgramByteViewerCompon
|
|||
|
||||
public P createNewDisconnectedProvider() {
|
||||
P newProvider = createProvider(false);
|
||||
disconnectedProviders.add(newProvider);
|
||||
addProvider(newProvider);
|
||||
tool.showComponentProvider(newProvider, true);
|
||||
return newProvider;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
|
|||
}
|
||||
|
||||
decorationComponent = new DecoratorPanel(panel, isConnected);
|
||||
clipboardProvider = new ByteViewerClipboardProvider(this, tool);
|
||||
clipboardProvider = newClipboardProvider();
|
||||
addToTool();
|
||||
|
||||
createProgramActions();
|
||||
|
@ -98,6 +98,10 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
|
|||
registerNavigatable();
|
||||
}
|
||||
|
||||
protected ByteViewerClipboardProvider newClipboardProvider() {
|
||||
return new ByteViewerClipboardProvider(this, tool);
|
||||
}
|
||||
|
||||
public void createProgramActions() {
|
||||
cloneByteViewerAction = new CloneByteViewerAction();
|
||||
tool.addLocalAction(this, cloneByteViewerAction);
|
||||
|
@ -343,11 +347,11 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
|
|||
@Override
|
||||
public Icon getIcon() {
|
||||
if (isConnected()) {
|
||||
return super.getIcon();
|
||||
return getBaseIcon();
|
||||
}
|
||||
|
||||
if (navigatableIcon == null) {
|
||||
Icon primaryIcon = super.getIcon();
|
||||
Icon primaryIcon = getBaseIcon();
|
||||
navigatableIcon = NavigatableIconFactory.createSnapshotOverlayIcon(primaryIcon);
|
||||
}
|
||||
return navigatableIcon;
|
||||
|
|
|
@ -628,6 +628,22 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
dockingTool.getWindowManager().setIcon(this, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon provided to {@link #setIcon(Icon)}
|
||||
*
|
||||
* <p>
|
||||
* This method is final, guaranteeing there is always a means for extensions of this class to
|
||||
* obtain the original icon. Some classes may override {@link #getIcon()} to apply modifications
|
||||
* when the icon is displayed in the UI. Further extensions of that class may wish to override
|
||||
* {@link #getIcon()}, too, and so might want access to the original base icon. This method
|
||||
* provides that access.
|
||||
*
|
||||
* @return the base icon
|
||||
*/
|
||||
protected final Icon getBaseIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that this provider's action for showing the provider should appear in the main
|
||||
* toolbar
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue