OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / plaf / basic / BasicFileChooserUI.java
1 /* BasicFileChooserUI.java --
2    Copyright (C) 2005  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package javax.swing.plaf.basic;
39
40 import java.awt.Window;
41 import java.awt.event.ActionEvent;
42 import java.awt.event.MouseAdapter;
43 import java.awt.event.MouseEvent;
44 import java.awt.event.MouseListener;
45 import java.beans.PropertyChangeEvent;
46 import java.beans.PropertyChangeListener;
47 import java.io.File;
48 import java.io.IOException;
49 import java.util.ArrayList;
50 import java.util.Hashtable;
51
52 import javax.swing.AbstractAction;
53 import javax.swing.Action;
54 import javax.swing.Icon;
55 import javax.swing.JButton;
56 import javax.swing.JComponent;
57 import javax.swing.JDialog;
58 import javax.swing.JFileChooser;
59 import javax.swing.JList;
60 import javax.swing.JPanel;
61 import javax.swing.JTextField;
62 import javax.swing.SwingUtilities;
63 import javax.swing.UIDefaults;
64 import javax.swing.UIManager;
65 import javax.swing.event.ListSelectionEvent;
66 import javax.swing.event.ListSelectionListener;
67 import javax.swing.filechooser.FileFilter;
68 import javax.swing.filechooser.FileSystemView;
69 import javax.swing.filechooser.FileView;
70 import javax.swing.plaf.ComponentUI;
71 import javax.swing.plaf.FileChooserUI;
72 import javax.swing.plaf.metal.MetalIconFactory;
73
74
75 /**
76  * A UI delegate for the {@link JFileChooser} component under the 
77  * {@link BasicLookAndFeel}.
78  */
79 public class BasicFileChooserUI extends FileChooserUI
80 {
81   /**
82    * A file filter that accepts all files.
83    */
84   protected class AcceptAllFileFilter extends FileFilter
85   {
86     /**
87      * Creates a new instance.
88      */
89     public AcceptAllFileFilter()
90     {
91       // Nothing to do here.
92     }
93     
94     /**
95      * Returns <code>true</code> always, as all files are accepted by this
96      * filter.
97      *
98      * @param f  the file.
99      *
100      * @return Always <code>true</code>.
101      */
102     public boolean accept(File f)
103     {
104       return true;
105     }
106
107     /**
108      * Returns a description for this filter.
109      *
110      * @return A description for the file filter.
111      */
112     public String getDescription()
113     {
114       return acceptAllFileFilterText;
115     }
116   }
117
118   /**
119    * Handles a user action to approve the dialog selection.
120    * 
121    * @see BasicFileChooserUI#getApproveSelectionAction()
122    */
123   protected class ApproveSelectionAction extends AbstractAction
124   {
125     /**
126      * Creates a new ApproveSelectionAction object.
127      */
128     protected ApproveSelectionAction()
129     {
130       super("approveSelection");
131     }
132
133     /**
134      * Sets the current selection and closes the dialog.
135      * 
136      * @param e  the action event.
137      */
138     public void actionPerformed(ActionEvent e)
139     {
140       Object obj = null;
141       if (parentPath != null)
142         obj = new String(parentPath + getFileName());
143       else
144         obj = filechooser.getSelectedFile();
145       if (obj != null)
146         {
147           File f = filechooser.getFileSystemView().createFileObject(obj.toString());
148           File currSelected = filechooser.getSelectedFile();
149           if (filechooser.isTraversable(f))
150             {
151               filechooser.setCurrentDirectory(currSelected);
152               filechooser.rescanCurrentDirectory();
153             }
154           else
155             {
156               filechooser.approveSelection();
157               closeDialog();
158             }
159         }
160       else
161         {
162           File f = new File(filechooser.getCurrentDirectory(), getFileName());
163           if ( selectedDir != null )
164             f = selectedDir;
165           if (filechooser.isTraversable(f))
166             {
167               filechooser.setCurrentDirectory(f);
168               filechooser.rescanCurrentDirectory();
169             }
170           else
171             {
172               filechooser.setSelectedFile(f);
173               filechooser.approveSelection();
174               closeDialog();
175             }
176         }
177     }
178   }
179
180   /**
181    * Provides presentation information about files and directories.
182    */
183   protected class BasicFileView extends FileView
184   {
185     /** Storage for cached icons. */
186     protected Hashtable<File, Icon> iconCache = new Hashtable<File, Icon>();
187
188     /**
189      * Creates a new instance.
190      */
191     public BasicFileView()
192     {
193       // Nothing to do here.
194     }
195
196     /**
197      * Adds an icon to the cache, associating it with the given file/directory.
198      *
199      * @param f  the file/directory.
200      * @param i  the icon.
201      */
202     public void cacheIcon(File f, Icon i)
203     {
204       iconCache.put(f, i);
205     }
206
207     /**
208      * Clears the icon cache.
209      */
210     public void clearIconCache()
211     {
212       iconCache.clear();
213     }
214
215     /**
216      * Retrieves the icon associated with the specified file/directory, if 
217      * there is one.
218      *
219      * @param f  the file/directory.
220      *
221      * @return The cached icon (or <code>null</code>).
222      */
223     public Icon getCachedIcon(File f)
224     {
225       return (Icon) iconCache.get(f);
226     }
227
228     /**
229      * Returns a description of the given file/directory.  In this 
230      * implementation, the description is the same as the name returned by 
231      * {@link #getName(File)}.
232      *
233      * @param f  the file/directory.
234      *
235      * @return A description of the given file/directory.
236      */
237     public String getDescription(File f)
238     {
239       return getName(f);
240     }
241
242     /**
243      * Returns an icon appropriate for the given file or directory.
244      *
245      * @param f  the file/directory.
246      *
247      * @return An icon.
248      */
249     public Icon getIcon(File f)
250     {
251       Icon val = getCachedIcon(f);
252       if (val != null)
253         return val;
254       if (filechooser.isTraversable(f))
255         val = directoryIcon;
256       else
257         val = fileIcon;
258       cacheIcon(f, val);
259       return val;
260     }
261
262     /**
263      * Returns the name for the given file/directory.
264      *
265      * @param f  the file/directory.
266      *
267      * @return The name of the file/directory.
268      */
269     public String getName(File f)
270     {
271       String name = null;
272       if (f != null)
273         {
274           JFileChooser c = getFileChooser();
275           FileSystemView v = c.getFileSystemView();
276           name = v.getSystemDisplayName(f);
277         }
278       return name;
279     }
280
281     /**
282      * Returns a localised description for the type of file/directory.
283      *
284      * @param f  the file/directory.
285      *
286      * @return A type description for the given file/directory.
287      */
288     public String getTypeDescription(File f)
289     {
290       if (filechooser.isTraversable(f))
291         return dirDescText;
292       else
293         return fileDescText;
294     }
295
296     /**
297      * Returns {@link Boolean#TRUE} if the given file/directory is hidden,
298      * and {@link Boolean#FALSE} otherwise.
299      *
300      * @param f  the file/directory.
301      *
302      * @return {@link Boolean#TRUE} or {@link Boolean#FALSE}.
303      */
304     public Boolean isHidden(File f)
305     {
306       return Boolean.valueOf(filechooser.getFileSystemView().isHiddenFile(f));
307     }
308   }
309
310   /**
311    * Handles an action to cancel the file chooser.
312    * 
313    * @see BasicFileChooserUI#getCancelSelectionAction()
314    */
315   protected class CancelSelectionAction extends AbstractAction
316   {
317     /**
318      * Creates a new <code>CancelSelectionAction</code> object.
319      */
320     protected CancelSelectionAction()
321     {
322       super(null);
323     }
324
325     /**
326      * Cancels the selection and closes the dialog.
327      *
328      * @param e  the action event (ignored).
329      */
330     public void actionPerformed(ActionEvent e)
331     {
332       filechooser.setSelectedFile(null);
333       filechooser.setSelectedFiles(null);
334       filechooser.cancelSelection();
335       closeDialog();
336     }
337   }
338
339   /**
340    * An action to handle changes to the parent directory (for example, via
341    * a click on the "up folder" button).
342    * 
343    * @see BasicFileChooserUI#getChangeToParentDirectoryAction()
344    */
345   protected class ChangeToParentDirectoryAction extends AbstractAction
346   {
347     /**
348      * Creates a new <code>ChangeToParentDirectoryAction</code> object.
349      */
350     protected ChangeToParentDirectoryAction()
351     {
352       super("Go Up");
353     }
354
355     /**
356      * Handles the action event.
357      *
358      * @param e  the action event.
359      */
360     public void actionPerformed(ActionEvent e)
361     {
362       filechooser.changeToParentDirectory();
363       filechooser.revalidate();
364       filechooser.repaint();
365     }
366   }
367
368   /**
369    * A mouse listener that handles double-click events.
370    * 
371    * @see BasicFileChooserUI#createDoubleClickListener(JFileChooser, JList)
372    */
373   protected class DoubleClickListener extends MouseAdapter
374   {
375
376     /** DOCUMENT ME! */
377     private Object lastSelected;
378
379     /** DOCUMENT ME! */
380     private JList list;
381
382     /**
383      * Creates a new DoubleClickListener object.
384      *
385      * @param list DOCUMENT ME!
386      */
387     public DoubleClickListener(JList list)
388     {
389       this.list = list;
390       lastSelected = list.getSelectedValue();
391       setDirectorySelected(false);
392     }
393
394     /**
395      * Handles a mouse click event.
396      * 
397      * @param e  the event.
398      */
399     public void mouseClicked(MouseEvent e)
400     {
401       Object p = list.getSelectedValue();
402       if (p == null)
403         return;
404       FileSystemView fsv = filechooser.getFileSystemView();
405       if (e.getClickCount() >= 2 && lastSelected != null &&
406           p.toString().equals(lastSelected.toString()))
407         {
408           File f = fsv.createFileObject(lastSelected.toString());
409           if (filechooser.isTraversable(f))
410             {
411               filechooser.setCurrentDirectory(f);
412               filechooser.rescanCurrentDirectory();
413             }
414           else
415             {
416               filechooser.setSelectedFile(f);
417               filechooser.approveSelection();
418               closeDialog();
419             }
420         }
421       else // single click
422         {
423           String path = p.toString();
424           File f = fsv.createFileObject(path);
425           filechooser.setSelectedFile(f);
426           
427           if (filechooser.isMultiSelectionEnabled())
428             {
429               int[] inds = list.getSelectedIndices();
430               File[] allFiles = new File[inds.length];
431               for (int i = 0; i < inds.length; i++)
432                 allFiles[i] = (File) list.getModel().getElementAt(inds[i]);
433               filechooser.setSelectedFiles(allFiles);
434             }
435           
436           if (filechooser.isTraversable(f))
437             {
438               setDirectorySelected(true);
439               setDirectory(f);
440             }
441           else
442             {
443               setDirectorySelected(false);
444               setDirectory(null);
445             }
446           lastSelected = path;
447           parentPath = f.getParent();
448             
449           if (f.isFile())
450             setFileName(f.getName());
451           else if (filechooser.getFileSelectionMode() != 
452                    JFileChooser.FILES_ONLY)
453             setFileName(path);
454         }
455     }
456
457     /**
458      * Handles a mouse entered event (NOT IMPLEMENTED).
459      * 
460      * @param e  the mouse event.
461      */
462     public void mouseEntered(MouseEvent e)
463     {
464       // FIXME: Implement
465     }
466   }
467
468   /**
469    * An action that changes the file chooser to display the user's home 
470    * directory. 
471    * 
472    * @see BasicFileChooserUI#getGoHomeAction()
473    */
474   protected class GoHomeAction extends AbstractAction
475   {
476     /**
477      * Creates a new <code>GoHomeAction</code> object.
478      */
479     protected GoHomeAction()
480     {
481       super("Go Home");
482     }
483
484     /**
485      * Sets the directory to the user's home directory, and repaints the
486      * file chooser component.
487      *
488      * @param e  the action event (ignored).
489      */
490     public void actionPerformed(ActionEvent e)
491     {
492       filechooser.setCurrentDirectory(filechooser.getFileSystemView()
493                                                  .getHomeDirectory());
494       filechooser.revalidate();
495       filechooser.repaint();
496     }
497   }
498
499   /**
500    * An action that handles the creation of a new folder/directory.
501    * 
502    * @see BasicFileChooserUI#getNewFolderAction()
503    */
504   protected class NewFolderAction extends AbstractAction
505   {
506     /**
507      * Creates a new <code>NewFolderAction</code> object.
508      */
509     protected NewFolderAction()
510     {
511       super("New Folder");
512     }
513
514     /**
515      * Handles the event by creating a new folder.
516      *
517      * @param e  the action event (ignored).
518      */
519     public void actionPerformed(ActionEvent e)
520     {
521       try
522         {
523           filechooser.getFileSystemView().createNewFolder(filechooser
524                                                           .getCurrentDirectory());
525         }
526       catch (IOException ioe)
527         {
528           return;
529         }
530       filechooser.rescanCurrentDirectory();
531       filechooser.repaint();
532     }
533   }
534
535   /**
536    * A listener for selection events in the file list.
537    * 
538    * @see BasicFileChooserUI#createListSelectionListener(JFileChooser)
539    */
540   protected class SelectionListener implements ListSelectionListener
541   {
542     /**
543      * Creates a new <code>SelectionListener</code> object.
544      */
545     protected SelectionListener()
546     {
547       // Nothing to do here.
548     }
549
550     /**
551      * Sets the JFileChooser to the selected file on an update
552      *
553      * @param e DOCUMENT ME!
554      */
555     public void valueChanged(ListSelectionEvent e)
556     {
557       JList list = (JList) e.getSource();
558       Object f = list.getSelectedValue();
559       if (f == null)
560         return;
561       File file = filechooser.getFileSystemView().createFileObject(f.toString());
562       if (! filechooser.isTraversable(file))
563         {
564           selectedDir = null;
565           filechooser.setSelectedFile(file);
566         }
567       else
568         {
569           selectedDir = file;
570           filechooser.setSelectedFile(null);
571         }
572     }
573   }
574
575   /**
576    * DOCUMENT ME!
577    * 
578    * @see BasicFileChooserUI#getUpdateAction()
579    */
580   protected class UpdateAction extends AbstractAction
581   {
582     /**
583      * Creates a new UpdateAction object.
584      */
585     protected UpdateAction()
586     {
587       super(null);
588     }
589
590     /**
591      * NOT YET IMPLEMENTED.
592      *
593      * @param e  the action event.
594      */
595     public void actionPerformed(ActionEvent e)
596     {
597       // FIXME: implement this
598     }
599   }
600
601   /** The localised mnemonic for the cancel button. */
602   protected int cancelButtonMnemonic;
603
604   /** The localised text for the cancel button. */
605   protected String cancelButtonText;
606
607   /** The localised tool tip text for the cancel button. */
608   protected String cancelButtonToolTipText;
609
610   /** An icon representing a computer. */
611   protected Icon computerIcon;
612
613   /** An icon for the "details view" button. */
614   protected Icon detailsViewIcon;
615
616   /** An icon representing a directory. */
617   protected Icon directoryIcon;
618
619   /** The localised Mnemonic for the open button. */
620   protected int directoryOpenButtonMnemonic;
621
622   /** The localised text for the open button. */
623   protected String directoryOpenButtonText;
624
625   /** The localised tool tip text for the open button. */
626   protected String directoryOpenButtonToolTipText;
627
628   /** An icon representing a file. */
629   protected Icon fileIcon;
630
631   /** An icon representing a floppy drive. */
632   protected Icon floppyDriveIcon;
633
634   /** An icon representing a hard drive. */
635   protected Icon hardDriveIcon;
636
637   /** The localised mnemonic for the "help" button. */
638   protected int helpButtonMnemonic;
639
640   /** The localised text for the "help" button. */
641   protected String helpButtonText;
642
643   /** The localised tool tip text for the help button. */
644   protected String helpButtonToolTipText;
645
646   /** An icon representing the user's home folder. */
647   protected Icon homeFolderIcon;
648
649   /** An icon for the "list view" button. */
650   protected Icon listViewIcon;
651
652   /** An icon for the "new folder" button. */
653   protected Icon newFolderIcon = directoryIcon;
654
655   /** The localised mnemonic for the "open" button. */
656   protected int openButtonMnemonic;
657
658   /** The localised text for the "open" button. */
659   protected String openButtonText;
660
661   /** The localised tool tip text for the "open" button. */
662   protected String openButtonToolTipText;
663
664   /** The localised mnemonic for the "save" button. */
665   protected int saveButtonMnemonic;
666
667   /** The localised text for the "save" button. */
668   protected String saveButtonText;
669
670   /** The localised tool tip text for the save button. */
671   protected String saveButtonToolTipText;
672
673   /** The localised mnemonic for the "update" button. */
674   protected int updateButtonMnemonic;
675
676   /** The localised text for the "update" button. */
677   protected String updateButtonText;
678
679   /** The localised tool tip text for the "update" button. */
680   protected String updateButtonToolTipText;
681
682   /** An icon for the "up folder" button. */
683   protected Icon upFolderIcon;
684
685   // -- begin private, but package local since used in inner classes --
686
687   /** The file chooser component represented by this UI delegate. */
688   JFileChooser filechooser;
689
690   /** The model for the directory list. */
691   BasicDirectoryModel model;
692
693   /** The file filter for all files. */
694   FileFilter acceptAll = new AcceptAllFileFilter();
695
696   /** The default file view. */
697   FileView fv = new BasicFileView();
698
699   /** The accept (open/save) button. */
700   JButton accept;
701
702   /** An optional accessory panel. */
703   JPanel accessoryPanel = new JPanel();
704
705   /** A property change listener. */
706   PropertyChangeListener propertyChangeListener;
707
708   /** The text describing the filter for "all files". */
709   String acceptAllFileFilterText;
710
711   /** The text describing a directory type. */
712   String dirDescText;
713
714   /** The text describing a file type. */
715   String fileDescText;
716
717   /** Is a directory selected? */
718   boolean dirSelected;
719
720   /** The current directory. */
721   File currDir;
722
723   // FIXME: describe what is contained in the bottom panel
724   /** The bottom panel. */
725   JPanel bottomPanel;
726   
727   /** The close panel. */
728   JPanel closePanel;
729
730   /** Text box that displays file name */
731   JTextField entry;
732     
733   /** Current parent path */
734   String parentPath;
735   
736   /**
737    * The action for the 'approve' button.
738    * @see #getApproveSelectionAction()
739    */
740   private ApproveSelectionAction approveSelectionAction;
741   
742   /**
743    * The action for the 'cancel' button.
744    * @see #getCancelSelectionAction()
745    */
746   private CancelSelectionAction cancelSelectionAction;
747   
748   /**
749    * The action for the 'go home' control button.
750    * @see #getGoHomeAction()
751    */
752   private GoHomeAction goHomeAction;
753   
754   /**
755    * The action for the 'up folder' control button.
756    * @see #getChangeToParentDirectoryAction()
757    */
758   private ChangeToParentDirectoryAction changeToParentDirectoryAction;
759   
760   /**
761    * The action for the 'new folder' control button.
762    * @see #getNewFolderAction()
763    */
764   private NewFolderAction newFolderAction;
765   
766   /**
767    * The action for ???.  // FIXME: what is this?
768    * @see #getUpdateAction()
769    */
770   private UpdateAction updateAction;
771
772   /**
773    * When in FILES_ONLY, mode a directory cannot be selected, so
774    * we save a reference to any it here. This is used to enter
775    * the directory on "Open" when in that mode.
776    */
777   private File selectedDir;
778   
779   // -- end private --
780
781   /**
782    * Closes the dialog.
783    */
784   void closeDialog()
785   {
786     Window owner = SwingUtilities.windowForComponent(filechooser);
787     if (owner instanceof JDialog)
788       ((JDialog) owner).dispose();
789   }
790
791   /**
792    * Creates a new <code>BasicFileChooserUI</code> object.
793    *
794    * @param b  the file chooser component.
795    */
796   public BasicFileChooserUI(JFileChooser b)
797   {
798   }
799
800   /**
801    * Returns a UI delegate for the given component.
802    *
803    * @param c  the component (should be a {@link JFileChooser}).
804    *
805    * @return A new UI delegate.
806    */
807   public static ComponentUI createUI(JComponent c)
808   {
809     return new BasicFileChooserUI((JFileChooser) c);
810   }
811
812   /**
813    * Installs the UI for the specified component.
814    * 
815    * @param c  the component (should be a {@link JFileChooser}).
816    */
817   public void installUI(JComponent c)
818   {
819     if (c instanceof JFileChooser)
820       {
821         JFileChooser fc = (JFileChooser) c;
822         this.filechooser = fc;
823         fc.resetChoosableFileFilters();
824         createModel();
825         clearIconCache();
826         installDefaults(fc);
827         installComponents(fc);
828         installListeners(fc);
829         
830         File path = filechooser.getCurrentDirectory();
831         if (path != null)
832           parentPath = path.getParent();
833       }
834   }
835
836   /**
837    * Uninstalls this UI from the given component.
838    * 
839    * @param c  the component (should be a {@link JFileChooser}).
840    */
841   public void uninstallUI(JComponent c)
842   {
843     model = null;
844     uninstallListeners(filechooser);
845     uninstallComponents(filechooser);
846     uninstallDefaults(filechooser);
847     filechooser = null;
848   }
849
850   // FIXME: Indent the entries in the combobox
851   // Made this method package private to access it from within inner classes
852   // with better performance
853   void boxEntries()
854   {
855     ArrayList parentFiles = new ArrayList();
856     File parent = filechooser.getCurrentDirectory();
857     if (parent == null)
858       parent = filechooser.getFileSystemView().getDefaultDirectory();
859     while (parent != null)
860       {
861         String name = parent.getName();
862         if (name.equals(""))
863           name = parent.getAbsolutePath();
864
865         parentFiles.add(parentFiles.size(), name);
866         parent = parent.getParentFile();
867       }
868
869     if (parentFiles.size() == 0)
870       return;
871
872   }  
873
874   /**
875    * Creates and install the subcomponents for the file chooser.
876    *
877    * @param fc  the file chooser.
878    */
879   public void installComponents(JFileChooser fc)
880   {
881   }
882
883   /**
884    * Uninstalls the components from the file chooser.
885    *
886    * @param fc  the file chooser.
887    */
888   public void uninstallComponents(JFileChooser fc)
889   {
890   }
891
892   /**
893    * Installs the listeners required by this UI delegate.
894    *
895    * @param fc  the file chooser.
896    */
897   protected void installListeners(JFileChooser fc)
898   {
899     propertyChangeListener = createPropertyChangeListener(filechooser);
900     if (propertyChangeListener != null)
901       filechooser.addPropertyChangeListener(propertyChangeListener);
902     fc.addPropertyChangeListener(getModel());
903   }
904
905   /**
906    * Uninstalls the listeners previously installed by this UI delegate.
907    *
908    * @param fc  the file chooser.
909    */
910   protected void uninstallListeners(JFileChooser fc)
911   {
912     if (propertyChangeListener != null)
913       {
914         filechooser.removePropertyChangeListener(propertyChangeListener);
915         propertyChangeListener = null;
916       }
917     fc.removePropertyChangeListener(getModel());
918   }
919
920   /**
921    * Installs the defaults for this UI delegate.
922    *
923    * @param fc  the file chooser.
924    */
925   protected void installDefaults(JFileChooser fc)
926   {
927     installIcons(fc);
928     installStrings(fc);
929   }
930
931   /**
932    * Uninstalls the defaults previously added by this UI delegate.
933    *
934    * @param fc  the file chooser.
935    */
936   protected void uninstallDefaults(JFileChooser fc)
937   {
938     uninstallStrings(fc);
939     uninstallIcons(fc);
940   }
941
942   /**
943    * Installs the icons for this UI delegate.
944    *
945    * @param fc  the file chooser (ignored).
946    */
947   protected void installIcons(JFileChooser fc)
948   {
949     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
950     computerIcon = MetalIconFactory.getTreeComputerIcon();
951     detailsViewIcon = defaults.getIcon("FileChooser.detailsViewIcon");
952     directoryIcon = new MetalIconFactory.TreeFolderIcon();
953     fileIcon = new MetalIconFactory.TreeLeafIcon();
954     floppyDriveIcon = MetalIconFactory.getTreeFloppyDriveIcon();
955     hardDriveIcon = MetalIconFactory.getTreeHardDriveIcon();
956     homeFolderIcon = defaults.getIcon("FileChooser.homeFolderIcon");
957     listViewIcon = defaults.getIcon("FileChooser.listViewIcon");
958     newFolderIcon = defaults.getIcon("FileChooser.newFolderIcon");
959     upFolderIcon = defaults.getIcon("FileChooser.upFolderIcon");
960   }
961
962   /**
963    * Uninstalls the icons previously added by this UI delegate.
964    *
965    * @param fc  the file chooser.
966    */
967   protected void uninstallIcons(JFileChooser fc)
968   {
969     computerIcon = null;
970     detailsViewIcon = null;
971     directoryIcon = null;
972     fileIcon = null;
973     floppyDriveIcon = null;
974     hardDriveIcon = null;
975     homeFolderIcon = null;
976     listViewIcon = null;
977     newFolderIcon = null;
978     upFolderIcon = null;
979   }
980
981   /**
982    * Installs the strings used by this UI delegate.
983    *
984    * @param fc  the file chooser.
985    */
986   protected void installStrings(JFileChooser fc)
987   {
988     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
989
990     dirDescText = defaults.getString("FileChooser.directoryDescriptionText");
991     fileDescText = defaults.getString("FileChooser.fileDescriptionText");
992
993     acceptAllFileFilterText = defaults.getString("FileChooser.acceptAllFileFilterText");
994     cancelButtonText = "Cancel";
995     cancelButtonToolTipText = "Abort file chooser dialog";
996     cancelButtonMnemonic = new Integer((String) UIManager.get("FileChooser.cancelButtonMnemonic")).intValue();
997
998     directoryOpenButtonText = "Open";
999     directoryOpenButtonToolTipText = "Open selected directory";
1000     directoryOpenButtonMnemonic 
1001         = new Integer((String) UIManager.get("FileChooser.directoryOpenButtonMnemonic")).intValue();
1002     
1003     helpButtonText = "Help";
1004     helpButtonToolTipText = "FileChooser help";
1005     helpButtonMnemonic = new Integer((String) UIManager.get("FileChooser.helpButtonMnemonic")).intValue();
1006
1007     openButtonText = "Open";
1008     openButtonToolTipText = "Open selected file";
1009     openButtonMnemonic = new Integer((String) UIManager.get("FileChooser.openButtonMnemonic")).intValue();
1010
1011     saveButtonText = "Save";
1012     saveButtonToolTipText = "Save selected file";
1013     saveButtonMnemonic = new Integer((String) UIManager.get("FileChooser.saveButtonMnemonic")).intValue();
1014   
1015     updateButtonText = "Update";
1016     updateButtonToolTipText = "Update directory listing";
1017     updateButtonMnemonic = new Integer((String) UIManager.get("FileChooser.updateButtonMnemonic")).intValue();
1018   }
1019
1020   /**
1021    * Uninstalls the strings previously added by this UI delegate.
1022    *
1023    * @param fc  the file chooser.
1024    */
1025   protected void uninstallStrings(JFileChooser fc)
1026   {
1027     acceptAllFileFilterText = null;
1028     dirDescText = null;
1029     fileDescText = null;
1030
1031     cancelButtonText = null;
1032     cancelButtonToolTipText = null;
1033
1034     directoryOpenButtonText = null;
1035     directoryOpenButtonToolTipText = null;
1036
1037     helpButtonText = null;
1038     helpButtonToolTipText = null;
1039
1040     openButtonText = null;
1041     openButtonToolTipText = null;
1042
1043     saveButtonText = null;
1044     saveButtonToolTipText = null;
1045     
1046     updateButtonText = null;
1047     updateButtonToolTipText = null;
1048   }
1049
1050   /**
1051    * Creates a new directory model.
1052    */
1053   protected void createModel()
1054   {
1055     model = new BasicDirectoryModel(filechooser);
1056   }
1057
1058   /**
1059    * Returns the directory model.
1060    *
1061    * @return The directory model.
1062    */
1063   public BasicDirectoryModel getModel()
1064   {
1065     return model;
1066   }
1067
1068   /**
1069    * Creates a listener to handle changes to the properties of the given
1070    * file chooser component.
1071    * 
1072    * @param fc  the file chooser component.
1073    * 
1074    * @return A new listener.
1075    */
1076   public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
1077   {
1078     // The RI returns null here, so do we.
1079     return null;
1080   }
1081
1082   /**
1083    * Returns the current file name.
1084    * 
1085    * @return The current file name.
1086    */
1087   public String getFileName()
1088   {
1089     return entry.getText();
1090   }
1091
1092   /**
1093    * Returns the current directory name.
1094    *
1095    * @return The directory name.
1096    * 
1097    * @see #setDirectoryName(String)
1098    */
1099   public String getDirectoryName()
1100   {
1101     // XXX: I don't see a case where the thing returns something non-null..
1102     return null;
1103   }
1104
1105   /**
1106    * Sets the file name.
1107    *
1108    * @param filename  the file name.
1109    * 
1110    * @see #getFileName()
1111    */
1112   public void setFileName(String filename)
1113   {
1114     // FIXME:  it might be the case that this method provides an access 
1115     // point for the JTextField (or whatever) a subclass is using...
1116     //this.filename = filename;
1117   }
1118
1119   /**
1120    * Sets the directory name (NOT IMPLEMENTED).
1121    *
1122    * @param dirname  the directory name.
1123    * 
1124    * @see #getDirectoryName()
1125    */
1126   public void setDirectoryName(String dirname)
1127   {
1128     // FIXME: Implement
1129   }
1130
1131   /**
1132    * Rescans the current directory.
1133    *
1134    * @param fc  the file chooser.
1135    */
1136   public void rescanCurrentDirectory(JFileChooser fc)
1137   {
1138     getModel().validateFileCache();
1139   }
1140
1141   /**
1142    * NOT YET IMPLEMENTED.
1143    *
1144    * @param fc  the file chooser.
1145    * @param f  the file.
1146    */
1147   public void ensureFileIsVisible(JFileChooser fc, File f)
1148   {
1149     // XXX: Not sure what this does.
1150   }
1151
1152   /**
1153    * Returns the {@link JFileChooser} component that this UI delegate 
1154    * represents.
1155    *
1156    * @return The component represented by this UI delegate.
1157    */
1158   public JFileChooser getFileChooser()
1159   {
1160     return filechooser;
1161   }
1162
1163   /**
1164    * Returns the optional accessory panel.
1165    *
1166    * @return The optional accessory panel.
1167    */
1168   public JPanel getAccessoryPanel()
1169   {
1170     return accessoryPanel;
1171   }
1172
1173   /**
1174    * Returns the approve (open or save) button for the dialog.
1175    *
1176    * @param fc  the file chooser.
1177    *
1178    * @return The button.
1179    */
1180   protected JButton getApproveButton(JFileChooser fc)
1181   {
1182     return accept;
1183   }
1184
1185   /**
1186    * Returns the tool tip text for the approve (open/save) button.  This first
1187    * checks the file chooser to see if a value has been explicitly set - if
1188    * not, a default value appropriate for the type of file chooser is 
1189    * returned.
1190    *
1191    * @param fc  the file chooser.
1192    *
1193    * @return The tool tip text.
1194    */
1195   public String getApproveButtonToolTipText(JFileChooser fc)
1196   {
1197     if (fc.getApproveButtonToolTipText() != null)
1198       return fc.getApproveButtonToolTipText();
1199     else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1200       return saveButtonToolTipText;
1201     else
1202       return openButtonToolTipText;
1203   }
1204
1205   /**
1206    * Clears the icon cache.
1207    */
1208   public void clearIconCache()
1209   {
1210     if (fv instanceof BasicFileView)
1211       ((BasicFileView) fv).clearIconCache();
1212   }
1213
1214   /**
1215    * Creates a new listener to handle selections in the file list.
1216    *
1217    * @param fc  the file chooser component.
1218    *
1219    * @return A new instance of {@link SelectionListener}.
1220    */
1221   public ListSelectionListener createListSelectionListener(JFileChooser fc)
1222   {
1223     return new SelectionListener();
1224   }
1225
1226   /**
1227    * Creates a new listener to handle double-click events.
1228    *
1229    * @param fc  the file chooser component.
1230    * @param list  the list.
1231    *
1232    * @return A new instance of {@link DoubleClickListener}.
1233    */
1234   protected MouseListener createDoubleClickListener(JFileChooser fc, JList list)
1235   {
1236     return new DoubleClickListener(list);
1237   }
1238
1239   /**
1240    * Returns <code>true</code> if a directory is selected, and 
1241    * <code>false</code> otherwise.
1242    *
1243    * @return A boolean.
1244    */
1245   protected boolean isDirectorySelected()
1246   {
1247     return dirSelected;
1248   }
1249
1250   /**
1251    * Sets the flag that indicates whether the current directory is selected.
1252    *
1253    * @param selected  the new flag value.
1254    */
1255   protected void setDirectorySelected(boolean selected)
1256   {
1257     dirSelected = selected;
1258   }
1259
1260   /**
1261    * Returns the current directory.
1262    *
1263    * @return The current directory.
1264    */
1265   protected File getDirectory()
1266   {
1267     return currDir;
1268   }
1269
1270   /**
1271    * Sets the current directory.
1272    *
1273    * @param f  the directory.
1274    */
1275   protected void setDirectory(File f)
1276   {
1277     currDir = f;
1278   }
1279
1280   /**
1281    * Returns the "accept all" file filter.
1282    *
1283    * @param fc  the file chooser component.
1284    *
1285    * @return The "accept all" file filter.
1286    */
1287   public FileFilter getAcceptAllFileFilter(JFileChooser fc)
1288   {
1289     return acceptAll;
1290   }
1291
1292   /**
1293    * Returns the default file view (NOT the file view from the file chooser,
1294    * if there is one).
1295    *
1296    * @param fc  the file chooser component.
1297    *
1298    * @return The file view.
1299    * 
1300    * @see JFileChooser#getFileView()
1301    */
1302   public FileView getFileView(JFileChooser fc)
1303   {
1304     return fv;
1305   }
1306
1307   /**
1308    * Returns the dialog title.
1309    *
1310    * @param fc  the file chooser (<code>null</code> not permitted).
1311    *
1312    * @return The dialog title.
1313    * 
1314    * @see JFileChooser#getDialogTitle()
1315    */
1316   public String getDialogTitle(JFileChooser fc)
1317   {
1318     String result = fc.getDialogTitle();
1319     if (result == null)
1320       result = getApproveButtonText(fc);
1321     return result;
1322   }
1323
1324   /**
1325    * Returns the approve button mnemonic.
1326    *
1327    * @param fc  the file chooser (<code>null</code> not permitted).
1328    *
1329    * @return The approve button mnemonic.
1330    * 
1331    * @see JFileChooser#getApproveButtonMnemonic()
1332    */
1333   public int getApproveButtonMnemonic(JFileChooser fc)
1334   {
1335     if (fc.getApproveButtonMnemonic() != 0)
1336       return fc.getApproveButtonMnemonic();
1337     else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1338       return saveButtonMnemonic;
1339     else
1340       return openButtonMnemonic;
1341   }
1342
1343   /**
1344    * Returns the approve button text.
1345    *
1346    * @param fc  the file chooser (<code>null</code> not permitted).
1347    *
1348    * @return The approve button text.
1349    * 
1350    * @see JFileChooser#getApproveButtonText()
1351    */
1352   public String getApproveButtonText(JFileChooser fc)
1353   {
1354     String result = fc.getApproveButtonText();
1355     if (result == null)
1356       {
1357         if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
1358           result = saveButtonText;
1359         else
1360           result = openButtonText;
1361       }
1362     return result;
1363   }
1364
1365   /**
1366    * Creates and returns a new action that will be used with the "new folder" 
1367    * button.
1368    *
1369    * @return A new instance of {@link NewFolderAction}.
1370    */
1371   public Action getNewFolderAction()
1372   {
1373     if (newFolderAction == null)
1374       newFolderAction = new NewFolderAction();
1375     return newFolderAction;
1376   }
1377
1378   /**
1379    * Creates and returns a new action that will be used with the "home folder" 
1380    * button.
1381    *
1382    * @return A new instance of {@link GoHomeAction}.
1383    */
1384   public Action getGoHomeAction()
1385   {
1386     if (goHomeAction == null)
1387       goHomeAction = new GoHomeAction();
1388     return goHomeAction;
1389   }
1390
1391   /**
1392    * Returns the action that handles events for the "up folder" control button.
1393    *
1394    * @return An instance of {@link ChangeToParentDirectoryAction}.
1395    */
1396   public Action getChangeToParentDirectoryAction()
1397   {
1398     if (changeToParentDirectoryAction == null)
1399       changeToParentDirectoryAction = new ChangeToParentDirectoryAction();
1400     return changeToParentDirectoryAction;
1401   }
1402
1403   /**
1404    * Returns the action that handles events for the "approve" button.
1405    *
1406    * @return An instance of {@link ApproveSelectionAction}.
1407    */
1408   public Action getApproveSelectionAction()
1409   {
1410     if (approveSelectionAction == null)
1411       approveSelectionAction = new ApproveSelectionAction();
1412     return approveSelectionAction;
1413   }
1414
1415   /**
1416    * Returns the action that handles events for the "cancel" button.
1417    *
1418    * @return An instance of {@link CancelSelectionAction}.
1419    */
1420   public Action getCancelSelectionAction()
1421   {
1422     if (cancelSelectionAction == null)
1423       cancelSelectionAction = new CancelSelectionAction();
1424     return cancelSelectionAction;
1425   }
1426
1427   /**
1428    * Returns the update action (an instance of {@link UpdateAction}).
1429    *
1430    * @return An action. 
1431    */
1432   public Action getUpdateAction()
1433   {
1434     if (updateAction == null)
1435       updateAction = new UpdateAction();
1436     return updateAction;
1437   }
1438 }