source: trunk/gli/src/org/greenstone/gatherer/file/FileNode.java@ 4385

Last change on this file since 4385 was 4385, checked in by jmt12, 21 years ago

Added method getIcon() which returns the ImageIcon the file system thinks should be assigned to this file node, or null if the node has no file.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.2 KB
Line 
1package org.greenstone.gatherer.file;
2
3import java.io.File;
4import java.util.*;
5import javax.swing.filechooser.*;
6import javax.swing.tree.*;
7import org.greenstone.gatherer.file.FileFilter;
8import org.greenstone.gatherer.file.FileSystemModel;
9import org.greenstone.gatherer.util.ArrayTools;
10
11public class FileNode
12 implements MutableTreeNode {
13
14 static final private int FALSE = 0;
15 static final private int TRUE = 1;
16 static final private int UNKNOWN = 2;
17
18 private ArrayList children;
19 private boolean children_readonly = true;
20 private boolean readonly = true;
21 private File file;
22 private FileSystemModel model;
23 private int allows_children = UNKNOWN;
24 private MutableTreeNode parent;
25 private String title;
26
27 public FileNode(File file) {
28 ///ystem.err.println("New FileNode(" + file.getAbsolutePath() + ")");
29 this.file = file;
30 }
31
32 public FileNode(File file, boolean readonly) {
33 this(file);
34 this.children_readonly = readonly;
35 this.readonly = readonly;
36 }
37
38 public FileNode(File file, FileSystemModel model) {
39 this(file);
40 this.model = model;
41 }
42
43 public FileNode(File file, FileSystemModel model, boolean readonly) {
44 this(file, readonly);
45 this.model = model;
46 }
47
48 public FileNode(File file, FileSystemModel model, String title) {
49 this(file, model);
50 this.title = title;
51 }
52
53 public FileNode(File file, String title) {
54 this(file);
55 this.title = title;
56 }
57
58 public FileNode(File file, String title, boolean readonly) {
59 this(file, readonly);
60 this.title = title;
61 }
62
63 public FileNode(File file, FileSystemModel model, String title, boolean readonly) {
64 this(file, model, readonly);
65 this.title = title;
66 }
67
68 /** The special 'dummy' root node, that is not based on a particular file, but instead holds several special directory mappings. */
69 public FileNode(String title) {
70 this.children = new ArrayList();
71 this.title = title;
72 }
73
74 /** Returns the children of the receiver as an Enumeration. */
75 public Enumeration children() {
76 return new FileEnumeration();
77 }
78
79 /** Compare two filenodes for equality. */
80 public boolean equals(FileNode node) {
81 boolean result = false;
82 if(node != null) {
83 if(file != null) {
84 result = (file.equals(node.getFile()));
85 }
86 else {
87 result = toString().equals(node.toString());
88 }
89 }
90 return result;
91 }
92
93 /** Returns true if the receiver allows children. We have to cache the result of this call to prevent unceasing missing disk messages being thrown if the removable media was, um, removed after directory mapped. */
94 public boolean getAllowsChildren() {
95 if(readonly) {
96 if(allows_children == UNKNOWN) {
97 // If the file is non-null but doesn't exist (as is the case for removable media), return true anyway.
98 if(file != null) {
99 if(isFileSystemRoot()) {
100 allows_children = TRUE;
101 }
102 else if(file.exists() && file.isDirectory()) {
103 allows_children = TRUE;
104 }
105 // Any mapped directories always allow children.
106 else if(getParent() != null && getParent().getParent() == null) {
107 allows_children = TRUE;
108 }
109 else {
110 allows_children = FALSE;
111 }
112 }
113 // Allows children is always true for dummy nodes.
114 else {
115 allows_children = TRUE;
116 }
117 }
118 return (allows_children == TRUE);
119 }
120 else {
121 return (file == null || file.isDirectory());
122 }
123 }
124
125 /** Returns the child TreeNode at index childIndex. */
126 public TreeNode getChildAt(int index) {
127 TreeNode result = null;
128 map();
129 if(0 <= index && index < children.size()) {
130 result = (TreeNode) children.get(index);
131 }
132 else {
133 result = new DefaultMutableTreeNode("Error");
134 }
135 return result;
136 }
137
138 /** Returns the number of children TreeNodes the receiver contains. */
139 public int getChildCount() {
140 int size = 0;
141 // We don't automatically map if this is a system root, or we risk the 50,000 Disk not found error messages of death.
142 if(isFileSystemRoot()) {
143 size = 1; // Size is always non-zero for a system root
144 }
145 else {
146 map();
147 }
148 ///ystem.err.println(this + ".getChildCount() = " + children.size());
149 if(children != null) {
150 size = children.size();
151 }
152 return size;
153 }
154
155 public File getFile() {
156 return file;
157 }
158
159 /** Retrieve the icon the system thinks should be assigned to this node. If this node has no file then the icon will be null. */
160 public ImageIcon getIcon() {
161 ImageIcon icon = null; // Default icon according to tree...
162 if(file != null) {
163 Icon raw_icon = FileSystemView.getFileSystemView().getSystemIcon(file);
164 icon = new ImageIcon(raw_icon);
165 }
166 return icon;
167 }
168
169 /** Returns the index of node in the receivers children. */
170 public int getIndex(TreeNode node) {
171 map();
172 return children.indexOf(node);
173 }
174
175 /** Returns the parent TreeNode of the receiver. */
176 public TreeNode getParent() {
177 return parent;
178 }
179
180 /** Retrieves the tree path from the root node to this node. */
181 public TreeNode[] getPath() {
182 int count = 0;
183 TreeNode current = this;
184 while(current != null) {
185 count++;
186 current = current.getParent();
187 }
188 TreeNode[] path = new TreeNode[count];
189 current = this;
190 while(current != null) {
191 path[count - 1] = current;
192 count--;
193 current = current.getParent();
194 }
195 return path;
196 }
197
198 public void insert(MutableTreeNode child) {
199 insert(child, children.size());
200 }
201
202 /** Adds child to the receiver at index. */
203 public void insert(MutableTreeNode child, int index) {
204 ///ystem.err.println("Insert " + child + " in " + this + " at index " + index);
205 //map();
206 try {
207 children.add(index, child);
208 // Set parent and model.
209 FileNode new_child = (FileNode) child;
210 new_child.setModel(model);
211 new_child.setParent(this);
212 new_child.setReadOnly(readonly);
213 }
214 catch(Exception error) {
215 error.printStackTrace();
216 }
217 }
218
219 /** Returns true if the receiver is a leaf. */
220 public boolean isLeaf() {
221 return !getAllowsChildren();
222 }
223
224 public boolean isReadOnly() {
225 return readonly;
226 }
227
228 public boolean isFileSystemRoot() {
229 boolean result = false;
230 if(file != null) {
231 result = FileSystemView.getFileSystemView().isFileSystemRoot(file);
232 }
233 return result;
234 }
235
236 public void map() {
237 // Only map if there are no children.
238 if(children == null && file != null && getAllowsChildren()) {
239 ///ystem.err.println("Map: " + this);
240 children = new ArrayList();
241 File[] files = file.listFiles();
242 if(files != null && files.length > 0) {
243 ArrayTools tools = new ArrayTools();
244 // Apply the filters set in the model.
245 FileFilter[] filters = model.getFilters();
246 for(int i = 0; filters != null && i < filters.length; i++) {
247 files = tools.filter(files, filters[i].filter, filters[i].exclude);
248 }
249 // Sort the remaining files.
250 tools.sort(files, true);
251 // Now add them to children.
252 for(int i = 0; i < files.length; i++) {
253 FileNode child = new FileNode(files[i], model, children_readonly);
254 child.setParent(this);
255 children.add(child);
256 }
257 }
258 model.nodeStructureChanged(this);
259 }
260 else {
261 ///ystem.err.println("Can't map: " + this + ". No file or doesn't allow children.");
262 }
263 }
264
265 /** Removes the child at index from the receiver. */
266 public void remove(int index) {
267 if(0 <= index && index < children.size()) {
268 children.remove(index);
269 }
270 }
271
272 /** Removes node from the receiver. */
273 public void remove(MutableTreeNode node){
274 int index = getIndex(node);
275 if(index != -1) {
276 children.remove(index);
277 }
278 }
279
280 /** Removes the receiver from its parent. */
281 public void removeFromParent() {
282 parent.remove(this);
283 parent = null;
284 }
285
286 public void setChildrenReadOnly(boolean children_readonly) {
287 this.children_readonly = children_readonly;
288 }
289
290 public void setFile(File file) {
291 this.file = file;
292 }
293
294 public void setModel(FileSystemModel model) {
295 this.model = model;
296 }
297
298 public void setParent(MutableTreeNode parent) {
299 this.parent = parent;
300 }
301
302 public void setReadOnly(boolean readonly) {
303 this.readonly = readonly;
304 }
305
306 /** Resets the user object of the receiver to object. */
307 public void setUserObject(Object object) {
308 try {
309 file = (File) object;
310 title = null;
311 }
312 catch(Exception error) {
313 error.printStackTrace();
314 }
315 }
316
317 public String toString() {
318 if(title == null) {
319 if(isFileSystemRoot()) {
320 title = file.getAbsolutePath();
321 }
322 else {
323 title = file.getName();
324 }
325 }
326 return title;
327 }
328
329 /** Unmap this nodes children. */
330 public void unmap() {
331 // You cannot unmap nodes that have no file basis.
332 if(file != null) {
333 ///ystem.err.println("Unmap: " + this);
334 children = null;
335 }
336 else {
337 ///ystem.err.println("No file for " + this + " - can't unmap.");
338 }
339 }
340
341 private class FileEnumeration
342 implements Enumeration {
343 private int index = 0;
344 /** Tests if this enumeration contains more elements. */
345 public boolean hasMoreElements() {
346 return (index < children.size());
347 }
348 /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
349 public Object nextElement() {
350 Object result = null;
351 if(index < children.size()) {
352 result = children.get(index);
353 index++;
354 }
355 return result;
356 }
357 }
358}
Note: See TracBrowser for help on using the repository browser.