mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Merge remote-tracking branch 'origin/GP-4293_Dan_doubleClickModelActions--SQUASHED'
This commit is contained in:
commit
611aae64ae
30 changed files with 470 additions and 144 deletions
|
@ -23,6 +23,7 @@ import ghidra.debug.api.breakpoint.LogicalBreakpoint;
|
|||
import ghidra.debug.api.breakpoint.LogicalBreakpoint.State;
|
||||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
||||
|
@ -82,6 +83,10 @@ public class BreakpointLocationRow {
|
|||
return loc.getMinAddress();
|
||||
}
|
||||
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return new ProgramLocation(loc.getTrace().getProgramView(), getAddress());
|
||||
}
|
||||
|
||||
public String getTraceName() {
|
||||
return loc.getTrace().getName();
|
||||
}
|
||||
|
|
|
@ -1153,7 +1153,7 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
|||
}
|
||||
traceManager.activateTrace(trace);
|
||||
}
|
||||
listingService.goTo(row.getAddress(), true);
|
||||
listingService.goTo(row.getProgramLocation(), true);
|
||||
}
|
||||
|
||||
protected void createActions() {
|
||||
|
|
|
@ -267,8 +267,8 @@ public class DebuggerLegacyRegionsPanel extends JPanel {
|
|||
int selectedRow = regionTable.getSelectedRow();
|
||||
int selectedColumn = regionTable.getSelectedColumn();
|
||||
Object value = regionTable.getValueAt(selectedRow, selectedColumn);
|
||||
if (value instanceof Address) {
|
||||
listingService.goTo((Address) value, true);
|
||||
if (value instanceof Address address) {
|
||||
listingService.goTo(address, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTableModel createModel(Plugin plugin) {
|
||||
protected ObjectTableModel createModel() {
|
||||
return new RegionTableModel(plugin);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,27 +26,25 @@ import javax.swing.event.ListSelectionListener;
|
|||
|
||||
import docking.ComponentProvider;
|
||||
import ghidra.app.plugin.core.debug.gui.model.AbstractQueryTablePanel.CellActivationListener;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||
import ghidra.app.services.DebuggerListingService;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.AutoService;
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectInterface;
|
||||
import ghidra.trace.model.target.*;
|
||||
|
||||
public abstract class AbstractObjectsTableBasedPanel<U extends TraceObjectInterface>
|
||||
extends ObjectsTablePanel implements ListSelectionListener, CellActivationListener {
|
||||
extends ObjectsTablePanel
|
||||
implements ListSelectionListener, CellActivationListener, ObjectDefaultActionsMixin {
|
||||
|
||||
private final ComponentProvider provider;
|
||||
private final Class<U> objType;
|
||||
|
||||
@AutoServiceConsumed
|
||||
protected DebuggerTraceManagerService traceManager;
|
||||
@AutoServiceConsumed
|
||||
protected DebuggerListingService listingService;
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -121,23 +119,32 @@ public abstract class AbstractObjectsTableBasedPanel<U extends TraceObjectInterf
|
|||
|
||||
@Override
|
||||
public void cellActivated(JTable table) {
|
||||
if (listingService == null) {
|
||||
if (performElementCellDefaultAction(table)) {
|
||||
return;
|
||||
}
|
||||
int row = table.getSelectedRow();
|
||||
int col = table.getSelectedColumn();
|
||||
Object value = table.getValueAt(row, col);
|
||||
if (!(value instanceof ValueProperty<?> property)) {
|
||||
performValueRowDefaultAction(getSelectedItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DebuggerCoordinates getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTool getTool() {
|
||||
return plugin.getTool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activatePath(TraceObjectKeyPath path) {
|
||||
if (current.getTrace() == null) {
|
||||
return;
|
||||
}
|
||||
Object propVal = property.getValue();
|
||||
if (propVal instanceof Address address) {
|
||||
listingService.goTo(address, true);
|
||||
try {
|
||||
traceManager.activate(current.pathNonCanonical(path));
|
||||
}
|
||||
else if (propVal instanceof AddressRange range) {
|
||||
listingService.setCurrentSelection(
|
||||
new ProgramSelection(range.getMinAddress(), range.getMaxAddress()));
|
||||
listingService.goTo(range.getMinAddress(), true);
|
||||
catch (IllegalArgumentException e) {
|
||||
plugin.getTool().setStatusInfo(e.getMessage(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public abstract class AbstractQueryTablePanel<T, M extends AbstractQueryTableMod
|
|||
void cellActivated(JTable table);
|
||||
}
|
||||
|
||||
protected final Plugin plugin;
|
||||
protected final M tableModel;
|
||||
protected final GhidraTable table;
|
||||
protected final GhidraTableFilterPanel<T> filterPanel;
|
||||
|
@ -54,7 +55,9 @@ public abstract class AbstractQueryTablePanel<T, M extends AbstractQueryTableMod
|
|||
|
||||
public AbstractQueryTablePanel(Plugin plugin) {
|
||||
super(new BorderLayout());
|
||||
tableModel = createModel(plugin);
|
||||
this.plugin = plugin;
|
||||
|
||||
tableModel = createModel();
|
||||
table = new GhidraTable(tableModel);
|
||||
filterPanel = new GhidraTableFilterPanel<>(table, tableModel);
|
||||
|
||||
|
@ -80,7 +83,7 @@ public abstract class AbstractQueryTablePanel<T, M extends AbstractQueryTableMod
|
|||
});
|
||||
}
|
||||
|
||||
protected abstract M createModel(Plugin plugin);
|
||||
protected abstract M createModel();
|
||||
|
||||
protected void coordinatesChanged() {
|
||||
// Extension point
|
||||
|
|
|
@ -45,11 +45,11 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources.CloneWindowAction;
|
|||
import ghidra.app.plugin.core.debug.gui.MultiProviderSaveBehavior.SaveableProvider;
|
||||
import ghidra.app.plugin.core.debug.gui.control.TargetActionTask;
|
||||
import ghidra.app.plugin.core.debug.gui.model.AbstractQueryTablePanel.CellActivationListener;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ObjectRow;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTreeModel.*;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTreeModel.RootNode;
|
||||
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
||||
import ghidra.app.services.DebuggerListingService;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||
import ghidra.debug.api.target.ActionName;
|
||||
|
@ -233,6 +233,8 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||
|
||||
@AutoServiceConsumed
|
||||
protected DebuggerTraceManagerService traceManager;
|
||||
@AutoServiceConsumed
|
||||
protected DebuggerListingService listingService;
|
||||
@SuppressWarnings("unused")
|
||||
private final AutoService.Wiring autoServiceWiring;
|
||||
|
||||
|
@ -431,8 +433,49 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||
mainPanel.revalidate();
|
||||
}
|
||||
|
||||
protected class ObjectsTreeListener implements Adapters.FocusListener,
|
||||
protected void activatePath(TraceObjectKeyPath path) {
|
||||
if (current.getTrace() == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
traceManager.activate(current.pathNonCanonical(path));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
plugin.getTool().setStatusInfo(e.getMessage(), true);
|
||||
}
|
||||
}
|
||||
|
||||
protected class MyMixin implements ObjectDefaultActionsMixin {
|
||||
@Override
|
||||
public DebuggerCoordinates getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTool getTool() {
|
||||
return plugin.getTool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activatePath(TraceObjectKeyPath path) {
|
||||
DebuggerModelProvider.this.activatePath(path);
|
||||
}
|
||||
}
|
||||
|
||||
protected class ObjectsTreeListener extends MyMixin implements Adapters.FocusListener,
|
||||
Adapters.TreeExpansionListener, Adapters.MouseListener, Adapters.KeyListener {
|
||||
|
||||
private void activateObjectSelectedInTree() {
|
||||
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
||||
if (sel.size() != 1) {
|
||||
// TODO: Multiple paths? PathMatcher can do it, just have to parse
|
||||
// Just leave whatever was there.
|
||||
return;
|
||||
}
|
||||
TraceObjectValue value = sel.get(0).getValue();
|
||||
performDefaultAction(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
|
@ -501,18 +544,14 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||
}
|
||||
}
|
||||
|
||||
protected class ElementsTableListener
|
||||
protected class ElementsTableListener extends MyMixin
|
||||
implements Adapters.FocusListener, CellActivationListener {
|
||||
@Override
|
||||
public void cellActivated(JTable table) {
|
||||
ValueRow row = elementsTablePanel.getSelectedItem();
|
||||
if (row == null) {
|
||||
if (performElementCellDefaultAction(table)) {
|
||||
return;
|
||||
}
|
||||
if (!(row instanceof ObjectRow objectRow)) {
|
||||
return;
|
||||
}
|
||||
activatePath(objectRow.getTraceObject().getCanonicalPath());
|
||||
performValueRowDefaultAction(elementsTablePanel.getSelectedItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -567,19 +606,11 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||
}
|
||||
}
|
||||
|
||||
protected class AttributesTableListener
|
||||
protected class AttributesTableListener extends MyMixin
|
||||
implements Adapters.FocusListener, CellActivationListener {
|
||||
@Override
|
||||
public void cellActivated(JTable table) {
|
||||
PathRow row = attributesTablePanel.getSelectedItem();
|
||||
if (row == null) {
|
||||
return;
|
||||
}
|
||||
Object value = row.getValue();
|
||||
if (!(value instanceof TraceObject object)) {
|
||||
return;
|
||||
}
|
||||
activatePath(object.getCanonicalPath());
|
||||
performPathRowDefaultAction(attributesTablePanel.getSelectedItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -746,19 +777,6 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||
}
|
||||
}
|
||||
|
||||
private void activateObjectSelectedInTree() {
|
||||
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
||||
if (sel.size() != 1) {
|
||||
// TODO: Multiple paths? PathMatcher can do it, just have to parse
|
||||
// Just leave whatever was there.
|
||||
return;
|
||||
}
|
||||
TraceObjectValue value = sel.get(0).getValue();
|
||||
if (value != null && value.getValue() instanceof TraceObject child) {
|
||||
activatePath(child.getCanonicalPath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionContext getActionContext(MouseEvent event) {
|
||||
if (event != null) {
|
||||
|
@ -970,26 +988,6 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||
}
|
||||
}
|
||||
|
||||
protected void activatePath(TraceObjectKeyPath path) {
|
||||
Trace trace = current.getTrace();
|
||||
if (trace != null) {
|
||||
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||
if (object != null) {
|
||||
traceManager.activateObject(object);
|
||||
return;
|
||||
}
|
||||
object = trace.getObjectManager()
|
||||
.getObjectsByPath(Lifespan.at(current.getSnap()), path)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (object != null) {
|
||||
traceManager.activateObject(object);
|
||||
return;
|
||||
}
|
||||
plugin.getTool().setStatusInfo("No such object at path " + path, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setPath(TraceObjectKeyPath path, JComponent source, EventOrigin origin) {
|
||||
if (Objects.equals(this.path, path) && getTreeSelection() != null) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.model;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.JTable;
|
||||
|
||||
import ghidra.app.plugin.core.debug.gui.control.TargetActionTask;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
||||
import ghidra.app.services.DebuggerListingService;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
||||
import ghidra.debug.api.target.ActionName;
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.debug.api.target.Target.ActionEntry;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.trace.model.target.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public interface ObjectDefaultActionsMixin {
|
||||
|
||||
PluginTool getTool();
|
||||
|
||||
DebuggerCoordinates getCurrent();
|
||||
|
||||
void activatePath(TraceObjectKeyPath path);
|
||||
|
||||
default void toggleObject(TraceObject object) {
|
||||
if (!getCurrent().isAliveAndPresent()) {
|
||||
return;
|
||||
}
|
||||
Target target = getCurrent().getTarget();
|
||||
Map<String, ActionEntry> actions = target.collectActions(ActionName.TOGGLE,
|
||||
new DebuggerSingleObjectPathActionContext(object.getCanonicalPath()));
|
||||
ActionEntry action = actions.values()
|
||||
.stream()
|
||||
.filter(e -> !e.requiresPrompt())
|
||||
.sorted(Comparator.comparing(e -> -e.specificity()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (action == null) {
|
||||
Msg.error(this, "No suitable toggle action for " + object);
|
||||
return;
|
||||
}
|
||||
TargetActionTask.runAction(getTool(), "Toggle", action);
|
||||
}
|
||||
|
||||
default void goToAddress(DebuggerListingService listingService, Address address) {
|
||||
ProgramLocation loc = new ProgramLocation(getCurrent().getView(), address);
|
||||
listingService.goTo(loc, true);
|
||||
}
|
||||
|
||||
default void goToAddress(Address address) {
|
||||
DebuggerListingService listingService = getTool().getService(DebuggerListingService.class);
|
||||
if (listingService == null) {
|
||||
return;
|
||||
}
|
||||
goToAddress(listingService, address);
|
||||
}
|
||||
|
||||
default void goToRange(AddressRange range) {
|
||||
DebuggerListingService listingService = getTool().getService(DebuggerListingService.class);
|
||||
if (listingService == null) {
|
||||
return;
|
||||
}
|
||||
listingService.setCurrentSelection(
|
||||
new ProgramSelection(range.getMinAddress(), range.getMaxAddress()));
|
||||
goToAddress(listingService, range.getMinAddress());
|
||||
}
|
||||
|
||||
default boolean performElementCellDefaultAction(JTable table) {
|
||||
int row = table.getSelectedRow();
|
||||
int col = table.getSelectedColumn();
|
||||
Object cellValue = table.getValueAt(row, col);
|
||||
if (cellValue instanceof ValueProperty<?> property) {
|
||||
Object propValue = property.getValue();
|
||||
if (performDefaultAction(propValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean performValueRowDefaultAction(ValueRow row) {
|
||||
if (row == null) {
|
||||
return false;
|
||||
}
|
||||
return performDefaultAction(row.getValue());
|
||||
}
|
||||
|
||||
default boolean performPathRowDefaultAction(PathRow row) {
|
||||
if (row == null) {
|
||||
return false;
|
||||
}
|
||||
return performDefaultAction(row.getValue());
|
||||
}
|
||||
|
||||
default boolean performDefaultAction(TraceObjectValue value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return performDefaultAction(value.getValue());
|
||||
}
|
||||
|
||||
default boolean performDefaultAction(TraceObject object) {
|
||||
Set<Class<? extends TargetObject>> interfaces = object.getTargetSchema().getInterfaces();
|
||||
if (interfaces.contains(TargetActivatable.class)) {
|
||||
activatePath(object.getCanonicalPath());
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Should I check aliveAndPresent() here? If I do, behavior changes when target is dead,
|
||||
* which might be unexpected.
|
||||
*/
|
||||
if (interfaces.contains(TargetTogglable.class)) {
|
||||
toggleObject(object);
|
||||
return true;
|
||||
}
|
||||
long snap = getCurrent().getSnap();
|
||||
TraceObjectValue valAddress = object.getAttribute(snap, "_address");
|
||||
if (valAddress != null && valAddress.getValue() instanceof Address address) {
|
||||
goToAddress(address);
|
||||
return true;
|
||||
}
|
||||
TraceObjectValue valRange = object.getAttribute(snap, "_range");
|
||||
if (valRange != null && valRange.getValue() instanceof AddressRange range) {
|
||||
goToRange(range);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean performDefaultAction(Object value) {
|
||||
if (value instanceof Address address) {
|
||||
goToAddress(address);
|
||||
return true;
|
||||
}
|
||||
if (value instanceof AddressRange range) {
|
||||
goToRange(range);
|
||||
return true;
|
||||
}
|
||||
if (value instanceof TraceObject object) {
|
||||
return performDefaultAction(object);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -69,7 +69,7 @@ public class ObjectsTablePanel extends AbstractQueryTablePanel<ValueRow, ObjectT
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTableModel createModel(Plugin plugin) {
|
||||
protected ObjectTableModel createModel() {
|
||||
return new ObjectTableModel(plugin);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public class PathsTablePanel extends AbstractQueryTablePanel<PathRow, PathTableM
|
|||
}
|
||||
|
||||
@Override
|
||||
protected PathTableModel createModel(Plugin plugin) {
|
||||
protected PathTableModel createModel() {
|
||||
return new PathTableModel(plugin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,8 +229,8 @@ public class DebuggerLegacyModulesPanel extends JPanel {
|
|||
int selectedRow = moduleTable.getSelectedRow();
|
||||
int selectedColumn = moduleTable.getSelectedColumn();
|
||||
Object value = moduleTable.getValueAt(selectedRow, selectedColumn);
|
||||
if (value instanceof Address) {
|
||||
provider.listingService.goTo((Address) value, true);
|
||||
if (value instanceof Address address) {
|
||||
provider.listingService.goTo(address, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,8 +273,8 @@ public class DebuggerLegacySectionsPanel extends JPanel {
|
|||
int selectedRow = sectionTable.getSelectedRow();
|
||||
int selectedColumn = sectionTable.getSelectedColumn();
|
||||
Object value = sectionTable.getValueAt(selectedRow, selectedColumn);
|
||||
if (value instanceof Address) {
|
||||
provider.listingService.goTo((Address) value, true);
|
||||
if (value instanceof Address address) {
|
||||
provider.listingService.goTo(address, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTableModel createModel(Plugin plugin) {
|
||||
protected ObjectTableModel createModel() {
|
||||
return new ModuleTableModel(plugin);
|
||||
}
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTableModel createModel(Plugin plugin) {
|
||||
protected ObjectTableModel createModel() {
|
||||
return new SectionTableModel(plugin);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ import ghidra.program.model.data.*;
|
|||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.listing.*;
|
||||
|
@ -639,7 +640,8 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
if (listingService == null) {
|
||||
return;
|
||||
}
|
||||
listingService.goTo(address, true);
|
||||
ProgramLocation loc = new ProgramLocation(current.getView(), address);
|
||||
listingService.goTo(loc, true);
|
||||
}).build());
|
||||
}
|
||||
return result;
|
||||
|
@ -658,7 +660,8 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||
if (address == null) {
|
||||
return;
|
||||
}
|
||||
listingService.goTo(address, true);
|
||||
ProgramLocation loc = new ProgramLocation(current.getView(), address);
|
||||
listingService.goTo(loc, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,7 +23,6 @@ import javax.swing.event.ListSelectionListener;
|
|||
import docking.widgets.table.AbstractDynamicTableColumn;
|
||||
import docking.widgets.table.TableColumnDescriptor;
|
||||
import ghidra.app.plugin.core.debug.gui.model.*;
|
||||
import ghidra.app.plugin.core.debug.gui.model.AbstractQueryTablePanel.CellActivationListener;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||
import ghidra.app.plugin.core.debug.gui.model.columns.TraceValueKeyColumn;
|
||||
import ghidra.app.plugin.core.debug.gui.model.columns.TraceValueObjectAttributeColumn;
|
||||
|
@ -46,7 +45,7 @@ import ghidra.trace.model.target.TraceObject;
|
|||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
|
||||
public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObjectStackFrame>
|
||||
implements ListSelectionListener, CellActivationListener {
|
||||
implements ListSelectionListener {
|
||||
|
||||
private static class FrameLevelColumn extends TraceValueKeyColumn {
|
||||
@Override
|
||||
|
@ -137,7 +136,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTableModel createModel(Plugin plugin) {
|
||||
protected ObjectTableModel createModel() {
|
||||
return new StackTableModel(plugin);
|
||||
}
|
||||
|
||||
|
@ -165,7 +164,11 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||
|
||||
@Override
|
||||
public void cellActivated(JTable table) {
|
||||
// No super
|
||||
/**
|
||||
* Override, because PC columns is fairly wide and representative of the stack frame.
|
||||
* Likely, when the user double-clicks, they mean to activate the frame, even if it happens
|
||||
* to be in that column. Simply going to the address will confuse and/or disappoint.
|
||||
*/
|
||||
ValueRow item = getSelectedItem();
|
||||
if (item != null) {
|
||||
traceManager.activateObject(item.getValue().getChild());
|
||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.plugin.core.debug.gui.thread;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
|
||||
import docking.widgets.table.AbstractDynamicTableColumn;
|
||||
|
@ -258,7 +257,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ObjectTableModel createModel(Plugin plugin) {
|
||||
protected ObjectTableModel createModel() {
|
||||
return new ThreadTableModel(plugin);
|
||||
}
|
||||
|
||||
|
@ -293,15 +292,6 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||
trySelectCurrentThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cellActivated(JTable table) {
|
||||
// No super
|
||||
ValueRow item = getSelectedItem();
|
||||
if (item != null) {
|
||||
traceManager.activateObject(item.getValue().getChild());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
super.valueChanged(e);
|
||||
|
|
|
@ -483,7 +483,8 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter
|
|||
return;
|
||||
}
|
||||
if (address.isMemoryAddress()) {
|
||||
listingService.goTo(address, true);
|
||||
ProgramLocation loc = new ProgramLocation(current.getView(), address);
|
||||
listingService.goTo(loc, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,6 +370,14 @@ public class TraceRecorderTarget extends AbstractTarget {
|
|||
return Map.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ActionEntry> collectToggleActions(ActionContext context) {
|
||||
return collectIfaceActions(context, TargetTogglable.class, "Toggle",
|
||||
ActionName.TOGGLE, "Toggle the object",
|
||||
togglable -> true,
|
||||
togglable -> togglable.toggle(!togglable.isEnabled()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trace getTrace() {
|
||||
return recorder.getTrace();
|
||||
|
|
|
@ -198,7 +198,8 @@ public abstract class AbstractTarget implements Target {
|
|||
collectStepOverActions(context),
|
||||
collectStepOutActions(context),
|
||||
collectStepExtActions(context),
|
||||
collectRefreshActions(context))
|
||||
collectRefreshActions(context),
|
||||
collectToggleActions(context))
|
||||
.flatMap(m -> m.entrySet().stream())
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||
}
|
||||
|
@ -219,6 +220,8 @@ public abstract class AbstractTarget implements Target {
|
|||
|
||||
protected abstract Map<String, ActionEntry> collectRefreshActions(ActionContext context);
|
||||
|
||||
protected abstract Map<String, ActionEntry> collectToggleActions(ActionContext context);
|
||||
|
||||
@Override
|
||||
public Map<String, ActionEntry> collectActions(ActionName name, ActionContext context) {
|
||||
if (name == null) {
|
||||
|
@ -251,6 +254,9 @@ public abstract class AbstractTarget implements Target {
|
|||
else if (ActionName.REFRESH.equals(name)) {
|
||||
return collectRefreshActions(context);
|
||||
}
|
||||
else if (ActionName.TOGGLE.equals(name)) {
|
||||
return collectToggleActions(context);
|
||||
}
|
||||
Msg.warn(this, "Unrecognized action name: " + name);
|
||||
return Map.of();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue