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 org.w3c.dom.Element;
033
034 import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
035
036 import ucar.unidata.data.DataSource;
037
038 import ucar.unidata.data.DataSourceDescriptor;
039 import ucar.unidata.data.radar.Level2RadarDataSource;
040
041 import ucar.unidata.idv.*;
042 import ucar.unidata.idv.chooser.IdvChooserManager;
043 import ucar.unidata.idv.control.DisplayControlBase;
044
045 import ucar.unidata.metdata.*;
046
047 import ucar.unidata.ui.ChooserPanel;
048 import ucar.unidata.util.FileManager;
049 import ucar.unidata.util.GuiUtils;
050 import ucar.unidata.util.Misc;
051
052 import ucar.unidata.util.PatternFileFilter;
053 import ucar.unidata.util.PollingInfo;
054 import ucar.unidata.util.TwoFacedObject;
055 import ucar.unidata.xml.XmlResourceCollection;
056
057
058 import ucar.unidata.xml.XmlUtil;
059
060 import java.awt.*;
061 import java.awt.event.*;
062
063 import java.io.File;
064
065 import java.util.ArrayList;
066 import java.util.Collections;
067 import java.util.Hashtable;
068 import java.util.Iterator;
069 import java.util.List;
070 import java.util.Map;
071 import java.util.Vector;
072
073 import javax.swing.*;
074 import javax.swing.event.*;
075
076 import javax.swing.filechooser.FileFilter;
077
078
079
080 /**
081 * A chooser for Level II NEXRAD data. This loads in
082 * files from the file system. Since (right now) the
083 * data does not contain the station we rely on
084 * the heuristic of looking at the directory path
085 * name to see if it contains a station name.
086 * The user can also specify the station from the GUI
087 *
088 *
089 * @author IDV development team
090 * @version $Revision$Date: 2011/03/24 16:06:31 $
091 */
092 public class Level2RadarChooser extends FileChooser {
093
094 /** Holds the predefined list of nexrad stations */
095 private JComboBox stationsCbx;
096
097 /** List of predefined nexrad stations */
098 private List nexradStations;
099
100 /** Label used in the widgets to show an unknown station */
101 private static String UNKNOWN_STATION = "I'm Feeling Lucky";
102
103 /**
104 * The data source id we pass the files to.
105 * This is the oone defined in idv/resources/datasources.xml
106 */
107 private static String DATA_TYPE = "FILE.LEVEL2RADAR";
108
109 /** the type for the CDM radar */
110 private static String CDM_DATA_TYPE = "FILE.RADAR";
111
112 /** checkbox for switching data types */
113 private JCheckBox typeCbx;
114
115 /**
116 * Create the chooser with the given chooser manager
117 * and xml root (from the xml that defines this chooser).
118 *
119 * @param mgr The manager
120 * @param root The xml
121 *
122 */
123 public Level2RadarChooser(IdvChooserManager mgr, Element root) {
124 super(mgr, root);
125 }
126
127 /**
128 * Label for getDataSourcesComponent selector
129 * @return
130 */
131 protected String getDataSourcesLabel() {
132 return "Station:";
133 }
134
135 /**
136 * Overridden so that McIDAS-V can attempt auto-selecting the default data
137 * source type.
138 */
139 @Override protected JComboBox getDataSourcesComponent() {
140 stationsCbx = new JComboBox();
141 List stations = Misc.newList(UNKNOWN_STATION);
142 stations.addAll(nexradStations = getStations());
143 DisplayControlBase.setStations(stations, stationsCbx, false);
144 return stationsCbx;
145 }
146
147 /**
148 * Get the tooltip for the load button
149 *
150 * @return The tooltip for the load button
151 */
152 protected String getLoadToolTip() {
153 return "Load the selected Level II radar files";
154 }
155
156 /**
157 * Make the file chooser
158 *
159 * @param path the initial path
160 *
161 * @return the JFileChooser
162 */
163 protected JFileChooser doMakeFileChooser(String path) {
164 MyFileChooser fileChooser = new Level2RadarFileChooser(this, path);
165 fileChooser.addChoosableFileFilter(new PatternFileFilter(".*\\.raw$", "Raw files"));
166 // fileChooser.setApproveButtonText(ChooserPanel.CMD_LOAD);
167 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
168 if (path != null) {
169 fileChooser.setCurrentDirectory(new File(path));
170 }
171 return fileChooser;
172 }
173
174 /**
175 * Process the set of selected files
176 *
177 * @param files Array of files
178 * @param directory The last directory chosen
179 *
180 * @return true if successful
181 */
182 protected boolean selectFilesInner(File[] files, final File directory) {
183 final Object selected =
184 ((TwoFacedObject) stationsCbx.getSelectedItem()).getId();
185
186 if (selected.equals(UNKNOWN_STATION)
187 && ((typeCbx != null) && !typeCbx.isSelected())) {
188 userMessage("Unknown location of selected files, "
189 + "please select from list");
190 return false;
191 }
192
193 int recentCnt = getFileCount();
194 if (recentCnt <= 0) {
195 if ((files == null) || (files.length == 0)) {
196 userMessage("Please select one or more files");
197 return false;
198 }
199 }
200 if ((files != null) && (files.length > 0)) {
201 FileManager.addToHistory(files[0]);
202 }
203
204 String[] tmpDataLoc = getFileNames(((recentCnt <= 0)
205 ? files
206 : null));
207 if (recentCnt <= 0) {
208 if (tmpDataLoc == null) {
209 return false;
210 }
211 }
212
213 final Hashtable properties =
214 Misc.newHashtable(Level2RadarDataSource.STATION_LOCATION,
215 selected);
216 String pattern = getFilePattern();
217 if ((pattern != null) && (pattern.length() > 0)) {
218 properties.put(DataSource.PROP_FILEPATTERN,
219 pattern.toLowerCase());
220 } else {
221 pattern = null;
222 }
223
224 if (recentCnt > 0) {
225 properties.put(DataSource.MOST_RECENT, new Integer(recentCnt));
226 tmpDataLoc = new String[] { directory.toString() };
227 PollingInfo pollingInfo = new PollingInfo(directory.toString(),
228 60000, pattern, false, false);
229 pollingInfo.setMode(PollingInfo.MODE_COUNT);
230 pollingInfo.setFileCount(recentCnt);
231 properties.put(DataSource.PROP_POLLINFO, pollingInfo);
232 }
233
234 String dataType = ((typeCbx != null) && !typeCbx.isSelected())
235 ? DATA_TYPE
236 : CDM_DATA_TYPE;
237 // System.out.println("dataType = " + dataType);
238 makeDataSource(tmpDataLoc, dataType, properties);
239 return true;
240 }
241
242 /**
243 * Read in the nexrad stations from the
244 * idv/resources/nexradstns.xml resource
245 *
246 * @return List of of {@link ucar.unidata.metdata.NamedStation}-s
247 */
248 private List getStations() {
249 if (nexradStations == null) {
250 nexradStations = new Vector();
251 List radarLocations =
252 getIdv().getResourceManager().findLocationsByType("radar");
253 for (int i = 0; i < radarLocations.size(); i++) {
254 NamedStationTable nexrTable =
255 (NamedStationTable) radarLocations.get(i);
256 nexradStations.addAll(nexrTable.values());
257 }
258 Collections.sort(nexradStations);
259 }
260 return nexradStations;
261 }
262
263 /**
264 * Try to guess at the station of the selected
265 * file based on directory name.
266 *
267 * @param file The selected file
268 */
269 protected void guessAtStation(File file) {
270
271 if ((file == null) || !file.isDirectory()) {
272 return;
273 }
274 if ((nexradStations == null) || nexradStations.isEmpty()) {
275 return;
276 }
277 File tmpFile = file;
278
279 //Walk up the directory tree, looking at the names of each file
280
281 //Use the dirLevel so we only do the println on the first check.
282 //Though we could use it to only check one or two directory levels
283 int dirLevel = 0;
284 boolean found = false;
285 while ((tmpFile != null) && (found == false)) {
286 String name = tmpFile.getName().toLowerCase();
287 for (Iterator iter =
288 nexradStations.iterator(); iter.hasNext(); ) {
289 NamedStation station = (NamedStation) iter.next();
290 if (station == null) {
291 continue;
292 }
293
294 String id = station.getIdentifier();
295 //Do a .equals - perhaps we do want to do the .indexOf check??
296 //Though that might mean some odd matches.
297 if (name.indexOf(id.toLowerCase()) >= 0) {
298 stationsCbx.setSelectedItem(
299 DisplayControlBase.createStationTfo(station));
300 found = true;
301 break;
302 }
303 }
304 dirLevel++;
305 tmpFile = tmpFile.getParentFile();
306 }
307 if ( !found) {
308 stationsCbx.setSelectedItem(UNKNOWN_STATION);
309 }
310 }
311
312 /**
313 * This class allows us to add in our own functionality
314 * to the file chooser. It has a hook to support the guessing
315 * of the station from the directory name and passes through
316 * to the chooser the select and cancel events
317 *
318 * @author IDV development team
319 */
320 public class Level2RadarFileChooser extends FileChooser.MyFileChooser {
321
322 /** my chooser */
323 Level2RadarChooser myChooser;
324
325 /** Keeps track of the last directory the user chose */
326 File lastDirectory = null;
327
328 /**
329 * Create the special file chooser
330 *
331 *
332 * @param chooser the chooser to relate to
333 * @param path path to start with
334 */
335 public Level2RadarFileChooser(Level2RadarChooser chooser,
336 String path) {
337 super(path);
338 myChooser = chooser;
339 }
340
341 /**
342 * Try to guess at the station name
343 *
344 * @param file The currently selected dir
345 */
346 public void setCurrentDirectory(File file) {
347 super.setCurrentDirectory(file);
348 if ( !Misc.equals(file, lastDirectory)) {
349 if (myChooser != null) {
350 myChooser.guessAtStation(file);
351 }
352 lastDirectory = file;
353 }
354 }
355 }
356
357 /**
358 * Get the bottom panel for the chooser
359 * @return the bottom panel
360 */
361 protected JPanel getBottomPanel() {
362 // do this because the original check is made before the list is inited
363 if (getFileChooser() != null) {
364 guessAtStation(getFileChooser().getCurrentDirectory());
365 }
366 JComponent recentComponent = getRecentFilesComponent();
367 Component [] components = recentComponent.getComponents();
368 if (components != null) {
369 for (int i = 0; i < components.length; i++) {
370 if (components[i] instanceof JLabel) {
371 McVGuiUtils.setComponentWidth((JLabel)components[i], McVGuiUtils.Width.SINGLE);
372 McVGuiUtils.setLabelPosition((JLabel)components[i], McVGuiUtils.Position.RIGHT);
373 }
374 else if (components[i] instanceof JComboBox) {
375 McVGuiUtils.setComponentWidth((JComboBox)components[i], McVGuiUtils.Width.DOUBLE);
376 }
377 else if (components[i] instanceof JTextField) {
378 McVGuiUtils.setComponentWidth((JTextField)components[i], McVGuiUtils.Width.SINGLE);
379 }
380 }
381 recentComponent = GuiUtils.left(GuiUtils.hbox(components));
382 }
383 return McVGuiUtils.makeLabeledComponent("Times:", recentComponent);
384 }
385
386 }
387