Merge branch 'subtree'
[nikiroo-utils.git] / ui / TreeSnapshot.java
1 package be.nikiroo.utils.ui;
2
3 import java.util.ArrayList;
4 import java.util.LinkedList;
5 import java.util.List;
6
7 import javax.swing.JTree;
8 import javax.swing.tree.TreeModel;
9 import javax.swing.tree.TreeNode;
10 import javax.swing.tree.TreePath;
11
12 public class TreeSnapshot {
13 private interface NodeAction {
14 public void run(TreeNode node);
15 }
16
17 private JTree tree;
18 private TreePath[] selectionPaths;
19 private List<TreePath> expanded;
20
21 public TreeSnapshot(JTree tree) {
22 this.tree = tree;
23
24 selectionPaths = tree.getSelectionPaths();
25 if (selectionPaths == null) {
26 selectionPaths = new TreePath[0];
27 }
28
29 expanded = new ArrayList<TreePath>();
30 forEach(tree, new NodeAction() {
31 @Override
32 public void run(TreeNode node) {
33 TreePath path = nodeToPath(node);
34 if (path != null) {
35 if (TreeSnapshot.this.tree.isExpanded(path)) {
36 expanded.add(path);
37 }
38 }
39 }
40 });
41 }
42
43 public void apply() {
44 applyTo(tree);
45 }
46
47 public void applyTo(JTree tree) {
48 final List<TreePath> newExpanded = new ArrayList<TreePath>();
49 final List<TreePath> newSlectionPaths = new ArrayList<TreePath>();
50
51 forEach(tree, new NodeAction() {
52 @Override
53 public void run(TreeNode newNode) {
54 TreePath newPath = nodeToPath(newNode);
55 if (newPath != null) {
56 for (TreePath path : selectionPaths) {
57 if (isSamePath(path, newPath)) {
58 newSlectionPaths.add(newPath);
59 if (expanded.contains(path)) {
60 newExpanded.add(newPath);
61 }
62 }
63 }
64 }
65 }
66 });
67
68 for (TreePath newPath : newExpanded) {
69 tree.expandPath(newPath);
70 }
71
72 tree.setSelectionPaths(newSlectionPaths.toArray(new TreePath[0]));
73 }
74
75 // You can override this
76 protected boolean isSamePath(TreePath oldPath, TreePath newPath) {
77 return newPath.toString().equals(oldPath.toString());
78 }
79
80 private void forEach(JTree tree, NodeAction action) {
81 forEach(tree.getModel(), tree.getModel().getRoot(), action);
82 }
83
84 private void forEach(TreeModel model, Object parent, NodeAction action) {
85 if (!(parent instanceof TreeNode))
86 return;
87
88 TreeNode node = (TreeNode) parent;
89
90 action.run(node);
91 int count = model.getChildCount(node);
92 for (int i = 0; i < count; i++) {
93 Object child = model.getChild(node, i);
94 forEach(model, child, action);
95 }
96 }
97
98 private static TreePath nodeToPath(TreeNode node) {
99 List<Object> nodes = new LinkedList<Object>();
100 if (node != null) {
101 nodes.add(node);
102 node = node.getParent();
103 while (node != null) {
104 nodes.add(0, node);
105 node = node.getParent();
106 }
107 }
108
109 return nodes.isEmpty() ? null : new TreePath(nodes.toArray());
110 }
111
112 @Override
113 public String toString() {
114 StringBuilder builder = new StringBuilder();
115 builder.append("Tree Snapshot of: ").append(tree).append("\n");
116 builder.append("Selected paths:\n");
117 for (TreePath path : selectionPaths) {
118 builder.append("\t").append(path).append("\n");
119 }
120 builder.append("Expanded paths:\n");
121 for (TreePath epath : expanded) {
122 builder.append("\t").append(epath).append("\n");
123 }
124
125 return builder.toString();
126 }
127 }