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