001/*
002 * $Id: HydraChooser.java,v 1.8 2011/03/24 16:06:31 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2011
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 * 
012 * All Rights Reserved
013 * 
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.  
016 * 
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 * 
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025 * GNU Lesser Public License for more details.
026 * 
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program.  If not, see http://www.gnu.org/licenses.
029 */
030
031package edu.wisc.ssec.mcidasv.chooser;
032
033
034import edu.wisc.ssec.mcidasv.*;
035
036import java.awt.*;
037import java.awt.event.*;
038
039import java.io.File;
040
041import java.util.ArrayList;
042import java.util.List;
043import java.util.Hashtable;
044import java.util.Vector;
045
046import javax.swing.*;
047import javax.swing.event.*;
048import javax.swing.filechooser.FileFilter;
049
050import org.w3c.dom.Element;
051
052import ucar.unidata.data.DataSourceResults;
053
054import ucar.unidata.idv.*;
055
056import ucar.unidata.idv.chooser.FileChooser;
057import ucar.unidata.idv.chooser.IdvChooser;
058import ucar.unidata.idv.chooser.IdvChooserManager;
059
060import ucar.unidata.ui.ChooserPanel;
061
062import ucar.unidata.util.FileManager;
063import ucar.unidata.util.GuiUtils;
064import ucar.unidata.util.PatternFileFilter;
065import ucar.unidata.util.PreferenceList;
066import ucar.unidata.util.StringUtil;
067
068import ucar.unidata.xml.XmlResourceCollection;
069import ucar.unidata.xml.XmlUtil;
070
071
072public class HydraChooser extends IdvChooser {
073
074    private Element chooserNode;
075
076    private JFileChooser fileChooser;
077
078    private IntegratedDataViewer idv = getIdv();
079
080    /**
081     *  The chooser xml can specify a datasourceid attribute.
082     */
083    private String dfltDataSourceId = "HYDRA";
084
085    /**
086     * Create the chooser with the given manager and xml
087     *
088     * @param mgr The manager
089     * @param root The xml
090     *
091     */
092    public HydraChooser(IdvChooserManager mgr, Element root) {
093        super(mgr, root);
094        this.chooserNode = root;
095    }
096
097
098    /**
099     * Get the tooltip for the load button
100     *
101     * @return The tooltip for the load button
102     */
103    protected String getLoadToolTip() {
104        return "";
105    }
106
107
108    /**
109     * Get the tooltip for the update button
110     *
111     * @return The tooltip for the update button
112     */
113    protected String getUpdateToolTip() {
114        return "Rescan the directory";
115    }
116
117
118    /**
119     * Make the GUI
120     *
121     * @return The GUI for HYDRA Chooser
122     */
123    protected JComponent doMakeContents() {
124        String path = (String) idv.getPreference(PREF_DEFAULTDIR + getId());
125        if (path == null) {
126            path = XmlUtil.getAttribute(this.chooserNode, FileChooser.ATTR_PATH,
127                                        (String) null);
128        }
129        //System.out.println("path=" + path);
130        fileChooser = doMakeFileChooser(path);
131        fileChooser.setPreferredSize(new Dimension(300, 300));
132        fileChooser.setMultiSelectionEnabled(true);
133        fileChooser.setApproveButtonText(ChooserPanel.CMD_LOAD);
134
135        PatternFileFilter ff = new PatternFileFilter(".hdf", "*.hdf files");
136        //fileChooser.setFileFilter(ff);
137
138        JComponent chooserPanel = fileChooser;
139        JPanel filePanel = GuiUtils.vbox(chooserPanel, getDefaultButtons());
140        return filePanel;
141    }
142
143
144    /**
145     * Make the file chooser
146     *
147     * @param path   the initial path
148     *
149     * @return  the file chooser
150     */
151    protected JFileChooser doMakeFileChooser(String path) {
152        return new MyFileChooser(path);
153    }
154
155    /**
156     * An extension of JFileChooser
157     *
158     * @author IDV Development Team
159     * @version $Revision: 1.8 $
160     */
161    public class MyFileChooser extends JFileChooser {
162
163        /**
164         * Create the file chooser
165         *
166         * @param path   the initial path
167         */
168        public MyFileChooser(String path) {
169            super(path);
170            setControlButtonsAreShown(false);
171            setMultiSelectionEnabled(true);
172        }
173
174        /**
175         * Approve the selection
176         */
177        public void approveSelection() {
178            HydraChooser.this.doLoad();
179        }
180
181        /**
182         * Cancel the selection
183         */
184        public void cancelSelection() {
185            closeChooser();
186        }
187
188        /**
189         * Set the selected files
190         *
191         * @param selectedFiles  the selected files
192         */
193        public void setSelectedFiles(File[] selectedFiles) {
194            super.setSelectedFiles(selectedFiles);
195            setHaveData( !((selectedFiles == null)
196                           || (selectedFiles.length == 0)));
197        }
198    }
199
200
201    /**
202     * Handle the selection of the set of files
203     *
204     * @param files The files the user chose
205     * @param directory The directory they chose them from
206     */
207    protected final void selectFiles(File[] files, File directory) {
208        try {
209            if (selectFilesInner(files, directory)) {
210                idv.getStateManager().writePreference(PREF_DEFAULTDIR
211                        + getId(), directory.getPath());
212            }
213        } catch (Exception excp) {
214            logException("File selection", excp);
215        }
216    }
217
218    /**
219     * Get the file chooser
220     *
221     * @return  the chooser for this instance
222     */
223    protected JFileChooser getFileChooser() {
224        return fileChooser;
225    }
226
227    /**
228     * Override the base class method to catch the do load
229     */
230    public void doLoadInThread() {
231        selectFiles(fileChooser.getSelectedFiles(),
232                    fileChooser.getCurrentDirectory());
233    }
234
235
236
237    /**
238     * Override the base class method to catch the do update
239     */
240    public void doUpdate() {
241        fileChooser.rescanCurrentDirectory();
242    }
243
244
245    /**
246     * Handle the selection of the set of files
247     *
248     * @param files The files the user chose
249     * @param directory The directory they chose them from
250     * @return True if the file was successful
251     * @throws Exception
252     */
253    protected boolean selectFilesInner(File[] files, File directory)
254            throws Exception {
255        if ((files == null) || (files.length == 0)) {
256            userMessage("Please select a file");
257            return false;
258        }
259        FileManager.addToHistory(files[0]);
260        List    selectedFiles      = new ArrayList();
261        String  fileNotExistsError = "";
262        boolean didXidv            = false;
263
264        for (int i = 0; i < files.length; i++) {
265            if ( !files[i].exists()) {
266                fileNotExistsError += "File does not exist: " + files[i]
267                                      + "\n";
268            } else {
269                String filename = files[i].toString();
270                //Check for the bundle or jnlp file
271                if (idv.getArgsManager().isXidvFile(filename)
272                        || idv.getArgsManager().isZidvFile(filename)
273                        || idv.getArgsManager().isJnlpFile(filename)) {
274                    didXidv = idv.handleAction(filename, null);
275                } else {
276                    selectedFiles.add(filename);
277                }
278            }
279        }
280
281        if (didXidv) {
282            closeChooser();
283            return true;
284        }
285
286
287        if (selectedFiles.size() == 0) {
288            return false;
289        }
290
291        if (fileNotExistsError.length() > 0) {
292            userMessage(fileNotExistsError);
293            return false;
294        }
295
296        Object definingObject = selectedFiles;
297        if (selectedFiles.size() == 1) {
298            definingObject = selectedFiles.get(0);
299        }
300
301        String dataSourceId = getDataSourceId();
302        if (dataSourceId == null) {
303            dataSourceId = dfltDataSourceId;
304        }
305
306        //If the user specifically selected a data source type then pass all files to that data source and be done.
307        DataSourceResults results;
308        if (dataSourceId == null) {
309            //If they selected one directory then ask if they want to load all the files
310            if (selectedFiles.size() == 1) {
311                File file = new File(selectedFiles.get(0).toString());
312                if (file.isDirectory()) {
313                    if ( !GuiUtils.showYesNoDialog(null,
314                            "Do you want to load all of the files in the selected directory: "
315                            + file, "Directory Load")) {
316                        return false;
317                    }
318                    selectedFiles  = new ArrayList();
319                    definingObject = selectedFiles;
320                    File[] subFiles = file.listFiles();
321                    for (int i = 0; i < subFiles.length; i++) {
322                        if ( !subFiles[i].isDirectory()) {
323                            selectedFiles.add(subFiles[i].toString());
324                        }
325                    }
326                }
327            }
328        }
329
330        Hashtable   properties  = new Hashtable();
331        return makeDataSource(definingObject, dataSourceId, properties);
332    }
333
334
335    /**
336     * Convert the given array of File objects
337     * to an array of String file names. Only
338     * include the files that actually exist.
339     *
340     * @param files Selected files
341     * @return Selected files as Strings
342     */
343    protected String[] getFileNames(File[] files) {
344        if (files == null) {
345            return (String[]) null;
346        }
347        Vector v                  = new Vector();
348        String fileNotExistsError = "";
349
350        // NOTE:  If multiple files are selected, then missing files
351        // are not in the files array.  If one file is selected and
352        // it is not there, then it is in the array and file.exists()
353        // is false
354        for (int i = 0; i < files.length; i++) {
355            if ((files[i] != null) && !files[i].isDirectory()) {
356                if ( !files[i].exists()) {
357                    fileNotExistsError += "File does not exist: " + files[i]
358                                          + "\n";
359                } else {
360                    v.add(files[i].toString());
361                }
362            }
363        }
364
365        if (fileNotExistsError.length() > 0) {
366            userMessage(fileNotExistsError);
367            return null;
368        }
369
370        return v.isEmpty()
371               ? null
372               : StringUtil.listToStringArray(v);
373    }
374}