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