KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > swingwtx > swing > JFileChooser


1 /*
2    SwingWT
3    Copyright(c)2003-2004, R. Rawson-Tetley
4
5    For more information on distributing and using this program, please
6    see the accompanying "COPYING" file.
7
8    Contact me by electronic mail: bobintetley@users.sourceforge.net
9
10    $Log: JFileChooser.java,v $
11    Revision 1.16 2004/05/05 13:24:32 bobintetley
12    Bugfixes and Laurent's patch for binary compatibility on Container.add()
13
14    Revision 1.15 2004/04/30 16:52:17 bobintetley
15    MenuListener support, JViewport support, TreeSelectionModel stubs, additional JTree methods
16
17    Revision 1.14 2004/04/19 15:43:25 bobintetley
18    Missing (and incorrect) Dialog/JDialog constructors implemented
19
20    Revision 1.13 2004/04/16 10:19:06 dannaab
21    Misc bug fixes, InputMap implementation, preliminary undo support
22
23    Revision 1.12 2004/04/06 10:16:15 bobintetley
24    (Antonio Weber) JFileChooser fixes to getSelectedFile() and FileFilter
25
26    Revision 1.11 2004/03/31 08:47:49 bobintetley
27    Fixed JFileChooser no border bug (fault with JDialog empty constructor)
28
29    Revision 1.10 2004/03/23 09:58:58 bobintetley
30    SystemColor and FileDialog implementation, plus JOptionPane.showOptionDialog support
31
32    Revision 1.9 2004/03/19 15:34:37 bobintetley
33    Drive support in custom JFileChooser
34
35    Revision 1.8 2004/03/18 16:21:37 bobintetley
36    JTextComponent/Caret implementation and fix to JFileChooser for bug in GNU classpath
37
38    Revision 1.7 2004/03/16 22:17:18 bobintetley
39    Fixes for JDK 1.3
40
41    Revision 1.6 2004/03/12 14:21:47 bobintetley
42    Fix to threading issue and removal of debug messages
43
44    Revision 1.5 2004/03/01 15:58:47 bobintetley
45    Various little bug fixes
46
47    Revision 1.4 2004/01/26 08:11:00 bobintetley
48    Many bugfixes and addition of SwingSet
49
50    Revision 1.3 2003/12/14 09:13:38 bobintetley
51    Added CVS log to source headers
52
53 */

54
55 package swingwtx.swing;
56
57 import java.beans.PropertyChangeEvent JavaDoc;
58 import java.beans.PropertyChangeListener JavaDoc;
59 import java.io.File JavaDoc;
60 import java.util.Vector JavaDoc;
61
62 import org.eclipse.swt.SWT;
63
64 import swingwt.awt.BorderLayout;
65 import swingwt.awt.Component;
66 import swingwt.awt.Dimension;
67 import swingwt.awt.FlowLayout;
68 import swingwt.awt.Frame;
69 import swingwt.awt.GridLayout;
70 import swingwt.awt.event.ActionEvent;
71 import swingwt.awt.event.ActionListener;
72 import swingwt.awt.event.ItemEvent;
73 import swingwt.awt.event.ItemListener;
74 import swingwt.awt.event.MouseAdapter;
75 import swingwt.awt.event.MouseEvent;
76
77
78 /**
79  * JFileChooser is now a custom control (like Swing's), however
80  * if you only use the showXDialog() methods without calling
81  * setAccessory() or setExtensions(), you will get a native
82  * platform file chooser dialog instead.
83  *
84  * You can force native or non-native by creating an instance
85  * of JFileChooser and doing [instance].useNative = true/false
86  *
87  * This hopefully supplies the best of both worlds.
88  *
89  * FIXME: Does not support multiple file selection or directories
90  * in custom mode (works fine for platform native)
91  *
92  * @author Robin Rawson-Tetley
93  */

94 public class JFileChooser extends JPanel {
95
96     public static final int OPEN_DIALOG = 0;
97     public static final int SAVE_DIALOG = 1;
98     public static final int CUSTOM_DIALOG = 2;
99
100     public static final int CANCEL_OPTION = 1;
101     public static final String JavaDoc CANCEL_SELECTION = "CANCEL";
102     public static final int APPROVE_OPTION = 0;
103
104     public static final int ERROR_OPTION = -1;
105     public static final int FILES_ONLY = 0;
106     public static final int DIRECTORIES_ONLY = 1;
107     public static final int FILES_AND_DIRECTORIES = 2;
108
109     // Property strings
110
public static final String JavaDoc ACCESSORY_CHANGED_PROPERTY = "AccessoryChangedProperty";
111     public static final String JavaDoc ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY = "acceptAllFileFilterUsedChanged";
112     public static final String JavaDoc DIALOG_TITLE_CHANGED_PROPERTY = "DialogTitleChangedProperty";
113     public static final String JavaDoc DIALOG_TYPE_CHANGED_PROPERTY = "DialogTypeChangedProperty";
114     public static final String JavaDoc CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY = "ChoosableFileFilterChangedProperty";
115     public static final String JavaDoc FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
116     public static final String JavaDoc FILE_HIDING_CHANGED_PROPERTY = "FileHidingChanged";
117     public static final String JavaDoc FILE_FILTER_CHANGED_PROPERTY = "fileFilterChanged";
118     public static final String JavaDoc FILE_SELECTION_MODE_CHANGED_PROPERTY = "fileSelectionChanged";
119     public static final String JavaDoc APPROVE_BUTTON_TEXT_CHANGED_PROPERTY = "ApproveButtonTextChangedProperty";
120     public static final String JavaDoc APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY = "ApproveButtonToolTipTextChangedProperty";
121     public static final String JavaDoc APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY = "ApproveButtonMnemonicChangedProperty";
122     public static final String JavaDoc CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY = "ControlButtonsAreShownChangedProperty";
123     public static final String JavaDoc DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
124     public static final String JavaDoc SELECTED_FILE_CHANGED_PROPERTY = "SelectedFileChangedProperty";
125     public static final String JavaDoc SELECTED_FILES_CHANGED_PROPERTY = "SelectedFilesChangedProperty";
126     public static final String JavaDoc MULTI_SELECTION_ENABLED_CHANGED_PROPERTY = "MultiSelectionEnabledChangedProperty";
127     public static final String JavaDoc FILE_SYSTEM_VIEW_CHANGED_PROPERTY = "FileSystemViewChanged";
128
129     protected int dialogType = OPEN_DIALOG;
130     protected String JavaDoc dialogTitle = "";
131     protected int fileSelection = FILES_ONLY;
132     protected File JavaDoc curPath = new File JavaDoc("");
133     protected File JavaDoc curFile = new File JavaDoc("");
134     protected File JavaDoc[] curFiles = null;
135     protected boolean multiSelect = false;
136     protected String JavaDoc[] filters = null;
137     protected String JavaDoc[] filterNames = null;
138
139     protected Vector JavaDoc fileFilters = new Vector JavaDoc();
140
141     /**
142      * Whether or not to use native chooser - is set to false if setAccessory()
143      * or setExtensions() is called. Since native ones can't support this.
144      *
145      * If this is embedded in a container as a component, then this value is ignored
146      * anyway. It is only relevant for showOpenDialog()/showSaveDialog()
147      *
148      * You can set this value directly prior to calling a show method to force
149      * the component to use either native, or custom dialogs as you wish if you don't
150      * want it to intelligently work out what to use.
151      */

152     public boolean useNative = true;
153
154     // Controls used for presenting our file chooser when not
155
// using the native platform one.
156
protected JTextField location = null;
157     protected JComboBox filter = null;
158     protected JPanel centralPanel = null;
159     protected JList fileList = null;
160     protected JPanel buttonPanel = null;
161     protected JButton okButton = null;
162     protected JComponent fcAccessory = null;
163     protected FileChooserDialog customDialog = null;
164     protected int dialogReturnValue = CANCEL_OPTION;
165     protected JFileChooser.FileFilterWrapper allFiles = null;
166
167     /** Creates a new instance of JFileChooser */
168     public JFileChooser() {this(new File JavaDoc("")); }
169     public JFileChooser(String JavaDoc currentDirectoryPath) {
170         this(new File JavaDoc(currentDirectoryPath));
171     }
172     public JFileChooser(File JavaDoc currentDirectory) {
173         curPath = currentDirectory;
174         layoutComponent();
175     }
176
177     public File JavaDoc getSelectedFile() { return curFile; }
178     public void setSelectedFile(File JavaDoc file) { curFile = file; ensureFileIsVisible(file); }
179
180     public File JavaDoc[] getSelectedFiles() { return curFiles; }
181     public void setSelectedFiles(File JavaDoc[] selectedFiles) { curFiles = selectedFiles; }
182
183     public File JavaDoc getCurrentDirectory() { return curPath; }
184     public void setCurrentDirectory(File JavaDoc dir) { curPath = dir; ensureFileIsVisible(dir); }
185     public void changeToParentDirectory() { setCurrentDirectory(curPath.getParentFile()); }
186
187     /**
188      * Scans "drives" according to platform. UNIX platforms have / (root), plus
189      * the contents of the /mnt directory, along with /cdrom and /cdrom1 if
190      * they exist.
191      *
192      * Win32 machines we scan a: through to z: and any that exist are added
193      * to the list.
194      *
195      * I am well aware that this is a quick and dirty solution that will work
196      * for probably 99% of PC owners with Windows and a popular *nix distro
197      * (Mandrake, Red Hat, Debian, FreeBSD are fine with this stuff)
198      */

199     public void scanDrives(JComboBox driveBox) {
200
201         if (SwingWTUtils.isWindows()) {
202             // Don't check floppies as Win2K+ barf with stupid messages
203
// to insert one - HOW STUPID?
204
driveBox.addItem(new DriveEntry(new File JavaDoc("A:"), "Floppy Disk (A:)"));
205             checkDriveEntry("C:", "Disk (C:)", driveBox);
206             checkDriveEntry("D:", "Disk (D:)", driveBox);
207             checkDriveEntry("E:", "Disk (E:)", driveBox);
208             checkDriveEntry("F:", "Disk (F:)", driveBox);
209             checkDriveEntry("G:", "Network Disk (G:)", driveBox);
210             checkDriveEntry("H:", "Network Disk (H:)", driveBox);
211             checkDriveEntry("I:", "Network Disk (I:)", driveBox);
212             checkDriveEntry("J:", "Network Disk (J:)", driveBox);
213             checkDriveEntry("K:", "Network Disk (K:)", driveBox);
214             checkDriveEntry("L:", "Network Disk (L:)", driveBox);
215             checkDriveEntry("M:", "Network Disk (M:)", driveBox);
216             checkDriveEntry("N:", "Network Disk (N:)", driveBox);
217             checkDriveEntry("O:", "Network Disk (O:)", driveBox);
218             checkDriveEntry("P:", "Network Disk (P:)", driveBox);
219             checkDriveEntry("Q:", "Network Disk (Q:)", driveBox);
220             checkDriveEntry("R:", "Network Disk (R:)", driveBox);
221             checkDriveEntry("S:", "Network Disk (S:)", driveBox);
222             checkDriveEntry("T:", "Network Disk (T:)", driveBox);
223             checkDriveEntry("U:", "Network Disk (U:)", driveBox);
224             checkDriveEntry("V:", "Network Disk (V:)", driveBox);
225             checkDriveEntry("W:", "Network Disk (W:)", driveBox);
226             checkDriveEntry("X:", "Network Disk (X:)", driveBox);
227             checkDriveEntry("Y:", "Network Disk (Y:)", driveBox);
228             checkDriveEntry("Z:", "Network Disk (Z:)", driveBox);
229             // Make sure the first selected entry is the first drive (ie. Not floppy)
230
// so that the list is synchronised.
231
driveBox.setSelectedIndex(1);
232         }
233         else
234         {
235             checkDriveEntry("/", "Root (/)", driveBox);
236             checkDriveEntry("/mnt/auto", "Automatic Mount (/mnt/auto)", driveBox);
237             checkDriveEntry("/mnt/floppy", "Floppy Disk (/mnt/floppy)", driveBox);
238             checkDriveEntry("/cdrom", "CDROM (/cdrom)", driveBox);
239             checkDriveEntry("/cdrom1", "CDROM (/cdrom1)", driveBox);
240             checkDriveEntry("/mnt/cdrom", "CDROM (/mnt/cdrom)", driveBox);
241             checkDriveEntry("/mnt/dvd", "DVD ROM (/mnt/dvd)", driveBox);
242             checkDriveEntry("/mnt/windows", "Windows Disk (/mnt/windows)", driveBox);
243             checkDriveEntry("/mnt/win_c", "Windows Disk (/mnt/win_c)", driveBox);
244             checkDriveEntry("/mnt/win_d", "Windows Disk (/mnt/win_d)", driveBox);
245             checkDriveEntry("/mnt/removable", "Removable Device (/mnt/removable)", driveBox);
246             checkDriveEntry("/mnt/zip", "Zip Disk (/mnt/zip)", driveBox);
247         }
248
249     }
250
251     /**
252      * Checks if the specified file path exists and if it does, creates
253      * a <code>DriveEntry</code> object, wraps the path and description
254      * up with it and loads it into the drives combo box for display.
255      */

256     protected void checkDriveEntry(String JavaDoc path, String JavaDoc displayName, JComboBox driveBox) {
257         try {
258             File JavaDoc f = new File JavaDoc(path);
259             if (f.exists())
260                 driveBox.addItem(new DriveEntry(f, displayName));
261         }
262         catch (Exception JavaDoc e) {}
263     }
264
265     /**
266      * Refreshes the on-screen list for the current location
267      */

268     public void rescanCurrentDirectory() {
269
270         // Drop out if the filter box isn't created yet
271
if (filter == null) return;
272
273         try {
274
275             File JavaDoc loc = new File JavaDoc(curFile.getAbsolutePath());
276
277             // Back up if it's not a directory
278
if (!loc.isDirectory())
279                 loc = curFile.getParentFile();
280
281             // Drop out if we don't have a directory (getParent() returns
282
// null if the File object has no directory.
283
if (loc == null) return;
284
285             // Filter the list of files according to the filter (if any) chosen
286
File JavaDoc[] fulldir = loc.listFiles();
287             Vector JavaDoc matches = new Vector JavaDoc();
288             JFileChooser.FileFilterWrapper w = (JFileChooser.FileFilterWrapper) filter.getSelectedItem();
289             swingwtx.swing.filechooser.FileFilter theFilter = null;
290             if (w != null) theFilter = w.getFilter();
291
292             for (int i = 0; i < fulldir.length; i++) {
293                 if (fulldir[i].getName().startsWith(".")){}
294                     //i = i; // Ignore hidden files
295
else if (theFilter == null)
296                     matches.add(fulldir[i]);
297                 else if (theFilter.accept(fulldir[i]))
298                     matches.add(fulldir[i]);
299             }
300
301             boolean needsParent = (loc.getParentFile() != null);
302
303             File JavaDoc[] filteredDir = null;
304
305             int noFiles = ( needsParent ? matches.size() + 1 : matches.size() );
306             filteredDir = new File JavaDoc[noFiles];
307
308             // Add the ".." directory
309
if (needsParent)
310                 filteredDir[0] = curFile.getAbsoluteFile().getParentFile();
311
312             for (int i = 0; i < matches.size(); i++) {
313                 if (needsParent)
314                     filteredDir[i + 1] = (File JavaDoc) matches.get(i);
315                 else
316                     filteredDir[i] = (File JavaDoc) matches.get(i);
317             }
318
319             // Sort the list
320
sortFiles(filteredDir);
321
322             // Add them to the list
323
fileList.setListData( filteredDir );
324
325         }
326         catch (StringIndexOutOfBoundsException JavaDoc e) {
327             // I hate having to write special case handlers, but there is a nasty
328
// bug in the GNU Classpath stuff that prevents reading of parent directories
329
// -- this gets around it. Besides, this exception type shouldn't ever be thrown
330
// up to the parent.
331
e.printStackTrace();
332         }
333
334     }
335
336     public void ensureFileIsVisible(File JavaDoc f) { /* FIXME: Find and display file */ }
337
338     public boolean getControlButtonsAreShown() { return buttonPanel.getParent() != null; }
339     public void setControlButtonsAreShown(boolean b) {
340         if (b)
341             add(buttonPanel, BorderLayout.SOUTH);
342         else
343             remove(buttonPanel);
344     }
345     public int getDialogType() { return dialogType; }
346     public void setDialogType(int dialogType) { this.dialogType = dialogType; }
347     public void setDialogTitle(String JavaDoc dialogTitle) { this.dialogTitle = dialogTitle; }
348     public void setApproveButtonToolTipText(String JavaDoc toolTipText) { okButton.setToolTipText(toolTipText); }
349     public String JavaDoc getApproveButtonToolTipText() { return okButton.getToolTipText(); }
350     public void setApproveButtonMnemonic(int mnemonic) { okButton.setMnemonic(mnemonic); }
351     public void setApproveButtonMnemonic(char mnemonic) { okButton.setMnemonic(mnemonic); }
352     public void setApproveButtonText(String JavaDoc approveButtonText) { okButton.setText(approveButtonText); }
353     public String JavaDoc getApproveButtonText() { return okButton.getText(); }
354     public JComponent getAccessory() { return fcAccessory; }
355     public void setAccessory(JComponent newAccessory) { useNative = false; fcAccessory = newAccessory; centralPanel.add(newAccessory, BorderLayout.EAST); }
356     public void setFileSelectionMode(int mode) { fileSelection = mode; }
357     public int getFileSelectionMode() { return fileSelection; }
358     public boolean isFileSelectionEnabled() {return (fileSelection == FILES_ONLY || fileSelection == FILES_AND_DIRECTORIES);}
359     public boolean isDirectorySelectionEnabled() { return (fileSelection == FILES_AND_DIRECTORIES || fileSelection == DIRECTORIES_ONLY);}
360     public void setMultiSelectionEnabled(boolean b) { multiSelect = b; }
361     public boolean isMultiSelectionEnabled() { return multiSelect; }
362     public boolean isFileHidingEnabled() { return false;}
363     public void setFileHidingEnabled(boolean b) {}
364
365     /**
366      * NOT A REAL SWING METHOD - THIS SETS FILTERS FOR THE PLATFORM
367      * DIALOGS INSTEAD OF OUR CUSTOM FILECHOOSER.
368      *
369      * Because setting Swing-style filters trips use of our custom
370      * dialog instead of the platform-native one, you can use this
371      * method instead to add filters to the native dialogs.
372      */

373     public void setExtensionFilters(String JavaDoc[] extensions, String JavaDoc[] names) {
374         filters = extensions;
375         filterNames = names;
376     }
377
378     public void setFileFilter(swingwtx.swing.filechooser.FileFilter fileFilter) {
379         useNative = false;
380         FileFilterWrapper wrapper = new FileFilterWrapper(fileFilter);
381         filter.addItem(wrapper);
382         filter.setSelectedItem(wrapper);
383     }
384
385     public swingwtx.swing.filechooser.FileFilter getFileFilter() { return (swingwtx.swing.filechooser.FileFilter) filter.getSelectedItem(); }
386     public swingwtx.swing.filechooser.FileFilter[] getChoosableFileFilters() {
387         swingwtx.swing.filechooser.FileFilter[] ff = new swingwtx.swing.filechooser.FileFilter[fileFilters.size()];
388         for (int i = 0; i < fileFilters.size(); i++) {
389             ff[i] = (swingwtx.swing.filechooser.FileFilter) fileFilters.get(i);
390         }
391         return ff;
392     }
393     public void addChoosableFileFilter(swingwtx.swing.filechooser.FileFilter f) {
394         JFileChooser.FileFilterWrapper w = new JFileChooser.FileFilterWrapper(f);
395         filter.addItem(w);
396     }
397     public boolean removeChoosableFileFilter(swingwtx.swing.filechooser.FileFilter f) {
398         for (int i = 0; i < filter.getItemCount(); i++)
399             if ( ((FileFilterWrapper) filter.getItemAt(i)).getFilter().equals(f) ) {
400                 filter.removeItemAt(i);
401                  return true;
402             }
403         return false;
404     }
405     public void resetChoosableFileFilters() {
406         filter.removeAllItems();
407         fileFilters.removeAllElements();
408     }
409     public boolean isAcceptAllFileFilterUsed() { return true; }
410     public void setAcceptAllFileFilterUsed(boolean b) {}
411
412     /** Wrapper routine - calls either showNativeOpenDialog or showCustomOpenDialog
413      * depending on options chosen
414      */

415     public int showOpenDialog(Component parent) {
416         if (useNative)
417             return showNativeOpenDialog(parent);
418         else
419             return showCustomOpenDialog(parent);
420     }
421
422     protected int showCustomOpenDialog(Component parent) {
423         dialogType = OPEN_DIALOG;
424         String JavaDoc dt = (dialogTitle.equals("") ? "Open" : dialogTitle);
425         customDialog = new FileChooserDialog(dt, this);
426         rescanCurrentDirectory(); // perhaps not the best place but now its consistent
427
customDialog.show();
428         return dialogReturnValue;
429     }
430
431     protected int showNativeOpenDialog(Component parent) {
432         dialogType = OPEN_DIALOG;
433         org.eclipse.swt.widgets.FileDialog f = new org.eclipse.swt.widgets.FileDialog(parent.getPeer().getShell(), SWT.OPEN | (multiSelect ? SWT.MULTI : SWT.NONE) );
434         if (dialogTitle.equals(""))
435             f.setText("Open");
436         else
437             f.setText(dialogTitle);
438  
439         if (curPath == null) curPath = new File JavaDoc("");
440         f.setFilterPath(curPath.getAbsolutePath());
441         
442         if (filters != null) {
443             f.setFilterExtensions(filters);
444             f.setFilterNames(filterNames);
445         }
446         String JavaDoc chosen = f.open();
447         if (chosen == null) return CANCEL_OPTION;
448         // If it's a multi-select, set the files
449
// 3.4.2004; aweber : in normal java swing curFile is the first selected File here it's the last but i
450
// think this doesn't matter
451

452         if (multiSelect) {
453             curFile = new File JavaDoc(chosen);
454             curFiles = new File JavaDoc[f.getFileNames().length];
455             for (int i = 0; i < f.getFileNames().length; i++) {
456                 curFiles[i] = new File JavaDoc(f.getFileNames()[i]);
457             }
458             curPath = curFile.getParentFile();
459         }
460         else {
461             curFile = new File JavaDoc(chosen);
462             curPath = curFile.getParentFile();
463         }
464         return APPROVE_OPTION;
465     }
466
467     public int showSaveDialog(Component parent) {
468         if (useNative)
469             return showNativeSaveDialog(parent);
470         else
471             return showCustomSaveDialog(parent);
472     }
473
474     protected int showNativeSaveDialog(Component parent) {
475         dialogType = SAVE_DIALOG;
476         org.eclipse.swt.widgets.FileDialog f = new org.eclipse.swt.widgets.FileDialog(parent.getPeer().getShell(), SWT.SAVE );
477         if (dialogTitle.equals(""))
478             f.setText("Save As");
479         else
480             f.setText(dialogTitle);
481         f.setFilterPath(curPath.getAbsolutePath());
482         if (filters != null) {
483             f.setFilterExtensions(filters);
484             f.setFilterNames(filterNames);
485         }
486
487         String JavaDoc chosen = f.open();
488         if (chosen == null) return CANCEL_OPTION;
489         // If it's a multi-select, set the files
490
// 3.4.2004; aweber : in normal java swing curFile is the first selected File here it's the last but i
491
// think this doesn't matter
492

493         if (multiSelect) {
494             curFile = new File JavaDoc(chosen);
495             curFiles = new File JavaDoc[f.getFileNames().length];
496             for (int i = 0; i < f.getFileNames().length; i++) {
497                 curFiles[i] = new File JavaDoc(f.getFileNames()[i]);
498             }
499             curPath = curFile.getParentFile();
500         }
501         else {
502             curFile = new File JavaDoc(chosen);
503             curPath = curFile.getParentFile();
504         }
505         return APPROVE_OPTION;
506     }
507
508     protected int showCustomSaveDialog(Component parent) {
509         dialogType = SAVE_DIALOG;
510         String JavaDoc dt = (dialogTitle.equals("") ? "Save" : dialogTitle);
511         customDialog = new FileChooserDialog(dt, this);
512         rescanCurrentDirectory(); // perhaps not the best place but now its consistent
513
customDialog.show();
514
515         // Build the file for return. curPath could be a complete file
516
// path, but it might just be a directory with the name still
517
// in the box
518
if (curPath.isDirectory()) {
519             String JavaDoc newFile = curPath.getAbsolutePath();
520             if (!newFile.endsWith(File.separator))
521                 newFile += File.separator;
522             curPath = new File JavaDoc(newFile + location.getText());
523         }
524
525         return dialogReturnValue;
526     }
527
528     public String JavaDoc getTitle() { return dialogTitle; }
529     public void setTitle(String JavaDoc title) { dialogTitle = title; }
530
531     /**
532      * Sorts an array of Java <code>File</code> references
533      * into alphabetical order.
534      */

535     public File JavaDoc[] sortFiles(File JavaDoc[] sort) {
536
537         boolean madeAChange = true;
538         while (madeAChange) {
539             madeAChange = false;
540             for (int i = 0; i < sort.length-1; i++) {
541                 int pos = sort[i].toString().compareTo(sort[i+1].toString());
542                 if ( pos > 0 ) {
543                     File JavaDoc buf = sort[i+1];
544                     sort[i+1] = sort[i];
545                     sort[i] = buf;
546                     buf = null;
547                     madeAChange = true;
548                 }
549             }
550         }
551         return sort;
552     }
553
554     /**
555      * Sends property change event to all listeners
556      */

557     protected void firePropertyChangeEvent(String JavaDoc propertyName, Object JavaDoc oldValue, Object JavaDoc newValue) {
558         PropertyChangeEvent JavaDoc e = new PropertyChangeEvent JavaDoc(this, propertyName, oldValue, newValue);
559         for (int i = 0; i < propertyChangeListeners.size(); i++) {
560             ((PropertyChangeListener JavaDoc) propertyChangeListeners.get(i)).propertyChange(e);
561         }
562     }
563
564     /**
565      * Lays out native widgets for this component.
566      */

567     protected void layoutComponent() {
568
569         setLayout(new BorderLayout());
570
571         // NORTH - Drives, CENTER - centre pane with table and accessory, SOUTH - file, type, Ok and Cancel
572
JPanel pnlTool = new JPanel(new BorderLayout());
573
574         // Drives selector
575
pnlTool.add(new JLabel("Drive:"), BorderLayout.WEST);
576         final JComboBox drives = new JComboBox();
577         drives.setPreferredSize(new Dimension(200, 25));
578         pnlTool.add(drives, BorderLayout.CENTER);
579         scanDrives(drives);
580         drives.addItemListener(new ItemListener() {
581             public void itemStateChanged(ItemEvent e) {
582
583                 DriveEntry d = (DriveEntry) drives.getSelectedItem();
584
585                 // Update where we are
586
curPath = (File JavaDoc) d.fileRef;
587                 rescanCurrentDirectory();
588             }
589         });
590
591         // Toolbar
592
add(pnlTool, BorderLayout.NORTH);
593
594         // ===== CENTRAL PANEL - HOLDS FILE LIST AND ENTRY BOXES ===============
595
centralPanel = new JPanel();
596         centralPanel.setLayout(new BorderLayout());
597
598         // File list component
599
fileList = new JList();
600         fileList.setCellRenderer(new JFileChooser.FileListRenderer());
601         // Used for changing into directories and firing property change
602
fileList.addMouseListener(new MouseAdapter() {
603             public void mouseClicked(MouseEvent e) {
604
605                 // Assume no file selected
606
curFile = null;
607                 // Don't do anything if there's no selection
608
if (fileList.getSelectedIndex() == -1) return;
609                 if (fileList.getSelectedValue() == null) return;
610
611                 // Update where we are
612
curFile = (File JavaDoc) fileList.getSelectedValue();
613                 curPath = curFile.getParentFile();
614
615                 // If it isn't a directory, show the name in the text entry
616
// box and fire the property changed event for accessories
617
if(e.getClickCount() == 2) {
618                     if (!curFile.isDirectory()) {
619                         location.setText( curFile.getName() );
620                         firePropertyChangeEvent( SELECTED_FILE_CHANGED_PROPERTY, null, fileList.getSelectedValue());
621                         okButton.processActionEvent(0); // simuate mouseclick
622
} else {
623                         rescanCurrentDirectory();
624                     }
625                 } else {
626                     if (!curFile.isDirectory()) {
627                         location.setText( curFile.getName() );
628                         firePropertyChangeEvent( SELECTED_FILE_CHANGED_PROPERTY, null, fileList.getSelectedValue());
629                     }
630                 }
631             }
632         });
633
634         centralPanel.add(fileList, BorderLayout.CENTER);
635
636         // Entry boxes panel
637
JPanel entryBoxes = new JPanel();
638         entryBoxes.setLayout(new GridLayout(2, 0));
639
640         // Location panel
641
JPanel pnlLocation = new JPanel();
642         pnlLocation.setLayout(new BorderLayout());
643         JLabel lblLoc = new JLabel("Location:");
644         pnlLocation.add(lblLoc, BorderLayout.WEST);
645         lblLoc.setPreferredSize(new Dimension(100, 25));
646
647         location = new JTextField();
648         pnlLocation.add(location, BorderLayout.CENTER);
649
650         entryBoxes.add(pnlLocation);
651
652         // Filter panel
653
JPanel pnlFilter = new JPanel();
654         pnlFilter.setLayout(new BorderLayout());
655         JLabel lblFilter = new JLabel("Filter:");
656         pnlFilter.add(lblFilter, BorderLayout.WEST);
657         lblFilter.setPreferredSize(new Dimension(100, 25));
658
659         filter = new JComboBox();
660         pnlFilter.add(filter, BorderLayout.CENTER);
661         filter.setPreferredSize(new Dimension(300, 25));
662         allFiles = new JFileChooser.FileFilterWrapper(new JFileChooser.AllFileFilter());
663         filter.addItem(allFiles);
664         filter.addItemListener( new ItemListener() {
665             public void itemStateChanged(ItemEvent e) {
666                 rescanCurrentDirectory();
667             }
668         });
669
670         entryBoxes.add(pnlFilter);
671
672         centralPanel.add(entryBoxes, BorderLayout.SOUTH);
673
674
675         add(centralPanel, BorderLayout.CENTER);
676
677         // Buttons
678
buttonPanel = new JPanel();
679         buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
680
681         okButton = (JButton) buttonPanel.add(new JButton("Ok"));
682         okButton.setMnemonic('o');
683         //okButton.setPreferredSize(new Dimension(100, 35));
684
okButton.addActionListener(new ActionListener() {
685             public void actionPerformed(ActionEvent e) {
686                 dialogReturnValue = APPROVE_OPTION;
687
688                 if(multiSelect) {
689                     Object JavaDoc[] aktFiles = fileList.getSelectedValues();
690                     int length = aktFiles.length;
691                     curFiles = new File JavaDoc[length];
692                     for(int i = 0; i < length; i++) {
693                         curFiles[i] = (File JavaDoc) aktFiles[i];
694                     }
695                 }
696
697                 if (customDialog != null) customDialog.dispose();
698             }
699         });
700
701         JButton cancelButton = (JButton) buttonPanel.add(new JButton("Cancel"));
702         cancelButton.setMnemonic('c');
703         //cancelButton.setPreferredSize(new Dimension(100, 35));
704
cancelButton.addActionListener(new ActionListener() {
705             public void actionPerformed(ActionEvent e) {
706                 dialogReturnValue = CANCEL_OPTION;
707                 if (customDialog != null) customDialog.dispose();
708             }
709         });
710
711         add(buttonPanel, BorderLayout.SOUTH);
712
713         // rescanCurrentDirectory(); // if there are file filters definied by the user they're not set at this Point
714
}
715
716     /**
717      * Simple JDialog subclass so we can override size and things
718      * like that.
719      */

720     private class FileChooserDialog extends JDialog {
721         public FileChooserDialog(String JavaDoc title, JFileChooser fc) {
722             super((Frame) null, title);
723             this.setSize(512, 384);
724             this.getContentPane().setLayout(new BorderLayout());
725             this.getContentPane().add(fc, BorderLayout.CENTER);
726             this.setModal(true);
727             this.setLocationRelativeTo(null);
728         }
729     }
730
731     /**
732      * Rendering class for showing file entries. Handles icons.
733      */

734     private class FileListRenderer extends JLabel implements ListCellRenderer {
735
736         ImageIcon dirIcon = new ImageIcon(getClass().getResource("/swingwtx/swing/filechooser/dir.gif"));
737
738         public FileListRenderer() {
739             //setOpaque(true);
740
}
741
742         public swingwt.awt.Component getListCellRendererComponent(JList list, Object JavaDoc value, int index, boolean isSelected, boolean cellHasFocus) {
743
744             File JavaDoc f = (File JavaDoc) value;
745
746             // Parent folder - special case
747
if (index == 0) {
748                 setText("..");
749                 setIcon(dirIcon);
750                 return this;
751             }
752
753             // Name
754
String JavaDoc name = f.getName();
755             if (name.indexOf(File.separator) != -1)
756                 name = name.substring(name.lastIndexOf(File.separator), name.length());
757             setText(name);
758
759             // Icon
760
boolean isDir = f.isDirectory();
761             setIcon(isDir ? dirIcon : null);
762
763             return this;
764          }
765     }
766
767     private class AllFileFilter extends swingwtx.swing.filechooser.FileFilter {
768         public boolean accept(File JavaDoc f) {
769             return true;
770         }
771         public String JavaDoc getDescription() {
772             return "All Files";
773         }
774     }
775
776     /** Wraps up the FileFilter class. Why the fuck didn't the interface on that
777      * use toString() to return the description? Did they do it on purpose to make
778      * it an arse with list components or what?
779      */

780     private class FileFilterWrapper {
781         private swingwtx.swing.filechooser.FileFilter filter = null;
782         public FileFilterWrapper(swingwtx.swing.filechooser.FileFilter f) {
783             filter = f;
784         }
785         public swingwtx.swing.filechooser.FileFilter getFilter() { return filter; }
786         public String JavaDoc toString() {
787             return filter.getDescription();
788         }
789     }
790
791
792     /**
793      * Objects stored in the Drives combo box. Encapsulates a display name
794      * and a file reference.
795      */

796     private class DriveEntry {
797         public File JavaDoc fileRef = null;
798         public String JavaDoc displayName = null;
799         public DriveEntry(File JavaDoc file, String JavaDoc displayName) { fileRef = file; this.displayName = displayName; }
800         public String JavaDoc toString() { return displayName; }
801     }
802 }
803
Popular Tags