mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GP-4361_Dan_modelTreeContext--SQUASHED'
This commit is contained in:
commit
5fc6105f0d
3 changed files with 302 additions and 136 deletions
|
@ -0,0 +1,78 @@
|
||||||
|
/* ###
|
||||||
|
* 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.awt.event.*;
|
||||||
|
|
||||||
|
import javax.swing.event.TreeExpansionEvent;
|
||||||
|
|
||||||
|
public interface Adapters {
|
||||||
|
interface FocusListener extends java.awt.event.FocusListener {
|
||||||
|
@Override
|
||||||
|
default void focusGained(FocusEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void focusLost(FocusEvent e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KeyListener extends java.awt.event.KeyListener {
|
||||||
|
@Override
|
||||||
|
default void keyPressed(KeyEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void keyReleased(KeyEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void keyTyped(KeyEvent e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MouseListener extends java.awt.event.MouseListener {
|
||||||
|
@Override
|
||||||
|
default void mouseClicked(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void mouseEntered(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void mouseExited(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void mousePressed(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void mouseReleased(MouseEvent e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TreeExpansionListener extends javax.swing.event.TreeExpansionListener {
|
||||||
|
@Override
|
||||||
|
default void treeCollapsed(TreeExpansionEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void treeExpanded(TreeExpansionEvent event) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,8 +25,8 @@ import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.TreeExpansionEvent;
|
import javax.swing.event.TreeExpansionEvent;
|
||||||
import javax.swing.event.TreeExpansionListener;
|
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
|
@ -35,6 +35,7 @@ import docking.action.ToggleDockingAction;
|
||||||
import docking.action.builder.ActionBuilder;
|
import docking.action.builder.ActionBuilder;
|
||||||
import docking.action.builder.ToggleActionBuilder;
|
import docking.action.builder.ToggleActionBuilder;
|
||||||
import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener;
|
import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener;
|
||||||
|
import docking.widgets.tree.support.GTreeSelectionEvent;
|
||||||
import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin;
|
import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin;
|
||||||
import generic.theme.GColor;
|
import generic.theme.GColor;
|
||||||
import generic.theme.GIcon;
|
import generic.theme.GIcon;
|
||||||
|
@ -266,10 +267,9 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
||||||
|
|
||||||
DebuggerObjectActionContext myActionContext;
|
DebuggerObjectActionContext myActionContext;
|
||||||
|
|
||||||
private final CellActivationListener elementActivationListener =
|
final ObjectsTreeListener objectsTreeListener = new ObjectsTreeListener();
|
||||||
table -> activatedElementsTable();
|
final ElementsTableListener elementsTableListener = new ElementsTableListener();
|
||||||
private final CellActivationListener attributeActivationListener =
|
final AttributesTableListener attributesTableListener = new AttributesTableListener();
|
||||||
table -> activatedAttributesTable();
|
|
||||||
|
|
||||||
private final SeekListener seekListener = pos -> {
|
private final SeekListener seekListener = pos -> {
|
||||||
long snap = Math.round(pos);
|
long snap = Math.round(pos);
|
||||||
|
@ -430,6 +430,197 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
||||||
mainPanel.revalidate();
|
mainPanel.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected class ObjectsTreeListener implements Adapters.FocusListener,
|
||||||
|
Adapters.TreeExpansionListener, Adapters.MouseListener, Adapters.KeyListener {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
activateObjectSelectedInTree();
|
||||||
|
e.consume(); // lest is select the next row down
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
|
||||||
|
activateObjectSelectedInTree();
|
||||||
|
e.consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void treeExpanded(TreeExpansionEvent event) {
|
||||||
|
if (EventQueue.getCurrentEvent() instanceof InputEvent inputEvent &&
|
||||||
|
!inputEvent.isShiftDown()) {
|
||||||
|
refreshTargetChildren(event.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
setContextFromSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(GTreeSelectionEvent evt) {
|
||||||
|
setContextFromSelection();
|
||||||
|
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
||||||
|
if (sel.size() == 1) {
|
||||||
|
TraceObjectValue value = sel.get(0).getValue();
|
||||||
|
setPath(value == null ? TraceObjectKeyPath.of() : value.getCanonicalPath(),
|
||||||
|
objectsTreePanel, EventOrigin.INTERNAL_GENERATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setContextFromSelection() {
|
||||||
|
myActionContext = computeContext(false);
|
||||||
|
contextChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*test access*/
|
||||||
|
DebuggerObjectActionContext computeContext(boolean ignoreFocus) {
|
||||||
|
if (!objectsTreePanel.tree.tree().isFocusOwner() && !ignoreFocus) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Trace trace = current.getTrace();
|
||||||
|
if (trace == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (trace.getObjectManager().getRootObject() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
||||||
|
if (sel.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new DebuggerObjectActionContext(sel.stream()
|
||||||
|
.map(n -> n.getValue())
|
||||||
|
.filter(o -> o != null) // Root for no trace would return null
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
DebuggerModelProvider.this, objectsTreePanel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ElementsTableListener
|
||||||
|
implements Adapters.FocusListener, CellActivationListener {
|
||||||
|
@Override
|
||||||
|
public void cellActivated(JTable table) {
|
||||||
|
ValueRow row = elementsTablePanel.getSelectedItem();
|
||||||
|
if (row == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(row instanceof ObjectRow objectRow)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activatePath(objectRow.getTraceObject().getCanonicalPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
setContextFromSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(ListSelectionEvent evt) {
|
||||||
|
if (evt.getValueIsAdjusting()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setContextFromSelection();
|
||||||
|
|
||||||
|
List<ValueRow> sel = elementsTablePanel.getSelectedItems();
|
||||||
|
if (sel.size() != 1) {
|
||||||
|
attributesTablePanel.setQuery(ModelQuery.attributesOf(path));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TraceObjectValue value = sel.get(0).getValue();
|
||||||
|
if (!value.isObject()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TraceObject object = value.getChild();
|
||||||
|
attributesTablePanel.setQuery(ModelQuery.attributesOf(object.getCanonicalPath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setContextFromSelection() {
|
||||||
|
myActionContext = computeContext(false);
|
||||||
|
contextChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*test access*/
|
||||||
|
DebuggerObjectActionContext computeContext(boolean ignoreFocus) {
|
||||||
|
if (!elementsTablePanel.table.isFocusOwner() && !ignoreFocus) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Trace trace = current.getTrace();
|
||||||
|
if (trace == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (trace.getObjectManager().getRootObject() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<ValueRow> sel = elementsTablePanel.getSelectedItems();
|
||||||
|
if (sel.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new DebuggerObjectActionContext(sel.stream()
|
||||||
|
.map(r -> r.getValue())
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
DebuggerModelProvider.this, elementsTablePanel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class AttributesTableListener
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
setContextFromSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(ListSelectionEvent evt) {
|
||||||
|
if (evt.getValueIsAdjusting()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setContextFromSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setContextFromSelection() {
|
||||||
|
myActionContext = computeContext(false);
|
||||||
|
contextChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*test access*/
|
||||||
|
DebuggerObjectActionContext computeContext(boolean ignoreFocus) {
|
||||||
|
if (!attributesTablePanel.table.isFocusOwner() && !ignoreFocus) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Trace trace = current.getTrace();
|
||||||
|
if (trace == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (trace.getObjectManager().getRootObject() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<PathRow> sel = attributesTablePanel.getSelectedItems();
|
||||||
|
if (sel.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new DebuggerObjectActionContext(sel.stream()
|
||||||
|
.map(r -> Objects.requireNonNull(r.getPath().getLastEntry()))
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
DebuggerModelProvider.this, attributesTablePanel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void buildMainPanel() {
|
protected void buildMainPanel() {
|
||||||
mainPanel = new JPanel(new BorderLayout());
|
mainPanel = new JPanel(new BorderLayout());
|
||||||
pathField = new MyTextField();
|
pathField = new MyTextField();
|
||||||
|
@ -487,114 +678,20 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
||||||
queryPanel.add(pathField, BorderLayout.CENTER);
|
queryPanel.add(pathField, BorderLayout.CENTER);
|
||||||
queryPanel.add(goButton, BorderLayout.EAST);
|
queryPanel.add(goButton, BorderLayout.EAST);
|
||||||
|
|
||||||
objectsTreePanel.addTreeSelectionListener(evt -> {
|
objectsTreePanel.addTreeSelectionListener(objectsTreeListener::selectionChanged);
|
||||||
Trace trace = current.getTrace();
|
objectsTreePanel.tree.tree().addFocusListener(objectsTreeListener);
|
||||||
if (trace == null) {
|
objectsTreePanel.tree.addTreeExpansionListener(objectsTreeListener);
|
||||||
return;
|
objectsTreePanel.tree.addMouseListener(objectsTreeListener);
|
||||||
}
|
objectsTreePanel.tree.tree().addKeyListener(objectsTreeListener);
|
||||||
if (trace.getObjectManager().getRootObject() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
|
||||||
if (!sel.isEmpty()) {
|
|
||||||
myActionContext = new DebuggerObjectActionContext(sel.stream()
|
|
||||||
.map(n -> n.getValue())
|
|
||||||
.filter(o -> o != null) // Root for no trace would return null
|
|
||||||
.collect(Collectors.toList()),
|
|
||||||
this, objectsTreePanel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myActionContext = null;
|
|
||||||
}
|
|
||||||
contextChanged();
|
|
||||||
if (sel.size() != 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TraceObjectValue value = sel.get(0).getValue();
|
|
||||||
setPath(value == null ? TraceObjectKeyPath.of() : value.getCanonicalPath(),
|
|
||||||
objectsTreePanel, EventOrigin.INTERNAL_GENERATED);
|
|
||||||
});
|
|
||||||
objectsTreePanel.tree.addTreeExpansionListener(new TreeExpansionListener() {
|
|
||||||
@Override
|
|
||||||
public void treeExpanded(TreeExpansionEvent expEvent) {
|
|
||||||
if (EventQueue.getCurrentEvent() instanceof InputEvent event &&
|
|
||||||
!event.isShiftDown()) {
|
|
||||||
refreshTargetChildren(expEvent.getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void treeCollapsed(TreeExpansionEvent event) {
|
|
||||||
// I don't care
|
|
||||||
}
|
|
||||||
});
|
|
||||||
objectsTreePanel.tree.addMouseListener(new MouseAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseClicked(MouseEvent e) {
|
|
||||||
if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
|
|
||||||
activateObjectSelectedInTree();
|
|
||||||
e.consume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
objectsTreePanel.tree.tree().addKeyListener(new KeyAdapter() {
|
|
||||||
@Override
|
|
||||||
public void keyPressed(KeyEvent e) {
|
|
||||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
|
||||||
activateObjectSelectedInTree();
|
|
||||||
e.consume(); // lest is select the next row down
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
elementsTablePanel.addSelectionListener(evt -> {
|
|
||||||
if (evt.getValueIsAdjusting()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<ValueRow> sel = elementsTablePanel.getSelectedItems();
|
|
||||||
if (!sel.isEmpty()) {
|
|
||||||
myActionContext = new DebuggerObjectActionContext(sel.stream()
|
|
||||||
.map(r -> r.getValue())
|
|
||||||
.collect(Collectors.toList()),
|
|
||||||
this, elementsTablePanel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myActionContext = null;
|
|
||||||
}
|
|
||||||
contextChanged();
|
|
||||||
|
|
||||||
if (sel.size() != 1) {
|
|
||||||
attributesTablePanel.setQuery(ModelQuery.attributesOf(path));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TraceObjectValue value = sel.get(0).getValue();
|
|
||||||
if (!value.isObject()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TraceObject object = value.getChild();
|
|
||||||
attributesTablePanel.setQuery(ModelQuery.attributesOf(object.getCanonicalPath()));
|
|
||||||
});
|
|
||||||
attributesTablePanel.addSelectionListener(evt -> {
|
|
||||||
if (evt.getValueIsAdjusting()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<PathRow> sel = attributesTablePanel.getSelectedItems();
|
|
||||||
if (!sel.isEmpty()) {
|
|
||||||
myActionContext = new DebuggerObjectActionContext(sel.stream()
|
|
||||||
.map(r -> Objects.requireNonNull(r.getPath().getLastEntry()))
|
|
||||||
.collect(Collectors.toList()),
|
|
||||||
this, attributesTablePanel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myActionContext = null;
|
|
||||||
}
|
|
||||||
contextChanged();
|
|
||||||
});
|
|
||||||
|
|
||||||
elementsTablePanel.addCellActivationListener(elementActivationListener);
|
|
||||||
attributesTablePanel.addCellActivationListener(attributeActivationListener);
|
|
||||||
|
|
||||||
|
elementsTablePanel.addSelectionListener(elementsTableListener::selectionChanged);
|
||||||
|
elementsTablePanel.table.addFocusListener(elementsTableListener);
|
||||||
|
elementsTablePanel.addCellActivationListener(elementsTableListener);
|
||||||
elementsTablePanel.addSeekListener(seekListener);
|
elementsTablePanel.addSeekListener(seekListener);
|
||||||
|
|
||||||
|
attributesTablePanel.addSelectionListener(attributesTableListener::selectionChanged);
|
||||||
|
attributesTablePanel.table.addFocusListener(attributesTableListener);
|
||||||
|
attributesTablePanel.addCellActivationListener(attributesTableListener);
|
||||||
attributesTablePanel.addSeekListener(seekListener);
|
attributesTablePanel.addSeekListener(seekListener);
|
||||||
|
|
||||||
rebuildPanels();
|
rebuildPanels();
|
||||||
|
@ -663,6 +760,17 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
|
if (event != null) {
|
||||||
|
if (event.getComponent() == objectsTreePanel.tree.tree()) {
|
||||||
|
return objectsTreeListener.computeContext(true);
|
||||||
|
}
|
||||||
|
else if (event.getComponent() == elementsTablePanel.table) {
|
||||||
|
return elementsTableListener.computeContext(true);
|
||||||
|
}
|
||||||
|
else if (event.getComponent() == attributesTablePanel.table) {
|
||||||
|
return attributesTableListener.computeContext(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (myActionContext != null) {
|
if (myActionContext != null) {
|
||||||
return myActionContext;
|
return myActionContext;
|
||||||
}
|
}
|
||||||
|
@ -705,29 +813,6 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
||||||
.buildAndInstallLocal(this);
|
.buildAndInstallLocal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activatedElementsTable() {
|
|
||||||
ValueRow row = elementsTablePanel.getSelectedItem();
|
|
||||||
if (row == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(row instanceof ObjectRow objectRow)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
activatePath(objectRow.getTraceObject().getCanonicalPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void activatedAttributesTable() {
|
|
||||||
PathRow row = attributesTablePanel.getSelectedItem();
|
|
||||||
if (row == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Object value = row.getValue();
|
|
||||||
if (!(value instanceof TraceObject object)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
activatePath(object.getCanonicalPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void activatedCloneWindow() {
|
private void activatedCloneWindow() {
|
||||||
DebuggerModelProvider clone = plugin.createDisconnectedProvider();
|
DebuggerModelProvider clone = plugin.createDisconnectedProvider();
|
||||||
SaveState configState = new SaveState();
|
SaveState configState = new SaveState();
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.jdom.JDOMException;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
|
import docking.ActionContext;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.*;
|
||||||
import docking.widgets.table.ColumnSortState.SortDirection;
|
import docking.widgets.table.ColumnSortState.SortDirection;
|
||||||
import docking.widgets.tree.GTree;
|
import docking.widgets.tree.GTree;
|
||||||
|
@ -641,8 +642,10 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
||||||
selectAttribute("_next");
|
selectAttribute("_next");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
assertEnabled(modelProvider, modelProvider.actionFollowLink);
|
ActionContext ctx =
|
||||||
performAction(modelProvider.actionFollowLink, modelProvider, true);
|
runSwing(() -> modelProvider.attributesTableListener.computeContext(true));
|
||||||
|
assertTrue(runSwing(() -> modelProvider.actionFollowLink.isEnabledForContext(ctx)));
|
||||||
|
performAction(modelProvider.actionFollowLink, ctx, true);
|
||||||
|
|
||||||
TraceObjectKeyPath thread3Path = TraceObjectKeyPath.parse("Processes[0].Threads[3]");
|
TraceObjectKeyPath thread3Path = TraceObjectKeyPath.parse("Processes[0].Threads[3]");
|
||||||
assertPathIs(thread3Path, 0, 5);
|
assertPathIs(thread3Path, 0, 5);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue