mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
GP-4134: Less abreasive refreshing of the Model tree.
This commit is contained in:
parent
804fb5ec17
commit
e7fcf5f24a
@ -30,6 +30,7 @@ import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.Trace.TraceObjectChangeType;
|
||||
import ghidra.trace.model.target.*;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
import utilities.util.IDKeyed;
|
||||
|
||||
@ -51,7 +52,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
}
|
||||
|
||||
public void domainObjectRestored(DomainObjectChangeRecord rec) {
|
||||
reload();
|
||||
reloadSameTrace();
|
||||
}
|
||||
|
||||
protected boolean isEventValue(TraceObjectValue value) {
|
||||
@ -167,7 +168,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
}
|
||||
AbstractNode node =
|
||||
byValue.computeIfAbsent(new IDKeyed<>(value), k -> createNode(value));
|
||||
node.unloadChildren();
|
||||
//node.unloadChildren();
|
||||
//AbstractNode node = createNode(value);
|
||||
if (value.isCanonical()) {
|
||||
byObject.put(new IDKeyed<>(value.getChild()), node);
|
||||
@ -204,6 +205,18 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
addNode(i, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
/**
|
||||
* Our nodes are re-usable. They're cached so that as an item comes and goes, its
|
||||
* corresponding node can also come and go without being re-instantiated each time.
|
||||
* Furthermore, it's like to have all the same children as before, too. For now, we'll
|
||||
* just ignore dispose. If there's too many unexpected behaviors resulting from this,
|
||||
* then perhaps we should just have dispose also remove itself from the node cache.
|
||||
*/
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GTreeNode node) {
|
||||
return TargetObjectKeyComparator.CHILD.compare(this.getName(), node.getName());
|
||||
@ -211,7 +224,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getValue().getEntryKey() + "\n" + getValue().getMinSnap();
|
||||
return getValue().getEntryKey() + "@" + getValue().getMinSnap();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -260,6 +273,50 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
protected boolean isModified() {
|
||||
return isValueModified(getValue());
|
||||
}
|
||||
|
||||
protected synchronized void reloadChildrenNow() {
|
||||
if (!isLoaded()) {
|
||||
return;
|
||||
}
|
||||
// Use a merge to effect the minimal changes to set the children
|
||||
var current = List.copyOf(children());
|
||||
var generated = generateChildren();
|
||||
// NB. The two lists ought to be sorted already.
|
||||
int ic = 0;
|
||||
int ig = 0;
|
||||
int diff = 0;
|
||||
while (ic < current.size() && ig < generated.size()) {
|
||||
GTreeNode nc = current.get(ic);
|
||||
GTreeNode ng = generated.get(ig);
|
||||
int comp = nc.compareTo(ng);
|
||||
if (comp == 0) {
|
||||
ic++;
|
||||
ig++;
|
||||
}
|
||||
else if (comp < 0) {
|
||||
removeNode(nc);
|
||||
diff--;
|
||||
ic++;
|
||||
}
|
||||
else { // comp > 0
|
||||
addNode(ic + diff, ng);
|
||||
diff++;
|
||||
ig++;
|
||||
}
|
||||
}
|
||||
while (ic < current.size()) {
|
||||
GTreeNode nc = current.get(ic);
|
||||
removeNode(nc);
|
||||
// diff--; // Not really needed
|
||||
ic++;
|
||||
}
|
||||
while (ig < generated.size()) {
|
||||
GTreeNode ng = generated.get(ig);
|
||||
addNode(ic + diff, ng);
|
||||
diff++;
|
||||
ig++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RootNode extends AbstractNode {
|
||||
@ -670,6 +727,15 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
root.unloadChildren();
|
||||
}
|
||||
|
||||
protected void reloadSameTrace() {
|
||||
try (LockHold hold = trace == null ? null : trace.lockRead()) {
|
||||
for (AbstractNode node : List.copyOf(nodeCache.byObject.values())) {
|
||||
node.reloadChildrenNow();
|
||||
}
|
||||
root.reloadChildrenNow();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTrace(Trace trace) {
|
||||
if (this.trace == trace) {
|
||||
return;
|
||||
@ -761,7 +827,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
}
|
||||
|
||||
protected void spanChanged() {
|
||||
reload();
|
||||
reloadSameTrace();
|
||||
}
|
||||
|
||||
public void setSpan(Lifespan span) {
|
||||
@ -777,7 +843,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
}
|
||||
|
||||
protected void showHiddenChanged() {
|
||||
reload();
|
||||
reloadSameTrace();
|
||||
}
|
||||
|
||||
public void setShowHidden(boolean showHidden) {
|
||||
@ -793,7 +859,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
}
|
||||
|
||||
protected void showPrimitivesChanged() {
|
||||
reload();
|
||||
reloadSameTrace();
|
||||
}
|
||||
|
||||
public void setShowPrimitives(boolean showPrimitives) {
|
||||
@ -809,7 +875,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
||||
}
|
||||
|
||||
protected void showMethodsChanged() {
|
||||
reload();
|
||||
reloadSameTrace();
|
||||
}
|
||||
|
||||
public void setShowMethods(boolean showMethods) {
|
||||
|
@ -153,7 +153,7 @@ public class ObjectsTreePanel extends JPanel {
|
||||
if (limitToSnap) {
|
||||
treeModel.setSpan(Lifespan.at(current.getSnap()));
|
||||
}
|
||||
tree.filterChanged();
|
||||
//tree.filterChanged();
|
||||
// Repaint for bold current path is already going to happen
|
||||
}
|
||||
}
|
||||
@ -298,7 +298,6 @@ public class ObjectsTreePanel extends JPanel {
|
||||
tree.expandPath(parentPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setSelectedObject(TraceObject object) {
|
||||
if (object == null) {
|
||||
|
@ -410,7 +410,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
||||
GTree tree = modelProvider.objectsTreePanel.tree;
|
||||
GTreeNode node = waitForPass(() -> {
|
||||
GTreeNode n = Unique.assertOne(tree.getSelectedNodes());
|
||||
assertEquals("Processes\n0", n.getName());
|
||||
assertEquals("Processes@0", n.getName());
|
||||
return n;
|
||||
});
|
||||
clickTreeNode(tree, node, MouseEvent.BUTTON1);
|
||||
|
Loading…
Reference in New Issue
Block a user