001/* ---------------------------------------------------------------------------- 002 The Kiwi Toolkit - A Java Class Library 003 Copyright (C) 1998-2004 Mark A. Lindner 004 005 This library is free software; you can redistribute it and/or 006 modify it under the terms of the GNU General Public License as 007 published by the Free Software Foundation; either version 2 of the 008 License, or (at your option) any later version. 009 010 This library is distributed in the hope that it will be useful, 011 but WITHOUT ANY WARRANTY; without even the implied warranty of 012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 General Public License for more details. 014 015 You should have received a copy of the GNU General Public License 016 along with this library; if not, write to the Free Software 017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 02111-1307, USA. 019 020 The author may be contacted at: mark_a_lindner@yahoo.com 021 ---------------------------------------------------------------------------- 022 $Log: FilesystemDataSource.java,v $ 023 Revision 1.7 2004/05/31 07:30:26 markl 024 Final cleanup and bugfixes of kiwi.ui.model. 025 026 Revision 1.6 2004/03/23 06:50:13 markl 027 I18N, modified to use KTreeTable, added support for multiple roots 028 029 Revision 1.5 2003/01/19 09:33:06 markl 030 Javadoc & comment header updates. 031 032 Revision 1.4 2001/03/12 04:11:42 markl 033 Source code cleanup. 034 035 Revision 1.3 1999/07/05 08:07:04 markl 036 Bug fix. 037 038 Revision 1.2 1999/01/10 03:12:19 markl 039 added GPL header & RCS tag 040 ---------------------------------------------------------------------------- 041*/ 042 043package kiwi.ui.model; 044 045import java.awt.Image; 046import java.io.File; 047import java.text.SimpleDateFormat; 048import java.util.*; 049import javax.swing.Icon; 050 051import kiwi.util.*; 052 053/** This class is an implementation of <code>HierarchicalDataSource</code> 054 * wherein tree nodes represent files in the local filesystem. The 055 * <code>ignoreFiles</code> argument of some forms of the constructor allows 056 * for the creation of directory-only data sources. These are useful for 057 * driving a directory chooser, for example. 058 * 059 * @see java.io.File 060 * 061 * @author Mark Lindner 062 */ 063 064public class FilesystemDataSource implements TreeDataSource 065 { 066 private FileRoot root; 067 private Date date = new Date(); 068 private static final Icon FOLDER_OPEN_ICON = KiwiUtils.getResourceManager() 069 .getIcon("folder-open.gif"); 070 private static final Icon FOLDER_CLOSED_ICON = KiwiUtils.getResourceManager() 071 .getIcon("folder-closed.gif"); 072 private static final Icon FOLDER_LOCKED_ICON = KiwiUtils.getResourceManager() 073 .getIcon("folder-locked.gif"); 074 private static final Icon DOCUMENT_ICON = KiwiUtils.getResourceManager() 075 .getIcon("document.gif"); 076 private static final Icon COMPUTER_ICON = KiwiUtils.getResourceManager() 077 .getIcon("computer.gif"); 078 private boolean ignoreFiles = false; 079 private static final String columns[]; 080 private LocaleManager lm; 081 private static final String[] emptyList = new String[0]; 082 private static final String FILE_COLUMN, SIZE_COLUMN, DATE_COLUMN, 083 TIME_COLUMN; 084 private static final Class types[] = new Class[] { String.class, 085 String.class, 086 String.class, 087 String.class }; 088 private static final String ALL_FILESYSTEMS; 089 090 /* 091 */ 092 093 static 094 { 095 LocaleManager lm = LocaleManager.getDefault(); 096 LocaleData loc = lm.getLocaleData("KiwiMisc"); 097 098 FILE_COLUMN = loc.getMessage("kiwi.column.file"); 099 SIZE_COLUMN = loc.getMessage("kiwi.column.size"); 100 DATE_COLUMN = loc.getMessage("kiwi.column.date"); 101 TIME_COLUMN = loc.getMessage("kiwi.column.time"); 102 ALL_FILESYSTEMS = loc.getMessage("kiwi.label.all_filesystems"); 103 104 columns = new String[] { FILE_COLUMN, SIZE_COLUMN, DATE_COLUMN, 105 TIME_COLUMN }; 106 107 } 108 109 /** Construct a new <code>FilesystemDataSource</code> with roots 110 * for all available filesystems. 111 * 112 * @since Kiwi 2.0 113 */ 114 115 public FilesystemDataSource() 116 { 117 _init(new FileRoot(), false); 118 } 119 120 /** Construct a new <code>FilesystemDataSource</code> wiht the given roots. 121 * 122 * @param roots The filesystem roots for this datasource. 123 * @since Kiwi 2.0 124 */ 125 126 public FilesystemDataSource(File roots[]) 127 { 128 _init(new FileRoot(roots), false); 129 } 130 131 /** Construct a new <code>FilesystemDataSource</code> with roots 132 * for all available filesystems. 133 * 134 * @param ignoreFiles A flag specifying whether ordinary files 135 * (non-directories) should be ignored or displayed. 136 */ 137 138 public FilesystemDataSource(boolean ignoreFiles) 139 { 140 _init(new FileRoot(), ignoreFiles); 141 } 142 143 /** Construct a new <code>FilesystemDataSource</code>. 144 * 145 * @param root The root directory. 146 * @param ignoreFiles A flag specifying whether ordinary files 147 * (non-directories) should be ignored or displayed. 148 * 149 * @exception java.lang.IllegalArgumentException if <code>root</code> is not 150 * a directory. 151 */ 152 153 public FilesystemDataSource(File root, boolean ignoreFiles) 154 { 155 if(root != null && !root.isDirectory()) 156 throw(new IllegalArgumentException("Root must be a directory!")); 157 158 _init(new FileRoot(root), ignoreFiles); 159 } 160 161 /** Construct a new <code>FilesystemDataSource</code>. 162 * 163 * @param roots The root directories. 164 * @param ignoreFiles A flag specifying whether ordinary files 165 * (non-directories) should be ignored or displayed. 166 * 167 * @exception java.lang.IllegalArgumentException if <code>root</code> is not 168 * a directory. 169 * 170 * @since Kiwi 2.0 171 */ 172 173 public FilesystemDataSource(File roots[], boolean ignoreFiles) 174 { 175 for(int i = 0; i < roots.length; i++) 176 if(!roots[i].isDirectory()) 177 throw(new IllegalArgumentException("Roots must be directories!")); 178 179 _init(new FileRoot(roots), ignoreFiles); 180 } 181 182 /* 183 */ 184 185 private void _init(FileRoot root, boolean ignoreFiles) 186 { 187 this.ignoreFiles = ignoreFiles; 188 this.root = root; 189 190 lm = LocaleManager.getDefault(); 191 } 192 193 /** Get the root object. 194 * 195 * @return The <code>FileRoot</code> "virtual root" object which is 196 * the parent of the root files with which this data source was 197 * created. 198 */ 199 200 public Object getRoot() 201 { 202 return(root); 203 } 204 205 /** Get the children of a given node. */ 206 207 public Object[] getChildren(Object node) 208 { 209 System.out.println("In FilesystemDataSource.getChildren()"); 210 211 if(node.getClass() == FileRoot.class) 212 return(((FileRoot)node).getRoots()); 213 214 File f = (File)node; 215 String[] children = emptyList; 216 217 try { children = f.list(); } catch(Exception e) { } 218 219 Arrays.sort(children); 220 221 return(makeNodes(f, children)); 222 } 223 224 /* create an array of Files from an array of filenames */ 225 226 private File[] makeNodes(File parent, String[] list) 227 { 228 File f; 229 Vector v = new Vector(); 230 231 for(int i = 0; i < list.length; i++) 232 { 233 if(parent == null) 234 f = new File(list[i]); 235 else 236 f = new File(parent, list[i]); 237 238 if(ignoreFiles && !f.isDirectory()) 239 continue; 240 v.addElement(f); 241 } 242 243 File nodes[] = new File[v.size()]; 244 v.copyInto(nodes); 245 return(nodes); 246 } 247 248 /* 249 */ 250 251 public String getLabel(Object node) 252 { 253 if(node.getClass() == FileRoot.class) 254 return(ALL_FILESYSTEMS); 255 256 File f = (File)node; 257 if(root.isRoot(f)) 258 return(f.getPath()); 259 else 260 return(f.getName()); 261 } 262 263 /* 264 */ 265 266 public Icon getIcon(Object node, boolean isExpanded) 267 { 268 if(node.getClass() == FileRoot.class) 269 return(COMPUTER_ICON); 270 271 File f = (File)node; 272 273 if(f.isDirectory()) 274 { 275 if(! f.canRead()) 276 return(FOLDER_LOCKED_ICON); 277 278 return(isExpanded ? FOLDER_OPEN_ICON : FOLDER_CLOSED_ICON); 279 } 280 else 281 return(DOCUMENT_ICON); 282 } 283 284 /* 285 */ 286 287 public boolean isExpandable(Object node) 288 { 289 if(node.getClass() == FileRoot.class) 290 return(true); 291 292 File f = (File)node; 293 294 return(f.isDirectory() && f.canRead()); 295 } 296 297 /** Get the value for a given property. */ 298 299 public Object getValueForProperty(Object node, String property) 300 { 301 if(node == null) 302 { 303 if(property.equals(COLUMN_NAMES_PROPERTY)) 304 return(columns); 305 else if(property.equals(COLUMN_TYPES_PROPERTY)) 306 return(types); 307 else 308 return(null); 309 } 310 311 if(! (node instanceof File)) 312 return(null); 313 314 File f = (File)node; 315 316 if(property.equals(FILE_COLUMN)) 317 return(f); 318 319 else if(property.equals(SIZE_COLUMN)) 320 { 321 long len = f.length(); 322 323 len = (len + 1023) / 1024; 324 if(len < 1024) 325 return(lm.formatInteger(len, true) + " Kb"); 326 327 len = (len + 1023) / 1024; 328 return(lm.formatInteger(len, true) + " Mb"); 329 } 330 331 else if(property.equals(DATE_COLUMN)) 332 { 333 date.setTime(f.lastModified()); 334 return(lm.formatDate(date, lm.MEDIUM)); 335 } 336 337 else if(property.equals(TIME_COLUMN)) 338 { 339 date.setTime(f.lastModified()); 340 return(lm.formatTime(date, lm.SHORT)); 341 } 342 343 else 344 return(null); 345 } 346 347 /** A virtual filesystem root. This object encapsulates the 348 * collection of filesystem roots. (Some platforms, namely Windows, have 349 * more than one root directory in the filesystem.) 350 */ 351 352 public final class FileRoot 353 { 354 File roots[]; 355 356 FileRoot() 357 { 358 roots = File.listRoots(); 359 } 360 361 FileRoot(File roots[]) 362 { 363 this.roots = roots; 364 } 365 366 FileRoot(File root) 367 { 368 if(root != null) 369 { 370 roots = new File[1]; 371 roots[0] = root; 372 } 373 else 374 roots = File.listRoots(); 375 } 376 377 public boolean isRoot(File file) 378 { 379 for(int i = 0; i < roots.length; i++) 380 { 381 if(roots[i] == file) 382 return(true); 383 } 384 385 return(false); 386 } 387 388 /** Get the list of roots. */ 389 390 public File[] getRoots() 391 { 392 return(roots); 393 } 394 395 /** Get the string representation of this object. 396 * 397 * @return The empty string. 398 */ 399 400 public String toString() 401 { 402 return(""); 403 } 404 } 405 406 } 407 408/* end of source file */