001 /* 002 * $Id: BadNetCDFWidget.java,v 1.6 2012/04/19 19:02:35 jbeavers 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 package edu.wisc.ssec.mcidasv.data; 031 032 import static javax.swing.GroupLayout.Alignment.BASELINE; 033 import static javax.swing.GroupLayout.Alignment.LEADING; 034 import static javax.swing.GroupLayout.Alignment.TRAILING; 035 import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 036 037 import java.awt.Container; 038 import java.awt.Dimension; 039 import java.awt.EventQueue; 040 import java.awt.Font; 041 import java.awt.event.ActionEvent; 042 import java.awt.event.ActionListener; 043 import java.awt.event.WindowEvent; 044 import java.awt.event.WindowAdapter; 045 import java.awt.event.WindowListener; 046 import java.io.ByteArrayInputStream; 047 import java.io.ByteArrayOutputStream; 048 import java.io.File; 049 import java.io.IOException; 050 import java.util.Iterator; 051 import java.util.LinkedList; 052 import java.util.List; 053 054 import javax.swing.BoxLayout; 055 import javax.swing.GroupLayout; 056 import javax.swing.JButton; 057 import javax.swing.JCheckBox; 058 import javax.swing.JComboBox; 059 import javax.swing.JDialog; 060 import javax.swing.JEditorPane; 061 import javax.swing.JFrame; 062 import javax.swing.JLabel; 063 import javax.swing.JOptionPane; 064 import javax.swing.JPanel; 065 import javax.swing.JRadioButton; 066 import javax.swing.JScrollPane; 067 import javax.swing.JSeparator; 068 import javax.swing.JTextField; 069 import javax.swing.JTextPane; 070 import javax.swing.JToolBar; 071 import javax.swing.ScrollPaneConstants; 072 import javax.swing.UIManager; 073 import javax.swing.WindowConstants; 074 import javax.swing.border.EmptyBorder; 075 import javax.swing.event.HyperlinkEvent; 076 import javax.swing.event.HyperlinkListener; 077 import javax.swing.text.PlainDocument; 078 079 import org.slf4j.Logger; 080 import org.slf4j.LoggerFactory; 081 082 import net.miginfocom.swing.MigLayout; 083 084 import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 085 import edu.wisc.ssec.mcidasv.util.McVGuiUtils.IconPanel; 086 import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Prefer; 087 import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width; 088 import edu.wisc.ssec.mcidasv.util.WebBrowser; 089 import edu.wisc.ssec.mcidasv.Constants; 090 091 import ucar.ma2.Array; 092 import ucar.nc2.Variable; 093 import ucar.nc2.dataset.NetcdfDataset; 094 import ucar.nc2.ncml.NcMLReader; 095 import ucar.nc2.dt.grid.GridDataset; 096 097 import ucar.unidata.util.FileManager; 098 import ucar.unidata.util.GuiUtils; 099 import ucar.unidata.util.IOUtil; 100 import ucar.unidata.util.Misc; 101 102 import ucar.unidata.data.DataSourceDescriptor; 103 import ucar.unidata.data.grid.GeoGridDataSource; 104 import ucar.unidata.idv.IntegratedDataViewer; 105 106 import visad.ConstantMap; 107 import visad.Display; 108 import visad.FlatField; 109 import visad.python.JPythonMethods; 110 import visad.ss.BasicSSCell; 111 import visad.ss.FancySSCell; 112 113 114 public class BadNetCDFWidget implements Constants { 115 116 private static final Logger logger = LoggerFactory.getLogger(BadNetCDFWidget.class); 117 118 private IntegratedDataViewer idv; 119 120 private NetcdfDataset ncFile; 121 private List<Variable> varList; 122 private List<String> varNames; 123 124 125 // For NcML Editor 126 private JEditorPane NcMLeditor; 127 128 129 // For variable display 130 BasicSSCell display; 131 ConstantMap[] cmaps; 132 133 134 // For nav specification 135 private JRadioButton radioLatLonVars = new JRadioButton("Variables", true); 136 private JRadioButton radioLatLonBounds = new JRadioButton("Bounds", false); 137 138 private JComboBox refComboBox = new JComboBox(); 139 private JComboBox latComboBox = new JComboBox(); 140 private JComboBox lonComboBox = new JComboBox(); 141 142 private JPanel panelLatLonVars = new JPanel(); 143 private JPanel panelLatLonBounds = new JPanel(); 144 145 private JTextField textLatUL = new JTextField(); 146 private JTextField textLonUL = new JTextField(); 147 private JTextField textLatLR = new JTextField(); 148 private JTextField textLonLR = new JTextField(); 149 150 151 // TODO: DO WE NEED THESE? 152 private JTextField textLatLonScale = new JTextField(); 153 private JCheckBox checkEastPositive = new JCheckBox("East positive"); 154 155 156 157 158 public BadNetCDFWidget(NetcdfDataset ncFile, IntegratedDataViewer idv) 159 { 160 this.idv = idv; 161 this.ncFile = ncFile; 162 varList = ncFile.getVariables(); 163 164 varNames = new LinkedList<String>(); 165 166 //System.out.println("Our file has " + varList.size() + " variables named:"); 167 Iterator <Variable> varIt = varList.iterator(); 168 while(varIt.hasNext()) 169 { 170 Variable ourVar = varIt.next(); 171 varNames.add(ourVar.getName()); 172 //System.out.println("Name: " + ourVar.getName()); 173 } 174 } 175 176 177 // Passes through any exception from openDataset - this function 178 // doesn't provide an IDV and should only be used for testing. (Some functionality 179 // using the rest of the IDV won't work.) 180 public BadNetCDFWidget(String filepath) throws IOException 181 { 182 this(NetcdfDataset.openDataset(filepath), null); 183 } 184 185 186 187 // Tester function to pick a file and send it through the paces. 188 public static void main(String[] args) 189 { 190 String testfile = FileManager.getReadFile(); 191 System.out.println(testfile); 192 193 //String testfile = "/Users/nickb/testdata/tester.nc"; 194 195 196 BadNetCDFWidget bfReader; 197 try { bfReader = new BadNetCDFWidget(testfile); } 198 catch (Exception exe) 199 { 200 //System.out.println("This file cannot be read by the BadFileReader!"); 201 exe.printStackTrace(); 202 return; 203 } 204 205 bfReader.showChoices(); 206 //bfReader.showNavChooser(); 207 } 208 209 210 211 ///////////////////////////////////////////////////////// 212 // Displays our "main menu" of choices to fix the given file! 213 // Everything else needed can get called from here. 214 ///////////////////////////////////////////////////////// 215 public void showChoices() 216 { 217 EventQueue.invokeLater(new Runnable() { 218 public void run() { 219 try { 220 BadNetCDFDialog dialog = new BadNetCDFDialog(); 221 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 222 dialog.setVisible(true); 223 dialog.toFront(); 224 } catch (Exception e) { 225 e.printStackTrace(); 226 } 227 } 228 }); 229 } 230 231 ///////////////////////////////////////////////////////// 232 // Creates an editor for NcML and displays it in a window - includes buttons for saving just 233 // the NcML and the full NetCDF file with the changes made. 234 ///////////////////////////////////////////////////////// 235 private void showNcMLEditor() 236 { 237 NcMLeditor = new JEditorPane(); 238 239 // We use this to store the actual ncml - 10000 is just the number toolsUI used 240 ByteArrayOutputStream bos = new ByteArrayOutputStream(10000); 241 try 242 { 243 ncFile.writeNcML(bos, null); 244 NcMLeditor.setText(bos.toString()); 245 NcMLeditor.setCaretPosition(0); 246 247 } catch (IOException ioe) 248 { 249 ioe.printStackTrace(); 250 //setInError(true, false, ""); DataSourceImpl - doesn't work if we're not a data source 251 return; 252 } 253 254 NcMLeditor.setEditable(true); 255 256 // Set the font style. 257 NcMLeditor.setFont(new Font("Courier", Font.PLAIN, 12)); 258 259 // Set the tab size 260 NcMLeditor.getDocument().putProperty(PlainDocument.tabSizeAttribute, 2); 261 262 263 // Button to save NcML as text, 264 // popup allows them to specify where. 265 JButton saveNcMLBtn = new JButton("Save NcML as text"); 266 ActionListener saveAction = new ActionListener() 267 { 268 public void actionPerformed(ActionEvent ae) 269 { 270 // Begin with getting the filename we want to write to. 271 String ncLocation = ncFile.getLocation(); 272 273 if (ncLocation == null) ncLocation = "test"; 274 int pos = ncLocation.lastIndexOf("."); 275 if (pos > 0) 276 ncLocation = ncLocation.substring(0, pos); 277 278 String filename = FileManager.getWriteFile(ncLocation + ".ncml"); 279 if (filename == null) return; 280 // System.out.println("Write NcML to filename:" + filename); 281 282 283 // Once we have that, we can actually write to the file! 284 try{ 285 IOUtil.writeFile(new File(filename), NcMLeditor.getText()); 286 } catch(Exception exc) 287 { 288 // TODO: Should probably add some kind of exception handling. 289 exc.printStackTrace(); 290 return; 291 } 292 } 293 }; 294 saveNcMLBtn.addActionListener(saveAction); 295 296 297 // Button to merge the NcML with NetCDF 298 // a'la ToolsUI and write it back out as NetCDF3. 299 JButton saveNetCDFBtn = new JButton("Merge and save NetCDF"); 300 ActionListener saveNetCDFAction = new ActionListener() 301 { 302 public void actionPerformed(ActionEvent ae) 303 { 304 // Begin with getting the filename we want to write to. 305 String ncLocation = ncFile.getLocation(); 306 307 if (ncLocation == null) ncLocation = "test"; 308 int pos = ncLocation.lastIndexOf("."); 309 if (pos > 0) 310 ncLocation = ncLocation.substring(0, pos); 311 312 String filename = FileManager.getWriteFile(ncLocation + ".nc"); 313 if (filename == null) return; 314 // System.out.println("Write NetCDF to filename:" + filename); 315 316 317 // Once we have that, we can actually write to the file! 318 try { 319 ByteArrayInputStream bis = new ByteArrayInputStream(NcMLeditor.getText().getBytes()); 320 NcMLReader.writeNcMLToFile(bis, filename); 321 } catch(Exception exc) 322 { 323 // TODO: Should probably add some kind of exception handling. 324 exc.printStackTrace(); 325 return; 326 } 327 } 328 }; 329 saveNetCDFBtn.addActionListener(saveNetCDFAction); 330 331 332 // Button to load this data into McV from NcML 333 JButton sendToMcVBtn = new JButton("Attempt to load with this NcML"); 334 ActionListener sendToMcVAction = new ActionListener() 335 { 336 public void actionPerformed(ActionEvent ae) 337 { 338 // TODO: save the current NcML into the NetcdfDataSource 339 createIDVdisplay(); 340 return; 341 } 342 }; 343 sendToMcVBtn.addActionListener(sendToMcVAction); 344 345 346 JToolBar toolbar = new JToolBar("NcML Editor Controls"); 347 348 toolbar.add(saveNcMLBtn); 349 toolbar.add(saveNetCDFBtn); 350 toolbar.add(sendToMcVBtn); 351 352 353 JScrollPane scrollPane = new JScrollPane(NcMLeditor, 354 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, 355 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 356 357 scrollPane.setPreferredSize(new Dimension(600, 600)); // TODO: PREFERRED SIZE? 358 359 JPanel panel = GuiUtils.topCenter(toolbar, scrollPane); 360 JFrame editorWindow = GuiUtils.makeWindow("NcML Editor", GuiUtils.inset(panel, 10), 0, 0); 361 editorWindow.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 362 editorWindow.setVisible(true); 363 editorWindow.toFront(); 364 365 // System.out.println("NcML Editor Created!"); 366 } 367 368 369 370 371 372 ///////////////////////////////////////////////////////// 373 // Takes our ncFile and puts it back into IDV (McV) 374 ///////////////////////////////////////////////////////// 375 private void createIDVdisplay() 376 { 377 378 // Make a NetcdfDataset from our NcML 379 380 ByteArrayInputStream bis = new ByteArrayInputStream(NcMLeditor.getText().getBytes()); 381 382 try { 383 ncFile = NcMLReader.readNcML(bis, null); 384 } catch (IOException e1) { 385 // TODO Auto-generated catch block 386 e1.printStackTrace(); 387 return; 388 } 389 390 391 // Now try to turn that NetcdfDataset into a legitimate DataSource! 392 GridDataset gd; 393 394 // System.out.println("Creating the grid dataset..."); 395 396 try { 397 gd = new GridDataset(ncFile); 398 } catch (IOException e) { 399 // TODO Auto-generated catch block 400 e.printStackTrace(); 401 return; 402 } 403 404 ncFile.getLocation(); 405 // System.out.println("Grid dataset created! Adding to data manager..."); 406 // GeoGridDataSource ggds = new GeoGridDataSource(gd); 407 DataSourceDescriptor dsd = new DataSourceDescriptor(); 408 dsd.setLabel("NcML DS Label"); 409 GeoGridDataSource ggds = new GeoGridDataSource(dsd, gd, "NcML Data Source", ncFile.getLocation()); 410 ggds.initAfterCreation(); 411 this.idv.getDataManager().addDataSource(ggds); 412 } 413 414 415 416 417 418 ///////////////////////////////////////////////////////// 419 // Shows a window that gives a choice of variables! 420 ///////////////////////////////////////////////////////// 421 private void showVarPicker() 422 { 423 // DataImpl 424 //Array arr = var.read(); 425 426 JComboBox varDD = new JComboBox(); 427 GuiUtils.setListData(varDD, varNames); 428 429 ActionListener getVarAction = new ActionListener() 430 { 431 public void actionPerformed(ActionEvent ae) 432 { 433 JComboBox cb = (JComboBox)ae.getSource(); 434 Variable plotVar = varList.get(cb.getSelectedIndex()); 435 String varName = (String) cb.getSelectedItem(); 436 437 438 float [] varVals; 439 try{ 440 // TODO: Is there a better way to convert this? Is there another function like reshape? 441 Array varArray = plotVar.read(); 442 varVals = (float[]) varArray.get1DJavaArray(float.class); 443 // TODO: Better exception handling 444 } 445 catch (IOException IOexe) 446 { 447 IOexe.printStackTrace(); 448 return; 449 } 450 451 int size = plotVar.getDimensions().size(); 452 if( size != 2) 453 { 454 //System.err.println("We should fail here because size != 2, size ==" + size); 455 JOptionPane.showMessageDialog(null, 456 ("<html>Variables must have 2 dimensions to be displayed here.<br><br>\"" + varName + "\" has " + size + ".</html>"), 457 "Invalid Dimensions", 458 JOptionPane.ERROR_MESSAGE); 459 return; 460 } 461 462 int xdim = plotVar.getDimensions().get(0).getLength(); 463 int ydim = plotVar.getDimensions().get(1).getLength(); 464 465 // System.out.println("xdim: " + xdim + " ydim: " + ydim); 466 467 float[][] var2D = reshape(varVals, ydim, xdim); 468 469 //JPythonMethods.plot(varVals); 470 //JPythonMethods.plot(var2D); 471 472 try { 473 FlatField varField = JPythonMethods.field(var2D); 474 475 476 ConstantMap[] cmaps = { 477 new ConstantMap(1.0, Display.Red), 478 new ConstantMap(1.0, Display.Green), 479 new ConstantMap(1.0, Display.Blue) 480 }; 481 482 // Clear out the display or we get some weird stuff going on. 483 display.clearCell(); 484 display.clearMaps(); 485 display.clearDisplay(); 486 487 display.addData(varField, cmaps); 488 489 /* // Make sure data isn't lingering around: 490 String[] dataSources = display.getDataSources(); 491 System.out.println("Data sources: " + dataSources.length); */ 492 } 493 // TODO: Better exception handling - throughout this whole file, really. 494 catch (Exception exe) 495 { 496 exe.printStackTrace(); 497 return; 498 499 } 500 } 501 }; 502 varDD.addActionListener(getVarAction); 503 504 //BasicSSCell display = new FancySSCell("Variable!"); 505 //display.setDimension(BasicSSCell.JAVA3D_3D); 506 507 // TODO: exception handling 508 try 509 { 510 // Heavily borrowed from VISAD's JPythonMethods 511 display = new FancySSCell("Variable Viewer"); 512 display.setDimension(BasicSSCell.JAVA3D_3D); 513 display.setPreferredSize(new Dimension(256, 256)); 514 JFrame frame = new JFrame("Variable Viewer"); 515 JPanel pane = new JPanel(); 516 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 517 frame.setContentPane(pane); 518 pane.add(varDD); 519 pane.add(display); 520 JButton controls = new JButton("Controls"); 521 JPanel buttons = new JPanel(); 522 buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS)); 523 buttons.add(controls); 524 pane.add(buttons); 525 final FancySSCell fdisp = (FancySSCell) display; 526 fdisp.setAutoShowControls(false); 527 528 controls.addActionListener(new ActionListener() { 529 public void actionPerformed(ActionEvent e) { 530 fdisp.showWidgetFrame(); 531 } 532 }); 533 534 frame.pack(); 535 // frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 536 frame.setVisible(true); 537 frame.toFront(); 538 539 } 540 // TODO: Exception handling 541 catch (Exception exe) { 542 exe.printStackTrace(); 543 return; 544 } 545 546 } 547 548 549 550 // Quick and dirty function to reshape a 1D float array into a 2D 551 private static float[][] reshape(float[] arr, int m, int n) 552 { 553 float[][] newArr = new float[m][n]; 554 555 int index=0; 556 for (int i = 0; i < n; i++) 557 { 558 for(int j = 0; j< m; j++) 559 { 560 newArr[j][i] = arr[index++]; 561 } 562 } 563 return newArr; 564 } 565 566 567 568 ///////////////////////////////////////////////////////// 569 // Shows a window that gives the opportunity to either define 570 // coordinate variables or specify corner points. 571 // 572 // Borrowed heavily from FlatFileChooser's makeNavigationPanel for style 573 ///////////////////////////////////////////////////////// 574 private void showNavChooser() 575 { 576 JPanel midPanel = new JPanel(); 577 midPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Navigation")); 578 579 GuiUtils.setListData(refComboBox, varNames); 580 GuiUtils.setListData(latComboBox, varNames); 581 GuiUtils.setListData(lonComboBox, varNames); 582 583 McVGuiUtils.setComponentWidth(latComboBox, Width.QUADRUPLE); 584 McVGuiUtils.setComponentWidth(lonComboBox, Width.QUADRUPLE); 585 McVGuiUtils.setComponentWidth(refComboBox, Width.QUADRUPLE); 586 587 //panelLatLonVars = McVGuiUtils.topBottom(latComboBox, lonComboBox, Prefer.NEITHER); 588 panelLatLonVars = McVGuiUtils.topBottom(McVGuiUtils.makeLabeledComponent("Latitude:",latComboBox), 589 McVGuiUtils.makeLabeledComponent("Longitude:",lonComboBox), 590 Prefer.NEITHER); 591 592 593 GuiUtils.buttonGroup(radioLatLonVars, radioLatLonBounds); 594 595 // Images to make the bounds more clear 596 IconPanel urPanel = new IconPanel("/edu/wisc/ssec/mcidasv/images/upper_right.gif"); 597 IconPanel llPanel = new IconPanel("/edu/wisc/ssec/mcidasv/images/lower_left.gif"); 598 599 McVGuiUtils.setComponentWidth(textLatUL); 600 McVGuiUtils.setComponentWidth(textLonUL); 601 McVGuiUtils.setComponentWidth(textLatLR); 602 McVGuiUtils.setComponentWidth(textLonLR); 603 panelLatLonBounds = McVGuiUtils.topBottom( 604 McVGuiUtils.makeLabeledComponent("UL Lat/Lon:", GuiUtils.leftRight(GuiUtils.hbox(textLatUL, textLonUL), urPanel)), 605 McVGuiUtils.makeLabeledComponent("LR Lat/Lon:", GuiUtils.leftRight(llPanel, GuiUtils.hbox(textLatLR, textLonLR))), 606 Prefer.NEITHER); 607 608 panelLatLonBounds = McVGuiUtils.topBottom(panelLatLonBounds, McVGuiUtils.makeLabeledComponent("Reference:", refComboBox), Prefer.NEITHER); 609 610 611 McVGuiUtils.setComponentWidth(radioLatLonVars); 612 McVGuiUtils.setComponentWidth(radioLatLonBounds); 613 614 615 // Add a bit of a buffer to both 616 panelLatLonVars = GuiUtils.inset(panelLatLonVars, 5); 617 panelLatLonBounds = GuiUtils.inset(panelLatLonBounds, 5); 618 619 GroupLayout layout = new GroupLayout(midPanel); 620 midPanel.setLayout(layout); 621 layout.setHorizontalGroup( 622 layout.createParallelGroup(LEADING) 623 .addGroup(layout.createSequentialGroup() 624 .addContainerGap() 625 .addGroup(layout.createParallelGroup(LEADING) 626 .addGroup(layout.createSequentialGroup() 627 .addComponent(radioLatLonVars) 628 .addGap(GAP_RELATED) 629 .addComponent(panelLatLonVars)) 630 .addGroup(layout.createSequentialGroup() 631 .addComponent(radioLatLonBounds) 632 .addGap(GAP_RELATED) 633 .addComponent(panelLatLonBounds))) 634 .addContainerGap()) 635 ); 636 layout.setVerticalGroup( 637 layout.createParallelGroup(LEADING) 638 .addGroup(TRAILING, layout.createSequentialGroup() 639 .addContainerGap() 640 .addGroup(layout.createParallelGroup(BASELINE) 641 .addComponent(radioLatLonVars) 642 .addComponent(panelLatLonVars)) 643 .addPreferredGap(RELATED) 644 .addGroup(layout.createParallelGroup(BASELINE) 645 .addComponent(radioLatLonBounds) 646 .addComponent(panelLatLonBounds)) 647 .addPreferredGap(RELATED) 648 .addContainerGap()) 649 ); 650 651 652 653 radioLatLonVars.addActionListener(new ActionListener(){ 654 public void actionPerformed(ActionEvent e) { 655 checkSetLatLon(); 656 } 657 }); 658 659 radioLatLonBounds.addActionListener(new ActionListener(){ 660 public void actionPerformed(ActionEvent e) { 661 checkSetLatLon(); 662 } 663 }); 664 665 666 JButton goBtn = new JButton("Go!"); 667 ActionListener goBtnAction = new ActionListener() 668 { 669 public void actionPerformed(ActionEvent ae) 670 { 671 boolean isVar = radioLatLonVars.isSelected(); 672 if (isVar) 673 navVarAction(); 674 else 675 navCornersAction(); 676 } 677 }; 678 goBtn.addActionListener(goBtnAction); 679 680 681 JPanel wholePanel = McVGuiUtils.topBottom(midPanel, goBtn, Prefer.NEITHER); 682 683 JFrame myWindow = GuiUtils.makeWindow("Pick Your Navigation!", GuiUtils.inset(wholePanel, 10), 0, 0); 684 checkSetLatLon(); 685 myWindow.setVisible(true); 686 myWindow.toFront(); 687 } 688 689 690 /** 691 * enable/disable widgets for navigation 692 */ 693 private void checkSetLatLon() { 694 boolean isVar = radioLatLonVars.isSelected(); 695 GuiUtils.enableTree(panelLatLonVars, isVar); 696 GuiUtils.enableTree(panelLatLonBounds, !isVar); 697 } 698 699 700 /** 701 * 702 * One of the two workhorses of our nav chooser, it alters the chosen 703 * (existing) variables so they can be used as lat/lon pairs. 704 * 705 */ 706 private void navVarAction() 707 { 708 709 } 710 711 712 713 /** 714 * 715 * One of the two workhorses of our nav chooser, it creates new 716 * variables for lat/lon based on the specified cornerpoints and 717 * reference variable (for dimensions.) 718 * 719 */ 720 721 private void navCornersAction() 722 { 723 724 } 725 726 public class BadNetCDFDialog extends JDialog { 727 728 /** 729 * Create the dialog. 730 */ 731 public BadNetCDFDialog() { 732 setTitle("Non-Compliant NetCDF Tool"); 733 setMinimumSize(new Dimension(705, 325)); 734 setBounds(100, 100, 705, 325); 735 Container contentPane = getContentPane(); 736 contentPane.setLayout(new MigLayout("", "[grow][]", "[][grow][][][][]")); 737 738 JLabel headerLabel = new JLabel("McIDAS-V is unable to read your file."); 739 headerLabel.setFont(UIManager.getFont("OptionPane.font")); 740 headerLabel.setBorder(new EmptyBorder(0, 0, 4, 0)); 741 contentPane.add(headerLabel, "cell 0 0,alignx left,aligny top"); 742 743 JTextPane messageTextPane = new JTextPane(); 744 Font textPaneFont = UIManager.getFont("TextPane.font"); 745 String fontCss = String.format("style=\"font-family: '%s'; font-size: %d;\"", textPaneFont.getFamily(), textPaneFont.getSize()); 746 messageTextPane.setBackground(UIManager.getColor("Label.background")); 747 messageTextPane.setContentType("text/html"); 748 messageTextPane.setDragEnabled(false); 749 messageTextPane.setText("<html>\n<body "+fontCss +">To verify if your file is CF-compliant, you can run your file through an online compliance checker (<a href=\"http://titania.badc.rl.ac.uk/cgi-bin/cf-checker.pl\">example CF-compliance utility</a>).<br/><br/> \n\nIf the checker indicates that your file is not compliant you can attempt to fix it using the NcML Editor provided in this window.<br/><br/>\n\nIn a future release of McIDAS-V, this interface will present you with choices for the variables necessary for McIDAS-V to display your data.<br/></font></body></html>"); 750 messageTextPane.setEditable(false); 751 messageTextPane.addHyperlinkListener(new HyperlinkListener() { 752 public void hyperlinkUpdate(HyperlinkEvent e) { 753 if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) { 754 return; 755 } 756 String url = null; 757 if (e.getURL() == null) { 758 url = e.getDescription(); 759 } else { 760 url = e.getURL().toString(); 761 } 762 WebBrowser.browse(url); 763 } 764 }); 765 contentPane.add(messageTextPane, "cell 0 1 2 1,grow"); 766 767 JSeparator separator = new JSeparator(); 768 contentPane.add(separator, "cell 0 2 2 1,growx,aligny top"); 769 770 JLabel editorLabel = new JLabel("Open the file in the NcML editor:"); 771 contentPane.add(editorLabel, "cell 0 3,alignx left,aligny baseline"); 772 773 JButton editorButton = new JButton("NcML Editor"); 774 editorButton.addActionListener(new ActionListener() { 775 @Override public void actionPerformed(ActionEvent e) { 776 showNcMLEditor(); 777 } 778 }); 779 contentPane.add(editorButton, "cell 1 3,growx,aligny baseline"); 780 781 JLabel viewLabel = new JLabel("I just want to view one of the variables:"); 782 contentPane.add(viewLabel, "cell 0 4,alignx left,aligny baseline"); 783 784 JButton viewButton = new JButton("View Variable"); 785 viewButton.addActionListener(new ActionListener() { 786 @Override public void actionPerformed(ActionEvent e) { 787 showVarPicker(); 788 } 789 }); 790 contentPane.add(viewButton, "cell 1 4,growx,aligny baseline"); 791 792 JLabel noncompliantLabel = new JLabel("I have navigation variables, they just aren't CF-compliant: (FEATURE INCOMPLETE)"); 793 contentPane.add(noncompliantLabel, "cell 0 5,alignx left,aligny baseline"); 794 795 JButton noncompliantButton = new JButton("Choose Nav"); 796 noncompliantButton.addActionListener(new ActionListener() { 797 public void actionPerformed(ActionEvent e) { 798 showNavChooser(); 799 } 800 }); 801 this.addWindowListener(new WindowAdapter() { 802 public void windowClosing(WindowEvent e) { 803 logger.trace("disposing of dialog"); 804 BadNetCDFDialog.this.dispose(); 805 } 806 }); 807 contentPane.add(noncompliantButton, "cell 1 5,growx,aligny baseline"); 808 } 809 } 810 }