Merge remote-tracking branch 'origin/GP-6949_ghidra_red_GTreeTable_Sorting'

This commit is contained in:
Ryan Kurtz
2026-06-10 10:50:33 -04:00
2 changed files with 69 additions and 5 deletions

View File

@@ -51,6 +51,11 @@ public class GTreeTableModel<T extends GTreeTableNode> extends ThreadedTableMode
throws IllegalArgumentException {
return rowObject;
}
@Override
public Comparator<GTreeTableNode> getComparator() {
return Comparator.comparingInt(GTreeTableNode::getIndex);
}
}
private GTreeTableNode rootNode;
@@ -68,7 +73,7 @@ public class GTreeTableModel<T extends GTreeTableNode> extends ThreadedTableMode
@Override
protected TableColumnDescriptor<T> createTableColumnDescriptor() {
final TableColumnDescriptor<T> descriptor = new TableColumnDescriptor<>();
descriptor.addVisibleColumn(new TreeColumn(treeColumnName()));
descriptor.addVisibleColumn(new TreeColumn(treeColumnName()), 0, true);
return descriptor;
}
@@ -122,6 +127,7 @@ public class GTreeTableModel<T extends GTreeTableNode> extends ThreadedTableMode
protected void doLoad(Accumulator<T> accumulator, TaskMonitor monitor)
throws CancelledException {
if (rootNode != null) {
rootNode.reindex();
for (final GTreeTableNode c : rootNode.expandedDescendants()) {
monitor.checkCancelled();
if (c.isVisible()) {

View File

@@ -15,13 +15,12 @@
*/
package docking.widgets.gtreetable;
import javax.swing.*;
import java.io.Serializable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.swing.Icon;
public class GTreeTableNode implements Serializable {
private class EachAncestorIterator implements Iterator<GTreeTableNode> {
GTreeTableNode curNode = getParent();
@@ -53,7 +52,22 @@ public class GTreeTableNode implements Serializable {
nodes.addAll(curNode.getChildren());
return curNode;
}
}
private class EachDecendantDFSIterator implements Iterator<GTreeTableNode> {
final List<GTreeTableNode> nodes = new ArrayList<>(children);
@Override
public boolean hasNext() {
return !nodes.isEmpty();
}
@Override
public GTreeTableNode next() {
final GTreeTableNode curNode = nodes.removeFirst();
nodes.addAll(0, curNode.getChildren());
return curNode;
}
}
private class EachExpandedIterator implements Iterator<GTreeTableNode> {
@@ -68,11 +82,10 @@ public class GTreeTableNode implements Serializable {
public GTreeTableNode next() {
final GTreeTableNode curNode = nodes.removeFirst();
if (curNode.isExpanded()) {
nodes.addAll((curNode.getChildren()));
nodes.addAll(curNode.getChildren());
}
return curNode;
}
}
protected final String name;
@@ -85,6 +98,8 @@ public class GTreeTableNode implements Serializable {
protected boolean visible;
private int index;
public GTreeTableNode(final String name) {
this.name = name;
expanded = false;
@@ -92,6 +107,16 @@ public class GTreeTableNode implements Serializable {
visible = true;
}
/**
* Reindex the tree for sorting
*/
void reindex() {
int i = 0;
for (GTreeTableNode node : getRoot().descendantsDFS()) {
node.index = i++;
}
}
/**
* Add new child to this node's children
*
@@ -146,6 +171,15 @@ public class GTreeTableNode implements Serializable {
return EachDecendantIterator::new;
}
/**
* Get an iterable of all the descendants of this node in DFS order
*
* @return An iterable of descendants
*/
public Iterable<GTreeTableNode> descendantsDFS() {
return EachDecendantDFSIterator::new;
}
/**
* Get an iterable of all the expanded descendants of this node
*
@@ -209,6 +243,21 @@ public class GTreeTableNode implements Serializable {
}
}
/**
* Perform an action on each descendant of this node in DFS order
*
* @param action To perform on each descendant
*/
public void forEachDescendantDFS(final Consumer<GTreeTableNode> action) {
final List<GTreeTableNode> nodes = new ArrayList<>(children);
while (!nodes.isEmpty()) {
final GTreeTableNode curNode = nodes.removeFirst();
action.accept(curNode);
nodes.addAll(0, curNode.getChildren());
}
}
/**
* Perform an action on each expanded descendant of this node
*
@@ -454,6 +503,15 @@ public class GTreeTableNode implements Serializable {
child.setParent(null);
}
/**
* Get this node's index in the tree, for sorting purposes
*
* @return Index in tree
*/
int getIndex() {
return index;
}
/**
* Change node expanded state
*