Formatted source
[jalview.git] / src / jalview / io / JalviewFileChooser.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4 *\r
5 * This program is free software; you can redistribute it and/or\r
6 * modify it under the terms of the GNU General Public License\r
7 * as published by the Free Software Foundation; either version 2\r
8 * of the License, or (at your option) any later version.\r
9 *\r
10 * This program is distributed in the hope that it will be useful,\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 * GNU General Public License for more details.\r
14 *\r
15 * You should have received a copy of the GNU General Public License\r
16 * along with this program; if not, write to the Free Software\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18 */\r
19 /*///////////////////////////////////////////////////////////////////\r
20 // This file was taken from java forum\r
21 // Re: JFileChooser functioning like normal Windows Apps FileChooser\r
22 // Author: ddanimal\r
23 // http://forum.java.sun.com/thread.jspa?forumID=57&threadID=327712\r
24 */\r
25 \r
26 //////////////////////////////////////////////////////////////////\r
27 package jalview.io;\r
28 \r
29 import java.awt.*;\r
30 import java.awt.event.*;\r
31 \r
32 import java.io.*;\r
33 \r
34 import java.util.*;\r
35 \r
36 import javax.swing.*;\r
37 import javax.swing.plaf.*;\r
38 import javax.swing.plaf.basic.*;\r
39 import javax.swing.plaf.metal.*;\r
40 import javax.swing.table.*;\r
41 \r
42 \r
43 public class JalviewFileChooser extends JFileChooser {\r
44     private static final int COLUMN_FILENAME = 0;\r
45     private static final int COLUMN_FILESIZE = 1;\r
46     private static final int COLUMN_FILETYPE = 2;\r
47     private static final int COLUMN_FILEDATE = 3;\r
48     private static final int COLUMN_FILEATTR = 4;\r
49     private static final int COLUMN_COLCOUNT = 5;\r
50     private static String[] COLUMNS = null;\r
51 \r
52     public JalviewFileChooser(String dir, String[] suffix, String[] desc,\r
53         String selected) {\r
54         super(dir);\r
55 \r
56         JalviewFileFilter chosen = null;\r
57 \r
58         for (int i = 0; i < suffix.length; i++) {\r
59             JalviewFileFilter jvf = new JalviewFileFilter(suffix[i], desc[i]);\r
60             addChoosableFileFilter(jvf);\r
61 \r
62             if ((selected != null) && selected.equalsIgnoreCase(desc[i])) {\r
63                 chosen = jvf;\r
64             }\r
65         }\r
66 \r
67         if (chosen != null) {\r
68             setFileFilter(chosen);\r
69         }\r
70 \r
71         initColumns();\r
72     }\r
73 \r
74     public JalviewFileChooser(String dir) {\r
75         super(dir);\r
76         initColumns();\r
77     }\r
78 \r
79     public String getSelectedFormat() {\r
80         String format = getFileFilter().getDescription();\r
81 \r
82         if (format.toUpperCase().startsWith("JALVIEW")) {\r
83             format = "Jalview";\r
84         } else if (format.toUpperCase().startsWith("FASTA")) {\r
85             format = "FASTA";\r
86         } else if (format.toUpperCase().startsWith("MSF")) {\r
87             format = "MSF";\r
88         } else if (format.toUpperCase().startsWith("CLUSTAL")) {\r
89             format = "CLUSTAL";\r
90         } else if (format.toUpperCase().startsWith("BLC")) {\r
91             format = "BLC";\r
92         } else if (format.toUpperCase().startsWith("PIR")) {\r
93             format = "PIR";\r
94         } else if (format.toUpperCase().startsWith("PFAM")) {\r
95             format = "PFAM";\r
96         }\r
97 \r
98         return format;\r
99     }\r
100 \r
101     public int showSaveDialog(Component parent) throws HeadlessException {\r
102         setDialogType(SAVE_DIALOG);\r
103 \r
104         int ret = showDialog(parent, null);\r
105 \r
106         if (getFileFilter() instanceof JalviewFileFilter) {\r
107             JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();\r
108 \r
109             if (!jvf.accept(getSelectedFile())) {\r
110                 String withExtension = getSelectedFile() + "." +\r
111                     jvf.getAcceptableExtension();\r
112                 setSelectedFile(new File(withExtension));\r
113             }\r
114         }\r
115 \r
116         if ((ret == JalviewFileChooser.APPROVE_OPTION) &&\r
117                 getSelectedFile().exists()) {\r
118             int confirm = JOptionPane.showConfirmDialog(parent,\r
119                     "Overwrite existing file?", "File exists",\r
120                     JOptionPane.YES_NO_OPTION);\r
121 \r
122             if (confirm != JOptionPane.YES_OPTION) {\r
123                 ret = this.CANCEL_OPTION;\r
124             }\r
125         }\r
126 \r
127         return ret;\r
128     }\r
129 \r
130     void initColumns() {\r
131         if (COLUMNS == null) {\r
132             Locale l = getLocale();\r
133             COLUMNS = new String[] {\r
134                     UIManager.getString("FileChooser.fileNameHeaderText", l),\r
135                     UIManager.getString("FileChooser.fileSizeHeaderText", l),\r
136                     UIManager.getString("FileChooser.fileTypeHeaderText", l),\r
137                     UIManager.getString("FileChooser.fileDateHeaderText", l),\r
138                     UIManager.getString("FileChooser.fileAttrHeaderText", l)\r
139                 };\r
140         }\r
141     }\r
142 \r
143     /**************************************************************************\r
144      * Always create the local UI\r
145      * @param comp\r
146      *************************************************************************/\r
147     public final void setUI(ComponentUI comp) {\r
148         super.setUI(new UI(this));\r
149     }\r
150 \r
151     /**************************************************************************\r
152      * Internal implementation of Metal LookAndFeel to create the table sorting\r
153      * ability.\r
154      *************************************************************************/\r
155     private final static class UI extends MetalFileChooserUI {\r
156         private DirectoryModel model;\r
157 \r
158         /**************************************************************************\r
159          * Must be overridden to extend\r
160          * @param e\r
161          *************************************************************************/\r
162         public UI(JFileChooser e) {\r
163             super(e);\r
164         }\r
165 \r
166         /**************************************************************************\r
167          * Overridden to create our own model\r
168          *************************************************************************/\r
169         protected final void createModel() {\r
170             model = new DirectoryModel(getFileChooser());\r
171         }\r
172 \r
173         /**************************************************************************\r
174          * Overridden to get our own model\r
175          * @return\r
176          *************************************************************************/\r
177         public final BasicDirectoryModel getModel() {\r
178             return model;\r
179         }\r
180 \r
181         /**************************************************************************\r
182          * Calls the default method then adds a MouseListener to the JTable\r
183          * @param chooser\r
184          * @return\r
185          *************************************************************************/\r
186         protected final JPanel createDetailsView(JFileChooser chooser) {\r
187             final JPanel panel = super.createDetailsView(chooser);\r
188 \r
189             //Since we can't access MetalFileChooserUI's private member detailsTable\r
190             //directly, we have to find it in the JPanel\r
191             final JTable tbl = findJTable(panel.getComponents());\r
192 \r
193             if (tbl != null) {\r
194                 //Fix the columns so they can't be rearranged, if we don't do this\r
195                 //we would need to keep track when each column is moved\r
196                 tbl.getTableHeader().setReorderingAllowed(false);\r
197 \r
198                 //Add a mouselistener to listen for clicks on column headers\r
199                 tbl.getTableHeader().addMouseListener(new MouseAdapter() {\r
200                         public void mouseClicked(MouseEvent e) {\r
201                             //Only process single clicks\r
202                             if (e.getClickCount() > 1) {\r
203                                 return;\r
204                             }\r
205 \r
206                             e.consume();\r
207 \r
208                             final int col = tbl.getTableHeader().columnAtPoint(e.getPoint());\r
209 \r
210                             if ((col == COLUMN_FILENAME) ||\r
211                                     (col == COLUMN_FILESIZE) ||\r
212                                     (col == COLUMN_FILEDATE)) {\r
213                                 model.sort(col, tbl);\r
214                             }\r
215                         }\r
216                     });\r
217             }\r
218 \r
219             return panel;\r
220         }\r
221 \r
222         /**************************************************************************\r
223          * Finds the JTable in the panel so we can add MouseListener\r
224          * @param comp\r
225          * @return\r
226          *************************************************************************/\r
227         private final static JTable findJTable(Component[] comp) {\r
228             for (int i = 0; i < comp.length; i++) {\r
229                 if (comp[i] instanceof JTable) {\r
230                     return (JTable) comp[i];\r
231                 }\r
232 \r
233                 if (comp[i] instanceof Container) {\r
234                     JTable tbl = findJTable(((Container) comp[i]).getComponents());\r
235 \r
236                     if (tbl != null) {\r
237                         return tbl;\r
238                     }\r
239                 }\r
240             }\r
241 \r
242             return null;\r
243         }\r
244     }\r
245 \r
246     /***************************************************************************\r
247      * Implementation of BasicDirectoryModel that sorts the Files by column\r
248      **************************************************************************/\r
249     private final static class DirectoryModel extends BasicDirectoryModel {\r
250         int col = 0;\r
251         boolean ascending;\r
252 \r
253         /**************************************************************************\r
254          * Must be overridden to extend BasicDirectoryModel\r
255          * @param chooser\r
256          *************************************************************************/\r
257         DirectoryModel(JFileChooser chooser) {\r
258             super(chooser);\r
259         }\r
260 \r
261         /**************************************************************************\r
262          * Supposedly this is not used anymore, hopefully not.  We implemented\r
263          * some basic attempt at sorting just in case\r
264          * @param a\r
265          * @param b\r
266          * @return\r
267          *************************************************************************/\r
268         protected final boolean lt(File a, File b) {\r
269             System.out.println("DEBUG:LT called?");\r
270 \r
271             boolean less = false;\r
272 \r
273             switch (col) {\r
274             case COLUMN_FILEDATE:\r
275                 less = a.lastModified() > b.lastModified();\r
276 \r
277                 break;\r
278 \r
279             case COLUMN_FILESIZE:\r
280                 less = a.length() > b.length();\r
281 \r
282                 break;\r
283 \r
284             default:\r
285                 less = a.getName().compareToIgnoreCase(b.getName()) > 0;\r
286 \r
287                 break;\r
288             }\r
289 \r
290             if (ascending) {\r
291                 return less = !less;\r
292             }\r
293 \r
294             return less;\r
295         }\r
296 \r
297         /**************************************************************************\r
298          * Resorts the JFileChooser table based on new column\r
299          * @param c\r
300          *************************************************************************/\r
301         protected final void sort(int c, JTable tbl) {\r
302             //Set column and order\r
303             col = c;\r
304             ascending = !ascending;\r
305 \r
306             String indicator = " (^)";\r
307 \r
308             if (ascending) {\r
309                 indicator = " (v)";\r
310             }\r
311 \r
312             final JTableHeader th = tbl.getTableHeader();\r
313             final TableColumnModel tcm = th.getColumnModel();\r
314 \r
315             for (int i = 0; i < JalviewFileChooser.COLUMN_COLCOUNT; i++) {\r
316                 final TableColumn tc = tcm.getColumn(i); // the column to change\r
317                 tc.setHeaderValue(COLUMNS[i]);\r
318             }\r
319 \r
320             final TableColumn tc = tcm.getColumn(col); // the column to change\r
321             tc.setHeaderValue(COLUMNS[col] + indicator);\r
322 \r
323             th.repaint();\r
324 \r
325             //Requery the file listing\r
326             validateFileCache();\r
327         }\r
328 \r
329         /**************************************************************************\r
330          * Sorts the data based on current column setting\r
331          * @param data\r
332          *************************************************************************/\r
333         protected final void sort(Vector data) {\r
334             switch (col) {\r
335             case COLUMN_FILEDATE:\r
336                 Collections.sort(data,\r
337                     new Comparator() {\r
338                         public int compare(Object o1, Object o2) {\r
339                             int ret = 1;\r
340                             final File a = (File) o1;\r
341                             final File b = (File) o2;\r
342 \r
343                             if (a.lastModified() > b.lastModified()) {\r
344                                 ret = -1;\r
345                             } else if (a.lastModified() == b.lastModified()) {\r
346                                 ret = 0;\r
347                             }\r
348 \r
349                             if (ascending) {\r
350                                 ret *= -1;\r
351                             }\r
352 \r
353                             return ret;\r
354                         }\r
355                     });\r
356 \r
357 \r
358                 break;\r
359 \r
360             case COLUMN_FILESIZE:\r
361                 Collections.sort(data,\r
362                     new Comparator() {\r
363                         public int compare(Object o1, Object o2) {\r
364                             int ret = 1;\r
365                             final File a = (File) o1;\r
366                             final File b = (File) o2;\r
367 \r
368                             if (a.length() > b.length()) {\r
369                                 ret = -1;\r
370                             } else if (a.length() == b.length()) {\r
371                                 ret = 0;\r
372                             }\r
373 \r
374                             if (ascending) {\r
375                                 ret *= -1;\r
376                             }\r
377 \r
378                             return ret;\r
379                         }\r
380                     });\r
381 \r
382 \r
383                 break;\r
384 \r
385             case COLUMN_FILENAME:\r
386                 Collections.sort(data,\r
387                     new Comparator() {\r
388                         public int compare(Object o1, Object o2) {\r
389                             final File a = (File) o1;\r
390                             final File b = (File) o2;\r
391 \r
392                             if (ascending) {\r
393                                 return a.getName().compareToIgnoreCase(b.getName());\r
394                             } else {\r
395                                 return -1 * a.getName().compareToIgnoreCase(b.getName());\r
396                             }\r
397                         }\r
398                     });\r
399 \r
400 \r
401                 break;\r
402             }\r
403         }\r
404     }\r
405 }\r