source: trunk/gli/src/org/greenstone/gatherer/file/FileSystemModel.java@ 11083

Last change on this file since 11083 was 11083, checked in by mdewsnip, 18 years ago

Some tidy ups so that the file nodes are always refreshed correctly when expanding.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1package org.greenstone.gatherer.file;
2
3import java.io.File;
4import java.util.*;
5import java.util.regex.*;
6import javax.swing.event.*;
7import javax.swing.tree.*;
8import org.greenstone.gatherer.DebugStream;
9import org.greenstone.gatherer.Gatherer;
10import org.greenstone.gatherer.gui.tree.DragTree;
11import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
12
13public class FileSystemModel
14 extends DefaultTreeModel
15 implements TreeExpansionListener, TreeWillExpandListener
16{
17 private DragTree tree = null;
18 private FileFilter current_filter = null;
19 private FileFilter[] filters = null;
20 /** The filters in place for any file system model. */
21 private FileFilter[] default_filters = { new FileFilter("\\..*", true), new FileFilter("metadata\\.xml", true) };
22
23 public FileSystemModel(FileNode root) {
24 super(root);
25 root.setModel(this);
26 root.refresh();
27 }
28
29 public int getChildCount(Object parent) {
30 return ((TreeNode)parent).getChildCount();
31 }
32
33 public FileFilter[] getFilters() {
34 if(filters == null) {
35 if(current_filter != null) {
36 filters = new FileFilter[default_filters.length + 1];
37 filters[default_filters.length] = current_filter;
38 }
39 else {
40 filters = new FileFilter[default_filters.length];
41 }
42 System.arraycopy(default_filters, 0, filters, 0, default_filters.length);
43 }
44 return filters;
45 }
46
47 /** Retrieve the node denoted by the given tree path. Note that this isn't equivelent to saying path.lastPathComponent, as the references within the path may be stale. */
48 public FileNode getNode(TreePath path) {
49 FileNode last = (FileNode)path.getLastPathComponent();
50 DebugStream.println("Last Path Component = " + last);
51 return last;
52 /*
53 ///atherer.println("**** getNode(" + path + ") ****");
54 FileNode current = (FileNode)root;
55 // Special case for the root node. Check the first path component is the root node.
56 FileNode first_node = (FileNode)path.getPathComponent(0);
57 if(current.equals(first_node)) {
58 DebugStream.println("First path component matches root node.");
59 // For each path with this tree path
60 for(int i = 1; current != null && i < path.getPathCount(); i++) {
61 // Retrieve the stale path
62 Object stale_object = path.getPathComponent(i);
63 FileNode stale_node = null;
64 if(stale_object instanceof FileNode) {
65 stale_node = (FileNode) stale_object;
66 }
67 DebugStream.print("Searching for '" + stale_object + "': ");
68 // Locate the fresh node by searching current's children. Remember to ensure that current is mapped.
69 boolean found = false;
70
71 // First we search through the mapped children
72 for(int j = 0; !found && j < current.getChildCount(); j++) {
73 FileNode child_node = (FileNode) current.getChildAt(j);
74 DebugStream.print(child_node + " ");
75 if((stale_node != null && stale_node.equals(child_node)) || stale_object.toString().equals(child_node.toString())) {
76 found = true;
77 current = child_node;
78 DebugStream.println("Found!");
79 }
80 child_node = null;
81 }
82 // Failing that we search through all the children, including filtered files
83 for(int j = 0; !found && j < current.size(); j++) {
84 FileNode child_node = (FileNode) current.getChildAtUnfiltered(j);
85 DebugStream.print(child_node + " ");
86 if((stale_node != null && stale_node.equals(child_node)) || stale_object.toString().equals(child_node.toString())) {
87 found = true;
88 current = child_node;
89 DebugStream.println("Found!");
90 }
91 child_node = null;
92 }
93 // If no match is found, then set current to null and exit.
94 if(!found) {
95 current = null;
96 DebugStream.println("Not Found!");
97 }
98 else {
99 DebugStream.println("Returning node: " + new TreePath(current.getPath()));
100 }
101 // Repeat as necessary
102 }
103 }
104 return current;
105 */
106 }
107
108 public void insertNodeInto(MutableTreeNode newChild, MutableTreeNode parent, int index) {
109 ///ystem.err.println("insertNodeInto(" + newChild + ", " + parent + ", " + index + ")");
110 super.insertNodeInto(newChild, parent, index);
111 }
112
113
114 public void refresh(TreePath path)
115 {
116 // Can only refresh if the model is currently being displayed in a tree
117 if (tree == null) {
118 return;
119 }
120
121 // If no path is set, take the path to the root node (ie. update the whole tree)
122 if (path == null) {
123 // System.err.println("\nFileSystemModel.refresh(entire tree).");
124 path = new TreePath(((FileNode) root).getPath());
125
126 // Make sure the root node is expanded
127 tree.expandPath(path);
128 }
129 // else {
130 // System.err.println("\nFileSystemModel.refresh(" + path + ").");
131 // }
132
133 // Record all the expanded paths under this node
134 Enumeration old_expanded_paths_enumeration = tree.getExpandedDescendants(path);
135 if (old_expanded_paths_enumeration == null) {
136 return;
137 }
138
139 // Map and unmap the node to refresh its contents
140 FileNode node = (FileNode) path.getLastPathComponent();
141 node.refresh();
142
143 // Fire the appropriate event
144 nodeStructureChanged(node);
145
146 // Sort the old expanded paths by length, smallest first
147 ArrayList old_expanded_paths_list = Collections.list(old_expanded_paths_enumeration);
148 Collections.sort(old_expanded_paths_list, new TreePathComparator());
149
150 // Restore each of the expanded paths
151 for (int i = 0; i < old_expanded_paths_list.size(); i++) {
152 TreePath old_expanded_path = (TreePath) old_expanded_paths_list.get(i);
153 // System.err.println("Expanded path: " + old_expanded_path);
154
155 // Build up the new path in the tree
156 TreePath current_path = new TreePath(path.getPath());
157 FileNode current_node = node;
158
159 // Traverse the tree to find the node to expand (or find it no longer exists)
160 while (!current_path.toString().equals(old_expanded_path.toString())) {
161 // System.err.println("Current path: " + current_path);
162
163 FileNode old_expanded_node =
164 (FileNode) old_expanded_path.getPathComponent(current_path.getPathCount());
165 // System.err.println("Looking for: " + old_expanded_node);
166
167 // Find the child node that matches the next element in the path
168 boolean found = false;
169 for (int j = 0; j < current_node.getChildCount(); j++) {
170 FileNode child_node = (FileNode) current_node.getChildAt(j);
171 // System.err.println("Child node: " + child_node);
172 if (child_node.equals(old_expanded_node)) {
173 // System.err.println("Found!");
174 current_path = current_path.pathByAddingChild(child_node);
175 current_node = child_node;
176 found = true;
177 break;
178 }
179 }
180
181 // The node was not found, so we cannot expand this path
182 if (!found) {
183 // System.err.println("Not found...");
184 break;
185 }
186 }
187
188 // If we have built up the correct path, expand it
189 if (current_path.toString().equals(old_expanded_path.toString())) {
190 tree.expandPath(current_path);
191 }
192 }
193 }
194
195
196 // The file tree can be filtered, so check that the node to be removed is actually part of the model
197 public void removeNodeFromParent(MutableTreeNode node)
198 {
199 TreeNode parent_node = ((FileNode) node).getParent();
200 if (parent_node != null && parent_node.getIndex((FileNode) node) != -1) {
201 super.removeNodeFromParent(node);
202 }
203 }
204
205
206 private class TreePathComparator
207 implements Comparator {
208
209 public int compare(Object o1, Object o2)
210 {
211 return (((TreePath) o1).getPathCount() - ((TreePath) o2).getPathCount());
212 }
213 }
214
215
216 public void setFilter(String pattern) {
217 if(pattern != null) {
218 current_filter = new FileFilter(pattern, false);
219 }
220 else {
221 current_filter = null;
222 }
223 filters = null;
224 }
225
226 public void setTree(DragTree tree) {
227 this.tree = tree;
228 }
229
230 public String toString() {
231 if(tree != null) {
232 return tree.toString();
233 }
234 return "FileSystemModel";
235 }
236
237 /** Called whenever an item in the tree has been collapsed. */
238 public void treeCollapsed(TreeExpansionEvent event) {
239 // Deallocate the affected nodes children. Don't need to do this in a swing worker, as the nodes children are currently not visable.
240 TreePath path = event.getPath();
241 FileNode node = (FileNode) path.getLastPathComponent();
242 node.unmap();
243 // Fire the appropriate event.
244 nodeStructureChanged(node);
245 }
246
247 /** Called whenever an item in the tree has been expanded. */
248 public void treeExpanded(TreeExpansionEvent event) {
249 }
250
251 /** Invoked whenever a node in the tree is about to be collapsed. */
252 public void treeWillCollapse(TreeExpansionEvent event)
253 throws ExpandVetoException {
254 // Veto the event if the user is attempting to collapse the root node (regardless of whether it is visible).
255 TreePath path = event.getPath();
256 if(path.getPathCount() == 1) {
257 throw new ExpandVetoException(event, "Cannot collapse root node!");
258 }
259 }
260
261
262 /** Invoked whenever a node in the tree is about to be expanded. */
263 public void treeWillExpand(TreeExpansionEvent event)
264 throws ExpandVetoException
265 {
266 // Set the wait cursor
267 Gatherer.g_man.wait(true);
268
269 // Allocate the children (don't need a swing worker since the node's children are currently not visible)
270 TreePath path = event.getPath();
271 FileNode node = (FileNode) path.getLastPathComponent();
272 node.refresh();
273 nodeStructureChanged(node);
274
275 // Restore the cursor
276 Gatherer.g_man.wait(false);
277 }
278}
Note: See TracBrowser for help on using the repository browser.