001 /*
002 * $Id: SimpleFileSystemModel.java 2303 2007-09-14 12:18:16Z kschaefe $
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.Date;
026
027 import javax.swing.event.EventListenerList;
028 import javax.swing.event.TreeModelListener;
029 import 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 */
051 public 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 public File getChild(Object parent, int index) {
079 if (parent instanceof File) {
080 File parentFile = (File) parent;
081 File[] files = parentFile.listFiles();
082
083 if (files != null) {
084 return files[index];
085 }
086 }
087
088 return null;
089 }
090
091 /**
092 * {@inheritDoc}
093 */
094 public int getChildCount(Object parent) {
095 if (parent instanceof File) {
096 String[] children = ((File) parent).list();
097
098 if (children != null) {
099 return children.length;
100 }
101 }
102
103 return 0;
104 }
105
106 /**
107 * {@inheritDoc}
108 */
109 public Class<?> getColumnClass(int column) {
110 switch(column) {
111 case 0:
112 return String.class;
113 case 1:
114 return Long.class;
115 case 2:
116 return Boolean.class;
117 case 3:
118 return Date.class;
119 default:
120 return Object.class;
121 }
122 }
123
124 /**
125 * {@inheritDoc}
126 */
127 public int getColumnCount() {
128 return 4;
129 }
130
131 /**
132 * {@inheritDoc}
133 */
134 public String getColumnName(int column) {
135 switch (column) {
136 case 0:
137 return "Name";
138 case 1:
139 return "Size";
140 case 2:
141 return "Directory";
142 case 3:
143 return "Modification Date";
144 default:
145 return "Column " + column;
146 }
147 }
148
149 /**
150 * {@inheritDoc}
151 */
152 public Object getValueAt(Object node, int column) {
153 if (node instanceof File) {
154 File file = (File) node;
155 switch (column) {
156 case 0:
157 return file.getName();
158 case 1:
159 return file.isFile() ? file.length() : ZERO;
160 case 2:
161 return file.isDirectory();
162 case 3:
163 return new Date(file.lastModified());
164 }
165 }
166
167 return null;
168 }
169
170 /**
171 * {@inheritDoc}
172 */
173 public int getHierarchicalColumn() {
174 return 0;
175 }
176
177 /**
178 * {@inheritDoc}
179 */
180 public boolean isCellEditable(Object node, int column) {
181 return false;
182 }
183
184 /**
185 * {@inheritDoc}
186 */
187 public void setValueAt(Object value, Object node, int column) {
188 //does nothing
189 }
190
191 /**
192 * {@inheritDoc}
193 */
194 public void addTreeModelListener(TreeModelListener l) {
195 listenerList.add(TreeModelListener.class, l);
196 }
197
198 /**
199 * {@inheritDoc}
200 */
201 public int getIndexOfChild(Object parent, Object child) {
202 if (parent instanceof File && child instanceof File) {
203 File parentFile = (File) parent;
204 File[] files = parentFile.listFiles();
205
206 for (int i = 0, len = files.length; i < len; i++) {
207 if (files[i].equals(child)) {
208 return i;
209 }
210 }
211 }
212
213 return -1;
214 }
215
216 /**
217 * {@inheritDoc}
218 */
219 public File getRoot() {
220 return root;
221 }
222
223 /**
224 * {@inheritDoc}
225 */
226 public boolean isLeaf(Object node) {
227 if (node instanceof File) {
228 //do not use isFile(); some system files return false
229 return ((File) node).list() == null;
230 }
231
232 return true;
233 }
234
235 /**
236 * {@inheritDoc}
237 */
238 public void removeTreeModelListener(TreeModelListener l) {
239 listenerList.remove(TreeModelListener.class, l);
240 }
241
242 /**
243 * {@inheritDoc}
244 */
245 public void valueForPathChanged(TreePath path, Object newValue) {
246 //does nothing
247 }
248
249 /**
250 * Gets a an array of all the listeners attached to this model.
251 *
252 * @return an array of listeners; this array is guaranteed to be
253 * non-{@code null}
254 */
255 public TreeModelListener[] getTreeModelListeners() {
256 return listenerList.getListeners(TreeModelListener.class);
257 }
258 }