1 package org.catacomb.druid.swing;
2
3 import javax.swing.tree.*;
4
5 import java.util.Stack;
6 import java.util.ArrayList;
7
8
9 public class CheckTreeSelectionModel extends DefaultTreeSelectionModel {
10 private static final long serialVersionUID = 1L;
11
12 private TreeModel model;
13
14
15 public CheckTreeSelectionModel(TreeModel model) {
16 this.model = model;
17 setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
18 }
19
20
21
22 public boolean isPartiallySelected(TreePath path) {
23 if (isPathSelected(path, true)) {
24 return false;
25 }
26 TreePath[] selectionPaths = getSelectionPaths();
27 if (selectionPaths == null) {
28 return false;
29 }
30
31 for (int j = 0; j < selectionPaths.length; j++) {
32 if (isDescendant(selectionPaths[j], path)) {
33 return true;
34 }
35 }
36 return false;
37 }
38
39
40
41
42
43 public boolean isPathSelected(TreePath pathin, boolean dig) {
44 TreePath path = pathin;
45 if (!dig) {
46 return super.isPathSelected(path);
47 }
48 while (path != null && !super.isPathSelected(path)) {
49 path = path.getParentPath();
50 }
51 return path != null;
52 }
53
54
55
56 private boolean isDescendant(TreePath path1, TreePath path2) {
57 Object obj1[] = path1.getPath();
58 Object obj2[] = path2.getPath();
59 for (int i = 0; i < obj2.length; i++) {
60 if (obj1[i] != obj2[i]) {
61 return false;
62 }
63 }
64 return true;
65 }
66
67
68 public void setSelectionPaths(TreePath[] pPaths) {
69
70 }
71
72
73 public void addSelectionPaths(TreePath[] paths) {
74
75 for (int i = 0; i < paths.length; i++) {
76
77 TreePath path = paths[i];
78
79 TreePath[] selectionPaths = getSelectionPaths();
80 if (selectionPaths == null) {
81 break;
82 }
83 ArrayList<Object> toBeRemoved = new ArrayList<Object>();
84 for (int j = 0; j < selectionPaths.length; j++) {
85 if (isDescendant(selectionPaths[j], path)) {
86 toBeRemoved.add(selectionPaths[j]);
87 }
88 }
89 super.removeSelectionPaths(toBeRemoved.toArray(new TreePath[0]));
90 }
91
92
93
94
95 for (int i = 0; i < paths.length; i++) {
96 TreePath path = paths[i];
97 TreePath temp = null;
98 while (areSiblingsSelected(path)) {
99 temp = path;
100 if (path.getParentPath() == null) {
101 break;
102 }
103 path = path.getParentPath();
104 }
105 if (temp != null) {
106 if (temp.getParentPath() != null) {
107 addSelectionPath(temp.getParentPath());
108 } else {
109 if (!isSelectionEmpty()) {
110 removeSelectionPaths(getSelectionPaths());
111 }
112 super.addSelectionPaths(new TreePath[] { temp });
113 }
114 } else {
115 super.addSelectionPaths(new TreePath[] { path });
116 }
117 }
118 }
119
120
121
122 private boolean areSiblingsSelected(TreePath path) {
123 TreePath parent = path.getParentPath();
124 if (parent == null) {
125 return true;
126 }
127 Object node = path.getLastPathComponent();
128 Object parentNode = parent.getLastPathComponent();
129
130 int childCount = model.getChildCount(parentNode);
131 for (int i = 0; i < childCount; i++) {
132 Object childNode = model.getChild(parentNode, i);
133 if (childNode == node) {
134 continue;
135 }
136 if (!isPathSelected(parent.pathByAddingChild(childNode))) {
137 return false;
138 }
139 }
140 return true;
141 }
142
143
144 public void removeSelectionPaths(TreePath[] paths) {
145 for (int i = 0; i < paths.length; i++) {
146 TreePath path = paths[i];
147 if (path.getPathCount() == 1) {
148 super.removeSelectionPaths(new TreePath[] { path });
149 } else {
150 toggleRemoveSelection(path);
151 }
152 }
153 }
154
155
156
157
158
159 private void toggleRemoveSelection(TreePath path) {
160 Stack<Object> stack = new Stack<Object>();
161 TreePath parent = path.getParentPath();
162 while (parent != null && !isPathSelected(parent)) {
163 stack.push(parent);
164 parent = parent.getParentPath();
165 }
166 if (parent != null)
167 stack.push(parent);
168 else {
169 super.removeSelectionPaths(new TreePath[] { path });
170 return;
171 }
172
173 while (!stack.isEmpty()) {
174 TreePath temp = (TreePath)stack.pop();
175 TreePath peekPath = stack.isEmpty() ? path : (TreePath)stack.peek();
176 Object node = temp.getLastPathComponent();
177 Object peekNode = peekPath.getLastPathComponent();
178 int childCount = model.getChildCount(node);
179 for (int i = 0; i < childCount; i++) {
180 Object childNode = model.getChild(node, i);
181 if (childNode != peekNode)
182 super.addSelectionPaths(new TreePath[] { temp.pathByAddingChild(childNode) });
183 }
184 }
185 super.removeSelectionPaths(new TreePath[] { parent });
186 }
187
188
189 public ArrayList<TreePath> getDescendantPaths(TreePath tp) {
190 ArrayList<TreePath> tps = new ArrayList<TreePath>();
191 appendDescendantPaths(tps, tp);
192 return tps;
193 }
194
195 private void appendDescendantPaths(ArrayList<TreePath> atp , TreePath tp) {
196 Object lc = tp.getLastPathComponent();
197 if (model.isLeaf(lc)) {
198 atp.add(tp);
199 } else {
200 for (int i = 0; i < model.getChildCount(lc); i++) {
201 Object oc = model.getChild(lc, i);
202 TreePath ctp = tp.pathByAddingChild(oc);
203 appendDescendantPaths(atp, ctp);
204 }
205 }
206 }
207 }