mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-3457 - GTree Edit Fix - fixed bug that would cause new namespace tree
nodes to not be in edit mode as intended
This commit is contained in:
parent
cf0c434d51
commit
bd362d9cf6
11 changed files with 357 additions and 92 deletions
|
@ -27,6 +27,7 @@ import java.util.*;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.Timer;
|
||||
|
@ -44,6 +45,7 @@ import docking.widgets.tree.internal.*;
|
|||
import docking.widgets.tree.support.*;
|
||||
import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin;
|
||||
import docking.widgets.tree.tasks.*;
|
||||
import generic.timer.ExpiringSwingTimer;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -978,23 +980,45 @@ public class GTree extends JPanel implements BusyListener {
|
|||
}
|
||||
|
||||
public void addGTModelListener(TreeModelListener listener) {
|
||||
tree.getModel().addTreeModelListener(listener);
|
||||
model.addTreeModelListener(listener);
|
||||
}
|
||||
|
||||
public void removeGTModelListener(TreeModelListener listener) {
|
||||
tree.getModel().removeTreeModelListener(listener);
|
||||
model.removeTreeModelListener(listener);
|
||||
}
|
||||
|
||||
public void setEditable(boolean editable) {
|
||||
tree.setEditable(editable);
|
||||
}
|
||||
|
||||
public void startEditing(final GTreeNode parent, final String childName) {
|
||||
/**
|
||||
* Requests that the node with the given name, in the given parent, be edited. <b>This
|
||||
* operation (as with many others on this tree) is asynchronous.</b> This request will be
|
||||
* buffered as needed to wait for the given node to be added to the parent, up to a timeout
|
||||
* period.
|
||||
*
|
||||
* @param parent the parent node
|
||||
* @param childName the child node name
|
||||
*/
|
||||
public void startEditing(GTreeNode parent, final String childName) {
|
||||
|
||||
// we call this here, even though the JTree will do this for us, so that we will trigger
|
||||
// a load call before this task is run, in case lazy nodes are involved in this tree,
|
||||
// which must be loaded before we can edit
|
||||
expandPath(parent);
|
||||
runTask(new GTreeStartEditingTask(GTree.this, tree, parent, childName));
|
||||
|
||||
//
|
||||
// The request to edit the node may be for a node that has not yet been added to this
|
||||
// tree. Further, some clients will buffer events, which means that the node the client
|
||||
// wishes to edit may not yet be in the parent node even if we run this request later on
|
||||
// the Swing thread. To deal with this, we use a construct that will run our request
|
||||
// once the given node has been added to the parent.
|
||||
//
|
||||
BooleanSupplier isReady = () -> parent.getChild(childName) != null;
|
||||
int expireMs = 3000;
|
||||
ExpiringSwingTimer.runWhen(isReady, expireMs, () -> {
|
||||
runTask(new GTreeStartEditingTask(GTree.this, tree, parent, childName));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,6 +28,7 @@ import docking.widgets.tree.*;
|
|||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import util.CollectionUtils;
|
||||
|
||||
|
@ -43,7 +44,7 @@ public class GTreeStartEditingTask extends GTreeTask {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void run(final TaskMonitor monitor) {
|
||||
public void run(final TaskMonitor monitor) throws CancelledException {
|
||||
runOnSwingThread(() -> {
|
||||
if (monitor.isCancelled()) {
|
||||
return; // we can be cancelled while waiting for Swing to run us
|
||||
|
@ -58,18 +59,21 @@ public class GTreeStartEditingTask extends GTreeTask {
|
|||
}
|
||||
|
||||
private void edit() {
|
||||
final GTreeNode child = parent.getChild(childName);
|
||||
if (child == null) {
|
||||
|
||||
GTreeNode editNode = parent.getChild(childName);
|
||||
if (editNode == null) {
|
||||
if (tree.isFiltered()) {
|
||||
Msg.showWarn(getClass(), tree, "Cannot Edit Tree Node",
|
||||
"Cannot edit tree node \"" + childName + "\" while tree is filtered.");
|
||||
"Can't edit tree node \"" + childName + "\" while tree is filtered.");
|
||||
}
|
||||
else {
|
||||
Msg.debug(this,
|
||||
"Can't find node \"" + childName + "\" to edit.");
|
||||
}
|
||||
Msg.debug(this,
|
||||
"Can't find node for \"" + childName + "\". Perhaps it is filtered out?");
|
||||
return;
|
||||
}
|
||||
|
||||
TreePath path = child.getTreePath();
|
||||
TreePath path = editNode.getTreePath();
|
||||
final Set<GTreeNode> childrenBeforeEdit = new HashSet<>(parent.getChildren());
|
||||
|
||||
final CellEditor cellEditor = tree.getCellEditor();
|
||||
|
@ -95,7 +99,7 @@ public class GTreeStartEditingTask extends GTreeTask {
|
|||
* has finished and been applied.
|
||||
*/
|
||||
private void reselectNode() {
|
||||
String newName = child.getName();
|
||||
String newName = editNode.getName();
|
||||
GTreeNode newChild = parent.getChild(newName);
|
||||
if (newChild == null) {
|
||||
throw new AssertException("Unable to find new node by name: " + newName);
|
||||
|
@ -140,7 +144,7 @@ public class GTreeStartEditingTask extends GTreeTask {
|
|||
}
|
||||
});
|
||||
|
||||
tree.setNodeEditable(child);
|
||||
tree.setNodeEditable(editNode);
|
||||
jTree.startEditingAtPath(path);
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue