001 /* 002 * $Id: FileSystemModel.java 2713 2008-02-15 15:08:23Z kleopatra $ 003 * 004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library 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 GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021 022 package org.jdesktop.swingx.treetable; 023 024 import java.io.File; 025 import java.util.Arrays; 026 import java.util.Date; 027 028 /** 029 * A tree table model to simulate a file system. 030 * <p> 031 * This tree table model implementation extends {@code AbstractTreeTableModel}. 032 * The file system metaphor demonstrates that it is often easier to directly 033 * implement tree structures directly instead of using intermediaries, such as 034 * {@code TreeTableNode}. 035 * <p> 036 * A comparison of this class with {@code SimpleFileSystemModel}, shows that 037 * extending {@code AbstractTreeTableModel} is often easier than creating a model 038 * from scratch. 039 * <p> 040 * A "full" version of this model might allow editing of file names, the 041 * deletion of files, and the movement of files. This simple implementation does 042 * not intend to tackle such problems, but this implementation may be extended 043 * to handle such details. 044 * 045 * @author Ramesh Gupta 046 * @author Karl Schaefer 047 */ 048 public class FileSystemModel extends AbstractTreeTableModel { 049 // The the returned file length for directories. 050 private static final Long DIRECTORY = 0L; 051 052 /** 053 * Creates a file system model using the root directory as the model root. 054 */ 055 public FileSystemModel() { 056 this(new File(File.separator)); 057 } 058 059 /** 060 * Creates a file system model using the specified {@code root}. 061 * 062 * @param root 063 * the root for this model; this may be different than the root 064 * directory for a file system. 065 */ 066 public FileSystemModel(File root) { 067 super(root); 068 } 069 070 private boolean isValidFileNode(Object file) { 071 boolean result = false; 072 073 if (file instanceof File) { 074 File f = (File) file; 075 076 while (!result && f != null) { 077 result = f.equals(root); 078 079 f = f.getParentFile(); 080 } 081 } 082 083 return result; 084 } 085 086 /** 087 * {@inheritDoc} 088 */ 089 public File getChild(Object parent, int index) { 090 if (!isValidFileNode(parent)) { 091 throw new IllegalArgumentException("parent is not a file governed by this model"); 092 } 093 094 File parentFile = (File) parent; 095 String[] children = parentFile.list(); 096 097 if (children != null) { 098 return new File(parentFile, children[index]); 099 } 100 101 return null; 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 public int getChildCount(Object parent) { 108 if (parent instanceof File) { 109 String[] children = ((File) parent).list(); 110 111 if (children != null) { 112 return children.length; 113 } 114 } 115 116 return 0; 117 } 118 119 /** 120 * {@inheritDoc} 121 */ 122 @Override 123 public Class<?> getColumnClass(int column) { 124 switch (column) { 125 case 0: 126 return String.class; 127 case 1: 128 return Long.class; 129 case 2: 130 return Boolean.class; 131 case 3: 132 return Date.class; 133 default: 134 return super.getColumnClass(column); 135 } 136 } 137 138 public int getColumnCount() { 139 return 4; 140 } 141 142 @Override 143 public String getColumnName(int column) { 144 switch (column) { 145 case 0: 146 return "Name"; 147 case 1: 148 return "Size"; 149 case 2: 150 return "Directory"; 151 case 3: 152 return "Modification Date"; 153 default: 154 return super.getColumnName(column); 155 } 156 } 157 158 public Object getValueAt(Object node, int column) { 159 if (node instanceof File) { 160 File file = (File) node; 161 switch (column) { 162 case 0: 163 return file.getName(); 164 case 1: 165 return isLeaf(node) ? file.length() : DIRECTORY; 166 case 2: 167 return file.isDirectory(); 168 case 3: 169 return new Date(file.lastModified()); 170 } 171 } 172 173 return null; 174 } 175 176 /** 177 * {@inheritDoc} 178 */ 179 public int getIndexOfChild(Object parent, Object child) { 180 if (parent instanceof File && child instanceof File) { 181 File parentFile = (File) parent; 182 File[] files = parentFile.listFiles(); 183 184 Arrays.sort(files); 185 186 for (int i = 0, len = files.length; i < len; i++) { 187 if (files[i].equals(child)) { 188 return i; 189 } 190 } 191 } 192 193 return -1; 194 } 195 196 /** 197 * {@inheritDoc} 198 */ 199 @Override 200 public File getRoot() { 201 return (File) root; 202 } 203 204 /** 205 * Sets the root for this tree table model. This method will notify 206 * listeners that a change has taken place. 207 * 208 * @param root 209 * the new root node to set 210 */ 211 public void setRoot(File root) { 212 this.root = root; 213 214 modelSupport.fireNewRoot(); 215 } 216 217 /** 218 * {@inheritDoc} 219 */ 220 @Override 221 public boolean isLeaf(Object node) { 222 if (node instanceof File) { 223 //do not use isFile(); some system files return false 224 return ((File) node).list() == null; 225 } 226 227 return true; 228 } 229 }