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