acknowledge source and modify to take filter
[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)\r
35   {\r
36     super(dir);\r
37     JalviewFileFilter filter = new JalviewFileFilter(suffix, desc);\r
38     this.setFileFilter(filter);\r
39     initColumns();\r
40   }\r
41 \r
42   public JalviewFileChooser(String dir)\r
43   {\r
44     super(dir);\r
45     initColumns();\r
46   }\r
47 \r
48   void initColumns()\r
49   {\r
50     if (COLUMNS == null)\r
51     {\r
52         Locale l = getLocale();\r
53         COLUMNS = new String[]{\r
54         UIManager.getString("FileChooser.fileNameHeaderText",l),\r
55         UIManager.getString("FileChooser.fileSizeHeaderText",l),\r
56         UIManager.getString("FileChooser.fileTypeHeaderText",l),\r
57         UIManager.getString("FileChooser.fileDateHeaderText",l),\r
58         UIManager.getString("FileChooser.fileAttrHeaderText",l)\r
59       };\r
60     }\r
61 \r
62   }\r
63 \r
64   /**************************************************************************\r
65    * Always create the local UI\r
66    * @param comp\r
67    *************************************************************************/\r
68   public final void setUI(ComponentUI comp)\r
69   {\r
70     super.setUI(new UI(this));\r
71   }\r
72 \r
73    /**************************************************************************\r
74     * Internal implementation of Metal LookAndFeel to create the table sorting\r
75     * ability.\r
76     *************************************************************************/\r
77    private final static class UI extends MetalFileChooserUI\r
78    {\r
79      private DirectoryModel model;\r
80 \r
81      /**************************************************************************\r
82       * Must be overridden to extend\r
83       * @param e\r
84       *************************************************************************/\r
85      public UI(JFileChooser e)\r
86      {\r
87        super(e);\r
88      }\r
89 \r
90      /**************************************************************************\r
91       * Overridden to create our own model\r
92       *************************************************************************/\r
93      protected final void createModel()\r
94      {\r
95        model = new DirectoryModel(getFileChooser());\r
96      }\r
97 \r
98      /**************************************************************************\r
99       * Overridden to get our own model\r
100       * @return\r
101       *************************************************************************/\r
102      public final BasicDirectoryModel getModel() {       return model;     }\r
103 \r
104      /**************************************************************************\r
105       * Calls the default method then adds a MouseListener to the JTable\r
106       * @param chooser\r
107       * @return\r
108       *************************************************************************/\r
109      protected final JPanel createDetailsView(JFileChooser chooser)\r
110      {\r
111        final JPanel panel = super.createDetailsView(chooser);\r
112 \r
113        //Since we can't access MetalFileChooserUI's private member detailsTable\r
114        //directly, we have to find it in the JPanel\r
115        final JTable tbl = findJTable(panel.getComponents());\r
116        if (tbl != null)\r
117        {\r
118          //Fix the columns so they can't be rearranged, if we don't do this\r
119          //we would need to keep track when each column is moved\r
120          tbl.getTableHeader().setReorderingAllowed(false);\r
121 \r
122          //Add a mouselistener to listen for clicks on column headers\r
123          tbl.getTableHeader().addMouseListener(new MouseAdapter(){\r
124            public void mouseClicked(MouseEvent e)\r
125            {\r
126              //Only process single clicks\r
127              if (e.getClickCount() > 1) return;\r
128              e.consume();\r
129              final int col = tbl.getTableHeader().columnAtPoint(e.getPoint());\r
130              if (col == COLUMN_FILENAME || col == COLUMN_FILESIZE ||\r
131                  col == COLUMN_FILEDATE)\r
132                model.sort(col,tbl);\r
133            }\r
134          });\r
135        }\r
136        return panel;\r
137      }\r
138 \r
139      /**************************************************************************\r
140       * Finds the JTable in the panel so we can add MouseListener\r
141       * @param comp\r
142       * @return\r
143       *************************************************************************/\r
144      private final static JTable findJTable(Component[] comp)\r
145      {\r
146        for (int i=0;i<comp.length;i++)\r
147        {\r
148          if (comp[i] instanceof JTable)\r
149          {\r
150            return (JTable)comp[i];\r
151          }\r
152          if (comp[i] instanceof Container)\r
153          {\r
154            JTable tbl = findJTable(((Container)comp[i]).getComponents());\r
155            if (tbl != null) return tbl;\r
156          }\r
157        }\r
158        return null;\r
159      }\r
160    }\r
161 \r
162   /***************************************************************************\r
163    * Implementation of BasicDirectoryModel that sorts the Files by column\r
164    **************************************************************************/\r
165   private final static class DirectoryModel extends BasicDirectoryModel\r
166    {\r
167      int col = 0;\r
168      boolean ascending;\r
169 \r
170      /**************************************************************************\r
171       * Must be overridden to extend BasicDirectoryModel\r
172       * @param chooser\r
173       *************************************************************************/\r
174      DirectoryModel(JFileChooser chooser)\r
175      {\r
176        super(chooser);\r
177      }\r
178 \r
179 \r
180      /**************************************************************************\r
181       * Supposedly this is not used anymore, hopefully not.  We implemented\r
182       * some basic attempt at sorting just in case\r
183       * @param a\r
184       * @param b\r
185       * @return\r
186       *************************************************************************/\r
187      protected final boolean lt(File a, File b)\r
188      {\r
189        System.out.println("LT called?");\r
190        boolean less = false;\r
191        switch (col)\r
192        {\r
193          case COLUMN_FILEDATE:\r
194            less = a.lastModified() > b.lastModified();\r
195            break;\r
196          case COLUMN_FILESIZE:\r
197            less = a.length() > b.length();\r
198            break;\r
199          default:\r
200            less = a.getName().compareToIgnoreCase(b.getName()) > 0;\r
201          break;\r
202        }\r
203        if (ascending) return less = !less;\r
204        return less;\r
205      }\r
206 \r
207      /**************************************************************************\r
208       * Resorts the JFileChooser table based on new column\r
209       * @param c\r
210       *************************************************************************/\r
211      protected final void sort(int c, JTable tbl)\r
212      {\r
213        //Set column and order\r
214        col = c;\r
215        ascending = !ascending;\r
216        String indicator = " (^)";\r
217        if (ascending)\r
218          indicator = " (v)";\r
219 \r
220        final JTableHeader th = tbl.getTableHeader();\r
221        final TableColumnModel tcm = th.getColumnModel();\r
222 \r
223        for (int i=0;i<JalviewFileChooser.COLUMN_COLCOUNT;i++)\r
224        {\r
225          final TableColumn tc = tcm.getColumn( i ); // the column to change\r
226          tc.setHeaderValue( COLUMNS[i] );\r
227        }\r
228 \r
229        final TableColumn tc = tcm.getColumn( col ); // the column to change\r
230        tc.setHeaderValue( COLUMNS[col] + indicator );\r
231 \r
232        th.repaint();\r
233 \r
234        //Requery the file listing\r
235        validateFileCache();\r
236      }\r
237 \r
238      /**************************************************************************\r
239       * Sorts the data based on current column setting\r
240       * @param data\r
241       *************************************************************************/\r
242      protected final void sort(Vector data)\r
243      {\r
244        switch (col)\r
245        {\r
246          case COLUMN_FILEDATE:\r
247            Collections.sort(data,new Comparator(){\r
248              public int compare(Object o1,Object o2)\r
249              {\r
250                int ret = 1;\r
251                final File a = (File)o1;\r
252                final File b = (File)o2;\r
253                if (a.lastModified() > b.lastModified())\r
254                  ret = -1;\r
255                else if (a.lastModified() == b.lastModified())\r
256                  ret = 0;\r
257 \r
258                if (ascending)\r
259                  ret *= -1;\r
260                return ret;\r
261              }\r
262 \r
263            });\r
264            break;\r
265          case COLUMN_FILESIZE:\r
266            Collections.sort(data,new Comparator(){\r
267              public int compare(Object o1,Object o2)\r
268              {\r
269                int ret = 1;\r
270                final File a = (File)o1;\r
271                final File b = (File)o2;\r
272                if (a.length() > b.length())\r
273                  ret = -1;\r
274                else if (a.length() == b.length())\r
275                  ret = 0;\r
276 \r
277                if (ascending)\r
278                  ret *= -1;\r
279                return ret;\r
280              }\r
281 \r
282            });\r
283            break;\r
284          case COLUMN_FILENAME:\r
285            Collections.sort(data,new Comparator(){\r
286              public int compare(Object o1,Object o2)\r
287              {\r
288                final File a = (File)o1;\r
289                final File b = (File)o2;\r
290                if (ascending)\r
291                  return a.getName().compareToIgnoreCase(b.getName());\r
292                else\r
293                  return -1 * a.getName().compareToIgnoreCase(b.getName());\r
294              }\r
295 \r
296            });\r
297            break;\r
298        }\r
299      }\r
300   }\r
301 }\r
302 \r