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 }