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