001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2016 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 static javax.swing.GroupLayout.DEFAULT_SIZE; 032import static javax.swing.GroupLayout.PREFERRED_SIZE; 033import static javax.swing.GroupLayout.Alignment.BASELINE; 034import static javax.swing.GroupLayout.Alignment.LEADING; 035import static javax.swing.GroupLayout.Alignment.TRAILING; 036import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 037import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED; 038 039import java.awt.Component; 040import java.awt.event.ActionEvent; 041import java.awt.event.ActionListener; 042import java.awt.event.ItemEvent; 043import java.awt.event.ItemListener; 044import java.io.IOException; 045import java.net.URI; 046import java.util.ArrayList; 047import java.util.Date; 048import java.util.Hashtable; 049import java.util.List; 050import java.util.Vector; 051 052import javax.swing.GroupLayout; 053import javax.swing.JButton; 054import javax.swing.JComboBox; 055import javax.swing.JComponent; 056import javax.swing.JLabel; 057import javax.swing.JPanel; 058import javax.swing.JTabbedPane; 059 060import org.jdom2.Document; 061import org.jdom2.JDOMException; 062import org.jdom2.Namespace; 063import org.jdom2.input.SAXBuilder; 064import org.w3c.dom.Element; 065 066import thredds.catalog.XMLEntityResolver; 067import ucar.unidata.data.DataSelection; 068import ucar.unidata.data.radar.TDSRadarDatasetCollection; 069import ucar.nc2.units.DateUnit; 070import ucar.unidata.data.radar.RadarQuery; 071import ucar.unidata.geoloc.StationImpl; 072import ucar.unidata.idv.chooser.IdvChooserManager; 073import ucar.unidata.idv.chooser.TimesChooser; 074import ucar.unidata.metdata.NamedStation; 075import ucar.unidata.metdata.NamedStationImpl; 076import ucar.unidata.util.DateSelection; 077import ucar.unidata.util.DateUtil; 078import ucar.unidata.util.DatedThing; 079import ucar.unidata.util.GuiUtils; 080import ucar.unidata.util.LogUtil; 081import ucar.unidata.util.Misc; 082import ucar.unidata.util.PreferenceList; 083import ucar.unidata.util.Product; 084import ucar.unidata.util.TwoFacedObject; 085 086import visad.CommonUnit; 087import visad.DateTime; 088 089import edu.wisc.ssec.mcidasv.Constants; 090import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 091import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position; 092import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor; 093import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width; 094 095 096/** 097 * Created by IntelliJ IDEA. 098 * User: yuanho 099 * Date: Jan 16, 2008 100 * Time: 11:17:51 AM 101 * To change this template use File | Settings | File Templates. 102 */ 103public class TDSRadarChooser extends TimesChooser implements Constants { 104 105 /** The collection */ 106 private TDSRadarDatasetCollection collection; 107 108 109 /** The currently selected station */ 110 private NamedStation selectedStation; 111 112 /** The currently selected level3 product */ 113 private String selectedProduct; 114 115 /** Those urls we connect to */ 116 //"http://motherlode.ucar.edu:8080/thredds/radarServer/catalog.xml"; 117 private String serverUrl; 118 119 /** Each dataset collection URL */ 120 //"http://motherlode.ucar.edu:8080/thredds/radarServer/level2/idd/dataset.xml"; 121 //private String collectionUrl; 122 123 /** Component to hold collections */ 124 private JComboBox collectionSelector; 125 126 /** Component to hold product list */ 127 private JComboBox productComboBox; 128 129 /** Level 3 panel that can be hidden */ 130 private JPanel productPanel; 131 132 /** components that need a server for activation */ 133 private List compsThatNeedServer = new ArrayList(); 134 135 /** components that need a server for activation */ 136 private List level3CompsThatNeedServer = new ArrayList(); 137 138 /** persistent holder for catalog URLS */ 139 private PreferenceList urlListHandler; 140 141 /** catalog URL holder */ 142 private JComboBox urlBox; 143 144 /** ok flag */ 145 private boolean okToDoUrlListEvents = true; 146 147 /** dataset list */ 148 private List datasetList; 149 150 /** Command for connecting */ 151 protected static final String CMD_CONNECT = "cmd.connect"; 152 153 /** _more_ */ 154 private boolean isLevel3; 155 156 /** _more_ */ 157 public static final String[] level3_ExName = { "NVW", "DPA" }; 158 159 160 /** 161 * Create the RadarChooser. 162 * 163 * @param mgr {@code IdvChooserManager} 164 * @param root XML root that defines this chooser. 165 * 166 */ 167 public TDSRadarChooser(IdvChooserManager mgr, Element root) { 168 super(mgr, root); 169 170 loadButton = McVGuiUtils.makeImageTextButton(ICON_ACCEPT_SMALL, getLoadCommandName()); 171 loadButton.setActionCommand(getLoadCommandName()); 172 loadButton.addActionListener(this); 173 174 cancelButton = McVGuiUtils.makeImageButton(ICON_CANCEL, "Cancel"); 175 cancelButton.setActionCommand(GuiUtils.CMD_CANCEL); 176 cancelButton.addActionListener(this); 177 cancelButton.setEnabled(false); 178 179 } 180 181 182 183 /** 184 * Handle the update event. Just pass it through to the imageChooser 185 */ 186 public void doUpdate() { 187 if ((serverUrl == null) || (datasetList == null) 188 || (datasetList.size() == 0) || (selectedProduct == null)) { 189 if (urlBox != null) { 190 setServer((String) urlBox.getSelectedItem()); 191 } 192 return; 193 } 194 Misc.run(this, "stationOrProductChanged"); 195 } 196 197 198 199 /** 200 * Update the status of the gui 201 */ 202 protected void updateStatus() { 203 super.updateStatus(); 204 if (serverUrl == null) { 205 setHaveData(false); 206 setStatus("Please connect to the server"); 207 } 208 else if (selectedStation == null) { 209 setHaveData(false); 210 setStatus("Please select a station", "stations"); 211 } 212 else if (isLevel3 && (selectedProduct == null)) { 213 setHaveData(false); 214 setStatus("Please select a level 3 product", "products"); 215 } 216 else { 217 boolean haveTimesSelected; 218 if (getDoAbsoluteTimes()) { 219 haveTimesSelected = getSelectedAbsoluteTimes().size() > 0; 220 } else { 221 haveTimesSelected = true; 222 } 223 setHaveData(haveTimesSelected); 224 if (haveTimesSelected) { 225 setStatus("Press \"" + CMD_LOAD + "\" to load the selected radar data", "buttons"); 226 } else { 227 setStatus("Please select times", "timepanel"); 228 } 229 } 230 GuiUtils.enableTree(loadButton, getHaveData()); 231 if (drivercbx != null) { 232 drivercbx.setEnabled(anyTimeDrivers() && getHaveData()); 233 } 234 } 235 236 237 238 /** 239 * Handle when there are newly selected stations 240 * 241 * @param stations list of newly selected stations 242 */ 243 protected void newSelectedStations(List stations) { 244 super.newSelectedStations(stations); 245 if ((stations == null) || (stations.size() == 0)) { 246 selectedStation = null; 247 } else { 248 NamedStation newStation = (NamedStation) stations.get(0); 249 if (Misc.equals(newStation, selectedStation)) { 250 return; 251 } 252 selectedStation = newStation; 253 } 254 Misc.run(TDSRadarChooser.this, "stationOrProductChanged"); 255 } 256 257 258 /** A widget for the list of dataset descriptors */ 259 260 261 /** Flag to keep from infinite looping */ 262 private boolean ignoreProductChange = false; 263 264 /** Selection label text */ 265 protected static final String LABEL_SELECT = " -- Select -- "; 266 267 /** 268 * _more_ 269 */ 270 protected void productChanged() { 271 stationOrProductChanged(); 272 // updateStatus(); 273 } 274 275 /** 276 * Reset the descriptor stuff 277 */ 278 private void resetProductBox() { 279 ignoreProductChange = true; 280 productComboBox.setSelectedItem(LABEL_SELECT); 281 ignoreProductChange = false; 282 } 283 284 /** 285 * Should we update on first display 286 * 287 * @return true 288 */ 289 protected boolean shouldDoUpdateOnFirstDisplay() { 290 return false; 291 } 292 293 /** 294 * Set the server 295 * 296 * @param s the server URL 297 */ 298 private void setServer(String s) { 299 datasetList = new ArrayList(); 300 serverUrl = s; 301 try { 302 datasetList = getRadarCollections(serverUrl); 303 GuiUtils.setListData(collectionSelector, datasetList); 304 for (int i = 0; i < datasetList.size(); i++) { 305 TwoFacedObject obj = (TwoFacedObject) datasetList.get(i); 306 String tmpStr = (String) (obj.getLabel()); 307 if ((tmpStr).contains("NEXRAD Level II Radar from IDD")) { 308 collectionSelector.setSelectedIndex(i); 309 } 310 } 311 } catch (Exception e) { 312 GuiUtils.setListData(collectionSelector, new ArrayList()); 313 } 314 } 315 316 /** 317 * Set the active collection 318 * 319 * @param s collection URL 320 */ 321 private void setCollection(String s) { 322 isLevel3 = false; 323 GuiUtils.enableComponents(level3CompsThatNeedServer, false); 324 productPanel.setVisible(false); 325 GuiUtils.enableComponents(compsThatNeedServer, true); 326 if (drivercbx != null) { 327 drivercbx.setEnabled(anyTimeDrivers() && getHaveData()); 328 } 329 setAbsoluteTimes(new ArrayList()); 330 selectedProduct = null; 331 selectedStation = null; 332 Misc.run(this, "initializeCollection", s); 333 } 334 335 /** 336 * _more_ 337 * 338 * @param s _more_ 339 */ 340 private void setLevel3Collection(String s) { 341 isLevel3 = true; 342 GuiUtils.enableComponents(level3CompsThatNeedServer, true); 343 productPanel.setVisible(true); 344 GuiUtils.enableComponents(compsThatNeedServer, true); 345 if (drivercbx != null) { 346 drivercbx.setEnabled(anyTimeDrivers() && getHaveData()); 347 } 348 setAbsoluteTimes(new ArrayList()); 349 selectedProduct = null; 350 selectedStation = null; 351 Misc.run(this, "initializeLevel3Collection", s); 352 } 353 354 /** 355 * Add a component that needs to have a valid server 356 * 357 * @param comp the component 358 * 359 * @return the component 360 */ 361 protected JComponent addServerComp(JComponent comp) { 362 compsThatNeedServer.add(comp); 363 return comp; 364 } 365 366 /** 367 * Add a component that needs to have a valid server 368 * 369 * @param comp the component 370 * 371 * @return the component 372 */ 373 protected JComponent addLevel3ServerComp(JComponent comp) { 374 level3CompsThatNeedServer.add(comp); 375 return comp; 376 } 377 378 /** 379 * Get the radar collections for the given server URL 380 * 381 * @param radarServerURL server URL 382 * 383 * @return a map of the collection names to URL 384 */ 385 private List getRadarCollections(String radarServerURL) { 386 SAXBuilder builder; 387 Document doc = null; 388 XMLEntityResolver jaxp = new XMLEntityResolver(true); 389 builder = jaxp.getSAXBuilder(); 390 List collections = new ArrayList(); 391 392 try { 393 doc = builder.build(radarServerURL); 394 } catch (JDOMException e) { 395 userMessage("Invalid catalog"); 396 //e.printStackTrace(); 397 } catch (IOException e) { 398 userMessage("Unable to open catalog"); 399 //e.printStackTrace(); 400 } 401 402 org.jdom2.Element rootElem = doc.getRootElement(); 403 org.jdom2.Element serviceElem = readElements(rootElem, "service"); 404 String uriBase = serviceElem.getAttributeValue("base"); 405 org.jdom2.Element dsElem = readElements(rootElem, "dataset"); 406 String naming = "catalogRef"; 407 Namespace nss = rootElem.getNamespace("xlink"); 408 List children = dsElem.getChildren(); 409 for (int j = 0; j < children.size(); j++) { 410 org.jdom2.Element child = (org.jdom2.Element) children.get(j); 411 String childName = child.getName(); 412 if (childName.equals(naming)) { 413 //String id = child.getAttributeValue("ID"); 414 String desc = child.getAttributeValue("title", nss); 415 String urlpath = child.getAttributeValue("href", nss); 416 String[] c = radarServerURL.split(uriBase); //.replaceFirst("catalog.xml", ""); 417 String ul = c[0] + uriBase + urlpath; 418 TwoFacedObject twoObj = new TwoFacedObject(desc, ul); 419 collections.add(twoObj); 420 //collections.put(desc, ul); 421 } 422 423 } 424 425 return collections; 426 } 427 428 /** 429 * Read the elements 430 * 431 * @param elem element 432 * @param eleName element name 433 * 434 * @return an element 435 */ 436 public org.jdom2.Element readElements(org.jdom2.Element elem, 437 String eleName) { 438 List children = elem.getChildren(); 439 for (int j = 0; j < children.size(); j++) { 440 org.jdom2.Element child = (org.jdom2.Element) children.get(j); 441 String childName = child.getName(); 442 if (childName.equals(eleName)) { 443 return child; 444 } 445 } 446 return null; 447 } 448 449 /** 450 * Make the collection. If there is an error, pop up a user message. 451 * 452 * @param url URL for the collection 453 */ 454 public void initializeCollection(String url) { 455 456 List<NamedStationImpl> stations = new ArrayList<NamedStationImpl>(); 457 try { 458 StringBuffer errlog = new StringBuffer(); 459 try { 460 collection = TDSRadarDatasetCollection.factory("test", url, 461 errlog); 462 } catch (Exception exc) { 463 userMessage("Invalid catalog"); 464 465 return; 466 } 467 List tdsStations = collection.getRadarStations(); 468 for (int i = 0; i < tdsStations.size(); i++) { 469 StationImpl stn = (StationImpl) tdsStations.get(i); 470 // thredds.catalog.query.Location loc = stn.getLocation(); 471 //TODO: need better station need to switch lat lon 472 NamedStationImpl station = 473 new NamedStationImpl(stn.getName(), stn.getName(), 474 stn.getLatitude(), 475 stn.getLongitude(), 476 stn.getAltitude(), CommonUnit.meter); 477 stations.add(station); 478 479 } 480 481 getStationMap().setStations(stations); 482 } catch (Exception exc) { 483 userMessage("Unable to load stations"); 484 return; 485 } 486 urlListHandler.saveState(urlBox); 487 } 488 489 /** 490 * _more_ 491 * 492 * @param url _more_ 493 */ 494 public void initializeLevel3Collection(String url) { 495 496 List<NamedStationImpl> stations = new ArrayList<NamedStationImpl>(); 497 List<Product> products; 498 List<String> exProducts = new ArrayList<String>(); 499 500 for(String ename: level3_ExName){ 501 exProducts.add(ename); 502 } 503 504 try { 505 StringBuffer errlog = new StringBuffer(); 506 try { 507 collection = TDSRadarDatasetCollection.factory("test", url, 508 errlog); 509 } catch (Exception exc) { 510 userMessage("Invalid catalog"); 511 return; 512 } 513 products = collection.getRadarProducts(); 514 List tdsStations = collection.getRadarStations(); 515 for (int i = 0; i < tdsStations.size(); i++) { 516 StationImpl stn = (StationImpl) tdsStations.get(i); 517 // thredds.catalog.query.Location loc = stn.getLocation(); 518 //TODO: need better station need to switch lat lon 519 NamedStationImpl station = 520 new NamedStationImpl(stn.getName(), stn.getName(), 521 stn.getLatitude(), 522 stn.getLongitude(), 523 stn.getAltitude(), CommonUnit.meter); 524 stations.add(station); 525 526 } 527 List<TwoFacedObject> productNames = new ArrayList(); 528 for (Product product : products) { 529 // if ( !product.getID().contains("DPA") 530 // && !product.getID().contains("NVW")) { 531 if ( !exProducts.contains(product.getID())) { 532 String lable = product.getName() + " (" + product.getID() 533 + ")"; 534 TwoFacedObject twoObj = new TwoFacedObject(lable, 535 product.getID()); 536 productNames.add(twoObj); 537 } 538 } 539 GuiUtils.setListData(productComboBox, productNames); 540 541 // GuiUtils.setListData(dataTypeComboBox, dataTypes); 542 getStationMap().setStations(stations); 543 } catch (Exception exc) { 544 userMessage("Unable to load stations"); 545 return; 546 } 547 urlListHandler.saveState(urlBox); 548 } 549 550 551 /** 552 * Handle when the user has selected a new station 553 */ 554 public void stationOrProductChanged() { 555 Vector times = new Vector(); 556 setHaveData(false); 557 if ((!isLevel3 && selectedStation != null) || 558 (isLevel3 && selectedStation != null && selectedProduct != null)) { 559 List timeSpan = collection.getRadarTimeSpan(); 560 Date fromDate = DateUnit.getStandardOrISO((String) timeSpan.get(0)); 561 //Date toDate = DateUnit.getStandardOrISO((String) timeSpan.get(1)); 562 Date toDate = new Date(System.currentTimeMillis() 563 + DateUtil.daysToMillis(1)); 564 //Go back 10 years (or so) 565 //Date fromDate = new Date(System.currentTimeMillis() 566 // - DateUtil.daysToMillis(365 * 10)); 567 try { 568 showWaitCursor(); 569 setAbsoluteTimes(new ArrayList()); 570 setStatus("Reading times for station: " + selectedStation, 571 ""); 572 // LogUtil.message("Reading times for station: " 573 // + selectedStation); 574 String pid = null; 575 if(isLevel3) 576 pid = TwoFacedObject.getIdString( 577 productComboBox.getSelectedItem()); 578 List allTimes = 579 collection.getRadarStationTimes(selectedStation.getID(), 580 pid, fromDate, toDate); 581 582 // if(allTimes.size() == 0) { 583 // toDate = new Date(System.currentTimeMillis() 584 // + DateUtil.daysToMillis(1)); 585 // allTimes = 586 // collection.getRadarStationTimes(selectedStation.getID(), 587 // pid, fromDate, toDate); 588 // } 589 590 for (int timeIdx = 0; timeIdx < allTimes.size(); timeIdx++) { 591 Object timeObj = allTimes.get(timeIdx); 592 Date date; 593 if (timeObj instanceof Date) { 594 date = (Date) timeObj; 595 } else { 596 date = DateUnit.getStandardOrISO(timeObj.toString()); 597 } 598 times.add(new DateTime(date)); 599 } 600 // LogUtil.message(""); 601 showNormalCursor(); 602 } catch (Exception exc) { 603 userMessage("Error reading times for station: " 604 + selectedStation); 605 //logException("Getting times for station: " + selectedStation, 606 // exc); 607 setStatus("Select a different collection", "collections"); 608 showNormalCursor(); 609 return; 610 } 611 } 612 setAbsoluteTimes(times); 613 updateStatus(); 614 } 615 616 617 618 619 620 /** 621 * Load the data 622 */ 623 public void doLoadInThread() { 624 // to the CDMRadarDataSource 625 Hashtable ht = new Hashtable(); 626 if (selectedStation != null) { 627 ht.put(ucar.unidata.data.radar.RadarDataSource.STATION_LOCATION, 628 selectedStation.getNamedLocation()); 629 ht.put(DataSelection.PROP_CHOOSERTIMEMATCHING, getDoTimeDrivers()); 630 } else { 631 LogUtil.userMessage("No Station selected"); 632 } 633 634 if (isLevel3 && (selectedProduct == null)) { 635 636 LogUtil.userMessage("No Product selected"); 637 } 638 639 try { 640 DateSelection dateSelection = new DateSelection(); 641 String collectionUrl = TwoFacedObject.getIdString( 642 collectionSelector.getSelectedItem()); 643 String pid = null; 644 RadarQuery radarQuery; 645 if (isLevel3) { 646 pid = TwoFacedObject.getIdString( 647 productComboBox.getSelectedItem()); 648 radarQuery = new RadarQuery(collectionUrl, 649 selectedStation.getID(), pid, 650 dateSelection); 651 } else { 652 radarQuery = new RadarQuery(collectionUrl, 653 selectedStation.getID(), 654 dateSelection); 655 } 656 657 List urls = new ArrayList(); 658 659 if (getDoAbsoluteTimes()) { 660 List times = new ArrayList(); 661 List selected = makeDatedObjects(getSelectedAbsoluteTimes()); 662 for (int i = 0; i < selected.size(); i++) { 663 DatedThing datedThing = (DatedThing) selected.get(i); 664 Date date = datedThing.getDate(); 665 times.add(date); 666 URI uri = null; 667 try { 668 uri = collection.getRadarDatasetURI( 669 selectedStation.getID(), pid, date); 670 } catch (Exception excp) { 671 LogUtil.userMessage("incorrect times selected"); 672 return; 673 } 674 urls.add(uri.toString()); 675 } 676 if (urls.size() == 0) { 677 LogUtil.userMessage("No times selected"); 678 return; 679 } 680 dateSelection.setTimes(times); 681 } else { 682 int count = getRelativeTimesList().getSelectedIndex() + 1; 683 if (count == 0) { 684 LogUtil.userMessage("No relative times selected"); 685 return; 686 } 687 Date toDate = new Date(System.currentTimeMillis() 688 + DateUtil.daysToMillis(365 * 100)); 689 //Go back 10 years (or so) 690 Date fromDate = new Date(System.currentTimeMillis() 691 - DateUtil.daysToMillis(365 * 10)); 692 693 dateSelection.setStartFixedTime(fromDate); 694 dateSelection.setEndFixedTime(toDate); 695 dateSelection.setCount(count); 696 } 697 makeDataSource(radarQuery, "FILE.RADAR", ht); 698 } catch (Exception exc) { 699 logException("Loading radar data", exc); 700 } 701 // uncheck the check box every time click the add source button 702 drivercbx.setSelected(false); 703 enableTimeWidgets(); 704 setDoTimeDrivers(false); 705 } 706 707 protected int getNumTimesToSelect() { 708 return 5; 709 } 710 711 /** 712 * Get the default selected index for the relative times list. 713 * 714 * @return default index 715 */ 716 protected int getDefaultRelativeTimeIndex() { 717 return 4; 718 } 719 720 /** 721 * Check the times lists 722 */ 723 protected void checkTimesLists() { 724 super.checkTimesLists(); 725 if (timesCardPanelExtra == null) { 726 return; 727 } 728 if (getDoAbsoluteTimes()) { 729 timesCardPanelExtra.show("absolute"); 730 } else { 731 timesCardPanelExtra.show("relative"); 732 } 733 } 734 735 /** Card panel to hold extra relative and absolute time components */ 736 private GuiUtils.CardLayoutPanel timesCardPanelExtra; 737 738 /** 739 * Add the interval selector to the component. 740 * @return superclass component with extra stuff 741 */ 742 protected JPanel makeTimesPanel() { 743 JComponent extra = getExtraTimeComponent(); 744 GuiUtils.enableTree(extra, false); 745 JPanel timesPanel = makeTimesPanel(extra, null); 746 return timesPanel; 747 } 748 749 /** 750 * Set the relative and absolute extra components 751 */ 752 protected JPanel makeTimesPanel(JComponent relativeCard, JComponent absoluteCard) { 753 JPanel timesPanel = super.makeTimesPanel(false, true, getIdv().getUseTimeDriver()); 754 755 // Make a new timesPanel that has extra components tacked on the bottom, inside the tabs 756 Component[] comps = timesPanel.getComponents(); 757 758 if ((comps.length == 2) && (comps[0] instanceof JTabbedPane) && (comps[1] instanceof JLabel)) { 759 timesCardPanelExtra = new GuiUtils.CardLayoutPanel(); 760 if (relativeCard == null) { 761 relativeCard = new JPanel(); 762 } 763 if (absoluteCard == null) { 764 absoluteCard = new JPanel(); 765 } 766 absoluteCard = GuiUtils.hbox(comps[1], GuiUtils.right(absoluteCard)); 767 timesCardPanelExtra.add(relativeCard, "relative"); 768 timesCardPanelExtra.add(absoluteCard, "absolute"); 769 timesPanel = GuiUtils.centerBottom(comps[0], timesCardPanelExtra); 770 } 771 return timesPanel; 772 } 773 774 /** 775 * Get the time popup widget 776 * 777 * @return a widget for selecting the day 778 */ 779 protected JComponent getExtraTimeComponent() { 780 JPanel filler = new JPanel(); 781 McVGuiUtils.setComponentHeight(filler, new JComboBox()); 782 return filler; 783 } 784 785 /** 786 * Make the contents 787 * 788 * @return the contents 789 */ 790 protected JPanel doMakeInnerPanel() { 791 JPanel myPanel = new JPanel(); 792 793 JLabel collectionLabel = McVGuiUtils.makeLabelRight("Collection:"); 794 795 collectionSelector = new JComboBox(); 796 collectionSelector.addItemListener(new ItemListener() { 797 public void itemStateChanged(ItemEvent e) { 798 newSelectedStations(new ArrayList()); 799 if (collectionSelector.getSelectedItem() == null) { 800 return; 801 } 802 String collectionUrl = 803 TwoFacedObject.getIdString( 804 collectionSelector.getSelectedItem()); 805 806 if (collectionUrl.contains("level3")) { 807 setLevel3Collection(collectionUrl); 808 } else { 809 setCollection(collectionUrl); 810 } 811 } 812 813 }); 814 addServerComp(collectionLabel); 815 addServerComp(collectionSelector); 816 817 productComboBox = new JComboBox(); 818 productComboBox.addItemListener(new ItemListener() { 819 public void itemStateChanged(ItemEvent e) { 820 if (productComboBox.getSelectedItem() == null) { 821 return; 822 } 823 selectedProduct = 824 productComboBox.getSelectedItem().toString(); 825 resetProductBox(); 826 productChanged(); 827 } 828 829 }); 830 addLevel3ServerComp(productComboBox); 831 832 productPanel = McVGuiUtils.makeLabeledComponent("Product:", productComboBox); 833 834 JLabel stationLabel = McVGuiUtils.makeLabelRight("Station:"); 835 addServerComp(stationLabel); 836 837 JComponent stationPanel = getStationMap(); 838 registerStatusComp("stations", stationPanel); 839 addServerComp(stationPanel); 840 841 JLabel timesLabel = McVGuiUtils.makeLabelRight("Times:"); 842 addServerComp(timesLabel); 843 844 JPanel timesPanel = makeTimesPanel(); 845 timesPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); 846 addServerComp(timesPanel); 847 848 GuiUtils.enableComponents(compsThatNeedServer, false); 849 GuiUtils.enableComponents(level3CompsThatNeedServer, false); 850 productPanel.setVisible(false); 851 852 GroupLayout layout = new GroupLayout(myPanel); 853 myPanel.setLayout(layout); 854 layout.setHorizontalGroup( 855 layout.createParallelGroup(LEADING) 856 .addGroup(layout.createSequentialGroup() 857 .addGroup(layout.createParallelGroup(LEADING) 858 .addGroup(layout.createSequentialGroup() 859 .addComponent(collectionLabel) 860 .addGap(GAP_RELATED) 861 .addComponent(collectionSelector, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 862 .addComponent(productPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 863 .addGroup(layout.createSequentialGroup() 864 .addComponent(stationLabel) 865 .addGap(GAP_RELATED) 866 .addComponent(stationPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 867 .addGroup(layout.createSequentialGroup() 868 .addComponent(timesLabel) 869 .addGap(GAP_RELATED) 870 .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)))) 871 ); 872 layout.setVerticalGroup( 873 layout.createParallelGroup(LEADING) 874 .addGroup(layout.createSequentialGroup() 875 .addGroup(layout.createParallelGroup(BASELINE) 876 .addComponent(collectionLabel) 877 .addComponent(collectionSelector) 878 .addComponent(productPanel)) 879 .addPreferredGap(RELATED) 880 .addGroup(layout.createParallelGroup(LEADING) 881 .addComponent(stationLabel) 882 .addComponent(stationPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 883 .addPreferredGap(RELATED) 884 .addGroup(layout.createParallelGroup(LEADING) 885 .addComponent(timesLabel) 886 .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 887 .addPreferredGap(RELATED)) 888 ); 889 890 return myPanel; 891 } 892 893 private JPanel innerPanel = doMakeInnerPanel(); 894 895 private JLabel statusLabel = new JLabel("Status"); 896 897 @Override 898 public void setStatus(String statusString, String foo) { 899 if (statusString == null) 900 statusString = ""; 901 statusLabel.setText(statusString); 902 } 903 904 protected void setInnerPanel(JPanel newInnerPanel) { 905 innerPanel = newInnerPanel; 906 } 907 908 /** 909 * Make the UI for this selector. 910 * 911 * Thank you NetBeans for helping with the layout! 912 * 913 * @return The GUI. 914 */ 915 public JComponent doMakeContents() { 916 JPanel outerPanel = new JPanel(); 917 918 JLabel serverLabel = McVGuiUtils.makeLabelRight("Catalog:"); 919 920 //Get the list of catalogs but remove the old catalog.xml entry 921 urlListHandler = getPreferenceList(PREF_TDSRADARSERVER); 922 923 ActionListener catListListener = new ActionListener() { 924 public void actionPerformed(ActionEvent ae) { 925 if ( !okToDoUrlListEvents) { 926 return; 927 } 928 setServer((String) urlBox.getSelectedItem()); 929 } 930 }; 931 932 urlBox = urlListHandler.createComboBox(GuiUtils.CMD_UPDATE, catListListener, true); 933 McVGuiUtils.setComponentWidth(urlBox, Width.DOUBLEDOUBLE); 934 935 // productComboBox gets created a little too tall--set to same height as urlBox 936 if (productComboBox!=null) 937 McVGuiUtils.setComponentHeight(productComboBox, urlBox); 938 939 JButton connectButton = McVGuiUtils.makeImageTextButton(ICON_CONNECT_SMALL, "Connect"); 940 McVGuiUtils.setComponentWidth(connectButton, Width.DOUBLE); 941 connectButton.setActionCommand(GuiUtils.CMD_UPDATE); 942 connectButton.addActionListener(this); 943 944 JLabel statusLabelLabel = McVGuiUtils.makeLabelRight(""); 945 946 statusLabel.setText("Status"); 947 McVGuiUtils.setLabelPosition(statusLabel, Position.RIGHT); 948 McVGuiUtils.setComponentColor(statusLabel, TextColor.STATUS); 949 950 JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help"); 951 helpButton.setActionCommand(GuiUtils.CMD_HELP); 952 helpButton.addActionListener(this); 953 954 JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh"); 955 refreshButton.setActionCommand(GuiUtils.CMD_UPDATE); 956 refreshButton.addActionListener(this); 957 958 McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE); 959 960 GroupLayout layout = new GroupLayout(outerPanel); 961 outerPanel.setLayout(layout); 962 layout.setHorizontalGroup( 963 layout.createParallelGroup(LEADING) 964 .addGroup(TRAILING, layout.createSequentialGroup() 965 .addGroup(layout.createParallelGroup(TRAILING) 966 .addGroup(layout.createSequentialGroup() 967 .addContainerGap() 968 .addComponent(helpButton) 969 .addGap(GAP_RELATED) 970 .addComponent(refreshButton) 971 .addGap(GAP_RELATED) 972 .addComponent(cancelButton) 973 .addPreferredGap(RELATED) 974 .addComponent(loadButton)) 975 .addGroup(LEADING, layout.createSequentialGroup() 976 .addContainerGap() 977 .addGroup(layout.createParallelGroup(LEADING) 978 .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 979 .addGroup(layout.createSequentialGroup() 980 .addComponent(serverLabel) 981 .addGap(GAP_RELATED) 982 .addComponent(urlBox, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 983 .addGap(GAP_UNRELATED) 984 .addComponent(connectButton)) 985 .addGroup(layout.createSequentialGroup() 986 .addComponent(statusLabelLabel) 987 .addGap(GAP_RELATED) 988 .addComponent(statusLabel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))))) 989 .addContainerGap()) 990 ); 991 layout.setVerticalGroup( 992 layout.createParallelGroup(LEADING) 993 .addGroup(layout.createSequentialGroup() 994 .addContainerGap() 995 .addGroup(layout.createParallelGroup(BASELINE) 996 .addComponent(serverLabel) 997 .addComponent(urlBox) 998 .addComponent(connectButton)) 999 .addPreferredGap(UNRELATED) 1000 .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 1001 .addPreferredGap(UNRELATED) 1002 .addGroup(layout.createParallelGroup(BASELINE) 1003 .addComponent(statusLabelLabel) 1004 .addComponent(statusLabel)) 1005 .addPreferredGap(UNRELATED) 1006 .addGroup(layout.createParallelGroup(BASELINE) 1007 .addComponent(loadButton) 1008 .addComponent(cancelButton) 1009 .addComponent(refreshButton) 1010 .addComponent(helpButton)) 1011 .addContainerGap()) 1012 ); 1013 1014 return outerPanel; 1015 1016 } 1017 1018} 1019