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