mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Fixed open program dialog to not repeatedly load the root node
This commit is contained in:
parent
2eff37f655
commit
1d5da6dae1
9 changed files with 268 additions and 165 deletions
|
@ -57,8 +57,14 @@ import resources.Icons;
|
|||
|
||||
/**
|
||||
* Class for creating a JTree that supports filtering, threading, and a progress bar.
|
||||
* <p>
|
||||
* Note: when calling methods on this class to select nodes, if those nodes are threaded, or extend
|
||||
* from {@link GTreeSlowLoadingNode}, then you must first expand the paths you wish to select. You
|
||||
* can do this by calling {@link #expandAndSelectPaths(List)}. The various select methods of this
|
||||
* class will not expand nodes, but they will trigger children to be loaded. If those nodes are not
|
||||
* threaded, then the tree will add and expand the children by default. When using threaded nodes,
|
||||
* the delay in loading prevents the tree from correctly expanding the paths.
|
||||
*/
|
||||
|
||||
public class GTree extends JPanel implements BusyListener {
|
||||
private static final Color BACKGROUND = new GColor("color.bg.tree");
|
||||
private AutoScrollTree tree;
|
||||
|
@ -475,26 +481,36 @@ public class GTree extends JPanel implements BusyListener {
|
|||
}
|
||||
|
||||
public void expandPath(GTreeNode node) {
|
||||
expandPaths(new TreePath[] { node.getTreePath() });
|
||||
expandPaths(List.of(node.getTreePath()));
|
||||
}
|
||||
|
||||
public void expandPath(TreePath path) {
|
||||
expandPaths(new TreePath[] { path });
|
||||
expandPaths(List.of(path));
|
||||
}
|
||||
|
||||
public void expandPaths(TreePath[] paths) {
|
||||
runTask(new GTreeExpandPathsTask(this, Arrays.asList(paths)));
|
||||
expandPaths(Arrays.asList(paths));
|
||||
}
|
||||
|
||||
public void expandPaths(List<TreePath> pathsList) {
|
||||
TreePath[] treePaths = pathsList.toArray(new TreePath[pathsList.size()]);
|
||||
expandPaths(treePaths);
|
||||
public void expandPaths(List<TreePath> paths) {
|
||||
runTask(new GTreeExpandPathsTask(this, paths));
|
||||
}
|
||||
|
||||
public void clearSelectionPaths() {
|
||||
runTask(new GTreeClearSelectionTask(this, tree));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands and then selects the given paths. You must use this method if your tree is using
|
||||
* {@link GTreeSlowLoadingNode}s. Otherwise, if the given paths are not expanded, then the
|
||||
* select will not work. More info at the class javadoc.
|
||||
*
|
||||
* @param paths the paths
|
||||
*/
|
||||
public void expandAndSelectPaths(List<TreePath> paths) {
|
||||
setSelectionPaths(paths, true, EventOrigin.API_GENERATED);
|
||||
}
|
||||
|
||||
public void setSelectedNode(GTreeNode node) {
|
||||
setSelectionPaths(new TreePath[] { node.getTreePath() });
|
||||
}
|
||||
|
@ -568,8 +584,24 @@ public class GTree extends JPanel implements BusyListener {
|
|||
runTask(new GTreeSelectNodeByNameTask(this, tree, namePath, EventOrigin.API_GENERATED));
|
||||
}
|
||||
|
||||
public void setSelectionPaths(TreePath[] path, EventOrigin origin) {
|
||||
runTask(new GTreeSelectPathsTask(this, tree, Arrays.asList(path), origin));
|
||||
public void setSelectionPaths(TreePath[] paths, EventOrigin origin) {
|
||||
setSelectionPaths(Arrays.asList(paths), false, origin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the given paths, expanding them first if requested.
|
||||
*
|
||||
* @param paths the paths to select
|
||||
* @param expandPaths true to expand the paths first; this is only needed for multi-threaded
|
||||
* nodes. Non-threaded nodes should use false, as it increase performance.
|
||||
* @param origin the event type; use {@link EventOrigin#API_GENERATED} if unsure
|
||||
*/
|
||||
public void setSelectionPaths(List<TreePath> paths, boolean expandPaths, EventOrigin origin) {
|
||||
|
||||
if (expandPaths) {
|
||||
expandPaths(paths);
|
||||
}
|
||||
runTask(new GTreeSelectPathsTask(this, tree, paths, origin));
|
||||
}
|
||||
|
||||
public boolean isCollapsed(TreePath path) {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* 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.
|
||||
|
@ -15,10 +15,12 @@
|
|||
*/
|
||||
package docking.widgets.tree;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.collections4.IteratorUtils;
|
||||
|
||||
import docking.widgets.tree.internal.InProgressGTreeNode;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -124,4 +126,14 @@ public abstract class GTreeSlowLoadingNode extends GTreeLazyNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<GTreeNode> iterator(boolean depthFirst) {
|
||||
if (Swing.isSwingThread()) {
|
||||
Msg.warn(this, "Threaded tree nodes cannot be iterated on the Swing thread. " +
|
||||
"Change the call to this method to be run in a background task");
|
||||
return IteratorUtils.emptyIterator();
|
||||
}
|
||||
return super.iterator(depthFirst);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* 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.
|
||||
|
@ -17,8 +17,7 @@ package docking.widgets.tree;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@ -151,7 +150,27 @@ public class GTreeSlowLoadingNodeTest extends AbstractDockingTest {
|
|||
waitForTree();
|
||||
Swing.runNow(() -> children = nonLeaf1.getChildren());
|
||||
assertTrue("Did not find children for: " + nonLeaf1, nonLeaf1.getChildCount() > 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
|
||||
gTree.setRootNode(new TestRootNode(5000));
|
||||
waitForTree();
|
||||
|
||||
GTreeNode rootNode = gTree.getModelRoot();
|
||||
GTreeNode slowChild = rootNode.getChild(0); // slow; threaded
|
||||
assertNotNull(slowChild);
|
||||
|
||||
Swing.runNow(() -> children = slowChild.getChildren());
|
||||
assertEquals(1, children.size());
|
||||
assertTrue(children.get(0) instanceof InProgressGTreeNode);
|
||||
|
||||
Iterator<GTreeNode> it = runSwing(() -> slowChild.iterator(true));
|
||||
assertFalse(it.hasNext()); // empty when called on the Swing thread
|
||||
|
||||
it = slowChild.iterator(true);
|
||||
assertTrue(it.hasNext()); // not empty on non-Swing thread
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
@ -235,11 +254,11 @@ public class GTreeSlowLoadingNodeTest extends AbstractDockingTest {
|
|||
private class TestRootNode extends GTreeNode {
|
||||
|
||||
TestRootNode(int loadDelayMillis) {
|
||||
List<GTreeNode> children = new ArrayList<>();
|
||||
children.add(new TestSlowLoadingNode(loadDelayMillis, 1));
|
||||
children.add(new TestLeafNode());
|
||||
children.add(new TestSlowLoadingNode(loadDelayMillis, 1));
|
||||
setChildren(children);
|
||||
List<GTreeNode> newChildren = new ArrayList<>();
|
||||
newChildren.add(new TestSlowLoadingNode(loadDelayMillis, 1));
|
||||
newChildren.add(new TestLeafNode());
|
||||
newChildren.add(new TestSlowLoadingNode(loadDelayMillis, 1));
|
||||
setChildren(newChildren);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -289,18 +308,18 @@ public class GTreeSlowLoadingNodeTest extends AbstractDockingTest {
|
|||
}
|
||||
|
||||
int childCount = getRandomInt(MIN_CHILD_COUNT, MAX_CHILD_COUNT);
|
||||
List<GTreeNode> children = new ArrayList<>();
|
||||
List<GTreeNode> newChildren = new ArrayList<>();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
monitor.checkCancelled();
|
||||
int value = getRandomInt(0, 1);
|
||||
if (value == 0) {
|
||||
children.add(new TestSlowLoadingNode(loadDelayMillis, depth + 1));
|
||||
newChildren.add(new TestSlowLoadingNode(loadDelayMillis, depth + 1));
|
||||
}
|
||||
else {
|
||||
children.add(new TestLeafNode());
|
||||
newChildren.add(new TestLeafNode());
|
||||
}
|
||||
}
|
||||
return children;
|
||||
return newChildren;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue