001    /*
002     * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>.
003     *
004     * This file is part of
005     * CleanSheets - a spreadsheet application for the Java platform.
006     *
007     * CleanSheets is free software; you can redistribute it and/or modify
008     * it under the terms of the GNU General Public License as published by
009     * the Free Software Foundation; either version 2 of the License, or
010     * (at your option) any later version.
011     *
012     * CleanSheets is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with CleanSheets; if not, write to the Free Software
019     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
020     */
021    package csheets.ui;
022    
023    import java.awt.Component;
024    import java.io.File;
025    import java.io.FilenameFilter;
026    import java.util.ArrayList;
027    import java.util.List;
028    import java.util.Properties;
029    
030    import javax.swing.JFileChooser;
031    import javax.swing.filechooser.FileFilter;
032    
033    import csheets.SpreadsheetAppEvent;
034    import csheets.SpreadsheetAppListener;
035    import csheets.io.FilenameExtensionFilter;
036    
037    /**
038     * A file chooser that loads choosable file types from properties.
039     * @author Einar Pehrson
040     */
041    @SuppressWarnings("serial")
042    public class FileChooser extends JFileChooser implements SpreadsheetAppListener {
043    
044            /** The parent component of dialogs created by the chooser */
045            private Component parent;
046    
047            /** The file filters used by the chooser */
048            private List<Filter> filters = new ArrayList<Filter>();
049    
050            /**
051             * Creates a new file chooser. Choosable file types are loaded from the
052             * given properties. 
053             * Dialogs are shown with the given component as parent.
054             * @param parent the parent component of dialogs
055             * @param props the user properties
056             */
057            public FileChooser(Component parent, Properties props) {
058                    // Stores members
059                    this.parent = parent;
060    
061                    // Configures chooser
062                    setAcceptAllFileFilterUsed(false);
063    
064                    if (props != null) {
065                            // Loads file types
066                            String extension, description;
067                            for (int i = 0;
068                                    (extension = props.getProperty("filetype" + i + ".extension")) != null
069                             && (description = props.getProperty("filetype" + i + ".description")) != null;
070                                            i++) {
071                                    addChoosableFileFilter(new Filter(
072                                            new FilenameExtensionFilter(extension), description));
073                            }
074                            if (filters.size() > 0)
075                                    setFileFilter(filters.get(0));
076    
077                            // Loads current directory
078                            String currentDir = props.getProperty("recentfile0");
079                            if (currentDir != null)
080                                    setCurrentDirectory(new File(currentDir));
081                    }
082            }
083    
084            /**
085             * Shows a file chooser and returns the file the user selected, if any.
086             */
087            public File getFileToOpen() {
088                    if (showOpenDialog(parent) == JFileChooser.APPROVE_OPTION)
089                            return getChosenFile();
090                    else
091                            return null;
092            }
093    
094            /**
095             * Shows a file chooser and returns the file the user selected, if any.
096             */
097            public File getFileToSave() {
098                    if (showSaveDialog(parent) == JFileChooser.APPROVE_OPTION)
099                            return getChosenFile();
100                    else
101                            return null;
102            }
103    
104            /**
105             * Shows a file chooser and returns the file the user selected, if any.
106             */
107            private File getChosenFile() {
108                    File file = getSelectedFile();
109                    String filename = file.getName();
110                    if (filename.lastIndexOf('.') != -1) {
111                            // Checks if the file is acceptable by any of the filters.
112                            boolean filterAcceptable = filters.isEmpty();
113                            for (Filter filter : filters)
114                                    if (filter.getFilter().accept(file, filename)) {
115                                            filterAcceptable = true;
116                                            break;
117                                    }
118                            return file.isDirectory() || filterAcceptable ? file : null;
119                    } else {
120                            // Appends default extension from the chosen filter
121                            FileFilter filter = getFileFilter();
122                            if (filter instanceof Filter) {
123                                    FilenameFilter filenameFilter = ((Filter)filter).getFilter();
124                                    if (filenameFilter instanceof FilenameExtensionFilter) {
125                                            String[] extensions = ((FilenameExtensionFilter)
126                                                    filenameFilter).getExtensions();
127                                            return new File(file.getAbsolutePath() + "." + extensions[0]);
128                                    }
129                            }
130                            return null;
131                    }
132            }
133    
134            public void addChoosableFileFilter(FileFilter filter) {
135                    super.addChoosableFileFilter(filter);
136                    if (filter instanceof Filter) filters.add((Filter)filter);
137            }
138    
139            public void workbookCreated(SpreadsheetAppEvent event) {}
140    
141            public void workbookLoaded(SpreadsheetAppEvent event) {
142                    setCurrentDirectory(event.getFile());
143            }
144    
145            public void workbookUnloaded(SpreadsheetAppEvent event) {}
146    
147            public void workbookSaved(SpreadsheetAppEvent event) {
148                    setCurrentDirectory(event.getFile());
149            }
150    
151            /**
152             * A file filter for use in file choosers.
153             * @author Einar Pehrson
154             */
155            public static class Filter extends FileFilter {
156    
157                    /** The filename filter used to determine which files to accept. */
158                    private FilenameFilter filter;
159    
160                    /** The description of the filter. */
161                    private String description;
162    
163                    /**
164                     * Creates a new filter, using the given filename filter to determine which
165                     * files to accept.
166                     * @param filter the filename filter used to determine which files to accept
167                     * @param description the description of the filter
168                     */
169                    public Filter(FilenameFilter filter, String description) {
170                            this.filter = filter;
171                            this.description = description;
172                    }
173    
174                    public boolean accept(File f) {
175                            return f != null && (f.isDirectory() || filter.accept(f, f.getName()));
176                    }
177    
178                    /**
179                     * Returns the filename filter used to determine which files to accept.
180                     * @return the filename filter
181                     */
182                    public FilenameFilter getFilter() {
183                            return filter;
184                    }
185    
186                    /**
187                     * Returns the description of the filter
188                     * @return the description of the filter
189                     */
190                    public String getDescription() {
191                            return description;
192                    }
193            }
194    }