1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.gui.tree;
21
22 import java.io.File;
23 import java.util.Arrays;
24 import java.util.Comparator;
25 import java.util.Hashtable;
26 import java.util.Vector;
27
28 import javax.swing.event.TreeModelEvent;
29
30 public class FileTreeModel extends AbstractTreeModel implements Comparator
31 {
32
33
34
35 private Vector subRoots;
36 private Hashtable subChildren = new Hashtable();
37 private File cachedDir;
38 private boolean cacheSorted;
39 private File[] cache;
40 private boolean filterDotFiles = true;
41
42
43
44 public FileTreeModel(String root, File[] roots)
45 {
46 super(root);
47
48 if (roots != null) {
49 subRoots = new Vector(roots.length);
50 for (int i = 0; i < roots.length; i++) {
51 addSubRoot(roots[i]);
52 }
53 }
54 else {
55 subRoots = new Vector();
56 }
57 }
58
59 public FileTreeModel(String root)
60 {
61 this(root, null);
62 }
63
64
65
66 public int compare(Object o1, Object o2)
67 {
68 return
69 o1.toString().toLowerCase().compareTo(o2.toString().toLowerCase());
70 }
71
72 public boolean isLeaf(Object node)
73 {
74 return false;
75 }
76
77 public int getChildCount(Object node)
78 {
79 if (node instanceof File && ((File)node).canRead()) {
80 return getSubDirs((File)node, false).length;
81 }
82 else if (node instanceof String) {
83 if (node.equals(root)) {
84 return subRoots.size();
85 }
86 return ((Vector)subChildren.get(node)).size();
87 }
88 else {
89 return 0;
90 }
91 }
92
93 public Object getChild(Object parent, int index)
94 {
95 if (parent instanceof File) {
96 File[] children = getSubDirs((File)parent, true);
97
98 if ((children == null) || (index >= children.length))
99 return null;
100 return new FileNode(children[index]);
101 }
102 else if (parent instanceof String) {
103 if (parent.equals(root) && index < subRoots.size())
104 return subRoots.get(index);
105
106 Vector v = (Vector)subChildren.get(parent);
107 if (index < v.size())
108 return v.elementAt(index);
109
110 return null;
111 }
112 else {
113 return null;
114 }
115 }
116
117 public int getIndexOfChild(Object parent, Object child)
118 {
119 if (parent instanceof File) {
120 File[] children = getSubDirs((File)parent, true);
121
122 if (children == null)
123 return -1;
124
125 for (int i = 0; i < children.length; i++) {
126 if (children[i] == child)
127 return i;
128 }
129 }
130 else if (parent instanceof String) {
131 if (parent.equals(root)) {
132 return subRoots.indexOf(child);
133 }
134 return ((Vector)subChildren.get(parent)).indexOf(child);
135 }
136
137 return -1;
138 }
139
140 private File[] getSubDirs(File f, boolean doSort)
141 {
142 if (f == cachedDir && cacheSorted == doSort)
143 return cache;
144
145 File[] children = f.listFiles();
146 int count = 0;
147 if (children != null) {
148 for (int i = 0; i < children.length; i++) {
149 if (children[i].isDirectory()) {
150 if (filterDotFiles
151 && children[i].getName().startsWith("."))
152 continue;
153
154 children[count] = children[i];
155 count++;
156 }
157 }
158 }
159
160 cache = new File[count];
161 if (count > 0) {
162 System.arraycopy(children, 0, cache, 0, count);
163
164 if (doSort) {
165 Arrays.sort(cache, this);
166 }
167 }
168
169 cachedDir = f;
170 cacheSorted = doSort;
171
172 return cache;
173 }
174
175 public void addSubRoot(String s)
176 {
177 if (subRoots.contains(s))
178 return;
179
180 subRoots.add(s);
181
182
183 subChildren.put(s, new Vector());
184
185 Object[] path = { root };
186 int[] indices = { subRoots.size() - 1 };
187 Object[] children = { s };
188 fireTreeNodesInserted(new TreeModelEvent(this, path, indices,
189 children));
190
191 }
192
193 public void addSubRoot(File f)
194 {
195 if (subRoots.contains(f))
196 return;
197
198 subRoots.add(f);
199
200 Object[] path = { root };
201 int[] indices = { subRoots.size() - 1 };
202 Object[] children = { f };
203 fireTreeNodesInserted(new TreeModelEvent(this, path, indices,
204 children));
205 }
206
207 public void removeSubRoots()
208 {
209
210 for (int i = 0; i < subRoots.size(); i++)
211 subChildren.remove(subRoots.get(i));
212
213 subRoots.clear();
214
215 Object[] path = { root };
216 fireTreeStructureChanged(new TreeModelEvent(this, path));
217 }
218
219 public void removeChildrenOfSubRoot(String s)
220 {
221 if (!subRoots.contains(s))
222 return;
223
224 Vector v = (Vector)subChildren.get(s);
225
226 v.removeAllElements();
227
228 Object[] path = { root, s };
229 fireTreeStructureChanged(new TreeModelEvent(this, path));
230 }
231
232 public void addChildOfSubRoot(File f, String s)
233 {
234 addChildOfSubRoot(f, s, null);
235 }
236
237 public void addChildOfSubRoot(File f, String s, String label)
238 {
239 addSubRoot(s);
240
241 Vector kids = (Vector) subChildren.get(s);
242
243 FileNode node = new FileNode(f, true, label);
244
245 if (kids.contains(node))
246 return;
247
248 kids.add(node);
249 Object[] path = { root, s };
250 int[] indices = { kids.size() - 1 };
251 Object[] children = { f };
252 fireTreeNodesInserted(new TreeModelEvent(this, path, indices,
253 children ));
254 }
255
256 public void removeChildOfSubRoot(File f, String s)
257 {
258 if (!subRoots.contains(s))
259 return;
260
261 Vector kids = (Vector) subChildren.get(s);
262
263 FileNode node = new FileNode(f, true);
264
265 int index = kids.indexOf(node);
266
267 if (index == -1)
268 return;
269
270 kids.remove(index);
271
272 Object[] path = { root, s };
273 int[] indices = { index };
274 Object[] children = { node };
275 fireTreeNodesRemoved(new TreeModelEvent(this, path, indices,
276 children));
277 }
278 }