001/* 002 * $Id: SimpleFileSystemModel.java 3927 2011-02-22 16:34:11Z 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 022package org.jdesktop.swingx.treetable; 023 024import java.io.File; 025import java.util.Date; 026 027import javax.swing.event.EventListenerList; 028import javax.swing.event.TreeModelListener; 029import javax.swing.tree.TreePath; 030 031/** 032 * A tree table model to simulate a file system. 033 * <p> 034 * This tree table model implementation does not extends 035 * {@code AbstractTreeTableModel}. The file system metaphor demonstrates that 036 * it is often easier to directly implement tree structures directly instead of 037 * using intermediaries, such as {@code TreeNode}. 038 * <p> 039 * It would be possible to create this same class by extending 040 * {@code AbstractTreeTableModel}, however the number of methods that you would 041 * need to override almost precludes that means of implementation. 042 * <p> 043 * A "full" version of this model might allow editing of file names, the 044 * deletion of files, and the movement of files. This simple implementation does 045 * not intend to tackle such problems, but this implementation may be extended 046 * to handle such details. 047 * 048 * @author Ramesh Gupta 049 * @author Karl Schaefer 050 */ 051public class SimpleFileSystemModel implements TreeTableModel { 052 protected EventListenerList listenerList; 053 054 // the returned file length for directories 055 private static final Long ZERO = Long.valueOf(0); 056 057 private File root; 058 059 /** 060 * Creates a file system model, using the root directory as the model root. 061 */ 062 public SimpleFileSystemModel() { 063 this(new File(File.separator)); 064 } 065 066 /** 067 * Creates a file system model, using the specified {@code root} as the 068 * model root. 069 */ 070 public SimpleFileSystemModel(File root) { 071 this.root = root; 072 this.listenerList = new EventListenerList(); 073 } 074 075 /** 076 * {@inheritDoc} 077 */ 078 @Override 079 public File getChild(Object parent, int index) { 080 if (parent instanceof File) { 081 File parentFile = (File) parent; 082 File[] files = parentFile.listFiles(); 083 084 if (files != null) { 085 return files[index]; 086 } 087 } 088 089 return null; 090 } 091 092 /** 093 * {@inheritDoc} 094 */ 095 @Override 096 public int getChildCount(Object parent) { 097 if (parent instanceof File) { 098 String[] children = ((File) parent).list(); 099 100 if (children != null) { 101 return children.length; 102 } 103 } 104 105 return 0; 106 } 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 public Class<?> getColumnClass(int column) { 113 switch(column) { 114 case 0: 115 return String.class; 116 case 1: 117 return Long.class; 118 case 2: 119 return Boolean.class; 120 case 3: 121 return Date.class; 122 default: 123 return Object.class; 124 } 125 } 126 127 /** 128 * {@inheritDoc} 129 */ 130 @Override 131 public int getColumnCount() { 132 return 4; 133 } 134 135 /** 136 * {@inheritDoc} 137 */ 138 @Override 139 public String getColumnName(int column) { 140 switch (column) { 141 case 0: 142 return "Name"; 143 case 1: 144 return "Size"; 145 case 2: 146 return "Directory"; 147 case 3: 148 return "Modification Date"; 149 default: 150 return "Column " + column; 151 } 152 } 153 154 /** 155 * {@inheritDoc} 156 */ 157 @Override 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 file.isFile() ? file.length() : ZERO; 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 @Override 180 public int getHierarchicalColumn() { 181 return 0; 182 } 183 184 /** 185 * {@inheritDoc} 186 */ 187 @Override 188 public boolean isCellEditable(Object node, int column) { 189 return false; 190 } 191 192 /** 193 * {@inheritDoc} 194 */ 195 @Override 196 public void setValueAt(Object value, Object node, int column) { 197 //does nothing 198 } 199 200 /** 201 * {@inheritDoc} 202 */ 203 @Override 204 public void addTreeModelListener(TreeModelListener l) { 205 listenerList.add(TreeModelListener.class, l); 206 } 207 208 /** 209 * {@inheritDoc} 210 */ 211 @Override 212 public int getIndexOfChild(Object parent, Object child) { 213 if (parent instanceof File && child instanceof File) { 214 File parentFile = (File) parent; 215 File[] files = parentFile.listFiles(); 216 217 for (int i = 0, len = files.length; i < len; i++) { 218 if (files[i].equals(child)) { 219 return i; 220 } 221 } 222 } 223 224 return -1; 225 } 226 227 /** 228 * {@inheritDoc} 229 */ 230 @Override 231 public File getRoot() { 232 return root; 233 } 234 235 /** 236 * {@inheritDoc} 237 */ 238 @Override 239 public boolean isLeaf(Object node) { 240 if (node instanceof File) { 241 //do not use isFile(); some system files return false 242 return ((File) node).list() == null; 243 } 244 245 return true; 246 } 247 248 /** 249 * {@inheritDoc} 250 */ 251 @Override 252 public void removeTreeModelListener(TreeModelListener l) { 253 listenerList.remove(TreeModelListener.class, l); 254 } 255 256 /** 257 * {@inheritDoc} 258 */ 259 @Override 260 public void valueForPathChanged(TreePath path, Object newValue) { 261 //does nothing 262 } 263 264 /** 265 * Gets a an array of all the listeners attached to this model. 266 * 267 * @return an array of listeners; this array is guaranteed to be 268 * non-{@code null} 269 */ 270 public TreeModelListener[] getTreeModelListeners() { 271 return listenerList.getListeners(TreeModelListener.class); 272 } 273}