001: /*
002: * DirectoryTreeModel.java
003: *
004: * Copyright (C) 2000-2003 Peter Graves
005: * $Id: DirectoryTreeModel.java,v 1.3 2003/05/20 00:37:48 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.util.Arrays;
025: import java.util.Comparator;
026: import java.util.Vector;
027: import javax.swing.tree.DefaultMutableTreeNode;
028: import javax.swing.tree.DefaultTreeModel;
029: import javax.swing.tree.TreeNode;
030:
031: public class DirectoryTreeModel extends DefaultTreeModel {
032: private static final boolean ignoreCase = Platform
033: .isPlatformWindows();
034:
035: private static DirectoryTreeModel localTreeModel;
036: private static Vector remoteModels;
037:
038: private File rootFile; // Will be null for local tree.
039:
040: private DirectoryTreeModel(TreeNode root) {
041: super (root);
042: }
043:
044: private DirectoryTreeModel(TreeNode root, File f) {
045: super (root);
046: rootFile = f;
047: }
048:
049: private File getRootFile() {
050: return rootFile;
051: }
052:
053: private static DirectoryTreeModel getLocalDirectoryTreeModel(
054: File file) {
055: if (localTreeModel == null)
056: setLocalRoot(scanRoot(file));
057: return localTreeModel;
058: }
059:
060: public static DirectoryTreeModel getTreeModel(File file) {
061: if (file.isLocal())
062: return getLocalDirectoryTreeModel(file);
063: DirectoryTreeModel model;
064: File rootFile = file.getRoot();
065: if (remoteModels != null) {
066: for (int i = 0; i < remoteModels.size(); i++) {
067: model = (DirectoryTreeModel) remoteModels.get(i);
068: if (rootFile.equals(model.getRootFile()))
069: return model;
070: }
071: }
072: DefaultMutableTreeNode root = new DefaultMutableTreeNode(
073: new DirectoryTreeElement(rootFile));
074: model = new DirectoryTreeModel(root, rootFile);
075: addChildren(rootFile, root);
076: if (remoteModels == null)
077: remoteModels = new Vector();
078: remoteModels.add(model);
079: return model;
080: }
081:
082: private static synchronized void setLocalRoot(
083: DefaultMutableTreeNode root) {
084: if (localTreeModel != null)
085: localTreeModel.setRoot(root);
086: else
087: localTreeModel = new DirectoryTreeModel(root);
088: }
089:
090: public void rescan(File file) {
091: setRoot(scanRoot(file));
092: }
093:
094: private static DefaultMutableTreeNode scanRoot(File file) {
095: DefaultMutableTreeNode root = null;
096: if (Platform.isPlatformWindows()) {
097: File[] roots = File.listRoots();
098: if (roots != null) {
099: root = new DefaultMutableTreeNode("Local");
100: for (int i = 0; i < roots.length; i++) {
101: DefaultMutableTreeNode child = new DefaultMutableTreeNode(
102: new DirectoryTreeElement(roots[i]));
103: root.insert(child, root.getChildCount());
104: if (roots[i].equals(file.getRoot()))
105: addChildren(roots[i], child);
106: }
107: } else {
108: root = new DefaultMutableTreeNode(
109: new DirectoryTreeElement(file.getRoot()));
110: addChildren(file.getRoot(), root);
111: }
112: } else {
113: // Unix.
114: File f = file.getRoot();
115: root = new DefaultMutableTreeNode(new DirectoryTreeElement(
116: file.getRoot()));
117: addChildren(f, root);
118: }
119: return root;
120: }
121:
122: private static void addChildren(File parent,
123: DefaultMutableTreeNode node) {
124: File[] list = parent.listFiles();
125: if (list == null)
126: return;
127: Arrays.sort(list, ignoreCase ? ciFileNameComparator
128: : csFileNameComparator);
129: for (int i = 0; i < list.length; i++) {
130: File f = list[i];
131: if (f.isDirectory() && !f.isLink()) {
132: DefaultMutableTreeNode child = new DefaultMutableTreeNode(
133: new DirectoryTreeElement(f));
134: node.insert(child, node.getChildCount());
135: }
136: }
137: }
138:
139: public DefaultMutableTreeNode getNode(File file) {
140: return getNode((DefaultMutableTreeNode) getRoot(), file);
141: }
142:
143: private static DefaultMutableTreeNode getNode(
144: DefaultMutableTreeNode root, File file) {
145: if (root == null || file == null)
146: return null;
147: DefaultMutableTreeNode currentNode = root;
148: while (true) {
149: DefaultMutableTreeNode node = findMatchingChild(
150: currentNode, file);
151: if (node == null)
152: return null;
153: DirectoryTreeElement treeElement = (DirectoryTreeElement) node
154: .getUserObject();
155: File f = treeElement.getFile();
156: expandNode(node, f);
157: if (file.canonicalPath().equals(f.canonicalPath()))
158: return node;
159: currentNode = node;
160: }
161: }
162:
163: // Find child that is ancestor of file (so to speak).
164: private static DefaultMutableTreeNode findMatchingChild(
165: DefaultMutableTreeNode parent, File file) {
166: if (file != null) {
167: for (int i = 0; i < parent.getChildCount(); i++) {
168: DefaultMutableTreeNode node = (DefaultMutableTreeNode) parent
169: .getChildAt(i);
170: DirectoryTreeElement treeElement = (DirectoryTreeElement) node
171: .getUserObject();
172: File f = treeElement.getFile();
173: if (file.canonicalPath().equals(f.canonicalPath()))
174: return node;
175: String prefix = f.canonicalPath();
176: if (!prefix.endsWith(f.getSeparator()))
177: prefix += f.getSeparator();
178: if (file.canonicalPath().startsWith(prefix))
179: return node;
180: }
181: }
182: return null;
183: }
184:
185: public static void expandNode(DefaultMutableTreeNode node, File file) {
186: if (node.getChildCount() == 0) {
187: File[] list = file.listFiles();
188: if (list == null)
189: return;
190: Arrays.sort(list, ignoreCase ? ciFileNameComparator
191: : csFileNameComparator);
192: for (int i = 0; i < list.length; i++) {
193: File f = list[i];
194: if (f.isLink())
195: continue;
196: else if (f.isDirectory()) {
197: DefaultMutableTreeNode child = new DefaultMutableTreeNode(
198: new DirectoryTreeElement(f));
199: node.insert(child, node.getChildCount());
200: }
201: }
202: }
203: }
204:
205: // Case-sensitive filename comparator (Unix).
206: private final static Comparator csFileNameComparator = new Comparator() {
207: public int compare(Object o1, Object o2) {
208: String name1 = ((File) o1).getName();
209: String name2 = ((File) o2).getName();
210: return name1.compareTo(name2);
211: }
212: };
213:
214: // Case-insensitive filename comparator (Windows).
215: private final static Comparator ciFileNameComparator = new Comparator() {
216: public int compare(Object o1, Object o2) {
217: String name1 = ((File) o1).getName();
218: String name2 = ((File) o2).getName();
219: return name1.compareToIgnoreCase(name2);
220: }
221: };
222: }
|