* Bug 11852 fixed: now filebrowser updates (again)
[scilab.git] / scilab / modules / ui_data / src / java / org / scilab / modules / ui_data / filebrowser / FileNode.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - DIGITEO - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 package org.scilab.modules.ui_data.filebrowser;
17
18 import java.io.File;
19 import java.util.Comparator;
20 import java.util.TreeSet;
21 import java.util.regex.Pattern;
22 import javax.swing.Icon;
23 import javax.swing.SortOrder;
24 import org.scilab.modules.commons.CommonFileUtils;
25 import org.scilab.modules.commons.ScilabConstants;
26 import org.scilab.modules.ui_data.utils.UiDataMessages;
27
28 /**
29  * Handle a File as a node in the JTree
30  *
31  * @author Calixte DENIZET
32  */
33 public class FileNode {
34
35     public static final int NAMEORDER = 1;
36     public static final int SIZEORDER = 2;
37     public static final int DATEORDER = 3;
38     public static final int TYPEORDER = 4;
39
40     private static final File userHomeDir = new File(ScilabConstants.USERHOME);
41     private static final File SCIDIR = new File(System.getenv("SCI"));
42
43     private static Comparator<FileNode> comparator = FileComparators.ASCENDING_ALPHA;
44
45     protected File file;
46     protected Icon icon;
47     protected FileNode[] children;
48     protected long lastModified;
49     protected boolean isFile;
50     protected boolean canRead;
51     protected boolean canWrite;
52     protected boolean isEmpty;
53     protected boolean userHome;
54     protected boolean sci;
55     protected long length;
56     protected String name;
57     protected String extension;
58     private int order = 1;
59     private Pattern pat;
60     private int position;
61
62     /**
63      * Default constructor
64      *
65      * @param file the file in this node
66      */
67     public FileNode(File file, int position) {
68         this(file, file.getName(), file.canRead(), file.isFile());
69         this.position = position;
70     }
71
72     public FileNode(File file, String name, boolean canRead, boolean isFile) {
73         this.file = file;
74         this.name = name;
75         this.isFile = isFile;
76         this.canRead = canRead;
77         this.canWrite = file.canWrite();
78         this.lastModified = file.lastModified();
79         this.userHome = file.equals(userHomeDir);
80         if (isFile) {
81             this.length = file.length();
82         }
83         this.extension = FileUtils.getFileExtension(file);
84         this.sci = file.equals(SCIDIR);
85         this.isEmpty = isFile || CommonFileUtils.isEmptyDirectory(file.getAbsolutePath()) == 1;
86     }
87
88     public int getPosition() {
89         return position;
90     }
91
92     /** @param pat the pattern to filter the files */
93     public void setFilter(Pattern pat) {
94         this.pat = pat;
95         resetChildren();
96     }
97
98     /**
99      * @param order the order to use to sort the file. If order is positive, then ascending order is
100      *     used.
101      */
102     public void setOrder(int order) {
103         this.order = order;
104         switch (order) {
105             case NAMEORDER:
106                 comparator = FileComparators.ASCENDING_ALPHA;
107                 break;
108             case -NAMEORDER:
109                 comparator = FileComparators.DESCENDING_ALPHA;
110                 break;
111             case TYPEORDER:
112                 comparator = FileComparators.ASCENDING_TYPE;
113                 break;
114             case -TYPEORDER:
115                 comparator = FileComparators.DESCENDING_TYPE;
116                 break;
117             case DATEORDER:
118                 comparator = FileComparators.ASCENDING_DATE;
119                 break;
120             case -DATEORDER:
121                 comparator = FileComparators.DESCENDING_DATE;
122                 break;
123             case SIZEORDER:
124                 comparator = FileComparators.ASCENDING_SIZE;
125                 break;
126             case -SIZEORDER:
127                 comparator = FileComparators.DESCENDING_SIZE;
128                 break;
129         }
130     }
131
132     /**
133      * @param order the order to use to sort the file.
134      * @param ascending if true, the ascending order is used
135      */
136     public void setOrder(int order, boolean ascending) {
137         int sign = ascending ? +1 : -1;
138         setOrder(sign * order);
139     }
140
141     /** @return the used order */
142     public SortOrder getOrder() {
143         return order > 0 ? SortOrder.ASCENDING : SortOrder.DESCENDING;
144     }
145
146     /**
147      * Sort a column according to the natural order for its.
148      *
149      * @param nameColumn the column name
150      */
151     public void toggleSortOrder(String nameColumn) {
152         if (nameColumn.equals(UiDataMessages.NAME_COLUMN)) {
153             if (Math.abs(order) == NAMEORDER) {
154                 setOrder(-order);
155             } else {
156                 setOrder(NAMEORDER);
157             }
158         } else if (nameColumn.equals(UiDataMessages.TYPE_COLUMN)) {
159             if (Math.abs(order) == TYPEORDER) {
160                 setOrder(-order);
161             } else {
162                 setOrder(TYPEORDER);
163             }
164         } else if (nameColumn.equals(UiDataMessages.SIZE_COLUMN)) {
165             if (Math.abs(order) == SIZEORDER) {
166                 setOrder(-order);
167             } else {
168                 setOrder(SIZEORDER);
169             }
170         } else if (nameColumn.equals(UiDataMessages.LASTMODIF_COLUMN)) {
171             if (Math.abs(order) == DATEORDER) {
172                 setOrder(-order);
173             } else {
174                 setOrder(DATEORDER);
175             }
176         }
177     }
178
179     /**
180      * Sort the files
181      *
182      * @param order the order to use
183      * @param files the files to order
184      * @return the ordered FileNodes
185      */
186     protected void orderFiles() {
187         if (children != null) {
188             TreeSet<FileNode> set = new TreeSet<FileNode>(comparator);
189             for (FileNode fn : children) {
190                 set.add(fn);
191             }
192
193             children = set.toArray(children);
194             for (int i = 0; i < children.length; i++) {
195                 children[i].position = i;
196             }
197         }
198     }
199
200     /** Returns the string to be used to display this leaf in the JTree. */
201     public String toString() {
202         String name = file.getName();
203         if (name.isEmpty()) {
204             name = file.toString();
205         }
206         return name;
207     }
208
209     /** @return the file associated with this node */
210     public File getFile() {
211         return file;
212     }
213
214     /** @return true if this represents the user-home directory */
215     public boolean isUserHome() {
216         return userHome;
217     }
218
219     /** @return true if this represents the SCI directory */
220     public boolean isSCI() {
221         return sci;
222     }
223
224     /** @return the last modified time for this file */
225     public long getLastModified() {
226         return lastModified;
227     }
228
229     /** @return the icon associated with this file */
230     public Icon getIcon() {
231         if (icon == null) {
232             icon = FileUtils.getIconForFile(file);
233         }
234
235         return icon;
236     }
237
238     /** @return true if the file is not a directory or if it is an empty one */
239     public boolean isLeaf() {
240         return isEmpty;
241     }
242
243     /** @return the number of files in the directory representated by this file */
244     public int getChildrenCount() {
245         if (!isEmpty) {
246             synchronized (file) {
247                 if (children == null) {
248                     children = listFiles();
249                 }
250             }
251         }
252
253         if (children != null) {
254             return children.length;
255         }
256
257         return 0;
258     }
259
260     /** @return the children FileNode of this FileNode */
261     protected Object[] getChildren() {
262         if (children == null && !isEmpty) {
263             children = listFiles();
264         }
265
266         return children;
267     }
268
269     public FileNode[] getRawChildren() {
270         return children;
271     }
272
273     public FileNode[] listFiles() {
274         String[] filesName = file.list();
275         if (filesName != null) {
276             TreeSet<FileNode> nodes = new TreeSet<FileNode>(comparator);
277             for (String fileName : filesName) {
278                 File f = new File(file, fileName);
279                 if (pat != null && !pat.matcher(fileName).matches()) {
280                     continue;
281                 }
282                 if (f.isHidden()) {
283                     continue;
284                 }
285                 boolean canRead = f.canRead();
286                 if (!canRead) {
287                     continue;
288                 }
289                 boolean isFile = f.isFile();
290                 if (!isFile && !f.isDirectory()) {
291                     continue;
292                 }
293                 nodes.add(new FileNode(f, fileName, canRead, isFile));
294             }
295
296             FileNode[] fnodes = new FileNode[nodes.size()];
297             fnodes = nodes.toArray(fnodes);
298
299             for (int i = 0; i < fnodes.length; i++) {
300                 fnodes[i].position = i;
301             }
302
303             return fnodes;
304         }
305
306         return null;
307     }
308
309     /** Reset children only */
310     public void resetChildren() {
311         children = null;
312         isEmpty = isFile || CommonFileUtils.isEmptyDirectory(file.getAbsolutePath()) == 1;
313     }
314
315     /** {@inheritDoc} */
316     public boolean equals(Object o) {
317         return (o instanceof FileNode) && ((FileNode) o).file.equals(file);
318     }
319
320     /** {@inheritDoc} */
321     public int hashCode() {
322         return file.hashCode();
323     }
324 }