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