mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4691 - Program Tree - Updated navigation; updated keybindings; added an action to 'add to view'
This commit is contained in:
parent
e88fe40a1e
commit
c17d11a8d1
23 changed files with 1188 additions and 1351 deletions
|
@ -389,30 +389,44 @@
|
||||||
View</FONT></B> option.</LI>
|
View</FONT></B> option.</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<H3><A name="Replace_View"></A>Replace the View in the Code Browser with other
|
<H3><A name="Set_View"></A>Set the View in the Code Browser with Folders/Fragments</H3>
|
||||||
Folders/Fragments</H3>
|
|
||||||
|
|
||||||
<UL>
|
<UL>
|
||||||
<LI>
|
<LI>
|
||||||
To replace the view in the code browser with other folders and fragments,
|
To set the view in the code browser with folders and fragments,
|
||||||
|
|
||||||
<OL>
|
<OL>
|
||||||
<LI>Select a folder or fragment (or select multiple folders and fragments), </LI>
|
<LI>Select a folder or fragment (or select multiple folders and fragments), </LI>
|
||||||
|
|
||||||
<LI>Right mouse-click and choose the <B>Replace View</B> option. The code browser now
|
<LI>Right mouse-click and choose the <B>Set View</B> option. The code browser now
|
||||||
shows the code units for these folders and fragments.</LI>
|
shows the code units for these folders and fragments.</LI>
|
||||||
</OL>
|
</OL>
|
||||||
</LI>
|
</LI>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P><IMG src="help/shared/note.png"> The program tree can be configured, via tool
|
<P><IMG src="help/shared/note.png"> The program tree can be configured, via tool
|
||||||
options, such that a double-click performs a simple navigation, or the
|
options, such that a double-click performs the <B>Set View</B> action. The default
|
||||||
<B>Replace View</B> action. The default
|
behavior for a double-click is to navigate to the first address of the clicked
|
||||||
behavior for a double-click is to perform the <B>Replace View</B> action.</P>
|
fragment.</P>
|
||||||
|
|
||||||
<P>(Double-clicking on a folder always causes it to expand if it is collapsed and to
|
<P>(Double-clicking on a folder always causes it to expand if it is collapsed and to
|
||||||
collapse if it is expanded.)</P>
|
collapse if it is expanded.)</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
</UL>
|
||||||
|
|
||||||
|
<H3><A name="Add_to_View"></A>Add to the View in the Code Browser</H3>
|
||||||
|
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
To add a folder or fragment to the view in the code browser,
|
||||||
|
|
||||||
|
<OL>
|
||||||
|
<LI>Select a folder or fragment (or select multiple folders and fragments), </LI>
|
||||||
|
|
||||||
|
<LI>Right mouse-click and choose the <B>Add to View</B> option. The code browser now
|
||||||
|
shows the code units for these folders and fragments.</LI>
|
||||||
|
</OL>
|
||||||
|
</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<H3>Navigation</H3>
|
<H3>Navigation</H3>
|
||||||
|
|
|
@ -33,12 +33,8 @@ import docking.widgets.textfield.GValidatedTextField;
|
||||||
import docking.widgets.textfield.GValidatedTextField.LongField.LongValidator;
|
import docking.widgets.textfield.GValidatedTextField.LongField.LongValidator;
|
||||||
import docking.widgets.textfield.GValidatedTextField.ValidationFailedException;
|
import docking.widgets.textfield.GValidatedTextField.ValidationFailedException;
|
||||||
import docking.widgets.textfield.GValidatedTextField.ValidationMessageListener;
|
import docking.widgets.textfield.GValidatedTextField.ValidationMessageListener;
|
||||||
import generic.theme.Gui;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Enum;
|
|
||||||
import ghidra.program.model.listing.DataTypeArchive;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
|
|
||||||
|
@ -670,7 +666,7 @@ class EnumEditorPanel extends JPanel {
|
||||||
|
|
||||||
private class EnumValueRenderer extends GTableCellRenderer {
|
private class EnumValueRenderer extends GTableCellRenderer {
|
||||||
EnumValueRenderer() {
|
EnumValueRenderer() {
|
||||||
setFont(Gui.getFont("font.monospaced"));
|
setFont(getFixedWidthFont());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -61,7 +61,7 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
|
||||||
// data flavors that this tree can support
|
// data flavors that this tree can support
|
||||||
protected DataFlavor[] acceptableFlavors;
|
protected DataFlavor[] acceptableFlavors;
|
||||||
|
|
||||||
protected TreeTransferable transferable;
|
protected ProgramTreeTransferable transferable;
|
||||||
protected Color nonSelectionDragColor;
|
protected Color nonSelectionDragColor;
|
||||||
protected int relativeMousePos; // mouse position within the node
|
protected int relativeMousePos; // mouse position within the node
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
|
||||||
nodes[i] = (ProgramNode) selectionPaths[i].getLastPathComponent();
|
nodes[i] = (ProgramNode) selectionPaths[i].getLastPathComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
transferable = new TreeTransferable(nodes);
|
transferable = new ProgramTreeTransferable(nodes);
|
||||||
draggedNodes = nodes;
|
draggedNodes = nodes;
|
||||||
return transferable;
|
return transferable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,9 @@ package ghidra.app.plugin.core.programtree;
|
||||||
|
|
||||||
import java.awt.datatransfer.*;
|
import java.awt.datatransfer.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultTreeModel;
|
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
|
|
||||||
import docking.dnd.GClipboard;
|
import docking.dnd.GClipboard;
|
||||||
|
@ -29,48 +28,34 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage paste operations for the tree.
|
* Manage paste operations for the Program Tree.
|
||||||
*/
|
*/
|
||||||
class PasteManager {
|
class PasteManager {
|
||||||
|
|
||||||
private ProgramTreeActionManager actionMgr;
|
private ProgramTreeActionManager actionManager;
|
||||||
private ProgramDnDTree tree;
|
|
||||||
private DefaultTreeModel treeModel;
|
|
||||||
private Clipboard cutClipboard;
|
|
||||||
private String lastGroupPasted;
|
private String lastGroupPasted;
|
||||||
|
|
||||||
/**
|
PasteManager(ProgramTreeActionManager actionManager) {
|
||||||
* Constructor
|
this.actionManager = actionManager;
|
||||||
*/
|
|
||||||
PasteManager(ProgramTreeActionManager actionMgr) {
|
|
||||||
this.actionMgr = actionMgr;
|
|
||||||
cutClipboard = actionMgr.getCutClipboard();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the pasteNode can be pasted at the destNode.
|
|
||||||
* @param destNode destination node for where the pasteNode will be pasted
|
|
||||||
* @param pasteNode node to paste
|
|
||||||
* @param isCutOperation true if the operation was "cut" versus "copy"
|
|
||||||
*/
|
|
||||||
boolean isPasteAllowed(ProgramNode destNode, ProgramNode pasteNode, boolean isCutOperation) {
|
boolean isPasteAllowed(ProgramNode destNode, ProgramNode pasteNode, boolean isCutOperation) {
|
||||||
if (destNode.getProgram() != pasteNode.getProgram() ||
|
if (destNode.getProgram() != pasteNode.getProgram() ||
|
||||||
destNode.getRoot() != pasteNode.getRoot()) {
|
destNode.getRoot() != pasteNode.getRoot()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
if (destNode.getName().equals(pasteNode.getName())) {
|
if (destNode.getName().equals(pasteNode.getName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destNode.isNodeAncestor(pasteNode)) {
|
if (destNode.isNodeAncestor(pasteNode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destNode.isFragment() && pasteNode.isModule()) {
|
if (destNode.isFragment() && pasteNode.isModule()) {
|
||||||
if (isCutOperation && !pasteNode.getModule().isDescendant(destNode.getFragment())) {
|
if (isCutOperation && !pasteNode.getModule().isDescendant(destNode.getFragment())) {
|
||||||
|
return true; // pasted module can be flattened onto destination fragment
|
||||||
return true; // pasted module can be flattened onto
|
|
||||||
// destination fragment
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -81,6 +66,7 @@ class PasteManager {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destNode.isModule()) {
|
if (destNode.isModule()) {
|
||||||
ProgramModule destModule = destNode.getModule();
|
ProgramModule destModule = destNode.getModule();
|
||||||
|
|
||||||
|
@ -99,20 +85,9 @@ class PasteManager {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (RuntimeException e) {
|
|
||||||
// this is a hack for unknown reasons
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@SuppressWarnings("unchecked") // cast is OK, it is data that we are expecting
|
||||||
* Do the paste operation.
|
void paste(ProgramDnDTree tree, ProgramNode destNode) {
|
||||||
* @param destNode destination node for where the paste the contents of
|
|
||||||
* system clipboard.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
// cast is OK, it is data that we are expecting
|
|
||||||
void paste(ProgramNode destNode) {
|
|
||||||
|
|
||||||
int transactionID = tree.startTransaction("Paste");
|
int transactionID = tree.startTransaction("Paste");
|
||||||
if (transactionID < 0) {
|
if (transactionID < 0) {
|
||||||
|
@ -125,34 +100,32 @@ class PasteManager {
|
||||||
Clipboard systemClipboard = GClipboard.getSystemClipboard();
|
Clipboard systemClipboard = GClipboard.getSystemClipboard();
|
||||||
Transferable t = systemClipboard.getContents(tree);
|
Transferable t = systemClipboard.getContents(tree);
|
||||||
try {
|
try {
|
||||||
if (t == null || !t.isDataFlavorSupported(TreeTransferable.localTreeNodeFlavor)) {
|
if (t == null ||
|
||||||
|
!t.isDataFlavorSupported(ProgramTreeTransferable.localTreeNodeFlavor)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.setBusyCursor(true);
|
tree.setBusyCursor(true);
|
||||||
lastGroupPasted = null;
|
lastGroupPasted = null;
|
||||||
ArrayList<ProgramNode> list =
|
List<ProgramNode> list =
|
||||||
(ArrayList<ProgramNode>) t.getTransferData(TreeTransferable.localTreeNodeFlavor);
|
(List<ProgramNode>) t.getTransferData(ProgramTreeTransferable.localTreeNodeFlavor);
|
||||||
|
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
// SCR 7990--something bad has happened to the copy buffer
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (ProgramNode node : list) {
|
||||||
ProgramNode tnode = list.get(i);
|
if (destNode.getRoot() != node.getRoot()) {
|
||||||
|
|
||||||
if (destNode.getRoot() != tnode.getRoot()) {
|
|
||||||
lastGroupPasted = null;
|
lastGroupPasted = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!destNode.getName().equals(tnode.getName())) {
|
if (!destNode.getName().equals(node.getName())) {
|
||||||
if (pasteGroup(destNode, tnode)) {
|
if (pasteGroup(tree, destNode, node)) {
|
||||||
if (!(destNode.isFragment() && tnode.isModule())) {
|
if (!(destNode.isFragment() && node.isModule())) {
|
||||||
// this was not a "flatten module" operation
|
// this was not a "flatten module" operation
|
||||||
// so we can leave the busy cursor set
|
// so we can leave the busy cursor set
|
||||||
// until the domain object event comes in
|
// until the domain object event comes in
|
||||||
lastGroupPasted = tnode.getName();
|
lastGroupPasted = node.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,18 +136,14 @@ class PasteManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// do "cut" operations now if there are any
|
// do "cut" operations now if there are any
|
||||||
actionMgr.checkClipboard(true);
|
actionManager.cutClipboardNodes(tree);
|
||||||
actionMgr.clearSystemClipboard();
|
|
||||||
actionMgr.enablePasteAction(false);
|
|
||||||
tree.removeSelectionPath(path);
|
tree.removeSelectionPath(path);
|
||||||
tree.addSelectionPath(path);
|
tree.addSelectionPath(path);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (UnsupportedFlavorException e) {
|
catch (UnsupportedFlavorException e) {
|
||||||
// data flavor is not supported
|
// data flavor is not supported
|
||||||
Msg.showError(this, null, "Paste from Clipboard Failed",
|
Msg.showError(this, null, "Paste from Clipboard Failed",
|
||||||
"Data flavor in clipboard is not supported.", e);
|
"Data flavor in clipboard is not supported.", e);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
// data is no longer available
|
// data is no longer available
|
||||||
|
@ -182,33 +151,19 @@ class PasteManager {
|
||||||
"Data is no longer available for paste operation", e);
|
"Data is no longer available for paste operation", e);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Msg.showError(this, null, null, null, e);
|
Msg.showError(this, null, "Unexpected Exception Pasting",
|
||||||
|
"Unexpected exception pasting nodes", e);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
tree.endTransaction(transactionID, true);
|
tree.endTransaction(transactionID, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the last group that was pasted.
|
|
||||||
*/
|
|
||||||
String getLastGroupPasted() {
|
String getLastGroupPasted() {
|
||||||
return lastGroupPasted;
|
return lastGroupPasted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean pasteGroup(ProgramDnDTree tree, ProgramNode destNode, ProgramNode nodeToPaste) {
|
||||||
* Method setProgramTreeView.
|
|
||||||
* @param tree
|
|
||||||
*/
|
|
||||||
void setProgramTreeView(ProgramDnDTree tree) {
|
|
||||||
this.tree = tree;
|
|
||||||
treeModel = (DefaultTreeModel) tree.getModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Paste the group at nodeToPaste at destNode.
|
|
||||||
*/
|
|
||||||
private boolean pasteGroup(ProgramNode destNode, ProgramNode nodeToPaste) {
|
|
||||||
|
|
||||||
if (destNode.isFragment()) {
|
if (destNode.isFragment()) {
|
||||||
// can paste either a fragment or a module onto a fragment;
|
// can paste either a fragment or a module onto a fragment;
|
||||||
|
@ -216,11 +171,12 @@ class PasteManager {
|
||||||
// descendant fragments are moved to the destination fragment.
|
// descendant fragments are moved to the destination fragment.
|
||||||
try {
|
try {
|
||||||
tree.mergeGroup(nodeToPaste.getGroup(), destNode.getFragment());
|
tree.mergeGroup(nodeToPaste.getGroup(), destNode.getFragment());
|
||||||
actionMgr.removeFromClipboard(cutClipboard, nodeToPaste);
|
actionManager.removeFromClipboard(tree, nodeToPaste);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (ConcurrentModificationException e) {
|
catch (ConcurrentModificationException e) {
|
||||||
|
// ha!
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Msg.showError(this, null, null, "Error Merging Fragments", e);
|
Msg.showError(this, null, null, "Error Merging Fragments", e);
|
||||||
|
@ -231,30 +187,24 @@ class PasteManager {
|
||||||
ProgramModule targetModule = destNode.getModule();
|
ProgramModule targetModule = destNode.getModule();
|
||||||
|
|
||||||
if (targetModule == null) {
|
if (targetModule == null) {
|
||||||
nodeToPaste.setDeleted(false);
|
actionManager.clearCut(nodeToPaste);
|
||||||
treeModel.reload(nodeToPaste);
|
|
||||||
Msg.showError(this, null, "Paste from Clipboard Failed",
|
Msg.showError(this, null, "Paste from Clipboard Failed",
|
||||||
"Paste of " + nodeToPaste + " at\n" + destNode.getName() + " is not allowed.");
|
"Paste of " + nodeToPaste + " at\n" + destNode.getName() + " is not allowed.");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pasteNode(destNode, nodeToPaste);
|
return pasteNode(tree, destNode, nodeToPaste);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean pasteNode(ProgramDnDTree tree, ProgramNode destNode, ProgramNode nodeToPaste) {
|
||||||
* Paste the node at the destination node.
|
|
||||||
*/
|
|
||||||
private boolean pasteNode(ProgramNode destNode, ProgramNode nodeToPaste) {
|
|
||||||
|
|
||||||
ProgramModule targetModule = destNode.getModule();
|
ProgramModule targetModule = destNode.getModule();
|
||||||
// make sure we have something to paste
|
|
||||||
ProgramModule module = nodeToPaste.getModule();
|
ProgramModule module = nodeToPaste.getModule();
|
||||||
ProgramFragment fragment = nodeToPaste.getFragment();
|
ProgramFragment fragment = nodeToPaste.getFragment();
|
||||||
|
|
||||||
if (module == null && fragment == null) {
|
if (module == null && fragment == null) {
|
||||||
nodeToPaste.setDeleted(false);
|
actionManager.clearCut(nodeToPaste);
|
||||||
treeModel.reload(nodeToPaste);
|
|
||||||
Msg.showError(this, null, "Paste from Clipboard Failed",
|
Msg.showError(this, null, "Paste from Clipboard Failed",
|
||||||
"Could not paste " + nodeToPaste + " at " + targetModule.getName());
|
"Could not paste " + nodeToPaste + " at " + targetModule.getName());
|
||||||
return false;
|
return false;
|
||||||
|
@ -263,10 +213,10 @@ class PasteManager {
|
||||||
boolean pasteOK = false;
|
boolean pasteOK = false;
|
||||||
try {
|
try {
|
||||||
if (module != null) {
|
if (module != null) {
|
||||||
pasteOK = pasteModule(destNode, nodeToPaste, targetModule, module);
|
pasteOK = pasteModule(tree, destNode, nodeToPaste, targetModule, module);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pasteOK = pasteFragment(nodeToPaste, targetModule, fragment);
|
pasteOK = pasteFragment(tree, nodeToPaste, targetModule, fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't match the expansion state unless the destination
|
// don't match the expansion state unless the destination
|
||||||
|
@ -281,37 +231,35 @@ class PasteManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (CircularDependencyException e) {
|
catch (CircularDependencyException e) {
|
||||||
removeFromClipboard(nodeToPaste);
|
|
||||||
Msg.showError(this, null, "Paste from Clipboard Failed", e.getMessage());
|
Msg.showError(this, null, "Paste from Clipboard Failed", e.getMessage());
|
||||||
}
|
}
|
||||||
catch (DuplicateGroupException e) {
|
catch (DuplicateGroupException e) {
|
||||||
nodeToPaste.setDeleted(false);
|
// handled below
|
||||||
tree.reloadNode(nodeToPaste);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException e) {
|
catch (NotFoundException e) {
|
||||||
removeFromClipboard(nodeToPaste);
|
|
||||||
nodeToPaste.setDeleted(false);
|
|
||||||
Msg.showError(this, null, "Paste from Clipboard Failed", e.getMessage());
|
Msg.showError(this, null, "Paste from Clipboard Failed", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeFromClipboard(tree, nodeToPaste);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paste the fragment at the given module.
|
* Paste the fragment at the given module.
|
||||||
*/
|
*/
|
||||||
private boolean pasteFragment(ProgramNode nodeToPaste, ProgramModule targetModule,
|
private boolean pasteFragment(ProgramDnDTree tree, ProgramNode nodeToPaste,
|
||||||
ProgramFragment fragment) throws NotFoundException, DuplicateGroupException {
|
ProgramModule targetModule, ProgramFragment fragment)
|
||||||
|
throws NotFoundException, DuplicateGroupException {
|
||||||
boolean pasteOK = false;
|
boolean pasteOK = false;
|
||||||
|
|
||||||
if (targetModule.contains(fragment)) {
|
if (targetModule.contains(fragment)) {
|
||||||
if (targetModule.equals(nodeToPaste.getParentModule())) {
|
if (targetModule.equals(nodeToPaste.getParentModule())) {
|
||||||
removeFromClipboard(nodeToPaste);
|
removeFromClipboard(tree, nodeToPaste);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (actionMgr.clipboardContains(nodeToPaste)) {
|
else if (actionManager.clipboardContains(nodeToPaste)) {
|
||||||
targetModule.reparent(nodeToPaste.getName(), nodeToPaste.getParentModule());
|
targetModule.reparent(nodeToPaste.getName(), nodeToPaste.getParentModule());
|
||||||
removeFromClipboard(nodeToPaste);
|
removeFromClipboard(tree, nodeToPaste);
|
||||||
pasteOK = true;
|
pasteOK = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -321,7 +269,7 @@ class PasteManager {
|
||||||
return pasteOK;
|
return pasteOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean pasteModule(ProgramNode destNode, ProgramNode nodeToPaste,
|
private boolean pasteModule(ProgramDnDTree tree, ProgramNode destNode, ProgramNode nodeToPaste,
|
||||||
ProgramModule targetModule, ProgramModule module)
|
ProgramModule targetModule, ProgramModule module)
|
||||||
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
|
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
|
||||||
|
|
||||||
|
@ -332,12 +280,12 @@ class PasteManager {
|
||||||
}
|
}
|
||||||
if (targetModule.contains(module)) {
|
if (targetModule.contains(module)) {
|
||||||
if (targetModule.equals(nodeToPaste.getParentModule())) {
|
if (targetModule.equals(nodeToPaste.getParentModule())) {
|
||||||
removeFromClipboard(nodeToPaste);
|
removeFromClipboard(tree, nodeToPaste);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (actionMgr.clipboardContains(nodeToPaste)) {
|
else if (actionManager.clipboardContains(nodeToPaste)) {
|
||||||
targetModule.reparent(nodeToPaste.getName(), nodeToPaste.getParentModule());
|
targetModule.reparent(nodeToPaste.getName(), nodeToPaste.getParentModule());
|
||||||
removeFromClipboard(nodeToPaste);
|
removeFromClipboard(tree, nodeToPaste);
|
||||||
pasteOK = true;
|
pasteOK = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -352,15 +300,9 @@ class PasteManager {
|
||||||
return pasteOK;
|
return pasteOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void removeFromClipboard(ProgramDnDTree tree, ProgramNode node) {
|
||||||
* Remove the given node from the cut clipboard, so that "cut" changes
|
actionManager.removeFromClipboard(tree, node);
|
||||||
* will not be applied.
|
actionManager.clearCut(node);
|
||||||
* @param node node to remove from the cut clipboard
|
|
||||||
*/
|
|
||||||
private void removeFromClipboard(ProgramNode node) {
|
|
||||||
actionMgr.removeFromClipboard(cutClipboard, node);
|
|
||||||
node.setDeleted(false);
|
|
||||||
tree.reloadNode(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.tree.*;
|
import javax.swing.tree.*;
|
||||||
|
|
||||||
import docking.DockingUtils;
|
import docking.DockingUtils;
|
||||||
import docking.action.DockingAction;
|
|
||||||
import docking.actions.KeyBindingUtils;
|
import docking.actions.KeyBindingUtils;
|
||||||
import docking.dnd.DropTgtAdapter;
|
import docking.dnd.DropTgtAdapter;
|
||||||
import docking.widgets.JTreeMouseListenerDelegate;
|
import docking.widgets.JTreeMouseListenerDelegate;
|
||||||
|
@ -55,8 +54,8 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
private Program program;
|
private Program program;
|
||||||
private Listing listing;
|
private Listing listing;
|
||||||
|
|
||||||
private ArrayList<ProgramNode> nodeList; // list of nodes from preorder enumeration
|
private List<ProgramNode> nodeList; // list of nodes from preorder enumeration
|
||||||
private ArrayList<TreePath> viewList; // list of tree paths that are being viewed.
|
private List<TreePath> viewList; // list of tree paths that are being viewed.
|
||||||
|
|
||||||
//keeps track of module/fragment names to come up with a default name, e.g., New Folder (2)
|
//keeps track of module/fragment names to come up with a default name, e.g., New Folder (2)
|
||||||
private StringKeyIndexer nameIndexer;
|
private StringKeyIndexer nameIndexer;
|
||||||
|
@ -272,7 +271,7 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
static DataFlavor[] getDataFlavors() {
|
static DataFlavor[] getDataFlavors() {
|
||||||
return new DataFlavor[] { TreeTransferable.localTreeNodeFlavor,
|
return new DataFlavor[] { ProgramTreeTransferable.localTreeNodeFlavor,
|
||||||
GroupTransferable.localGroupFlavor, // a test data flavor
|
GroupTransferable.localGroupFlavor, // a test data flavor
|
||||||
DataFlavor.stringFlavor, // a test data flavor
|
DataFlavor.stringFlavor, // a test data flavor
|
||||||
SelectionTransferable.localProgramSelectionFlavor };
|
SelectionTransferable.localProgramSelectionFlavor };
|
||||||
|
@ -317,7 +316,7 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (chosen.equals(TreeTransferable.localTreeNodeFlavor)) {
|
else if (chosen.equals(ProgramTreeTransferable.localTreeNodeFlavor)) {
|
||||||
// fromObject is null, so we know this is
|
// fromObject is null, so we know this is
|
||||||
// from another tree, so don't allow the drop
|
// from another tree, so don't allow the drop
|
||||||
return false;
|
return false;
|
||||||
|
@ -385,6 +384,8 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
* that could potentially take a long time. The cursor is reset in the
|
* that could potentially take a long time. The cursor is reset in the
|
||||||
* domain object change listener when the event comes in for the group
|
* domain object change listener when the event comes in for the group
|
||||||
* that was last "pasted."
|
* that was last "pasted."
|
||||||
|
*
|
||||||
|
* @param busy true to use the busy cursor
|
||||||
*/
|
*/
|
||||||
void setBusyCursor(boolean busy) {
|
void setBusyCursor(boolean busy) {
|
||||||
if (busy) {
|
if (busy) {
|
||||||
|
@ -406,19 +407,11 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
treeListener = null;
|
treeListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
List<TreePath> getViewList() {
|
||||||
* Get the view list.
|
|
||||||
*
|
|
||||||
* @return ArrayList list of tree paths in the view
|
|
||||||
*/
|
|
||||||
ArrayList<TreePath> getViewList() {
|
|
||||||
return viewList;
|
return viewList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
List<ProgramNode> getNodeList() {
|
||||||
* Get the node list.
|
|
||||||
*/
|
|
||||||
ArrayList<ProgramNode> getNodeList() {
|
|
||||||
return nodeList;
|
return nodeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,10 +428,6 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds path to the view.
|
|
||||||
* @param path
|
|
||||||
*/
|
|
||||||
void addToView(TreePath path) {
|
void addToView(TreePath path) {
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -666,36 +655,6 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the given action should be added to popup, based
|
|
||||||
* on what is currently selected. Called by the ProgramTreeAction.
|
|
||||||
*/
|
|
||||||
boolean addActionToPopup(DockingAction action) {
|
|
||||||
|
|
||||||
if (!(action instanceof ProgramTreeAction)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgramTreeAction a = (ProgramTreeAction) action;
|
|
||||||
|
|
||||||
int selectionCount = getSelectionCount();
|
|
||||||
if (a.getSelectionType() == ProgramTreeAction.SINGLE_SELECTION) {
|
|
||||||
|
|
||||||
if (selectionCount == 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (selectionCount == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// allow 1 or many in selection
|
|
||||||
if (selectionCount > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a unique name to be used as the default when
|
* Generate a unique name to be used as the default when
|
||||||
* a Module or Fragment is created.
|
* a Module or Fragment is created.
|
||||||
|
@ -730,25 +689,6 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a list of selected ProgramNodes in postorder.
|
|
||||||
*/
|
|
||||||
// our data; we know it's good
|
|
||||||
ArrayList<ProgramNode> getSortedSelection() {
|
|
||||||
ArrayList<ProgramNode> list = new ArrayList<>();
|
|
||||||
Enumeration<? extends TreeNode> it = root.postorderEnumeration();
|
|
||||||
while (it.hasMoreElements()) {
|
|
||||||
ProgramNode node = (ProgramNode) it.nextElement();
|
|
||||||
if (isPathSelected(node.getTreePath())) {
|
|
||||||
list.add(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expand all descendants starting at node.
|
|
||||||
*/
|
|
||||||
void expandNode(ProgramNode node) {
|
void expandNode(ProgramNode node) {
|
||||||
|
|
||||||
expandPath(node.getTreePath());
|
expandPath(node.getTreePath());
|
||||||
|
@ -837,7 +777,7 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
* @param sb string buffer to use if there was an error
|
* @param sb string buffer to use if there was an error
|
||||||
* @return true if group was removed
|
* @return true if group was removed
|
||||||
*/
|
*/
|
||||||
boolean removeGroup(ProgramNode node, StringBuffer sb) {
|
boolean removeGroup(ProgramNode node, StringBuilder sb) {
|
||||||
|
|
||||||
boolean changesMade = false;
|
boolean changesMade = false;
|
||||||
|
|
||||||
|
@ -869,6 +809,7 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
* @param parent parent of the group to be inserted
|
* @param parent parent of the group to be inserted
|
||||||
* @param group group to add
|
* @param group group to add
|
||||||
* @param index index of new child
|
* @param index index of new child
|
||||||
|
* @return the new child node
|
||||||
*/
|
*/
|
||||||
ProgramNode insertGroup(ProgramNode parent, Group group, int index) {
|
ProgramNode insertGroup(ProgramNode parent, Group group, int index) {
|
||||||
|
|
||||||
|
@ -1086,65 +1027,46 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable all actions.
|
|
||||||
*/
|
|
||||||
void disableActions() {
|
|
||||||
actionManager.disableActions();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjust the selection based on the given popupPoint.
|
* Adjust the selection based on the given popupPoint.
|
||||||
* @param event mouse event
|
* @param event mouse event
|
||||||
* @return node that is selected
|
* @return node that is selected
|
||||||
*/
|
*/
|
||||||
ProgramNode prepareSelectionForPopup(MouseEvent event) {
|
ProgramNode adjustSelectionForPopup(MouseEvent event) {
|
||||||
// adjust the selection based on the popup location
|
|
||||||
synchronized (root) {
|
synchronized (root) {
|
||||||
|
|
||||||
if (event != null && event.getSource() != this) {
|
if (event != null && event.getSource() != this) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point popupPoint = event != null ? event.getPoint() : null;
|
Point popupPoint = event != null ? event.getPoint() : null;
|
||||||
int nselected = getSelectionCount();
|
|
||||||
TreePath selPath = null;
|
|
||||||
if (popupPoint != null) {
|
if (popupPoint != null) {
|
||||||
selPath = getPathForLocation((int) popupPoint.getX(), (int) popupPoint.getY());
|
return getMouseNode(popupPoint);
|
||||||
}
|
|
||||||
else {
|
|
||||||
selPath = getSelectionPath();
|
|
||||||
}
|
|
||||||
ProgramNode node = null;
|
|
||||||
if (selPath != null) {
|
|
||||||
node = (ProgramNode) selPath.getLastPathComponent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nselected <= 1) {
|
int nselected = getSelectionCount();
|
||||||
|
if (nselected < 1) {
|
||||||
|
return null; // nothing selected in the tree
|
||||||
|
}
|
||||||
|
|
||||||
if (selPath != null && !isPathSelected(selPath)) {
|
TreePath activePath = getSelectionPath();
|
||||||
setSelectionPath(selPath);
|
return (ProgramNode) activePath.getLastPathComponent();
|
||||||
actionManager.adjustSingleActions(node);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProgramNode getMouseNode(Point popupPoint) {
|
||||||
|
|
||||||
|
TreePath mousePath = getPathForLocation((int) popupPoint.getX(), (int) popupPoint.getY());
|
||||||
|
if (mousePath != null) {
|
||||||
|
ProgramNode node = (ProgramNode) mousePath.getLastPathComponent();
|
||||||
|
if (!isPathSelected(mousePath)) {
|
||||||
|
setSelectionPath(mousePath); // add the right-clicked node to the selection
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (selPath != null) {
|
|
||||||
actionManager.adjustSingleActions(node);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
actionManager.disableActions();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// if the path at the mouse pointer is in the selection OR
|
|
||||||
// the path is null, then adjust the multi-popup menu.
|
|
||||||
if ((selPath != null && isPathSelected(selPath)) || selPath == null) {
|
|
||||||
actionManager.adjustMultiActions();
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
// force the selection to be where the mouse pointer is
|
|
||||||
setSelectionPath(selPath);
|
|
||||||
actionManager.adjustSingleActions(node);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this when the given nodes children have changed.
|
* Call this when the given nodes children have changed.
|
||||||
|
@ -1171,9 +1093,7 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
|
|
||||||
ArrayList<ProgramNode> list = new ArrayList<>();
|
ArrayList<ProgramNode> list = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0; i < nodeList.size(); i++) {
|
for (ProgramNode node : nodeList) {
|
||||||
ProgramNode node = nodeList.get(i);
|
|
||||||
|
|
||||||
if (node.getName().equals(groupName)) {
|
if (node.getName().equals(groupName)) {
|
||||||
list.add(node);
|
list.add(node);
|
||||||
}
|
}
|
||||||
|
@ -1358,9 +1278,7 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||||
|
|
||||||
ArrayList<ProgramNode> list = new ArrayList<>();
|
ArrayList<ProgramNode> list = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0; i < nodeList.size(); i++) {
|
for (ProgramNode node : nodeList) {
|
||||||
ProgramNode node = nodeList.get(i);
|
|
||||||
|
|
||||||
Group group = node.getGroup();
|
Group group = node.getGroup();
|
||||||
if (group != null && group.equals(g)) {
|
if (group != null && group.equals(g)) {
|
||||||
list.add(node);
|
list.add(node);
|
||||||
|
|
|
@ -45,6 +45,8 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new ProgramNode with the given Group.
|
* Construct a new ProgramNode with the given Group.
|
||||||
|
* @param program the program
|
||||||
|
* @param g the group
|
||||||
*/
|
*/
|
||||||
ProgramNode(Program program, Group g) {
|
ProgramNode(Program program, Group g) {
|
||||||
this(program, g, g.getName());
|
this(program, g, g.getName());
|
||||||
|
@ -52,6 +54,8 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new ProgramNode with the given name.
|
* Construct a new ProgramNode with the given name.
|
||||||
|
* @param program the program
|
||||||
|
* @param name the name
|
||||||
*/
|
*/
|
||||||
ProgramNode(Program program, String name) {
|
ProgramNode(Program program, String name) {
|
||||||
this(program, null, name);
|
this(program, null, name);
|
||||||
|
@ -60,6 +64,9 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
/**
|
/**
|
||||||
* Create a new ProgramNode with the given group and name;
|
* Create a new ProgramNode with the given group and name;
|
||||||
* use name for the displayed name of this node.
|
* use name for the displayed name of this node.
|
||||||
|
* @param program the program
|
||||||
|
* @param g the group
|
||||||
|
* @param name the name
|
||||||
*/
|
*/
|
||||||
ProgramNode(Program program, Group g, String name) {
|
ProgramNode(Program program, Group g, String name) {
|
||||||
super(name);
|
super(name);
|
||||||
|
@ -148,6 +155,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name for this node.
|
* Get the name for this node.
|
||||||
|
* @return he name for this node.
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -155,6 +163,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the group for this node.
|
* Get the group for this node.
|
||||||
|
* @return the group for this node.
|
||||||
*/
|
*/
|
||||||
public Group getGroup() {
|
public Group getGroup() {
|
||||||
return group;
|
return group;
|
||||||
|
@ -162,6 +171,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this node represents a Fragment.
|
* Returns true if this node represents a Fragment.
|
||||||
|
* @return true if this node represents a Fragment.
|
||||||
*/
|
*/
|
||||||
public boolean isFragment() {
|
public boolean isFragment() {
|
||||||
return fragment != null;
|
return fragment != null;
|
||||||
|
@ -169,6 +179,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this node represents a Module.
|
* Returns true if this node represents a Module.
|
||||||
|
* @return true if this node represents a Module.
|
||||||
*/
|
*/
|
||||||
public boolean isModule() {
|
public boolean isModule() {
|
||||||
return module != null;
|
return module != null;
|
||||||
|
@ -192,6 +203,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the program for this node.
|
* Get the program for this node.
|
||||||
|
* @return the program for this node.
|
||||||
*/
|
*/
|
||||||
public Program getProgram() {
|
public Program getProgram() {
|
||||||
return program;
|
return program;
|
||||||
|
@ -199,6 +211,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the node is in the view.
|
* Return true if the node is in the view.
|
||||||
|
* @return true if the node is in the view.
|
||||||
*/
|
*/
|
||||||
public boolean isInView() {
|
public boolean isInView() {
|
||||||
return isInView;
|
return isInView;
|
||||||
|
@ -206,14 +219,12 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the group path for this node.
|
* Get the group path for this node.
|
||||||
|
* @return the group path for this node.
|
||||||
*/
|
*/
|
||||||
public GroupPath getGroupPath() {
|
public GroupPath getGroupPath() {
|
||||||
return groupPath;
|
return groupPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
|
||||||
// package-level methods
|
|
||||||
/////////////////////////////////////////////////////////////
|
|
||||||
/**
|
/**
|
||||||
* Mark this node as having been populated (visited).
|
* Mark this node as having been populated (visited).
|
||||||
*/
|
*/
|
||||||
|
@ -227,6 +238,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if this node was visited.
|
* Return true if this node was visited.
|
||||||
|
* @return true if this node was visited.
|
||||||
*/
|
*/
|
||||||
boolean wasVisited() {
|
boolean wasVisited() {
|
||||||
return visited;
|
return visited;
|
||||||
|
@ -238,6 +250,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the tree path for this node.
|
* Get the tree path for this node.
|
||||||
|
* @return the tree path for this node.
|
||||||
*/
|
*/
|
||||||
TreePath getTreePath() {
|
TreePath getTreePath() {
|
||||||
return path;
|
return path;
|
||||||
|
@ -245,6 +258,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the tree path for this node.
|
* Set the tree path for this node.
|
||||||
|
* @param path the tree path for this node.
|
||||||
*/
|
*/
|
||||||
void setTreePath(TreePath path) {
|
void setTreePath(TreePath path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
@ -252,6 +266,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parent module for this node.
|
* Get the parent module for this node.
|
||||||
|
* @return the parent module for this node.
|
||||||
*/
|
*/
|
||||||
ProgramModule getParentModule() {
|
ProgramModule getParentModule() {
|
||||||
return parentModule;
|
return parentModule;
|
||||||
|
@ -259,6 +274,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the parent module for this node.
|
* Set the parent module for this node.
|
||||||
|
* @param parent the parents
|
||||||
*/
|
*/
|
||||||
void setParentModule(ProgramModule parent) {
|
void setParentModule(ProgramModule parent) {
|
||||||
parentModule = parent;
|
parentModule = parent;
|
||||||
|
@ -266,6 +282,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the name for this node.
|
* Set the name for this node.
|
||||||
|
* @param name the name
|
||||||
*/
|
*/
|
||||||
void setName(String name) {
|
void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -273,8 +290,8 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this node to be deleted so that it can be
|
* Set this node to be deleted so that it can be rendered as such.
|
||||||
* rendered as such.
|
* @param deleted true if deleted
|
||||||
*/
|
*/
|
||||||
void setDeleted(boolean deleted) {
|
void setDeleted(boolean deleted) {
|
||||||
this.deleted = deleted;
|
this.deleted = deleted;
|
||||||
|
@ -282,6 +299,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this node is marked as deleted.
|
* Returns whether this node is marked as deleted.
|
||||||
|
* @return whether this node is marked as deleted.
|
||||||
*/
|
*/
|
||||||
boolean isDeleted() {
|
boolean isDeleted() {
|
||||||
return deleted;
|
return deleted;
|
||||||
|
@ -289,6 +307,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the group path for this node.
|
* Set the group path for this node.
|
||||||
|
* @param groupPath the path
|
||||||
*/
|
*/
|
||||||
void setGroupPath(GroupPath groupPath) {
|
void setGroupPath(GroupPath groupPath) {
|
||||||
this.groupPath = groupPath;
|
this.groupPath = groupPath;
|
||||||
|
@ -296,6 +315,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark this node as being in some view.
|
* Mark this node as being in some view.
|
||||||
|
* @param isInView true if in some view.
|
||||||
*/
|
*/
|
||||||
void setInView(boolean isInView) {
|
void setInView(boolean isInView) {
|
||||||
this.isInView = isInView;
|
this.isInView = isInView;
|
||||||
|
@ -326,6 +346,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the tree; this method is only called on the root node.
|
* Set the tree; this method is only called on the root node.
|
||||||
|
* @param tree the tree
|
||||||
*/
|
*/
|
||||||
void setTree(ProgramDnDTree tree) {
|
void setTree(ProgramDnDTree tree) {
|
||||||
this.tree = tree;
|
this.tree = tree;
|
||||||
|
@ -358,7 +379,7 @@ public class ProgramNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the node named childName.
|
* Get the node named childName.
|
||||||
* @param childName
|
* @param childName the name
|
||||||
* @return null if the node does not allow children, or the name was
|
* @return null if the node does not allow children, or the name was
|
||||||
* not found.
|
* not found.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* 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.
|
||||||
|
@ -28,36 +27,38 @@ import docking.action.KeyBindingData;
|
||||||
*/
|
*/
|
||||||
abstract class ProgramTreeAction extends DockingAction {
|
abstract class ProgramTreeAction extends DockingAction {
|
||||||
|
|
||||||
final static int SINGLE_SELECTION=0;
|
final static int SINGLE_SELECTION = 0;
|
||||||
final static int MULTI_SELECTION=1;
|
final static int MULTI_SELECTION = 1;
|
||||||
|
|
||||||
private int selectionType;
|
private int selectionType;
|
||||||
|
|
||||||
ProgramTreeAction(String name, String owner, String[] defaultPopupPath, KeyStroke defaultKeyBinding) {
|
ProgramTreeAction(String name, String owner, KeyStroke defaultKeyBinding) {
|
||||||
this(name, owner, defaultPopupPath,
|
this(name, owner, defaultKeyBinding, MULTI_SELECTION);
|
||||||
defaultKeyBinding, MULTI_SELECTION);
|
|
||||||
}
|
}
|
||||||
ProgramTreeAction(String name, String owner,
|
|
||||||
String[] defaultPopupPath,
|
ProgramTreeAction(String name, String owner, KeyStroke defaultKeyBinding, int selectionType) {
|
||||||
KeyStroke defaultKeyBinding,int selectionType) {
|
|
||||||
super(name, owner);
|
super(name, owner);
|
||||||
|
|
||||||
this.selectionType = selectionType;
|
this.selectionType = selectionType;
|
||||||
if (defaultKeyBinding != null) {
|
if (defaultKeyBinding != null) {
|
||||||
setKeyBindingData( new KeyBindingData( defaultKeyBinding ) );
|
setKeyBindingData(new KeyBindingData(defaultKeyBinding));
|
||||||
}
|
}
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidContext(ActionContext context) {
|
public boolean isValidContext(ActionContext context) {
|
||||||
return context.getContextObject() instanceof ProgramNode;
|
return context.getContextObject() instanceof ProgramNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAddToPopup(ActionContext context) {
|
public boolean isAddToPopup(ActionContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the selection type associated with this action.
|
* Get the selection type associated with this action.
|
||||||
|
* @return the selection type
|
||||||
*/
|
*/
|
||||||
int getSelectionType() {
|
int getSelectionType() {
|
||||||
return selectionType;
|
return selectionType;
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/* ###
|
||||||
|
* 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.programtree;
|
||||||
|
|
||||||
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
|
||||||
|
import ghidra.app.context.ProgramActionContext;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A context object for the {@link ProgramTreePlugin}.
|
||||||
|
*/
|
||||||
|
public class ProgramTreeActionContext extends ProgramActionContext {
|
||||||
|
|
||||||
|
private ViewManagerComponentProvider provider;
|
||||||
|
|
||||||
|
public ProgramTreeActionContext(ViewManagerComponentProvider provider, Program program,
|
||||||
|
ViewPanel viewPanel, Object contextObject) {
|
||||||
|
super(provider, program, viewPanel, contextObject);
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramDnDTree getTree() {
|
||||||
|
ViewProviderService viewProvider = provider.getCurrentViewProvider();
|
||||||
|
if (!(viewProvider instanceof TreeViewProvider treeProvider)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramTreePanel treePanel = treeProvider.getViewComponent();
|
||||||
|
return treePanel.getDnDTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePath[] getSelectionPaths() {
|
||||||
|
ProgramDnDTree tree = getTree();
|
||||||
|
if (tree == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tree.getSelectionPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramNode getLeadSelectedNode() {
|
||||||
|
ProgramNode node = getSingleSelectedNode();
|
||||||
|
if (node != null) {
|
||||||
|
return node; // only one node selected
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramDnDTree tree = getTree();
|
||||||
|
if (tree == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = tree.getSelectionCount();
|
||||||
|
if (n == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreePath path = tree.getSelectionPath();
|
||||||
|
if (n > 1) {
|
||||||
|
path = tree.getLeadSelectionPath();
|
||||||
|
}
|
||||||
|
return (ProgramNode) path.getLastPathComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramNode getSingleSelectedNode() {
|
||||||
|
TreePath[] paths = getSelectionPaths();
|
||||||
|
if (paths == null || paths.length != 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (ProgramNode) paths[0].getLastPathComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSingleNodeSelection() {
|
||||||
|
ProgramDnDTree tree = getTree();
|
||||||
|
if (tree == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return tree.getSelectionCount() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOnlyRootNodeSelected() {
|
||||||
|
ProgramDnDTree tree = getTree();
|
||||||
|
if (tree == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TreePath[] paths = tree.getSelectionPaths();
|
||||||
|
if (paths == null || paths.length != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramNode node = (ProgramNode) paths[0].getLastPathComponent();
|
||||||
|
DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
|
||||||
|
ProgramNode root = (ProgramNode) treeModel.getRoot();
|
||||||
|
return node == root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the selected paths: 1) do not contain the root node and 2) for each folder,
|
||||||
|
* either all children are selected or no children are selected.
|
||||||
|
*
|
||||||
|
* @return true if the criteria above are met
|
||||||
|
*/
|
||||||
|
public boolean hasFullNodeMultiSelection() {
|
||||||
|
|
||||||
|
ProgramDnDTree tree = getTree();
|
||||||
|
if (tree == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TreePath[] paths = tree.getSelectionPaths();
|
||||||
|
if (paths == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
|
||||||
|
ProgramNode root = (ProgramNode) treeModel.getRoot();
|
||||||
|
for (TreePath path : paths) {
|
||||||
|
ProgramNode node = (ProgramNode) path.getLastPathComponent();
|
||||||
|
|
||||||
|
if (node == root) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasMixedChildSelection(node, paths)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasMixedChildSelection(ProgramNode node, TreePath[] selectedPaths) {
|
||||||
|
|
||||||
|
if (!node.getAllowsChildren()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nchild = node.getChildCount();
|
||||||
|
int numberSelected = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < nchild; i++) {
|
||||||
|
ProgramNode child = (ProgramNode) node.getChildAt(i);
|
||||||
|
TreePath childPath = child.getTreePath();
|
||||||
|
|
||||||
|
// see if childPath is in selected list
|
||||||
|
for (TreePath element : selectedPaths) {
|
||||||
|
if (childPath.equals(element)) {
|
||||||
|
++numberSelected;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numberSelected == 0 || numberSelected == nchild) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,7 @@ import java.awt.*;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.*;
|
||||||
|
@ -56,9 +57,9 @@ class ProgramTreePanel extends JPanel implements ChangeListener {
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
// Disable tree expand/collapse on double-click.
|
// Disable tree expand/collapse on double-click.
|
||||||
if (tree != null) {
|
|
||||||
tree.setToggleClickCount(0);
|
tree.setToggleClickCount(0);
|
||||||
}
|
|
||||||
|
tree.addTreeSelectionListener(e -> plugin.contextChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeListener interface method
|
// ChangeListener interface method
|
||||||
|
@ -160,10 +161,9 @@ class ProgramTreePanel extends JPanel implements ChangeListener {
|
||||||
* Get the currently viewed group paths.
|
* Get the currently viewed group paths.
|
||||||
*/
|
*/
|
||||||
GroupView getGroupView() {
|
GroupView getGroupView() {
|
||||||
ArrayList<TreePath> viewList = tree.getViewList();
|
List<TreePath> viewList = tree.getViewList();
|
||||||
ArrayList<GroupPath> list = new ArrayList<GroupPath>();
|
ArrayList<GroupPath> list = new ArrayList<GroupPath>();
|
||||||
for (int i = 0; i < viewList.size(); i++) {
|
for (TreePath p : viewList) {
|
||||||
TreePath p = viewList.get(i);
|
|
||||||
ProgramNode node = (ProgramNode) p.getLastPathComponent();
|
ProgramNode node = (ProgramNode) p.getLastPathComponent();
|
||||||
GroupPath gp = node.getGroupPath();
|
GroupPath gp = node.getGroupPath();
|
||||||
if (gp != null) {
|
if (gp != null) {
|
||||||
|
@ -191,7 +191,7 @@ class ProgramTreePanel extends JPanel implements ChangeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramNode prepareSelectionForPopup(MouseEvent event) {
|
ProgramNode prepareSelectionForPopup(MouseEvent event) {
|
||||||
return tree.prepareSelectionForPopup(event);
|
return tree.adjustSelectionForPopup(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupPath[] getViewedGroups() {
|
GroupPath[] getViewedGroups() {
|
||||||
|
|
|
@ -83,14 +83,15 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
|
|
||||||
private final static Icon NAVIGATION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON;
|
private final static Icon NAVIGATION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON;
|
||||||
|
|
||||||
|
private ViewManagerComponentProvider componentProvider;
|
||||||
|
private ProgramTreeActionManager actionManager;
|
||||||
|
private TreeViewProvider defaultProvider;
|
||||||
|
private TreeViewProvider currentProvider;
|
||||||
private Map<String, TreeViewProvider> providerMap;// map of view providers, key is the name
|
private Map<String, TreeViewProvider> providerMap;// map of view providers, key is the name
|
||||||
private GoToService goToService;
|
private GoToService goToService;
|
||||||
private ViewManagerService viewManagerService;
|
private ViewManagerService viewManagerService;
|
||||||
private ProgramTreeActionManager actionManager;
|
|
||||||
private TreeViewProvider currentProvider;
|
|
||||||
private ViewManagerComponentProvider viewProvider;
|
|
||||||
private ProgramListener programListener;
|
private ProgramListener programListener;
|
||||||
private TreeViewProvider defaultProvider;
|
|
||||||
private boolean firingGoTo;
|
private boolean firingGoTo;
|
||||||
private RunManager runManager;
|
private RunManager runManager;
|
||||||
private DockingAction createAction;
|
private DockingAction createAction;
|
||||||
|
@ -99,31 +100,30 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
private JPopupMenu popup;
|
private JPopupMenu popup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tree signals that a user double-click will replace the view with the
|
* Tree signals that a user double-click will replace the view with the current node
|
||||||
* current node
|
|
||||||
*/
|
*/
|
||||||
private boolean isReplaceViewMode = true;
|
private boolean isReplaceViewMode = false;
|
||||||
|
|
||||||
public ProgramTreePlugin(PluginTool tool) {
|
public ProgramTreePlugin(PluginTool tool) {
|
||||||
super(tool);
|
super(tool);
|
||||||
|
|
||||||
viewProvider = new ViewManagerComponentProvider(tool, getName());
|
componentProvider = new ViewManagerComponentProvider(tool, getName());
|
||||||
registerServiceProvided(ViewManagerService.class, viewProvider);
|
registerServiceProvided(ViewManagerService.class, componentProvider);
|
||||||
|
|
||||||
providerMap = new HashMap<>();
|
providerMap = new HashMap<>();
|
||||||
|
|
||||||
actionManager = new ProgramTreeActionManager(this);
|
actionManager = new ProgramTreeActionManager(this);
|
||||||
registerActions();
|
registerProviderActions();
|
||||||
|
|
||||||
programListener = new ProgramListener(this);
|
programListener = new ProgramListener(this);
|
||||||
runManager = new RunManager();
|
runManager = new RunManager();
|
||||||
runManager.showProgressBar(false);
|
runManager.showProgressBar(false);
|
||||||
createActions();
|
createPluginActions();
|
||||||
|
|
||||||
// show default provider
|
// show default provider
|
||||||
defaultProvider = addTreeView(DEFAULT_TREE_NAME);
|
defaultProvider = addTreeView(DEFAULT_TREE_NAME);
|
||||||
|
|
||||||
initOptions(tool.getOptions(PROGRAM_TREE_OPTION_NAME));
|
initOptions(tool.getOptions(PROGRAM_TREE_OPTION_NAME));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -131,7 +131,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
if (interfaceClass != ViewProviderService.class) {
|
if (interfaceClass != ViewProviderService.class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viewProvider.serviceAdded((ViewProviderService) service);
|
componentProvider.serviceAdded((ViewProviderService) service);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,7 +142,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
if (interfaceClass != ViewProviderService.class) {
|
if (interfaceClass != ViewProviderService.class) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viewProvider.serviceRemoved((ViewProviderService) service);
|
componentProvider.serviceRemoved((ViewProviderService) service);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initOptions(ToolOptions options) {
|
private void initOptions(ToolOptions options) {
|
||||||
|
@ -218,7 +218,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
programListener.dispose();
|
programListener.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
viewProvider.dispose();
|
componentProvider.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void writeDataState(SaveState saveState) {
|
public void writeDataState(SaveState saveState) {
|
||||||
viewProvider.writeDataState(saveState);
|
componentProvider.writeDataState(saveState);
|
||||||
|
|
||||||
saveState.putInt(NUMBER_OF_VIEWS, providerMap.size());
|
saveState.putInt(NUMBER_OF_VIEWS, providerMap.size());
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
@ -312,7 +312,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
|
|
||||||
restoreTreeViews();
|
restoreTreeViews();
|
||||||
|
|
||||||
viewProvider.readDataState(saveState);
|
componentProvider.readDataState(saveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreTreeViews() {
|
private void restoreTreeViews() {
|
||||||
|
@ -332,7 +332,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
list.add(provider);
|
list.add(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
viewProvider.treeViewsRestored(list);
|
componentProvider.treeViewsRestored(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -369,12 +369,11 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
protected void programActivated(Program program) {
|
protected void programActivated(Program program) {
|
||||||
program.addListener(programListener);
|
program.addListener(programListener);
|
||||||
setProgram(program);
|
setProgram(program);
|
||||||
viewProvider.setCurrentProgram(program);
|
componentProvider.setCurrentProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeStaleProviders(ArrayList<TreeViewProvider> providerList) {
|
private void removeStaleProviders(ArrayList<TreeViewProvider> providerList) {
|
||||||
HashMap<String, TreeViewProvider> map = new HashMap<>(providerMap);
|
Map<String, TreeViewProvider> map = new HashMap<>(providerMap);
|
||||||
|
|
||||||
for (String treeName : map.keySet()) {
|
for (String treeName : map.keySet()) {
|
||||||
TreeViewProvider provider = map.get(treeName);
|
TreeViewProvider provider = map.get(treeName);
|
||||||
if (!providerList.contains(provider)) {
|
if (!providerList.contains(provider)) {
|
||||||
|
@ -384,9 +383,6 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialization method: Get the services we need.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
goToService = tool.getService(GoToService.class);
|
goToService = tool.getService(GoToService.class);
|
||||||
|
@ -414,6 +410,10 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void contextChanged() {
|
||||||
|
tool.contextChanged(componentProvider);
|
||||||
|
}
|
||||||
|
|
||||||
void treeViewAdded(String treeName) {
|
void treeViewAdded(String treeName) {
|
||||||
TreeViewProvider provider = providerMap.get(treeName);
|
TreeViewProvider provider = providerMap.get(treeName);
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
|
@ -430,10 +430,8 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
currentProvider.replaceView(node);
|
currentProvider.replaceView(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the node is NOT the root node, just go to the location
|
// If the node is NOT the root node, just go to the location of the first address in the
|
||||||
// of the first address in the fragment. If it's root, we
|
// fragment. If it's the root, we need to get the lowest address in the current view.
|
||||||
// need to get the lowest address of any item in the
|
|
||||||
// current view.
|
|
||||||
if (node.isFragment()) {
|
if (node.isFragment()) {
|
||||||
goTo(node.getFragment());
|
goTo(node.getFragment());
|
||||||
}
|
}
|
||||||
|
@ -445,7 +443,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void goTo(ProgramFragment fragment) {
|
private void goTo(ProgramFragment fragment) {
|
||||||
|
|
||||||
Address minAddress = fragment.getMinAddress();
|
Address minAddress = fragment.getMinAddress();
|
||||||
|
|
||||||
|
@ -671,6 +669,10 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
reloadTree(tree, false);
|
reloadTree(tree, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void repaintProvider() {
|
||||||
|
componentProvider.getComponent().repaint();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remember expansion and selection state, and the reload the program
|
* Remember expansion and selection state, and the reload the program
|
||||||
* because it just got restored from an undo operation.
|
* because it just got restored from an undo operation.
|
||||||
|
@ -781,10 +783,10 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
return currentProgram.getListing().getRootModule(treeName) != null;
|
return currentProgram.getListing().getRootModule(treeName) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerActions() {
|
private void registerProviderActions() {
|
||||||
DockingAction[] actions = actionManager.getActions();
|
DockingAction[] actions = actionManager.getActions();
|
||||||
for (DockingAction element : actions) {
|
for (DockingAction action : actions) {
|
||||||
tool.addAction(element);
|
tool.addLocalAction(componentProvider, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,7 +938,7 @@ public class ProgramTreePlugin extends ProgramPlugin
|
||||||
/**
|
/**
|
||||||
* Create the local actions that are shared among all the providers.
|
* Create the local actions that are shared among all the providers.
|
||||||
*/
|
*/
|
||||||
private void createActions() {
|
private void createPluginActions() {
|
||||||
|
|
||||||
openAction = new DockingAction("Open Tree View", getName()) {
|
openAction = new DockingAction("Open Tree View", getName()) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* ###
|
||||||
|
* 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.programtree;
|
||||||
|
|
||||||
|
import java.awt.datatransfer.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import docking.dnd.GenericDataFlavor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines data that is available for drag/drop and clipboard transfers.
|
||||||
|
* The data is an ArrayList of ProgramNode objects.
|
||||||
|
*/
|
||||||
|
class ProgramTreeTransferable implements Transferable, ClipboardOwner {
|
||||||
|
|
||||||
|
public static DataFlavor localTreeNodeFlavor = createLocalTreeNodeFlavor();
|
||||||
|
|
||||||
|
// create a data flavor that is an ArrayList of ProgramNode objects
|
||||||
|
private static DataFlavor createLocalTreeNodeFlavor() {
|
||||||
|
return new GenericDataFlavor(
|
||||||
|
DataFlavor.javaJVMLocalObjectMimeType + "; class=java.util.ArrayList",
|
||||||
|
"Local list of Tree Nodes");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DataFlavor[] flavors = { localTreeNodeFlavor };
|
||||||
|
|
||||||
|
private static List<DataFlavor> flavorList = Arrays.asList(flavors);
|
||||||
|
private List<ProgramNode> nodeList;
|
||||||
|
|
||||||
|
ProgramTreeTransferable(ProgramNode[] nodes) {
|
||||||
|
nodeList = new ArrayList<ProgramNode>(Arrays.asList(nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized DataFlavor[] getTransferDataFlavors() {
|
||||||
|
return flavors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDataFlavorSupported(DataFlavor f) {
|
||||||
|
return flavorList.contains(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Object getTransferData(DataFlavor f)
|
||||||
|
throws UnsupportedFlavorException, IOException {
|
||||||
|
|
||||||
|
if (f.equals(localTreeNodeFlavor)) {
|
||||||
|
return nodeList;
|
||||||
|
}
|
||||||
|
throw new UnsupportedFlavorException(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TreeTransferable";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearTransferData() {
|
||||||
|
nodeList = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,109 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
* 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.programtree;
|
|
||||||
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
import java.awt.datatransfer.Clipboard;
|
|
||||||
import java.awt.datatransfer.ClipboardOwner;
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import java.awt.datatransfer.Transferable;
|
|
||||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import docking.dnd.GenericDataFlavor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines data that is available for drag/drop and clipboard transfers.
|
|
||||||
* The data is an ArrayList of ProgramNode objects.
|
|
||||||
*/
|
|
||||||
class TreeTransferable implements Transferable, ClipboardOwner {
|
|
||||||
|
|
||||||
public static DataFlavor localTreeNodeFlavor = createLocalTreeNodeFlavor();
|
|
||||||
|
|
||||||
// create a data flavor that is an ArrayList of
|
|
||||||
// ProgramNode objects
|
|
||||||
private static DataFlavor createLocalTreeNodeFlavor() {
|
|
||||||
try {
|
|
||||||
return new GenericDataFlavor(
|
|
||||||
DataFlavor.javaJVMLocalObjectMimeType+
|
|
||||||
"; class=java.util.ArrayList",
|
|
||||||
"Local list of Tree Nodes");
|
|
||||||
}catch (Exception e) {
|
|
||||||
Msg.showError(TreeTransferable.class, null, null, null, e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private static DataFlavor []flavors= { localTreeNodeFlavor };
|
|
||||||
|
|
||||||
private static List<DataFlavor> flavorList = Arrays.asList(flavors);
|
|
||||||
private ArrayList<ProgramNode> nodeList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
TreeTransferable(ProgramNode []nodes) {
|
|
||||||
nodeList = new ArrayList<ProgramNode>(Arrays.asList(nodes));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all data flavors that this class supports.
|
|
||||||
*/
|
|
||||||
public synchronized DataFlavor []getTransferDataFlavors() {
|
|
||||||
return flavors;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the specified data flavor is supported.
|
|
||||||
*/
|
|
||||||
public boolean isDataFlavorSupported(DataFlavor f) {
|
|
||||||
return flavorList.contains(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the transfer data with the given data flavor.
|
|
||||||
*/
|
|
||||||
public synchronized Object getTransferData(DataFlavor f)
|
|
||||||
throws UnsupportedFlavorException, IOException {
|
|
||||||
|
|
||||||
if (f.equals(localTreeNodeFlavor)) {
|
|
||||||
return nodeList;
|
|
||||||
}
|
|
||||||
throw new UnsupportedFlavorException(f);
|
|
||||||
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the string representation for this transferable.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TreeTransferable";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ClipboardOwner interface method.
|
|
||||||
*/
|
|
||||||
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearTransferData() {
|
|
||||||
nodeList = null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,7 +19,6 @@ import java.awt.event.MouseEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
|
@ -76,7 +75,7 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JComponent getViewComponent() {
|
public ProgramTreePanel getViewComponent() {
|
||||||
return treePanel;
|
return treePanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
package ghidra.app.plugin.core.programtree;
|
package ghidra.app.plugin.core.programtree;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ public class ViewManagerComponentProvider extends ComponentProviderAdapter
|
||||||
public static final String CURRENT_VIEW = "Current Viewname";
|
public static final String CURRENT_VIEW = "Current Viewname";
|
||||||
|
|
||||||
private ViewPanel viewPanel;
|
private ViewPanel viewPanel;
|
||||||
private ArrayList<ViewChangeListener> listeners;
|
private List<ViewChangeListener> listeners;
|
||||||
private Program currentProgram;
|
private Program currentProgram;
|
||||||
private String restoredViewName;
|
private String restoredViewName;
|
||||||
|
|
||||||
|
@ -72,6 +71,8 @@ public class ViewManagerComponentProvider extends ComponentProviderAdapter
|
||||||
String currentName = NAME;
|
String currentName = NAME;
|
||||||
ComponentProvider.registerProviderNameOwnerChange(intermediateName, currentOwner,
|
ComponentProvider.registerProviderNameOwnerChange(intermediateName, currentOwner,
|
||||||
currentName, currentOwner);
|
currentName, currentOwner);
|
||||||
|
|
||||||
|
addToTool();
|
||||||
}
|
}
|
||||||
|
|
||||||
void serviceAdded(ViewProviderService service) {
|
void serviceAdded(ViewProviderService service) {
|
||||||
|
@ -186,11 +187,14 @@ public class ViewManagerComponentProvider extends ComponentProviderAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
return new ProgramActionContext(this, currentProgram, viewPanel,
|
// this should be a ProgramNode or a tab
|
||||||
getActivePopupObject(event));
|
Object clickedObject = getActivePopupObject(event);
|
||||||
|
return new ProgramTreeActionContext(this, currentProgram, viewPanel, clickedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProgramActionContext(this, currentProgram, viewPanel, getFocusedContext());
|
// this should be a ProgramNode
|
||||||
|
Object focusedObject = getFocusedContext();
|
||||||
|
return new ProgramTreeActionContext(this, currentProgram, viewPanel, focusedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getFocusedContext() {
|
private Object getFocusedContext() {
|
||||||
|
|
|
@ -17,8 +17,7 @@ package ghidra.app.plugin.core.programtree;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
|
@ -43,7 +42,7 @@ class ViewPanel extends JPanel implements ChangeListener {
|
||||||
|
|
||||||
private JTabbedPane tabbedPane;
|
private JTabbedPane tabbedPane;
|
||||||
private ViewManagerComponentProvider provider;
|
private ViewManagerComponentProvider provider;
|
||||||
private HashMap<String, ViewProviderService> map;
|
private Map<String, ViewProviderService> map;
|
||||||
private DockingAction closeAction;
|
private DockingAction closeAction;
|
||||||
private DockingAction deleteAction;
|
private DockingAction deleteAction;
|
||||||
private DockingAction renameAction;
|
private DockingAction renameAction;
|
||||||
|
@ -71,10 +70,6 @@ class ViewPanel extends JPanel implements ChangeListener {
|
||||||
*/
|
*/
|
||||||
void addView(ViewProviderService vp) {
|
void addView(ViewProviderService vp) {
|
||||||
|
|
||||||
if (!provider.isInTool()) {
|
|
||||||
provider.addToTool();
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = vp.getViewName();
|
String name = vp.getViewName();
|
||||||
if (map.remove(name) != null) {
|
if (map.remove(name) != null) {
|
||||||
map.put(name, vp);
|
map.put(name, vp);
|
||||||
|
@ -127,10 +122,6 @@ class ViewPanel extends JPanel implements ChangeListener {
|
||||||
tabbedPane.addChangeListener(this);
|
tabbedPane.addChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (isEmpty()) {
|
|
||||||
provider.removeFromTool();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.module;
|
package ghidra.app.plugin.core.module;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -54,8 +53,7 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
tool.addPlugin(ProgramTreePlugin.class.getName());
|
tool.addPlugin(ProgramTreePlugin.class.getName());
|
||||||
tool.addPlugin(ModuleSortPlugin.class.getName());
|
tool.addPlugin(ModuleSortPlugin.class.getName());
|
||||||
List<Plugin> list = tool.getManagedPlugins();
|
List<Plugin> list = tool.getManagedPlugins();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (Plugin p : list) {
|
||||||
Plugin p = list.get(i);
|
|
||||||
if (p.getClass() == ModuleSortPlugin.class) {
|
if (p.getClass() == ModuleSortPlugin.class) {
|
||||||
plugin = (ModuleSortPlugin) p;
|
plugin = (ModuleSortPlugin) p;
|
||||||
break;
|
break;
|
||||||
|
@ -200,8 +198,6 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ViewManagerService vmService = tool.getService(ViewManagerService.class);
|
ViewManagerService vmService = tool.getService(ViewManagerService.class);
|
||||||
ViewProviderService vps = vmService.getCurrentViewProvider();
|
ViewProviderService vps = vmService.getCurrentViewProvider();
|
||||||
|
|
||||||
Object context = vps.getActivePopupObject(null);
|
|
||||||
|
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
if (action.getName().indexOf("Address") > 0) {
|
if (action.getName().indexOf("Address") > 0) {
|
||||||
action.actionPerformed(vps.getActionContext(null));
|
action.actionPerformed(vps.getActionContext(null));
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.plugin.core.programtree;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
|
|
||||||
|
@ -87,6 +88,15 @@ public abstract class AbstractProgramTreePluginTest extends AbstractGhidraHeaded
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void performTreeAction(DockingActionIf action) {
|
||||||
|
performAction(action, getActionContext(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void waitForTreeEdit() {
|
||||||
|
BooleanSupplier bs = () -> runSwing(() -> tree.isEditing());
|
||||||
|
waitFor(bs);
|
||||||
|
}
|
||||||
|
|
||||||
protected void setTreeView(final String viewName) {
|
protected void setTreeView(final String viewName) {
|
||||||
tree = plugin.getTree(viewName);
|
tree = plugin.getTree(viewName);
|
||||||
root = (ProgramNode) tree.getModel().getRoot();
|
root = (ProgramNode) tree.getModel().getRoot();
|
||||||
|
|
|
@ -157,7 +157,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
DockingActionIf createFolderAction = getAction("Create Folder");
|
DockingActionIf createFolderAction = getAction("Create Folder");
|
||||||
|
|
||||||
String newFolderName = tree.getNewFolderName();
|
String newFolderName = tree.getNewFolderName();
|
||||||
performAction(createFolderAction);
|
performTreeAction(createFolderAction);
|
||||||
commitEdit();
|
commitEdit();
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
DockingActionIf createFragmentAction = getAction("Create Fragment");
|
DockingActionIf createFragmentAction = getAction("Create Fragment");
|
||||||
|
|
||||||
String newFragName = tree.getNewFragmentName();
|
String newFragName = tree.getNewFragmentName();
|
||||||
performAction(createFragmentAction);
|
performTreeAction(createFragmentAction);
|
||||||
commitEdit();
|
commitEdit();
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
int childCount = root.getChildCount();
|
int childCount = root.getChildCount();
|
||||||
DockingActionIf createFolderAction = getAction("Create Folder");
|
DockingActionIf createFolderAction = getAction("Create Folder");
|
||||||
performAction(createFolderAction);
|
performTreeAction(createFolderAction);
|
||||||
commitEdit();
|
commitEdit();
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
|
@ -221,9 +221,9 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
String newName = tree.getNewFolderName();
|
String newName = tree.getNewFolderName();
|
||||||
|
|
||||||
DockingActionIf createFolderAction = getAction("Create Folder");
|
DockingActionIf createFolderAction = getAction("Create Folder");
|
||||||
performAction(createFolderAction, getActionContext(), true);
|
performTreeAction(createFolderAction);
|
||||||
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
waitForTreeEdit();
|
||||||
|
|
||||||
String currentText = setEditorText("test1");
|
String currentText = setEditorText("test1");
|
||||||
assertEquals(newName, currentText);
|
assertEquals(newName, currentText);
|
||||||
|
@ -241,7 +241,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
int childCount = root.getChildCount();
|
int childCount = root.getChildCount();
|
||||||
|
|
||||||
DockingActionIf createFragmentAction = getAction("Create Fragment");
|
DockingActionIf createFragmentAction = getAction("Create Fragment");
|
||||||
performAction(createFragmentAction, getActionContext(), true);
|
performTreeAction(createFragmentAction);
|
||||||
commitEdit();
|
commitEdit();
|
||||||
|
|
||||||
waitFor(() -> root.getChildCount() == childCount + 1);
|
waitFor(() -> root.getChildCount() == childCount + 1);
|
||||||
|
@ -256,9 +256,9 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
String newName = tree.getNewFragmentName();
|
String newName = tree.getNewFragmentName();
|
||||||
|
|
||||||
DockingActionIf createFragmentAction = getAction("Create Fragment");
|
DockingActionIf createFragmentAction = getAction("Create Fragment");
|
||||||
performAction(createFragmentAction, getActionContext(), true);
|
performTreeAction(createFragmentAction);
|
||||||
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
waitForTreeEdit();
|
||||||
|
|
||||||
String currentText = setEditorText("test1");
|
String currentText = setEditorText("test1");
|
||||||
assertEquals(newName, currentText);
|
assertEquals(newName, currentText);
|
||||||
|
@ -278,7 +278,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
|
|
||||||
DockingActionIf deleteAction = getAction("Delete");
|
DockingActionIf deleteAction = getAction("Delete");
|
||||||
performAction(deleteAction, getActionContext(), true);
|
performTreeAction(deleteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertEquals(childCount - 1, root.getChildCount());
|
assertEquals(childCount - 1, root.getChildCount());
|
||||||
|
@ -409,7 +409,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
|
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
|
||||||
assertTrue(action.isEnabledForContext(getActionContext()));
|
assertTrue(action.isEnabledForContext(getActionContext()));
|
||||||
performAction(action);
|
performTreeAction(action);
|
||||||
String currentText = setEditorText("printf");
|
String currentText = setEditorText("printf");
|
||||||
assertEquals("submodule", currentText);
|
assertEquals("submodule", currentText);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(nodes[0]);
|
setSelectionPath(nodes[0]);
|
||||||
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
|
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
|
||||||
assertTrue(action.isEnabledForContext(getActionContext()));
|
assertTrue(action.isEnabledForContext(getActionContext()));
|
||||||
performAction(action);
|
performTreeAction(action);
|
||||||
String currentText = setEditorText(".data");
|
String currentText = setEditorText(".data");
|
||||||
|
|
||||||
ProgramModule module = getModule(root, "Module-1");
|
ProgramModule module = getModule(root, "Module-1");
|
||||||
|
@ -451,7 +451,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(nodes[0]);
|
setSelectionPath(nodes[0]);
|
||||||
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
|
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
|
||||||
assertTrue(action.isEnabledForContext(getActionContext()));
|
assertTrue(action.isEnabledForContext(getActionContext()));
|
||||||
performAction(action);
|
performTreeAction(action);
|
||||||
String currentText = setEditorText("My Module-1");
|
String currentText = setEditorText("My Module-1");
|
||||||
assertEquals("My Module-1", currentText);
|
assertEquals("My Module-1", currentText);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
@ -648,7 +648,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
DockingActionIf removeAction = getAction("Remove");
|
DockingActionIf removeAction = getAction("Remove");
|
||||||
assertTrue(removeAction.isEnabledForContext(getActionContext()));
|
assertTrue(removeAction.isEnabledForContext(getActionContext()));
|
||||||
performAction(removeAction, getActionContext(), true);
|
performTreeAction(removeAction);
|
||||||
|
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
set.add(node.getFragment());
|
set.add(node.getFragment());
|
||||||
|
@ -705,13 +705,13 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
}
|
}
|
||||||
setSelectionPaths(node);
|
setSelectionPaths(node);
|
||||||
|
|
||||||
DockingActionIf replaceAction = getAction("Replace");
|
DockingActionIf replaceAction = getAction("Set View");
|
||||||
performAction(replaceAction);
|
performTreeAction(replaceAction);
|
||||||
|
|
||||||
assertTrue(getView().hasSameAddresses(node.getModule().getAddressSet()));
|
assertTrue(getView().hasSameAddresses(node.getModule().getAddressSet()));
|
||||||
|
|
||||||
DockingActionIf removeAction = getAction("Remove");
|
DockingActionIf removeAction = getAction("Remove");
|
||||||
performAction(removeAction);
|
performTreeAction(removeAction);
|
||||||
|
|
||||||
assertTrue(getView().isEmpty());
|
assertTrue(getView().isEmpty());
|
||||||
assertTrue(cbPlugin.getView().isEmpty());
|
assertTrue(cbPlugin.getView().isEmpty());
|
||||||
|
@ -750,7 +750,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPaths(node0, node2);
|
setSelectionPaths(node0, node2);
|
||||||
|
|
||||||
DockingActionIf removeAction = getAction("Remove");
|
DockingActionIf removeAction = getAction("Remove");
|
||||||
performAction(removeAction);
|
performTreeAction(removeAction);
|
||||||
|
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
set.add(node0.getFragment());
|
set.add(node0.getFragment());
|
||||||
|
@ -799,7 +799,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(nodes[0]);
|
setSelectionPath(nodes[0]);
|
||||||
|
|
||||||
DockingActionIf removeAction = getAction("Remove");
|
DockingActionIf removeAction = getAction("Remove");
|
||||||
performAction(removeAction);
|
performTreeAction(removeAction);
|
||||||
|
|
||||||
// verify that all the descendants of the folder are removed from the view
|
// verify that all the descendants of the folder are removed from the view
|
||||||
assertFalse(getView().contains(child1.getFragment()));
|
assertFalse(getView().contains(child1.getFragment()));
|
||||||
|
@ -819,8 +819,8 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode child = (ProgramNode) node.getChildAt(0);
|
ProgramNode child = (ProgramNode) node.getChildAt(0);
|
||||||
setSelectionPath(child);
|
setSelectionPath(child);
|
||||||
|
|
||||||
DockingActionIf replaceAction = getAction("Replace");
|
DockingActionIf replaceAction = getAction("Set View");
|
||||||
performAction(replaceAction);
|
performTreeAction(replaceAction);
|
||||||
|
|
||||||
assertTrue(getView().hasSameAddresses(child.getFragment()));
|
assertTrue(getView().hasSameAddresses(child.getFragment()));
|
||||||
assertTrue(getView().hasSameAddresses(cbPlugin.getView()));
|
assertTrue(getView().hasSameAddresses(cbPlugin.getView()));
|
||||||
|
@ -841,9 +841,9 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode node = (ProgramNode) root.getChildAt(6);
|
ProgramNode node = (ProgramNode) root.getChildAt(6);
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
|
|
||||||
DockingActionIf replaceAction = getAction("Replace");
|
DockingActionIf replaceAction = getAction("Set View");
|
||||||
assertTrue(replaceAction.isEnabledForContext(getActionContext()));
|
assertTrue(replaceAction.isEnabledForContext(getActionContext()));
|
||||||
performAction(replaceAction, getActionContext(), true);
|
performTreeAction(replaceAction);
|
||||||
|
|
||||||
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
|
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
|
||||||
assertPluginViewAppliedToTool();
|
assertPluginViewAppliedToTool();
|
||||||
|
@ -869,8 +869,8 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
// descendant of that folder, and not in the view
|
// descendant of that folder, and not in the view
|
||||||
setSelectionPaths(dllsNode, sscanfNode);
|
setSelectionPaths(dllsNode, sscanfNode);
|
||||||
|
|
||||||
DockingActionIf replaceAction = getAction("Replace");
|
DockingActionIf replaceAction = getAction("Set View");
|
||||||
performAction(replaceAction);
|
performTreeAction(replaceAction);
|
||||||
|
|
||||||
AddressSet set = new AddressSet();
|
AddressSet set = new AddressSet();
|
||||||
set.add(dllsNode.getModule().getAddressSet());
|
set.add(dllsNode.getModule().getAddressSet());
|
||||||
|
@ -921,7 +921,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(dllsNode);
|
setSelectionPath(dllsNode);
|
||||||
|
|
||||||
DockingActionIf mergeAction = getAction("Merge");
|
DockingActionIf mergeAction = getAction("Merge");
|
||||||
performAction(mergeAction);
|
performTreeAction(mergeAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
int count = nodes[0].getChildCount();
|
int count = nodes[0].getChildCount();
|
||||||
|
@ -954,7 +954,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPaths(dNodes[0], bNodes[0]);
|
setSelectionPaths(dNodes[0], bNodes[0]);
|
||||||
|
|
||||||
DockingActionIf mergeAction = getAction("Merge");
|
DockingActionIf mergeAction = getAction("Merge");
|
||||||
performAction(mergeAction, getActionContext(), true);
|
performTreeAction(mergeAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertEquals(7, root.getChildCount());
|
assertEquals(7, root.getChildCount());
|
||||||
|
@ -1104,7 +1104,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
|
||||||
assertTrue(showAction.isEnabledForContext(getActionContext()));
|
assertTrue(showAction.isEnabledForContext(getActionContext()));
|
||||||
String[] treeNames = program.getListing().getTreeNames();
|
String[] treeNames = program.getListing().getTreeNames();
|
||||||
|
|
||||||
performAction(showAction);
|
performTreeAction(showAction);
|
||||||
|
|
||||||
JPopupMenu menu = plugin.getPopupMenu();
|
JPopupMenu menu = plugin.getPopupMenu();
|
||||||
assertNotNull(menu);
|
assertNotNull(menu);
|
||||||
|
|
|
@ -24,7 +24,6 @@ import javax.swing.tree.TreePath;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import docking.DefaultActionContext;
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import generic.theme.GIcon;
|
import generic.theme.GIcon;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
|
@ -108,14 +107,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(copyAction.isEnabled());
|
assertTrue(copyAction.isEnabled());
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
|
|
||||||
node = (ProgramNode) root.getChildAt(5);
|
node = (ProgramNode) root.getChildAt(5);
|
||||||
int origCount = node.getChildCount();
|
int origCount = node.getChildCount();
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
|
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
expandNode(node);
|
expandNode(node);
|
||||||
|
@ -142,7 +141,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode node = (ProgramNode) root.getChildAt(0);
|
ProgramNode node = (ProgramNode) root.getChildAt(0);
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(copyAction.isEnabled());
|
assertTrue(copyAction.isEnabled());
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
|
|
||||||
setSelectionPath(root);
|
setSelectionPath(root);
|
||||||
|
|
||||||
|
@ -161,7 +160,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(copyAction.isEnabled());
|
assertTrue(copyAction.isEnabled());
|
||||||
|
|
||||||
performAction(copyAction, true);
|
performTreeAction(copyAction);
|
||||||
ProgramNode[] nodes = findNodes("C");
|
ProgramNode[] nodes = findNodes("C");
|
||||||
setSelectionPath(nodes[0]);
|
setSelectionPath(nodes[0]);
|
||||||
|
|
||||||
|
@ -180,7 +179,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
// select USER32.DLL
|
// select USER32.DLL
|
||||||
setSelectionPath(fnode);
|
setSelectionPath(fnode);
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
// select DLLs
|
// select DLLs
|
||||||
node = (ProgramNode) root.getChildAt(6);
|
node = (ProgramNode) root.getChildAt(6);
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
|
@ -200,10 +199,10 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(cpNode);
|
setSelectionPath(cpNode);
|
||||||
|
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
setSelectionPath(pasteNode);
|
setSelectionPath(pasteNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertEquals(childCount + 1, pasteNode.getChildCount());
|
assertEquals(childCount + 1, pasteNode.getChildCount());
|
||||||
|
@ -228,7 +227,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
|
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
|
||||||
setSelectionPaths(cnode1, cnode2);
|
setSelectionPaths(cnode1, cnode2);
|
||||||
assertTrue(copyAction.isEnabled());
|
assertTrue(copyAction.isEnabled());
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
// create a new module and paste fragments there
|
// create a new module and paste fragments there
|
||||||
tx(program, () -> {
|
tx(program, () -> {
|
||||||
root.getModule().createModule("Test");
|
root.getModule().createModule("Test");
|
||||||
|
@ -238,7 +237,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(destNode);
|
setSelectionPath(destNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
visitNode(destNode);
|
visitNode(destNode);
|
||||||
|
@ -253,7 +252,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
|
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
|
||||||
setSelectionPaths(cnode1, cnode2);
|
setSelectionPaths(cnode1, cnode2);
|
||||||
assertTrue(copyAction.isEnabled());
|
assertTrue(copyAction.isEnabled());
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
// create a new module and paste fragments there
|
// create a new module and paste fragments there
|
||||||
tx(program, () -> {
|
tx(program, () -> {
|
||||||
ProgramModule m = root.getModule().createModule("Test");
|
ProgramModule m = root.getModule().createModule("Test");
|
||||||
|
@ -266,7 +265,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(destNode);
|
setSelectionPath(destNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
expandNode(root);
|
expandNode(root);
|
||||||
|
@ -300,7 +299,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
|
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
|
||||||
setSelectionPaths(cnode1, cnode2);
|
setSelectionPaths(cnode1, cnode2);
|
||||||
assertTrue(copyAction.isEnabled());
|
assertTrue(copyAction.isEnabled());
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
|
|
||||||
// get node for DLLs
|
// get node for DLLs
|
||||||
ProgramNode destNode = (ProgramNode) root.getChildAt(5);
|
ProgramNode destNode = (ProgramNode) root.getChildAt(5);
|
||||||
|
@ -308,7 +307,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(destNode);
|
setSelectionPath(destNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
expandNode(root);
|
expandNode(root);
|
||||||
|
@ -341,12 +340,12 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
// set the view to Functions
|
// set the view to Functions
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
setViewPaths(node);
|
setViewPaths(node);
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
|
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
|
||||||
|
|
||||||
setSelectionPath(subrNode);
|
setSelectionPath(subrNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
// verify the view is not affected
|
// verify the view is not affected
|
||||||
|
@ -375,10 +374,10 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(subrNode);
|
setSelectionPath(subrNode);
|
||||||
|
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
|
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
|
||||||
|
@ -399,12 +398,12 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
ProgramNode child = (ProgramNode) node.getChildAt(0);
|
ProgramNode child = (ProgramNode) node.getChildAt(0);
|
||||||
setSelectionPath(child);
|
setSelectionPath(child);
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
|
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
|
||||||
|
|
||||||
setSelectionPath(subrNode);
|
setSelectionPath(subrNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
// verify the view is not affected
|
// verify the view is not affected
|
||||||
|
@ -426,14 +425,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(fnode);
|
setSelectionPath(fnode);
|
||||||
assertTrue(cutAction.isEnabled());
|
assertTrue(cutAction.isEnabled());
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
ProgramNode funcNode = (ProgramNode) root.getChildAt(6);// Functions
|
ProgramNode funcNode = (ProgramNode) root.getChildAt(6);// Functions
|
||||||
ProgramNode destNode = (ProgramNode) funcNode.getChildAt(0);// doStuff fragment
|
ProgramNode destNode = (ProgramNode) funcNode.getChildAt(0);// doStuff fragment
|
||||||
|
|
||||||
// now select the doStuff fragment as the destination node
|
// now select the doStuff fragment as the destination node
|
||||||
setSelectionPath(destNode);
|
setSelectionPath(destNode);
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertTrue(destNode.getFragment().contains(fnodeSet));
|
assertTrue(destNode.getFragment().contains(fnodeSet));
|
||||||
|
@ -479,14 +478,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(fnode);
|
setSelectionPath(fnode);
|
||||||
assertTrue(cutAction.isEnabled());
|
assertTrue(cutAction.isEnabled());
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
ProgramNode funcNode = (ProgramNode) root.getChildAt(6);// Functions
|
ProgramNode funcNode = (ProgramNode) root.getChildAt(6);// Functions
|
||||||
ProgramNode destNode = (ProgramNode) funcNode.getChildAt(0);// ghidra fragment
|
ProgramNode destNode = (ProgramNode) funcNode.getChildAt(0);// ghidra fragment
|
||||||
|
|
||||||
// now select the ghidra fragment as the destination node
|
// now select the ghidra fragment as the destination node
|
||||||
setSelectionPath(destNode);
|
setSelectionPath(destNode);
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertTrue(destNode.getFragment().contains(fnodeSet));
|
assertTrue(destNode.getFragment().contains(fnodeSet));
|
||||||
|
@ -523,14 +522,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(cutAction.isEnabled());
|
assertTrue(cutAction.isEnabled());
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
node = (ProgramNode) root.getChildAt(5);//DLLs
|
node = (ProgramNode) root.getChildAt(5);//DLLs
|
||||||
int origCount = node.getChildCount();
|
int origCount = node.getChildCount();
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
|
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
expandNode(node);
|
expandNode(node);
|
||||||
|
@ -558,10 +557,10 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(cNode);
|
setSelectionPath(cNode);
|
||||||
// cut Functions
|
// cut Functions
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
setSelectionPath(destNode);// paste at DLLs
|
setSelectionPath(destNode);// paste at DLLs
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
assertEquals(childCount + 1, destNode.getChildCount());
|
assertEquals(childCount + 1, destNode.getChildCount());
|
||||||
|
@ -604,12 +603,12 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(stringsNode);
|
setSelectionPath(stringsNode);
|
||||||
|
|
||||||
// cut Strings
|
// cut Strings
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
// paste at Functions
|
// paste at Functions
|
||||||
ProgramNode funcNode = root.getChild("Functions");
|
ProgramNode funcNode = root.getChild("Functions");
|
||||||
setSelectionPath(funcNode);
|
setSelectionPath(funcNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
// Strings, L should be expanded
|
// Strings, L should be expanded
|
||||||
|
@ -636,13 +635,13 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(stringsNode);
|
setSelectionPath(stringsNode);
|
||||||
|
|
||||||
// cut Strings
|
// cut Strings
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
// paste at Functions
|
// paste at Functions
|
||||||
ProgramNode funcNode = root.getChild("Functions");
|
ProgramNode funcNode = root.getChild("Functions");
|
||||||
collapsePath(funcNode.getTreePath());
|
collapsePath(funcNode.getTreePath());
|
||||||
setSelectionPath(funcNode);
|
setSelectionPath(funcNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
// Functions should remain collapsed
|
// Functions should remain collapsed
|
||||||
assertTrue(tree.isCollapsed(funcNode.getTreePath()));
|
assertTrue(tree.isCollapsed(funcNode.getTreePath()));
|
||||||
|
@ -663,13 +662,13 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(stringsNode);
|
setSelectionPath(stringsNode);
|
||||||
|
|
||||||
// cut Strings
|
// cut Strings
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
// paste at Functions
|
// paste at Functions
|
||||||
ProgramNode funcNode = root.getChild("Functions");
|
ProgramNode funcNode = root.getChild("Functions");
|
||||||
expandPath(funcNode.getTreePath());
|
expandPath(funcNode.getTreePath());
|
||||||
setSelectionPath(funcNode);
|
setSelectionPath(funcNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
stringsNode = funcNode.getChild("Strings");
|
stringsNode = funcNode.getChild("Strings");
|
||||||
assertTrue(tree.isCollapsed(stringsNode.getTreePath()));
|
assertTrue(tree.isCollapsed(stringsNode.getTreePath()));
|
||||||
|
@ -690,14 +689,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPath(stringsNode);
|
setSelectionPath(stringsNode);
|
||||||
|
|
||||||
// cut Strings
|
// cut Strings
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
// paste at Functions
|
// paste at Functions
|
||||||
ProgramNode funcNode = root.getChild("Functions");
|
ProgramNode funcNode = root.getChild("Functions");
|
||||||
visitNode(funcNode);
|
visitNode(funcNode);
|
||||||
collapsePath(funcNode.getTreePath());
|
collapsePath(funcNode.getTreePath());
|
||||||
setSelectionPath(funcNode);
|
setSelectionPath(funcNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
assertTrue(tree.isCollapsed(funcNode.getTreePath()));
|
assertTrue(tree.isCollapsed(funcNode.getTreePath()));
|
||||||
}
|
}
|
||||||
|
@ -721,14 +720,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setSelectionPaths(new TreePath[] { rsrcNode.getTreePath(), textNode.getTreePath() });
|
setSelectionPaths(new TreePath[] { rsrcNode.getTreePath(), textNode.getTreePath() });
|
||||||
|
|
||||||
// cut Strings
|
// cut Strings
|
||||||
runSwing(() -> cutAction.actionPerformed(new DefaultActionContext()));
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
// select Strings (has no fragments)
|
// select Strings (has no fragments)
|
||||||
ProgramNode stringsNode = root.getChild("Strings");
|
ProgramNode stringsNode = root.getChild("Strings");
|
||||||
visitNode(stringsNode);
|
visitNode(stringsNode);
|
||||||
setSelectionPath(stringsNode);
|
setSelectionPath(stringsNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
assertEquals(3, stringsNode.getChildCount());
|
assertEquals(3, stringsNode.getChildCount());
|
||||||
assertEquals("rsrc", stringsNode.getChildAt(1).toString());
|
assertEquals("rsrc", stringsNode.getChildAt(1).toString());
|
||||||
|
@ -788,7 +787,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
addSelectionPath(cutNodes[i].getTreePath());
|
addSelectionPath(cutNodes[i].getTreePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
// select a destination fragment
|
// select a destination fragment
|
||||||
ProgramNode stringsNode = root.getChild("Strings");
|
ProgramNode stringsNode = root.getChild("Strings");
|
||||||
|
@ -798,7 +797,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode fnode = cNode.getChild("testl");
|
ProgramNode fnode = cNode.getChild("testl");
|
||||||
setSelectionPath(fnode);
|
setSelectionPath(fnode);
|
||||||
|
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
for (ProgramNode cutNode : cutNodes) {
|
for (ProgramNode cutNode : cutNodes) {
|
||||||
assertNull(listing.getFragment("Main Tree", cutNode.getName()));
|
assertNull(listing.getFragment("Main Tree", cutNode.getName()));
|
||||||
|
@ -859,7 +858,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode testNode = root.getChild("Test");
|
ProgramNode testNode = root.getChild("Test");
|
||||||
setSelectionPath(testNode);
|
setSelectionPath(testNode);
|
||||||
|
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
// paste at 010074d4
|
// paste at 010074d4
|
||||||
ProgramNode stringsNode = root.getChild("Strings");
|
ProgramNode stringsNode = root.getChild("Strings");
|
||||||
|
@ -869,7 +868,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode fnode = cNode.getChild("testl");
|
ProgramNode fnode = cNode.getChild("testl");
|
||||||
setSelectionPath(fnode);
|
setSelectionPath(fnode);
|
||||||
|
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
root = (ProgramNode) tree.getModel().getRoot();
|
root = (ProgramNode) tree.getModel().getRoot();
|
||||||
|
@ -937,12 +936,12 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
// set the view to DLLs
|
// set the view to DLLs
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
setViewPaths(new TreePath[] { node.getTreePath() });
|
setViewPaths(new TreePath[] { node.getTreePath() });
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
ProgramNode everythingNode = root.getChild("Everything");
|
ProgramNode everythingNode = root.getChild("Everything");
|
||||||
|
|
||||||
setSelectionPath(everythingNode);
|
setSelectionPath(everythingNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
waitForProgram(program);
|
waitForProgram(program);
|
||||||
|
|
||||||
// cut a fragment in the view and paste onto a collapsed folder
|
// cut a fragment in the view and paste onto a collapsed folder
|
||||||
|
@ -953,7 +952,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
ProgramNode dataNode = root.getChild(".data");
|
ProgramNode dataNode = root.getChild(".data");
|
||||||
setSelectionPath(dataNode);
|
setSelectionPath(dataNode);
|
||||||
setViewPaths(new TreePath[] { dataNode.getTreePath() });
|
setViewPaths(new TreePath[] { dataNode.getTreePath() });
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
// select DLLs in Everything
|
// select DLLs in Everything
|
||||||
ProgramNode evNode = root.getChild("Everything");
|
ProgramNode evNode = root.getChild("Everything");
|
||||||
|
@ -962,7 +961,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
visitNode(dllsNode);
|
visitNode(dllsNode);
|
||||||
setSelectionPath(dllsNode);
|
setSelectionPath(dllsNode);
|
||||||
|
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
// first occurrence of DLLs should have icon for descendant in view
|
// first occurrence of DLLs should have icon for descendant in view
|
||||||
ProgramNode[] nodes = findNodes("DLLs");
|
ProgramNode[] nodes = findNodes("DLLs");
|
||||||
|
@ -991,13 +990,13 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
assertTrue(plugin.getView().hasSameAddresses(set));
|
assertTrue(plugin.getView().hasSameAddresses(set));
|
||||||
|
|
||||||
setSelectionPath(debugNode);
|
setSelectionPath(debugNode);
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
// paste to an expanded folder not in the view
|
// paste to an expanded folder not in the view
|
||||||
ProgramNode subrNode = root.getChild("Subroutines");
|
ProgramNode subrNode = root.getChild("Subroutines");
|
||||||
expandNode(subrNode);
|
expandNode(subrNode);
|
||||||
setSelectionPath(subrNode);
|
setSelectionPath(subrNode);
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
assertTrue(plugin.getView().hasSameAddresses(set));
|
assertTrue(plugin.getView().hasSameAddresses(set));
|
||||||
}
|
}
|
||||||
|
@ -1012,14 +1011,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
setViewPaths(dataNode, debugNode);
|
setViewPaths(dataNode, debugNode);
|
||||||
|
|
||||||
setSelectionPath(debugNode);
|
setSelectionPath(debugNode);
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
// paste onto another fragment that is not in the view
|
// paste onto another fragment that is not in the view
|
||||||
ProgramNode funcNode = root.getChild("Functions");
|
ProgramNode funcNode = root.getChild("Functions");
|
||||||
visitNode(funcNode);
|
visitNode(funcNode);
|
||||||
ProgramNode sscanfNode = funcNode.getChild("sscanf");
|
ProgramNode sscanfNode = funcNode.getChild("sscanf");
|
||||||
|
|
||||||
setSelectionPath(sscanfNode);
|
setSelectionPath(sscanfNode);
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
assertTrue(plugin.getView().hasSameAddresses(dataNode.getFragment()));
|
assertTrue(plugin.getView().hasSameAddresses(dataNode.getFragment()));
|
||||||
}
|
}
|
||||||
|
@ -1042,11 +1041,11 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
// cut first fragment in Subroutines
|
// cut first fragment in Subroutines
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
performAction(cutAction);
|
performTreeAction(cutAction);
|
||||||
|
|
||||||
// paste at the debug node
|
// paste at the debug node
|
||||||
setSelectionPath(debugNode);
|
setSelectionPath(debugNode);
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
|
|
||||||
assertTrue(plugin.getView().contains(set));
|
assertTrue(plugin.getView().contains(set));
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,8 +428,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
Component comp = getCellRendererComponentForLeaf(n, row);
|
Component comp = getCellRendererComponentForLeaf(n, row);
|
||||||
assertEquals(new GIcon(DnDTreeCellRenderer.VIEWED_FRAGMENT),
|
assertEquals(new GIcon(DnDTreeCellRenderer.VIEWED_FRAGMENT), ((JLabel) comp).getIcon());
|
||||||
((JLabel) comp).getIcon());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1380,7 +1379,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
|
||||||
AtomicReference<Exception> ref = new AtomicReference<>();
|
AtomicReference<Exception> ref = new AtomicReference<>();
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
try {
|
try {
|
||||||
tree.processDropRequest(node, list, TreeTransferable.localTreeNodeFlavor,
|
tree.processDropRequest(node, list, ProgramTreeTransferable.localTreeNodeFlavor,
|
||||||
dropAction);
|
dropAction);
|
||||||
}
|
}
|
||||||
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
|
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
|
||||||
|
@ -1443,12 +1442,12 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
|
||||||
|
|
||||||
setSelectionPath(node);
|
setSelectionPath(node);
|
||||||
setViewPaths(node);
|
setViewPaths(node);
|
||||||
performAction(copyAction);
|
performTreeAction(copyAction);
|
||||||
ProgramNode everythingNode = root.getChild(dst);
|
ProgramNode everythingNode = root.getChild(dst);
|
||||||
|
|
||||||
setSelectionPath(everythingNode);
|
setSelectionPath(everythingNode);
|
||||||
assertTrue(pasteAction.isEnabled());
|
assertTrue(pasteAction.isEnabled());
|
||||||
performAction(pasteAction);
|
performTreeAction(pasteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,7 +277,7 @@ public class ProgramTreePluginShowInViewTest extends AbstractGhidraHeadedIntegra
|
||||||
|
|
||||||
ProgramNode textNode = root.getChild(".text");
|
ProgramNode textNode = root.getChild(".text");
|
||||||
setSelectionPath(textNode.getTreePath());
|
setSelectionPath(textNode.getTreePath());
|
||||||
DockingActionIf replaceAction = getAction(plugin, "Replace View");
|
DockingActionIf replaceAction = getAction(plugin, "Set View");
|
||||||
|
|
||||||
ActionContext context = getActionContext();
|
ActionContext context = getActionContext();
|
||||||
performAction(replaceAction, context, true);
|
performAction(replaceAction, context, true);
|
||||||
|
@ -312,7 +312,7 @@ public class ProgramTreePluginShowInViewTest extends AbstractGhidraHeadedIntegra
|
||||||
ProgramNode rsrcNode = root.getChild(".rsrc");
|
ProgramNode rsrcNode = root.getChild(".rsrc");
|
||||||
|
|
||||||
addSelectionPath(rsrcNode.getTreePath());
|
addSelectionPath(rsrcNode.getTreePath());
|
||||||
DockingActionIf replaceAction = getAction(plugin, "Replace View");
|
DockingActionIf replaceAction = getAction(plugin, "Set View");
|
||||||
ActionContext context = getActionContext();
|
ActionContext context = getActionContext();
|
||||||
performAction(replaceAction, context, true);
|
performAction(replaceAction, context, true);
|
||||||
|
|
||||||
|
|
|
@ -136,8 +136,7 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(treeNames.length, tabbedPane.getTabCount());
|
assertEquals(treeNames.length, tabbedPane.getTabCount());
|
||||||
assertEquals(DEFAULT_TREE_NAME + "(1)", vps.getViewName());
|
assertEquals(DEFAULT_TREE_NAME + "(1)", vps.getViewName());
|
||||||
assertEquals(tabbedPane.getSelectedComponent(), vps.getViewComponent());
|
assertEquals(tabbedPane.getSelectedComponent(), vps.getViewComponent());
|
||||||
SwingUtilities
|
performAction(createTreeAction);
|
||||||
.invokeAndWait(() -> createTreeAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
vps = provider.getCurrentViewProvider();
|
vps = provider.getCurrentViewProvider();
|
||||||
treeNames = program.getListing().getTreeNames();
|
treeNames = program.getListing().getTreeNames();
|
||||||
|
@ -152,8 +151,7 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void testUndoRedo() throws Exception {
|
public void testUndoRedo() throws Exception {
|
||||||
ProgramTreePlugin treePlugin = env.getPlugin(ProgramTreePlugin.class);
|
ProgramTreePlugin treePlugin = env.getPlugin(ProgramTreePlugin.class);
|
||||||
final DockingActionIf createTreeAction = getAction(treePlugin, "Create Default Tree View");
|
final DockingActionIf createTreeAction = getAction(treePlugin, "Create Default Tree View");
|
||||||
SwingUtilities
|
performAction(createTreeAction);
|
||||||
.invokeAndWait(() -> createTreeAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
env.showTool();
|
env.showTool();
|
||||||
ViewProviderService vps = provider.getCurrentViewProvider();
|
ViewProviderService vps = provider.getCurrentViewProvider();
|
||||||
|
@ -163,8 +161,7 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(treeNames.length, tabbedPane.getTabCount());
|
assertEquals(treeNames.length, tabbedPane.getTabCount());
|
||||||
assertEquals(DEFAULT_TREE_NAME + "(1)", vps.getViewName());
|
assertEquals(DEFAULT_TREE_NAME + "(1)", vps.getViewName());
|
||||||
assertEquals(tabbedPane.getSelectedComponent(), vps.getViewComponent());
|
assertEquals(tabbedPane.getSelectedComponent(), vps.getViewComponent());
|
||||||
SwingUtilities
|
performAction(createTreeAction);
|
||||||
.invokeAndWait(() -> createTreeAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
vps = provider.getCurrentViewProvider();
|
vps = provider.getCurrentViewProvider();
|
||||||
treeNames = program.getListing().getTreeNames();
|
treeNames = program.getListing().getTreeNames();
|
||||||
|
@ -237,7 +234,7 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void testCloseView() throws Exception {
|
public void testCloseView() throws Exception {
|
||||||
// close "Program Tree"
|
// close "Program Tree"
|
||||||
final DockingActionIf closeAction = getAction(plugin, "Close Tree View");
|
final DockingActionIf closeAction = getAction(plugin, "Close Tree View");
|
||||||
SwingUtilities.invokeAndWait(() -> closeAction.actionPerformed(new DefaultActionContext()));
|
performAction(closeAction);
|
||||||
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
|
@ -261,8 +258,7 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
setCurrentViewProvider("Tree Two");
|
setCurrentViewProvider("Tree Two");
|
||||||
|
|
||||||
final DockingActionIf deleteAction = getAction(plugin, "Delete Tree View");
|
final DockingActionIf deleteAction = getAction(plugin, "Delete Tree View");
|
||||||
SwingUtilities
|
performAction(deleteAction);
|
||||||
.invokeAndWait(() -> deleteAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
|
@ -300,31 +296,26 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
setCurrentViewProvider("Main Tree");
|
setCurrentViewProvider("Main Tree");
|
||||||
|
|
||||||
SwingUtilities
|
performAction(deleteAction);
|
||||||
.invokeAndWait(() -> deleteAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
setCurrentViewProvider("Tree One");
|
setCurrentViewProvider("Tree One");
|
||||||
|
|
||||||
SwingUtilities
|
performAction(deleteAction);
|
||||||
.invokeAndWait(() -> deleteAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
setCurrentViewProvider("Tree Two");
|
setCurrentViewProvider("Tree Two");
|
||||||
|
|
||||||
SwingUtilities
|
performAction(deleteAction);
|
||||||
.invokeAndWait(() -> deleteAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
setCurrentViewProvider("Tree Three");
|
setCurrentViewProvider("Tree Three");
|
||||||
|
|
||||||
SwingUtilities
|
performAction(deleteAction);
|
||||||
.invokeAndWait(() -> deleteAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
// attempt to delete the last view
|
// attempt to delete the last view
|
||||||
SwingUtilities
|
performAction(deleteAction);
|
||||||
.invokeAndWait(() -> deleteAction.actionPerformed(new DefaultActionContext()));
|
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
|
|
||||||
ViewProviderService vps = provider.getCurrentViewProvider();
|
ViewProviderService vps = provider.getCurrentViewProvider();
|
||||||
|
@ -341,10 +332,10 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
final DockingActionIf closeAction = getAction(plugin, "Close Tree View");
|
final DockingActionIf closeAction = getAction(plugin, "Close Tree View");
|
||||||
|
|
||||||
setCurrentViewProvider(DEFAULT_TREE_NAME);
|
setCurrentViewProvider(DEFAULT_TREE_NAME);
|
||||||
SwingUtilities.invokeAndWait(() -> closeAction.actionPerformed(new DefaultActionContext()));
|
performAction(closeAction);
|
||||||
|
|
||||||
setCurrentViewProvider("Main Tree");
|
setCurrentViewProvider("Main Tree");
|
||||||
SwingUtilities.invokeAndWait(() -> {
|
runSwing(() -> {
|
||||||
closeAction.actionPerformed(new DefaultActionContext());
|
closeAction.actionPerformed(new DefaultActionContext());
|
||||||
provider.setCurrentViewProvider("Tree One");
|
provider.setCurrentViewProvider("Tree One");
|
||||||
closeAction.actionPerformed(new DefaultActionContext());
|
closeAction.actionPerformed(new DefaultActionContext());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue