001    /*
002     * $Id: SoundingFileBrowser.java,v 1.8 2012/02/19 17:35:36 davep Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
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    
031    package edu.wisc.ssec.mcidasv.chooser;
032    
033    
034    import ucar.unidata.beans.NonVetoableProperty;
035    import ucar.unidata.beans.Property;
036    import ucar.unidata.beans.PropertySet;
037    import ucar.unidata.data.sounding.CMASoundingAdapter;
038    import ucar.unidata.data.sounding.NetcdfSoundingAdapter;
039    import ucar.unidata.data.sounding.SoundingAdapter;
040    
041    
042    import ucar.unidata.util.FileManager;
043    
044    import ucar.unidata.util.GuiUtils;
045    import ucar.unidata.util.LogUtil;
046    import ucar.unidata.util.Misc;
047    import ucar.unidata.util.PatternFileFilter;
048    
049    
050    
051    import java.awt.Component;
052    import java.awt.Insets;
053    import java.awt.event.ActionEvent;
054    import java.awt.event.ActionListener;
055    import java.awt.event.WindowAdapter;
056    import java.awt.event.WindowEvent;
057    import java.awt.event.WindowListener;
058    
059    import java.beans.*;
060    
061    import java.io.File;
062    
063    import javax.swing.BorderFactory;
064    import javax.swing.JButton;
065    import javax.swing.JFrame;
066    import javax.swing.JOptionPane;
067    import javax.swing.JPanel;
068    import javax.swing.JTextField;
069    
070    
071    /**
072     * A browser for finding netCDF upper air files.
073     *
074     * @author Unidata development team
075     * @version $Revision: 1.8 $
076     */
077    public class SoundingFileBrowser {
078    
079        /** PatternFileFilter for upper air netCDF files */
080        public static final PatternFileFilter FILTER_NC =
081            new PatternFileFilter(".*ua\\.nc$,Upperair.*\\.nc$",
082                                  "netCDF Upper Air files (*ua.nc)");
083    
084        /** PatternFileFilter for CMA upper air files */
085        public static final PatternFileFilter FILTER_CMA_UA =
086            new PatternFileFilter(".*\\.ta$", "CMA Upper Air files (*.ta)");
087    
088        /** property for the sounding adapter */
089        private Property soundingAdapterProperty;
090    
091        /** property set */
092        private PropertySet propertySet;
093    
094        /** selected file input */
095        protected JTextField selectedFileDisplay;
096    
097        /** flag for file changes */
098        private boolean ignoreChangingFile = false;
099    
100        /** frame for the browse */
101        private static JFrame frame = null;
102    
103        /** frame contents */
104        private JPanel contents;
105    
106        /**
107         * Construct an object for selecting sounding files starting at
108         * the current directory
109         */
110        SoundingFileBrowser() {
111            this(".");
112        }
113    
114        /**
115         * Construct an object for selecting sounding files starting at
116         * the specified directory.
117         *
118         * @param  directoryName   starting directory to search for files.
119         */
120        SoundingFileBrowser(String directoryName) {
121    
122            // set up the properties
123            propertySet = new PropertySet();
124    
125            propertySet.addProperty(soundingAdapterProperty =
126                new NonVetoableProperty(this, "soundingAdapter"));
127    
128            File selectedFile = new File(directoryName);
129    
130    
131            selectedFileDisplay = new JTextField(30);
132            selectedFileDisplay.addActionListener(new ActionListener() {
133                public void actionPerformed(ActionEvent ae) {
134                    checkNewFile(new File(selectedFileDisplay.getText().trim()));
135                }
136            });
137            GuiUtils.setNoFill();
138            GuiUtils.tmpInsets = new Insets(0, 2, 0, 2);
139            contents = GuiUtils.doLayout(new Component[] { selectedFileDisplay,
140                    fileSelectionButton() }, 2, GuiUtils.WT_N, GuiUtils.WT_N);
141        }
142    
143    
144        /**
145         * Create a file selection button
146         * @return the file selection button
147         */
148        private JButton fileSelectionButton() {
149            JButton fileSelectButton = new JButton("Select File...");
150            fileSelectButton.addActionListener(new ActionListener() {
151                public void actionPerformed(ActionEvent e) {
152                    //Read the file - don't include the "include all" file filter.
153                    String file =
154                        FileManager.getReadFile("Select Upper Air File",
155                                                Misc.newList(FILTER_NC,
156                                                    FILTER_CMA_UA));
157                    if (file == null) {
158                        return;
159                    }
160                    checkNewFile(new File(file));
161                }
162            });
163    
164            return fileSelectButton;
165        }
166    
167        /**
168         * Check the status of the file.
169         *
170         * @param selectedFile   file to use for checking
171         */
172        protected void checkNewFile(File selectedFile) {
173            if (ignoreChangingFile) {
174                return;
175            }
176            if ( !selectedFile.exists()) {
177                LogUtil.userMessage("File does not exist:" + selectedFile);
178                return;
179            }
180            SoundingAdapter adapter = null;
181            try {
182                adapter = new NetcdfSoundingAdapter(selectedFile);
183            } catch (IllegalArgumentException ill) {
184                System.out.println(ill.getMessage());
185                try {
186                    adapter = new CMASoundingAdapter(selectedFile);
187                } catch (Exception exc) {
188                    LogUtil.logException("Reading sounding:" + selectedFile, exc);
189                    return;
190                }
191            } catch (Exception exc) {
192                LogUtil.logException("Reading sounding:" + selectedFile, exc);
193                return;
194            }
195            if (adapter.getSoundingTimes() != null) {
196                try {
197                    soundingAdapterProperty.setValueAndNotifyListeners(adapter);
198                    ignoreChangingFile = true;
199                    selectedFileDisplay.setText(selectedFile.getPath());
200                    ignoreChangingFile = false;
201                } catch (PropertyVetoException excpt) {
202                    LogUtil.logException("New sounding dataset was vetoed: ",
203                                         excpt);
204                }
205            } else {
206                LogUtil.userMessage("Unable to read data from file "
207                                    + selectedFile);
208            }
209        }
210    
211    
212        /**
213         * Get the contents of this browser.
214         *
215         * @return browser contents
216         */
217        public JPanel getContents() {
218            return contents;
219        }
220    
221        /**
222         * Get the SoundingAdapter property
223         *
224         * @return the SoundingAdapter property
225         */
226        protected Property getSoundingAdapterProperty() {
227            return soundingAdapterProperty;
228        }
229    
230        /**
231         * Get the SoundingAdapter associated with this browser
232         * @return the associated SoundingAdapter
233         */
234        public SoundingAdapter getSoundingAdapter() {
235            return (SoundingAdapter) soundingAdapterProperty.getValue();
236        }
237    
238        /**
239         * Adds a property change listener.
240         *
241         * @param listener          The property change listener.
242         */
243        public void addPropertyChangeListener(PropertyChangeListener listener) {
244            propertySet.addPropertyChangeListener(listener);
245        }
246    
247        /**
248         * Removes a property change listener.
249         *
250         * @param listener          The property change listener.
251         */
252        public void removePropertyChangeListener(
253                PropertyChangeListener listener) {
254            propertySet.removePropertyChangeListener(listener);
255        }
256    
257        /**
258         * Adds a property change listener for a named property.
259         *
260         * @param name              The name of the property.
261         * @param listener          The property change listener.
262         */
263        public void addPropertyChangeListener(String name,
264                                              PropertyChangeListener listener) {
265            propertySet.addPropertyChangeListener(name, listener);
266        }
267    
268        /**
269         * Removes a property change listener for a named property.
270         *
271         * @param name              The name of the property.
272         * @param listener          The property change listener.
273         */
274        public void removePropertyChangeListener(
275                String name, PropertyChangeListener listener) {
276            propertySet.removePropertyChangeListener(name, listener);
277        }
278    
279        /**
280         * Test routine.
281         *
282         * @param args  name of file or directory if supplied
283         */
284        public static void main(String[] args) {
285    
286            frame = new JFrame("Sounding Browser Test");
287    
288            frame.addWindowListener(new WindowAdapter() {
289                public void windowClosing(WindowEvent e) {
290                    System.exit(0);
291                }
292            });
293    
294            SoundingFileBrowser ncfb = new SoundingFileBrowser((args.length > 0)
295                    ? args[0]
296                    : "/var/data/ldm/decoded");
297    
298            frame.getContentPane().add(ncfb.getContents());
299            frame.pack();
300            frame.setVisible(true);
301        }
302    }
303