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