001: package net.suberic.pooka.gui.filechooser;
002:
003: import javax.swing.*;
004: import java.io.*;
005: import net.suberic.pooka.Pooka;
006: import net.suberic.pooka.StoreInfo;
007: import net.suberic.pooka.FolderInfo;
008: import java.util.Vector;
009:
010: /**
011: * This class implements a FileSystemView based on the available Folders in
012: * a the Pooka StoreInfo hierarchy.
013: */
014:
015: public class PookaFileSystemView extends
016: javax.swing.filechooser.FileSystemView {
017:
018: StoreInfo[] storeList;
019: FolderInfoFileWrapper[] roots = null;
020:
021: /**
022: * This creates a new PookaFileSystemView at the top of the Store list;
023: * all available Stores will be listed, with their folders under them.
024: */
025: public PookaFileSystemView() {
026: Vector v = Pooka.getStoreManager().getStoreList();
027:
028: storeList = new StoreInfo[v.size()];
029: for (int i = 0; i < v.size(); i++) {
030: storeList[i] = (StoreInfo) v.elementAt(i);
031: }
032:
033: getRoots();
034: }
035:
036: /**
037: * This creates a PookaFileSystemView out of a Store object.
038: */
039: public PookaFileSystemView(StoreInfo newStore) {
040: storeList = new StoreInfo[] { newStore };
041: getLogger().info(
042: "creating new PookaFileSystemView for store "
043: + newStore.getStoreID());
044:
045: getRoots();
046: }
047:
048: /**
049: * This creates a new Folder and FolderInfoFileWrapper in the Folder
050: * corresponding to the directory dir with the name filename.
051: *
052: * @dir a FolderInfoFileWrapper representing either a FolderInfo or
053: * a StoreInfo
054: * @filename a string representing a FolderInfo name.
055: */
056: public File createFileObject(File dir, String filename) {
057: if (dir != null)
058: getLogger().info(
059: "calling createFileObject on directory "
060: + dir.getName() + " (" + dir.getPath()
061: + "), filename " + filename);
062: else
063: getLogger().info(
064: "calling createFileObject on directory null, filename "
065: + filename);
066:
067: if (dir != null && dir instanceof FolderInfoFileWrapper)
068: return ((FolderInfoFileWrapper) dir)
069: .getFileByName(filename);
070: else
071: return null;
072: }
073:
074: /**
075: * @filename is an IMAP folder name.
076: */
077: public File createFileObject(String filename) {
078:
079: // todo jph: strip off any leading directoy separators. we
080: // want to call getFileByName with a relative path (in this case
081: // to the root directory) always.
082:
083: getLogger().info(
084: "running createFileObject2 on filename '" + filename
085: + "'");
086:
087: if (roots == null || roots.length == 0) {
088: getLogger().info("root == null");
089: return null;
090: }
091:
092: getLogger().info("root != null");
093:
094: if (filename.equals("/") || filename.equals("")) {
095: return roots[0];
096: }
097:
098: int firstSlash = filename.indexOf('/');
099: String storeName = null;
100: String filePart = "";
101: if (firstSlash > -1) {
102: storeName = filename.substring(0, firstSlash);
103: getLogger().info("store name is " + storeName);
104: if (firstSlash < filename.length()) {
105: filePart = filename.substring(firstSlash + 1);
106: getLogger().info("file name is " + filePart);
107: }
108: } else {
109: getLogger().info("store name is " + filename);
110:
111: storeName = filename;
112: }
113:
114: getLogger().info(
115: "store name is " + filename + ", file name is "
116: + filePart);
117:
118: FolderInfoFileWrapper currentRoot = findRoot(storeName);
119: if (currentRoot == null) {
120: getLogger().info(
121: "found no matching store root for " + storeName
122: + ".");
123: return new File(filename);
124: }
125:
126: File returnValue = currentRoot.getFileByName(filePart);
127:
128: getLogger().info(
129: "returning " + returnValue + " for " + currentRoot
130: + ".getFileByName(\"" + filePart + "\")");
131:
132: return returnValue;
133:
134: }
135:
136: /**
137: * Creates a new File object for f with correct behavior for a file system
138: * root directory.
139: */
140: /*
141: protected File createFileSystemRoot(File f) {
142:
143: }
144: */
145:
146: /**
147: * Creates a new Folder under the containingDir.
148: */
149: public File createNewFolder(File containingDir)
150: throws java.io.IOException {
151: throw new IOException(
152: Pooka
153: .getProperty(
154: "error.folderinfofilewrapper.cantcreate",
155: "Cannot create new Folders here. Use Subscribe instead."));
156:
157: }
158:
159: /**
160: * Gets the child for the file.
161: */
162: public File getChild(File parent, String filename) {
163: if (parent instanceof FolderInfoFileWrapper) {
164: return ((FolderInfoFileWrapper) parent)
165: .getChildFile(filename);
166: } else {
167: return new File(parent, filename);
168: }
169: }
170:
171: /**
172: * Gets the default starting directory for the file chooser.
173: */
174: public File getDefaultDirectory() {
175: getLogger().info("calling getDefaultDirectory()");
176:
177: return getDefaultRoot();
178: }
179:
180: /**
181: * Returns all of the files under a particular directory.
182: */
183: public File[] getFiles(File dir, boolean useFileHiding) {
184: getLogger().info(
185: "running getFiles " + dir + ", " + useFileHiding + ".");
186:
187: if (dir instanceof FolderInfoFileWrapper) {
188: getLogger().info("getFiles: returning dir.listFiles()");
189: return ((FolderInfoFileWrapper) dir).listFiles();
190: } else {
191: getLogger().info("getFiles: dir isn't a FFW.");
192: if (dir == null) {
193: getLogger().info(
194: "getFiles: dir is null; returning null.");
195: return null; // FIXME: or set dir to root?
196: }
197:
198: // FIXME: ugly?
199:
200: getLogger().info("getFiles: just returning the root.");
201:
202: File f = ((FolderInfoFileWrapper) getDefaultRoot())
203: .getFileByName(dir.getAbsolutePath());
204:
205: if (f == null) {
206: getLogger()
207: .info(
208: "getFiles: tried returning the root, but got null. returning the root itself instead.");
209: return new FolderInfoFileWrapper[0];
210: }
211:
212: getLogger().info(
213: "getFiles: returning " + f
214: + ".listFiles() for getFiles()");
215: return f.listFiles();
216: }
217: }
218:
219: /**
220: * Returns the user's home directory. Kind of a strange thing
221: * on a mail system...
222: */
223: public File getHomeDirectory() {
224: getLogger().info("running getHomeDirectory().");
225:
226: return getDefaultRoot();
227: }
228:
229: /**
230: * Returns the parent directory of the current File.
231: */
232: public File getParentDirectory(File dir) {
233: getLogger().info("running getParentDirectory on " + dir);
234:
235: if (dir == null)
236: return null; // at root
237:
238: if (!(dir instanceof FolderInfoFileWrapper)) {
239: if (roots != null && roots.length > 0) {
240: dir = createFileObject(dir.getPath());
241: } else
242: return null; // FIXME error?
243:
244: }
245: if (dir == null)
246: return null; // at root
247: File returnValue = dir.getParentFile();
248:
249: return dir.getParentFile();
250: }
251:
252: /**
253: * Gets all the roots for this PookaFileSystemView.
254: */
255: public File[] getRoots() {
256: getLogger().info("calling getRoots() on PookaFileSystemView.");
257:
258: if (roots != null) {
259: getLogger().info("root has already been set.");
260: return roots;
261: }
262:
263: getLogger().info(
264: "setting folder f to store.getDefaultFolder().");
265: roots = new FolderInfoFileWrapper[storeList.length];
266: for (int i = 0; i < storeList.length; i++) {
267: roots[i] = new FolderInfoFileWrapper(storeList[i], null,
268: storeList[i].getStoreID());
269: }
270: return roots;
271: }
272:
273: /**
274: * always returns false for now.
275: */
276: public boolean isHiddenFile(File f) {
277: return false;
278: }
279:
280: /**
281: * returns true for all files in the roots array.
282: */
283: public boolean isRoot(File f) {
284: if (f.getParentFile() == null || f.getParentFile() == f)
285: return true;
286: else
287: return false;
288: }
289:
290: /**
291: * Returns true if the directory is traversable.
292: */
293: public Boolean isTraversable(File f) {
294: getLogger().info("pfsv: checking isTraversable on file " + f);
295:
296: if (f != null && f instanceof FolderInfoFileWrapper) {
297: if (((FolderInfoFileWrapper) f).isDirectory())
298: return new Boolean(true);
299: else
300: return new Boolean(false);
301: } else {
302: return new Boolean(false);
303: }
304: }
305:
306: /*
307: * Used by UI classes to decide whether to display a special icon
308: * for drives or partitions, e.g. a "hard disk" icon.
309: *
310: * The default implementation has no way of knowing, so always returns false.
311: *
312: * @param dir a directory
313: * @return <code>false</code> always
314: */
315: public boolean isDrive(File dir) {
316: return false;
317: }
318:
319: /*
320: * Used by UI classes to decide whether to display a special icon
321: * for a floppy disk. Implies isDrive(dir).
322: *
323: * The default implementation has no way of knowing, so always returns false.
324: *
325: * @param dir a directory
326: * @return <code>false</code> always
327: */
328: public boolean isFloppyDrive(File dir) {
329: return false;
330: }
331:
332: /*
333: * Used by UI classes to decide whether to display a special icon
334: * for a computer node, e.g. "My Computer" or a network server.
335: *
336: * The default implementation has no way of knowing, so always returns false.
337: *
338: * @param dir a directory
339: * @return <code>false</code> always
340: */
341: public boolean isComputerNode(File dir) {
342: return false;
343: }
344:
345: /**
346: * On Windows, a file can appear in multiple folders, other than its
347: * parent directory in the filesystem. Folder could for example be the
348: * "Desktop" folder which is not the same as file.getParentFile().
349: *
350: * @param folder a <code>File</code> object repesenting a directory or special folder
351: * @param file a <code>File</code> object
352: * @return <code>true</code> if <code>folder</code> is a directory or special folder and contains <code>file</code>.
353: */
354: public boolean isParent(File folder, File file) {
355: if (folder == null || file == null) {
356: return false;
357: } else {
358: return folder.equals(file.getParentFile());
359: }
360: }
361:
362: /**
363: * Type description for a file, directory, or folder as it would be displayed in
364: * a system file browser. Example from Windows: the "Desktop" folder
365: * is desribed as "Desktop".
366: *
367: * The Windows implementation gets information from the ShellFolder class.
368: */
369: public String getSystemTypeDescription(File f) {
370: if (f != null) {
371: return ("mail folder");
372: } else {
373: return null;
374: }
375: }
376:
377: /**
378: * Name of a file, directory, or folder as it would be displayed in
379: * a system file browser. Example from Windows: the "M:\" directory
380: * displays as "CD-ROM (M:)"
381: *
382: * The default implementation gets information from the ShellFolder class.
383: *
384: * @param f a <code>File</code> object
385: * @return the file name as it would be displayed by a native file chooser
386: * @see JFileChooser#getName
387: */
388: public String getSystemDisplayName(File f) {
389: String name = null;
390: if (f != null) {
391: name = f.getName();
392: }
393: return name;
394: }
395:
396: /**
397: * Icon for a file, directory, or folder as it would be displayed in
398: * a system file browser. Example from Windows: the "M:\" directory
399: * displays a CD-ROM icon.
400: *
401: * The default implementation gets information from the ShellFolder class.
402: *
403: * @param f a <code>File</code> object
404: * @return an icon as it would be displayed by a native file chooser
405: * @see JFileChooser#getIcon
406: */
407: public Icon getSystemIcon(File f) {
408: if (f != null) {
409: return UIManager
410: .getIcon(f.isDirectory() ? "FileView.directoryIcon"
411: : "FileView.fileIcon");
412: } else {
413: return null;
414: }
415: }
416:
417: /* Not inherited. */
418:
419: public File getDefaultRoot() {
420: getLogger().info("running getDefaultRoot().");
421:
422: if (roots == null) {
423: File[] localRoots = getRoots();
424: if (localRoots != null && localRoots.length > 0)
425: return localRoots[0];
426: else
427: return null;
428: }
429:
430: getLogger().info("returning " + roots[0] + " as default root.");
431:
432: return roots[0];
433: }
434:
435: /**
436: * This finds the Root with the given name, if any.
437: */
438: public FolderInfoFileWrapper findRoot(String name) {
439: for (int i = 0; i < roots.length; i++) {
440: if (roots[i].getPath().equals(name))
441: return roots[i];
442: }
443: return null;
444: }
445:
446: /**
447: * Returns the Logger object for this class.
448: */
449: public java.util.logging.Logger getLogger() {
450: return java.util.logging.Logger
451: .getLogger("Pooka.debug.gui.filechooser");
452: }
453: }
|