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

Last change on this file since 7491 was 7491, checked in by mdewsnip, 20 years ago

Even more improvements to the workspace and collection trees. These are now hugely improved -- with refreshing being much quicker and much more reliable.

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