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.adde; 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.KeyStroke.getKeyStroke; 036import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 037 038import java.awt.BorderLayout; 039import java.awt.Color; 040import java.awt.Component; 041import java.awt.FlowLayout; 042import java.awt.IllegalComponentStateException; 043import java.awt.Insets; 044import java.awt.Point; 045import java.awt.event.ActionEvent; 046import java.awt.event.ActionListener; 047import java.awt.event.KeyEvent; 048import java.awt.event.KeyListener; 049import java.text.SimpleDateFormat; 050import java.util.ArrayList; 051import java.util.Arrays; 052import java.util.Collections; 053import java.util.Date; 054import java.util.Hashtable; 055import java.util.Iterator; 056import java.util.List; 057import java.util.StringTokenizer; 058import java.util.Vector; 059import java.util.regex.Matcher; 060import java.util.regex.Pattern; 061 062import javax.swing.GroupLayout; 063import javax.swing.JButton; 064import javax.swing.JCheckBox; 065import javax.swing.JComboBox; 066import javax.swing.JComponent; 067import javax.swing.JDialog; 068import javax.swing.JLabel; 069import javax.swing.JOptionPane; 070import javax.swing.JPanel; 071import javax.swing.JSlider; 072import javax.swing.JTextField; 073import javax.swing.JToggleButton; 074import javax.swing.KeyStroke; 075import javax.swing.event.ChangeEvent; 076import javax.swing.event.ChangeListener; 077 078import org.slf4j.Logger; 079import org.slf4j.LoggerFactory; 080import org.w3c.dom.Element; 081 082import ucar.unidata.data.DataSelection; 083import ucar.unidata.data.imagery.AddeImageDescriptor; 084import ucar.unidata.data.imagery.AddeImageInfo; 085import ucar.unidata.data.imagery.BandInfo; 086import ucar.unidata.data.imagery.ImageDataSource; 087import ucar.unidata.data.imagery.ImageDataset; 088import ucar.unidata.idv.IdvResourceManager; 089import ucar.unidata.idv.chooser.IdvChooserManager; 090import ucar.unidata.idv.chooser.adde.AddeServer; 091import ucar.unidata.ui.LatLonWidget; 092import ucar.unidata.util.Format; 093import ucar.unidata.util.GuiUtils; 094import ucar.unidata.util.LogUtil; 095import ucar.unidata.util.Misc; 096import ucar.unidata.util.StringUtil; 097import ucar.unidata.util.TwoFacedObject; 098import ucar.unidata.xml.XmlNodeList; 099import ucar.unidata.xml.XmlResourceCollection; 100import ucar.unidata.xml.XmlUtil; 101import ucar.visad.UtcDate; 102 103import visad.DateTime; 104import visad.Gridded1DSet; 105import visad.VisADException; 106 107import edu.wisc.ssec.mcidas.AreaDirectory; 108import edu.wisc.ssec.mcidas.AreaDirectoryList; 109import edu.wisc.ssec.mcidas.McIDASException; 110import edu.wisc.ssec.mcidas.adde.AddeSatBands; 111import edu.wisc.ssec.mcidas.adde.AddeURL; 112import edu.wisc.ssec.mcidas.adde.AddeURLException; 113import edu.wisc.ssec.mcidasv.servermanager.EntryStore; 114import edu.wisc.ssec.mcidasv.ui.JCalendarDateEditor; 115import edu.wisc.ssec.mcidasv.ui.JCalendarPicker; 116import edu.wisc.ssec.mcidasv.ui.JTimeRangePicker; 117import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 118 119/** 120 * Widget to select images from a remote ADDE server Displays a list of the 121 * descriptors (names) of the image datasets available for a particular ADDE 122 * group on the remote server. 123 * 124 * @author Don Murray 125 */ 126 127public class AddeImageChooser extends AddeChooser implements 128 ucar.unidata.ui.imagery.ImageSelector { 129 130 private static final long serialVersionUID = 1L; 131 132 private static final Logger logger = LoggerFactory.getLogger(AddeImageChooser.class); 133 134 // TODO: get rid of this button right? 135 public static JToggleButton mineBtn = GuiUtils 136 .getToggleImageButton( 137 "/edu/wisc/ssec/mcidasv/resources/icons/toolbar/internet-web-browser16.png", 138 "/edu/wisc/ssec/mcidasv/resources/icons/toolbar/system-software-update16.png", 139 0, 0, true); 140 141 /** _more_ */ 142 public static final int SIZE_THRESHOLD = 50; 143 144 /** default magnification */ 145 private static final int DEFAULT_MAG = 0; 146 147 /** flag for center */ 148 private static final String PLACE_CENTER = "CENTER"; 149 150 /** flag for upper left */ 151 private static final String PLACE_ULEFT = "ULEFT"; 152 153 /** flag for lower left */ 154 private static final String PLACE_LLEFT = "LLEFT"; 155 156 /** flag for upper right */ 157 private static final String PLACE_URIGHT = "URIGHT"; 158 159 /** flag for lower right */ 160 private static final String PLACE_LRIGHT = "LRIGHT"; 161 162 /** Property for the satband file */ 163 protected static final String FILE_SATBAND = "SATBAND"; 164 165 /** Property for image default value band */ 166 protected static final String PROP_BAND = "BAND"; 167 168 /** Property for image default value id */ 169 protected static final String PROP_ID = "ID"; 170 171 /** Property for image default value key */ 172 protected static final String PROP_KEY = "key"; 173 174 /** Property for image default value lat/lon */ 175 protected static final String PROP_LATLON = "LATLON"; 176 177 /** Property for image default value line/ele */ 178 protected static final String PROP_LINELE = "LINELE"; 179 180 /** Property for image default value loc */ 181 protected static final String PROP_LOC = "LOC"; 182 183 /** Property for image default value mag */ 184 protected static final String PROP_MAG = "MAG"; 185 186 /** Property for num */ 187 protected static final String PROP_NUM = "NUM"; 188 189 /** Property for image default value place */ 190 protected static final String PROP_PLACE = "PLACE"; 191 192 /** Property for image default value size */ 193 protected static final String PROP_SIZE = "SIZE"; 194 195 /** Property for image default value spac */ 196 protected static final String PROP_SPAC = "SPAC"; 197 198 /** Property for image default value unit */ 199 protected static final String PROP_UNIT = "UNIT"; 200 201 /** Property for image default value unit */ 202 protected static final String PROP_NAV = "NAV"; 203 204 /** This is the list of properties that are used in the advanced gui */ 205 private static final String[] ADVANCED_PROPS = { PROP_UNIT, PROP_BAND, 206 PROP_PLACE, PROP_LOC, PROP_SIZE, PROP_MAG, PROP_NAV }; 207 208 /** This is the list of labels used for the advanced gui */ 209 private static final String[] ADVANCED_LABELS = { "Data Type:", "Channel:", 210 "Placement:", "Location:", "Image Size:", "Magnification:", 211 "Navigation Type:" }; 212 213 /** Xml tag name for the defaults */ 214 protected static final String TAG_DEFAULT = "default"; 215 216 /** identifier for the default value */ 217 protected static final String VALUE_DEFAULT = "default"; 218 219 /** Xml attr name for the defaults */ 220 protected static final String ATTR_NAME = "name"; 221 222 /** Xml attr name for the defaults */ 223 protected static final String ATTR_PATTERN = "pattern"; 224 225 /** Button label for day and optional time range selection */ 226 protected final static String DAY_TIME_RANGE_LABEL = "Set Day/Time Range"; 227 228 /** flag for setting properties */ 229 private boolean amSettingProperties = false; 230 231 /** Are we currently reading times */ 232 private Object readTimesTask; 233 234 /** archive date */ 235 protected String archiveDay = null; 236 237 /** archive date */ 238 protected String archiveBegTime = null; 239 240 /** archive date */ 241 protected String archiveEndTime = null; 242 243 /** number of image times to list */ 244 protected String numTimes = "all"; 245 246 /** Holds the properties */ 247 private JPanel propPanel; 248 249 /** Archive day selector button. */ 250 protected JButton archiveDayBtn; 251 252 protected JButton numImagesButton; 253 254 protected JTextField imageCountTextField; 255 256 /** Maps the PROP_ property name to the gui component */ 257 private Hashtable propToComps = new Hashtable(); 258 259 /** 260 * This is a list of hashtables, one per imagedefaults resource. The 261 * Hashtables map the pattern to the xml node 262 */ 263 private List resourceMaps; 264 265 /** Holds the subsetting defaults */ 266 private XmlResourceCollection addeDefaults; 267 268 /** archive date formatter */ 269 private SimpleDateFormat archiveDayFormatter; 270 271 /** Input for lat/lon center point */ 272 protected LatLonWidget latLonWidget; 273 274 /** Widget for the line magnification in the advanced section */ 275 protected JSlider lineMagSlider; 276 277 /** Label for the line mag. in the advanced section */ 278 protected JLabel lineMagLbl; 279 280 /** Widget for the element magnfication in the advanced section */ 281 protected JSlider elementMagSlider; 282 283 /** Label for the element mag. in the advanced section */ 284 protected JLabel elementMagLbl; 285 286 /** base number of lines */ 287 private double baseNumLines = 0.0; 288 289 /** size label */ 290 JLabel sizeLbl; 291 292 /** base number of lines */ 293 private double baseNumElements = 0.0; 294 295 /** Widget to hold the number of elements in the advanced */ 296 JTextField numElementsFld; 297 298 /** Widget to hold the number of lines in the advanced */ 299 JTextField numLinesFld; 300 301 /** Widget for the line center point in the advanced section */ 302 protected JTextField centerLineFld; 303 304 /** Widget for the element center point in the advanced section */ 305 protected JTextField centerElementFld; 306 307 /** _more_ */ 308 private JToggleButton lockBtn; 309 310 /** full resolution button */ 311 private JButton fullResBtn; 312 313 /** Identifier for the maximum number of bands */ 314 int MAX_BANDS = 100; 315 316 /** The last AreaDirectory we have seen. */ 317 private AreaDirectory lastAD; 318 319 /** The current AreaDirectory used for properties */ 320 private AreaDirectory propertiesAD; 321 322 /** The previous AreaDirectory used for properties */ 323 private AreaDirectory prevPropertiesAD; 324 325 /** Mapping of area directory to list of BandInfos */ 326 protected Hashtable bandTable; 327 328 /** Mapping of band index to {@link edu.wisc.ssec.mcidas.AreaDirectory}. */ 329 protected Hashtable bandDirs; 330 331 /** 332 * The list of currently loaded AddeImageDescriptor-s 333 */ 334 protected Vector imageDescriptors; 335 336 /** maximum size for the widget */ 337 private static final int MAX_SIZE = 700; 338 339 /** Widget for selecting image units */ 340 protected JComboBox unitComboBox; 341 342 /** place label */ 343 private JLabel placeLbl; 344 345 /** the place string */ 346 private String place; 347 348 /** location panel */ 349 private GuiUtils.CardLayoutPanel locationPanel; 350 351 /** Widget for selecting image nav type */ 352 protected JComboBox navComboBox; 353 354 /** 355 * Mapping of sensor id (String) to hashtable that maps Integer band number 356 * to name 357 */ 358 private Hashtable sensorToBandToName; 359 360 /** A flag so we can debug the new way of processing sat band file */ 361 private boolean useSatBandInfo = true; 362 363 /** Used to parse the sat band file */ 364 private AddeSatBands satBandInfo; 365 366 /** Widget for selecting the band */ 367 protected JComboBox bandComboBox; 368 369 /** string for ALL */ 370 protected static final String ALL = "ALL"; 371 372 /** object for selecting all bands */ 373 protected static final TwoFacedObject ALLBANDS = new TwoFacedObject( 374 "All Bands", ALL); 375 376 /** object for selecting all calibrations */ 377 protected static final TwoFacedObject ALLUNITS = new TwoFacedObject( 378 "All Types", ALL); 379 380 /** 381 * Keep track of the lines to element ratio 382 */ 383 private double linesToElements = 1.0; 384 385 /** 386 * limit of slider 387 */ 388 private static final int SLIDER_MAX = 29; 389 390 private static final String DEFAULT_ARCHIVE_IMAGE_COUNT = "100"; 391 392 /** 393 * the list of band infos 394 */ 395 private List<BandInfo> bandInfos; 396 397 /** 398 * Construct an Adde image selection widget 399 * 400 * 401 * @param mgr 402 * The chooser manager 403 * @param root 404 * The chooser.xml node 405 */ 406 public AddeImageChooser(IdvChooserManager mgr, Element root) { 407 super(mgr, root); 408 409 addDescComp(loadButton); 410 411 archiveDayBtn = new JButton(DAY_TIME_RANGE_LABEL); 412 archiveDayBtn.addActionListener(e -> getArchiveDay()); 413 archiveDayBtn.setToolTipText("Select a specific day and time range"); 414 415 numImagesButton = new JButton("List Images"); 416 numImagesButton.addActionListener(e -> readTimes(false)); 417 numImagesButton.setToolTipText("<html>By default, up to the 100 most " + 418 "recent times are listed.<br/><br/>For a different image count, " + 419 "provide a positive integer in<br/>the adjacent text box, " + 420 "or \"ALL\" for ALL relevant times.<br/><br/>Choosing ALL may be slow for" + 421 " datasets with many times.</html>"); 422 423 // Initialize the image count to default 424 imageCountTextField = new JTextField(AddeImageChooser.DEFAULT_ARCHIVE_IMAGE_COUNT, 4); 425 imageCountTextField.setToolTipText("<html>By default, up to the 100 most " + 426 "recent times are listed.<br/><br/>You may set this field to any positive " + 427 "integer, or the value ALL.<br/>Using ALL may take awhile for" + 428 " datasets with many times.</html>"); 429 430 this.addeDefaults = getImageDefaults(); 431 } 432 433 /** 434 * Number of absolute times to list in the chooser. 435 * Must be a positive integer, or the word "ALL". 436 * Will throw up a dialog for invalid entries. 437 * 438 * @return 0 for valid entries, -1 for invalid 439 */ 440 441 private int parseImageCount() { 442 String countStr = imageCountTextField.getText(); 443 try { 444 int newCount = Integer.parseInt(countStr); 445 // Make sure it's reasonable 446 if (newCount > 0) { 447 int addeParam = 0 - newCount + 1; 448 numTimes = "" + addeParam; 449 } else { 450 throw new NumberFormatException(); 451 } 452 } catch (NumberFormatException nfe) { 453 // Still ok if they entered "ALL" 454 if (imageCountTextField.getText().isEmpty()) { 455 JOptionPane.showMessageDialog(this, 456 "Empty field, please enter a valid positive integer"); 457 return -1; 458 } 459 if (! imageCountTextField.getText().equalsIgnoreCase("all")) { 460 JOptionPane.showMessageDialog(this, 461 "Invalid entry: " + imageCountTextField.getText()); 462 return -1; 463 } 464 numTimes = imageCountTextField.getText(); 465 } 466 return 0; 467 } 468 469 /** 470 * Get the xml resource collection that defines the image default xml 471 * 472 * @return Image defaults resources 473 */ 474 protected XmlResourceCollection getImageDefaults() { 475 return getIdv().getResourceManager().getXmlResources( 476 IdvResourceManager.RSC_IMAGEDEFAULTS); 477 } 478 479 /** 480 * Update labels, enable widgets, etc. 481 */ 482 @Override protected void updateStatus() { 483 super.updateStatus(); 484 if (getDoAbsoluteTimes()) { 485 setPropertiesState(getASelectedTime()); 486 } else { 487 setPropertiesState(lastAD); 488 } 489 490 if (readTimesTask != null) { 491 if (taskOk(readTimesTask)) { 492 setStatus("Reading available times from server"); 493 } 494 } else if ((getState() == STATE_CONNECTED) && getDoAbsoluteTimes() && !haveTimeSelected() && haveDescriptorSelected()) { 495 setStatus(MSG_TIMES); 496 } 497 enableWidgets(); 498 } 499 500 /** 501 * Do we have times selected. Either we are doing absolute times and there 502 * are some selected in the list. Or we are doing relative times and we have 503 * done a connect to the server 504 * 505 * @return Do we have times 506 */ 507 public boolean timesOk() { 508 if (getDoAbsoluteTimes() && !haveTimeSelected()) { 509 return false; 510 } 511 return (lastAD != null); 512 } 513 514 /** 515 * Get the list of advanced property names 516 * 517 * @return array of advanced property names 518 */ 519 protected String[] getAdvancedProps() { 520 return ADVANCED_PROPS; 521 } 522 523 /** 524 * Get the list of advanced property labels 525 * 526 * @return list of advanced property labels 527 */ 528 protected String[] getAdvancedLabels() { 529 return ADVANCED_LABELS; 530 } 531 532 /** 533 * Convenience method for lazy people who don't want to call 534 * {@link ucar.unidata.util.LogUtil#logException(String, Throwable)}. 535 * 536 * @param msg 537 * log message 538 * @param exc 539 * Exception to log 540 */ 541 @Override public void logException(String msg, Exception exc) { 542 LogUtil.logException(msg, exc); 543 } 544 545 /** 546 * This allows derived classes to provide their own name for labeling, etc. 547 * 548 * @return the dataset name 549 */ 550 @Override public String getDataName() { 551 return "Image Data"; 552 } 553 554 /** 555 * Get the descriptor widget label 556 * 557 * @return label for the descriptor widget 558 */ 559 @Override public String getDescriptorLabel() { 560 return "Image Type"; 561 } 562 563 /** 564 * Respond to a change in the descriptor list. 565 */ 566 protected void checkSetNav() { 567 String descriptor = getDescriptor(); 568 if (descriptor!=null) { 569 String[] suffixes = { "AMSU", "HIRS", "HRPT", "GAC", "LAC" }; 570 for (int i=0; i<suffixes.length; i++) { 571 Pattern p = Pattern.compile("N\\d\\d" + suffixes[i]); 572 Matcher m = p.matcher(descriptor); 573 if (m.find()) { 574 navComboBox.setSelectedIndex(1); 575 break; 576 } 577 } 578 } 579 } 580 581 /** 582 * Get the name of the dataset. 583 * 584 * @return descriptive name of the dataset. 585 */ 586 public String getDatasetName() { 587 StringBuffer buf = new StringBuffer(); 588 buf.append(getSelectedDescriptor()); 589 if (bandComboBox != null && bandComboBox.getItemCount() > 1) { 590 buf.append(" ("); 591 buf.append(bandComboBox.getSelectedItem()); 592 buf.append(")"); 593 } 594 return buf.toString(); 595 } 596 597 /** 598 * Check if we are ready to read times 599 * 600 * @return true if times can be read 601 */ 602 protected boolean canReadTimes() { 603 return haveDescriptorSelected(); 604 } 605 606 /** 607 * Handle when the user presses the update button 608 * 609 * @throws Exception 610 * On badness 611 */ 612 @Override public void handleUpdate() throws Exception { 613 if (getState() != STATE_CONNECTED) { 614 // If not connected then update the server list 615 updateServerList(); 616 } else { 617 // If we are already connected then update the rest of the chooser 618 descriptorChanged(); 619 } 620 updateStatus(); 621 } 622 623 /** 624 * Do server connection stuff... override this with type-specific methods 625 */ 626 @Override protected void readFromServer() { 627 archiveDay = null; 628 if (archiveDayBtn != null) { 629 archiveDayBtn.setText(DAY_TIME_RANGE_LABEL); 630 } 631 readSatBands(); 632 super.readFromServer(); 633 } 634 635 /** 636 * Overwrite base class method to clear out the lastAD member here. 637 */ 638 @Override protected void clearTimesList() { 639 lastAD = null; 640 super.clearTimesList(); 641 } 642 643 /** 644 * Show the day and time range dialog. This method is not meant to be called but is 645 * public by reason of implementation (or insanity). 646 */ 647 648 public void getArchiveDay() { 649 650 final JDialog dialog = GuiUtils.createDialog("Set Day and Time Range", true); 651 final JCalendarPicker picker = new JCalendarPicker(false); 652 final JTimeRangePicker trp = new JTimeRangePicker(); 653 654 if (archiveDay != null) { 655 if (archiveDayFormatter == null) { 656 archiveDayFormatter = new SimpleDateFormat(UtcDate.YMD_FORMAT); 657 } 658 Date d = null; 659 try { 660 d = archiveDayFormatter.parse(archiveDay); 661 picker.setDate(d); 662 } catch (Exception e) { 663 logException("parsing archive day " + archiveDay, e); 664 } 665 } 666 667 ActionListener listener = new ActionListener() { 668 public void actionPerformed(ActionEvent ae) { 669 String cmd = ae.getActionCommand(); 670 if (cmd.equals(GuiUtils.CMD_OK)) { 671 672 // bad time range, throw up error window 673 if (! trp.timeRangeOk()) { 674 String msg = "Time range is invalid.\n" + 675 "Please provide valid hours, minutes and\n" + 676 "seconds, with End Time > Start Time."; 677 Object[] params = { msg }; 678 JOptionPane.showMessageDialog(null, params, "Invalid Time Range", JOptionPane.OK_OPTION); 679 return; 680 } else { 681 archiveBegTime = trp.getBegTimeStr(); 682 archiveEndTime = trp.getEndTimeStr(); 683 } 684 try { 685 archiveDay = picker.getUserSelectedDay(); 686 archiveDayBtn.setText(archiveDay); 687 } catch (Exception e) { 688 } 689 690 setDoAbsoluteTimes(true); 691 descriptorChanged(); 692 } 693 dialog.dispose(); 694 } 695 }; 696 697 final JCalendarDateEditor dateEditor = 698 (JCalendarDateEditor)picker.getDateChooser().getDateEditor(); 699 dateEditor.getUiComponent().addKeyListener(new KeyListener() { 700 @Override public void keyTyped(KeyEvent e) { } 701 702 @Override public void keyPressed(KeyEvent e) { } 703 704 @Override public void keyReleased(KeyEvent e) { 705 if (!Color.RED.equals(dateEditor.getForeground())) { 706 KeyStroke stroke = 707 getKeyStroke(e.getKeyCode(), e.getModifiers()); 708 if (stroke.getKeyCode() == KeyEvent.VK_ENTER) { 709 try { 710 archiveDay = picker.getUserSelectedDay(); 711 archiveDayBtn.setText(archiveDay); 712 } catch (Exception ex) { 713 // nothing to do 714 } 715 setDoAbsoluteTimes(true); 716 descriptorChanged(); 717 dialog.dispose(); 718 } 719 } 720 } 721 }); 722 723 JPanel buttons = GuiUtils.makeButtons(listener, new String[] { 724 GuiUtils.CMD_OK, GuiUtils.CMD_CANCEL }); 725 726 JPanel dateTimePanel = new JPanel(new FlowLayout()); 727 dateTimePanel.add(picker); 728 dateTimePanel.add(trp); 729 730 JComponent contents = GuiUtils.topCenterBottom(GuiUtils.inset(GuiUtils 731 .lLabel("Please select a day and optional time range for this dataset:"), 10), GuiUtils 732 .inset(dateTimePanel, 10), buttons); 733 Point p = new Point(200, 200); 734 if (archiveDayBtn != null) { 735 try { 736 p = archiveDayBtn.getLocationOnScreen(); 737 } catch (IllegalComponentStateException ice) { 738 } 739 } 740 dialog.setLocation(p); 741 dialog.getContentPane().add(contents); 742 dialog.pack(); 743 dialog.setVisible(true); 744 } 745 746 /** 747 * Add the bottom advanced gui panel to the list 748 * 749 * @param bottomComps 750 * the bottom components 751 */ 752 protected void getBottomComponents(List bottomComps) { 753 754 String[] propArray = getAdvancedProps(); 755 String[] labelArray = getAdvancedLabels(); 756 // List bottomComps = new ArrayList(); 757 Insets dfltGridSpacing = new Insets(4, 0, 4, 0); 758 String dfltLblSpacing = " "; 759 760 boolean haveBand = Misc.toList(propArray).contains(PROP_BAND); 761 boolean haveNav = Misc.toList(propArray).contains(PROP_NAV); 762 for (int propIdx = 0; propIdx < propArray.length; propIdx++) { 763 JComponent propComp = null; 764 String prop = propArray[propIdx]; 765 if (prop.equals(PROP_UNIT)) { 766 unitComboBox = new JComboBox(); 767 addPropComp(PROP_UNIT, propComp = unitComboBox); 768 GuiUtils.setPreferredWidth(unitComboBox, 100); 769 if (haveBand) { 770 bandComboBox = new JComboBox(); 771 bandComboBox.addActionListener(new ActionListener() { 772 public void actionPerformed(ActionEvent e) { 773 setAvailableUnits(propertiesAD, getSelectedBand()); 774 } 775 }); 776 addPropComp(PROP_BAND, bandComboBox); 777 778 propComp = GuiUtils.hbox(propComp, GuiUtils.inset( 779 new JLabel("Channel:"), new Insets(0, 10, 0, 5)), 780 bandComboBox, 5); 781 } 782 } else if (prop.equals(PROP_BAND)) { 783 // Moved to PROP_UNIT 784 } else if (prop.equals(PROP_PLACE)) { 785 // Moved to PROP_LOC 786 } else if (prop.equals(PROP_LOC)) { 787 placeLbl = GuiUtils.getFixedWidthLabel(""); 788 changePlace(PLACE_CENTER); 789 addPropComp(PROP_PLACE, placeLbl); 790 791 latLonWidget = new LatLonWidget(); 792 centerLineFld = new JTextField("", 3); 793 centerElementFld = new JTextField("", 3); 794 795 fullResBtn = GuiUtils.makeImageButton( 796 "/auxdata/ui/icons/arrow_out.png", this, 797 "setToFullResolution"); 798 fullResBtn.setContentAreaFilled(false); 799 fullResBtn.setToolTipText("Set to full resolution"); 800 801 // lockBtn = 802 // GuiUtils.getToggleImageButton(IdvUIManager.ICON_UNLOCK, 803 // IdvUIManager.ICON_LOCK, 0, 0, true); 804 // lockBtn.setContentAreaFilled(false); 805 // lockBtn.setSelected(true); 806 // lockBtn.setToolTipText( 807 // "Unlock to automatically change size when changing magnification"); 808 809 final JButton centerPopupBtn = GuiUtils.getImageButton( 810 "/auxdata/ui/icons/MapIcon16.png", getClass()); 811 centerPopupBtn.setToolTipText("Center on current displays"); 812 centerPopupBtn.addActionListener(new ActionListener() { 813 public void actionPerformed(ActionEvent ae) { 814 getIdv().getIdvUIManager().popupCenterMenu( 815 centerPopupBtn, latLonWidget); 816 } 817 }); 818 JComponent centerPopup = GuiUtils.inset(centerPopupBtn, 819 new Insets(0, 0, 0, 4)); 820 821 GuiUtils.tmpInsets = dfltGridSpacing; 822 final JPanel latLonPanel = GuiUtils.hbox(new Component[] { 823 GuiUtils.rLabel(" Lat:" + dfltLblSpacing), 824 latLonWidget.getLatField(), 825 GuiUtils.rLabel(" Lon:" + dfltLblSpacing), 826 latLonWidget.getLonField(), new JLabel(" "), 827 centerPopup }); 828 829 final JPanel lineElementPanel = GuiUtils.hbox(new Component[] { 830 GuiUtils.rLabel(" Line:" + dfltLblSpacing), 831 centerLineFld, 832 GuiUtils.rLabel(" Element:" + dfltLblSpacing), 833 centerElementFld }); 834 835 locationPanel = new GuiUtils.CardLayoutPanel(); 836 locationPanel.addCard(latLonPanel); 837 locationPanel.addCard(lineElementPanel); 838 839 JButton locPosButton = GuiUtils.makeImageButton( 840 "/auxdata/ui/icons/Refresh16.gif", this, "cyclePlace", 841 null, true); 842 843 locPosButton.setToolTipText("Change place type"); 844 845 JButton locTypeButton = GuiUtils.makeImageButton( 846 "/auxdata/ui/icons/Refresh16.gif", locationPanel, 847 "flip", null, true); 848 locTypeButton 849 .setToolTipText("Toggle between Latitude/Longitude and Line/Element"); 850 851 propComp = GuiUtils.hbox(new Component[] { locPosButton, 852 placeLbl, locTypeButton, locationPanel }, 5); 853 addPropComp(PROP_LOC, propComp); 854 } else if (prop.equals(PROP_MAG)) { 855 boolean oldAmSettingProperties = amSettingProperties; 856 amSettingProperties = true; 857 ChangeListener lineListener = new javax.swing.event.ChangeListener() { 858 public void stateChanged(ChangeEvent evt) { 859 if (amSettingProperties) { 860 return; 861 } 862 lineMagSliderChanged(!getLockButton().isSelected()); 863 } 864 }; 865 ChangeListener elementListener = new ChangeListener() { 866 public void stateChanged(javax.swing.event.ChangeEvent evt) { 867 if (amSettingProperties) { 868 return; 869 } 870 elementMagSliderChanged(true); 871 } 872 }; 873 JComponent[] lineMagComps = GuiUtils.makeSliderPopup( 874 -SLIDER_MAX, SLIDER_MAX, 0, lineListener); 875 lineMagSlider = (JSlider) lineMagComps[1]; 876 lineMagSlider.setMajorTickSpacing(1); 877 lineMagSlider.setSnapToTicks(true); 878 lineMagSlider.setExtent(1); 879 lineMagComps[0].setToolTipText("Change the line magnification"); 880 JComponent[] elementMagComps = GuiUtils.makeSliderPopup( 881 -SLIDER_MAX, SLIDER_MAX, 0, elementListener); 882 elementMagSlider = (JSlider) elementMagComps[1]; 883 elementMagSlider.setExtent(1); 884 elementMagSlider.setMajorTickSpacing(1); 885 elementMagSlider.setSnapToTicks(true); 886 elementMagComps[0] 887 .setToolTipText("Change the element magnification"); 888 lineMagSlider 889 .setToolTipText("Slide to set line magnification factor"); 890 lineMagLbl = GuiUtils.getFixedWidthLabel(StringUtil.padLeft( 891 "1", 4)); 892 elementMagSlider 893 .setToolTipText("Slide to set element magnification factor"); 894 elementMagLbl = GuiUtils.getFixedWidthLabel(StringUtil.padLeft( 895 "1", 4)); 896 amSettingProperties = oldAmSettingProperties; 897 898 GuiUtils.tmpInsets = dfltGridSpacing; 899 /* 900 * JPanel magPanel = GuiUtils.doLayout(new Component[] { 901 * GuiUtils.rLabel("Line:" + dfltLblSpacing), lineMagLbl, 902 * GuiUtils.inset(lineMagComps[0], new Insets(0, 4, 0, 0)), 903 * GuiUtils.rLabel(" Element:" + dfltLblSpacing), 904 * elementMagLbl, GuiUtils.inset(elementMagComps[0], new 905 * Insets(0, 4, 0, 0)), }, 6, GuiUtils.WT_N, GuiUtils.WT_N); 906 */ 907 /* 908 * JPanel magPanel = GuiUtils.doLayout(new Component[] { 909 * lineMagLbl, GuiUtils.inset(lineMagComps[0], new Insets(0, 4, 910 * 0, 0)), new JLabel(" X "), elementMagLbl, 911 * GuiUtils.inset(elementMagComps[0], new Insets(0, 4, 0, 0)), 912 * }, 6, GuiUtils.WT_N, GuiUtils.WT_N); 913 */ 914 915 JPanel magPanel = GuiUtils.doLayout( 916 new Component[] { 917 lineMagLbl, 918 GuiUtils.inset(lineMagComps[0], new Insets(0, 919 4, 0, 0)), 920 new JLabel(" X"), 921 elementMagLbl, 922 GuiUtils.inset(elementMagComps[0], new Insets( 923 0, 4, 0, 0)), 924 GuiUtils.inset(getLockButton(), new Insets(0, 925 10, 0, 0)) }, 7, GuiUtils.WT_N, 926 GuiUtils.WT_N); 927 928 addPropComp(PROP_MAG, propComp = magPanel); 929 if (haveNav) { 930 navComboBox = new JComboBox(); 931 GuiUtils.setListData(navComboBox, Misc.newList( 932 new TwoFacedObject("Default", "X"), 933 new TwoFacedObject("Lat/Lon", "LALO"))); 934 addPropComp(PROP_NAV, navComboBox); 935 boolean showNav = false; 936 showNav = getProperty("includeNavComp", false); 937 if (showNav) { 938 propComp = GuiUtils.hbox(propComp, GuiUtils.inset( 939 new JLabel("Navigation Type:"), new Insets(0, 940 10, 0, 5)), navComboBox, 5); 941 } 942 } 943 } else if (prop.equals(PROP_SIZE)) { 944 numLinesFld = new JTextField("", 4); 945 numElementsFld = new JTextField("", 4); 946 numLinesFld.setToolTipText("Number of lines"); 947 numElementsFld.setToolTipText("Number of elements"); 948 GuiUtils.tmpInsets = dfltGridSpacing; 949 sizeLbl = GuiUtils.lLabel(""); 950 951 /* 952 * JPanel sizePanel = GuiUtils.left(GuiUtils.doLayout(new 953 * Component[] { GuiUtils.rLabel("Lines:" + dfltLblSpacing), 954 * numLinesFld, GuiUtils.rLabel(" Elements:" + dfltLblSpacing), 955 * numElementsFld, new JLabel(" "), sizeLbl }, 6, GuiUtils.WT_N, 956 * GuiUtils.WT_N)); 957 */ 958 959 JPanel sizePanel = GuiUtils.left(GuiUtils.doLayout( 960 new Component[] { numLinesFld, new JLabel(" X "), 961 numElementsFld, fullResBtn, /* new JLabel(" "), */ 962 sizeLbl }, 5, GuiUtils.WT_N, GuiUtils.WT_N)); 963 addPropComp(PROP_SIZE, propComp = sizePanel); 964 } 965 966 if (propComp != null) { 967 bottomComps.add(GuiUtils.rLabel(labelArray[propIdx])); 968 bottomComps.add(GuiUtils.left(propComp)); 969 } 970 971 } 972 973 GuiUtils.tmpInsets = new Insets(3, 4, 0, 4); 974 propPanel = GuiUtils.doLayout(bottomComps, 2, GuiUtils.WT_N, 975 GuiUtils.WT_N); 976 enableWidgets(); 977 } 978 979 /** 980 * Get the "lock" button 981 * 982 * @return the lock button 983 */ 984 private JToggleButton getLockButton() { 985 if (lockBtn == null) { 986 lockBtn = GuiUtils.getToggleImageButton( 987 "/auxdata/ui/icons/Linked.gif", 988 "/auxdata/ui/icons/Unlinked.gif", 0, 0, true); 989 lockBtn.setContentAreaFilled(false); 990 lockBtn.setSelected(true); 991 lockBtn 992 .setToolTipText("Unlock to automatically change size when changing magnification"); 993 } 994 return lockBtn; 995 996 } 997 998 /** 999 * Set to full resolution 1000 */ 1001 public void setToFullResolution() { 1002 1003 if (propertiesAD == null) { 1004 return; 1005 } 1006 amSettingProperties = true; 1007 numLinesFld.setText("" + propertiesAD.getLines()); 1008 numElementsFld.setText("" + propertiesAD.getElements()); 1009 changePlace(PLACE_CENTER); 1010 if (useLatLon()) { 1011 locationPanel.flip(); 1012 } 1013 centerLineFld.setText("" + (propertiesAD.getLines() / 2)); 1014 centerElementFld.setText("" + (propertiesAD.getElements() / 2)); 1015 1016 setMagSliders(1, 1); 1017 amSettingProperties = false; 1018 1019 } 1020 1021 /** 1022 * Cycle the place 1023 */ 1024 public void cyclePlace() { 1025 if (place.equals(PLACE_CENTER)) { 1026 changePlace(PLACE_ULEFT); 1027 } else { 1028 changePlace(PLACE_CENTER); 1029 } 1030 } 1031 1032 /** 1033 * Change the place 1034 * 1035 * @param newPlace 1036 * new place 1037 */ 1038 public void changePlace(String newPlace) { 1039 this.place = newPlace; 1040 String s = translatePlace(place) + "="; 1041 placeLbl.setText(StringUtil.padRight(s, 12)); 1042 } 1043 1044 /** 1045 * _more_ 1046 * 1047 * @param recomputeLineEleRatio 1048 * _more_ 1049 */ 1050 protected void elementMagSliderChanged(boolean recomputeLineEleRatio) { 1051 int value = getElementMagValue(); 1052 if ((Math.abs(value) < SLIDER_MAX)) { 1053 int lineMag = getLineMagValue(); 1054 if (lineMag > value) { 1055 linesToElements = Math.abs(lineMag / (double) value); 1056 } else { 1057 linesToElements = Math.abs((double) value / lineMag); 1058 } 1059 } 1060 // System.out.println(" changelistener: linesToElements = " + 1061 // linesToElements); 1062 elementMagLbl.setText(StringUtil.padLeft("" + value, 4)); 1063 if (!getLockButton().isSelected()) { 1064 if (value > 0) { 1065 numElementsFld.setText("" + (int) (baseNumElements * value)); 1066 } else { 1067 numElementsFld.setText("" 1068 + (int) (baseNumElements / (double) -value)); 1069 } 1070 } 1071 } 1072 1073 /** 1074 * Handle the line mag slider changed event 1075 * 1076 * 1077 * @param autoSetSize 1078 * _more_ 1079 */ 1080 protected void lineMagSliderChanged(boolean autoSetSize) { 1081 try { 1082 int value = getLineMagValue(); 1083 lineMagLbl.setText(StringUtil.padLeft("" + value, 4)); 1084 if (autoSetSize) { 1085 if (value > 0) { 1086 numLinesFld.setText("" + (int) (baseNumLines * value)); 1087 } else { 1088 numLinesFld.setText("" 1089 + (int) (baseNumLines / (double) -value)); 1090 } 1091 } 1092 1093 if (value == 1) { // special case 1094 if (linesToElements < 1.0) { 1095 value = (int) (-value / linesToElements); 1096 } else { 1097 value = (int) (value * linesToElements); 1098 } 1099 1100 } else if (value > 1) { 1101 value = (int) (value * linesToElements); 1102 1103 } else { 1104 value = (int) (value / linesToElements); 1105 } 1106 1107 value = (value > 0) ? value - 1 : value + 1; // since slider is one 1108 // off 1109 amSettingProperties = true; 1110 elementMagSlider.setValue(value); 1111 amSettingProperties = false; 1112 elementMagSliderChanged(false); 1113 } catch (Exception exc) { 1114 logException("Setting line magnification", exc); 1115 } 1116 // amSettingProperties = false; 1117 } 1118 1119 /** 1120 * Get the value of the line magnification slider. 1121 * 1122 * @return The magnification value for the line 1123 */ 1124 protected int getLineMagValue() { 1125 return getMagValue(lineMagSlider); 1126 } 1127 1128 /** 1129 * Get the value of the element magnification slider. 1130 * 1131 * @return The magnification value for the element 1132 */ 1133 protected int getElementMagValue() { 1134 return getMagValue(elementMagSlider); 1135 } 1136 1137 /** 1138 * Handle the absolute time selection changing 1139 */ 1140 @Override protected void absoluteTimesSelectionChanged() { 1141 if (!getDoAbsoluteTimes()) { 1142 return; 1143 } 1144 if (getIdv().getProperty("idv.chooser.addeimage.updateontimechange", 1145 true)) { 1146 setPropertiesState(getASelectedTime(), false); 1147 } 1148 } 1149 1150 /** 1151 * Set the relative and absolute extra components. 1152 */ 1153 @Override protected JPanel makeTimesPanel() { 1154 JPanel panel = 1155 super.makeTimesPanel(false, true, getIdv().getUseTimeDriver()); 1156 JPanel buttonPanel = new JPanel(new FlowLayout()); 1157 buttonPanel.add(archiveDayBtn); 1158 // TJJ stack num images button and associated text field, helps with smaller screens 1159 JPanel imgCountPanel = new JPanel(new BorderLayout()); 1160 imgCountPanel.add(numImagesButton, BorderLayout.NORTH); 1161 imgCountPanel.add(imageCountTextField, BorderLayout.SOUTH); 1162 buttonPanel.add(imgCountPanel); 1163 underTimelistPanel.add(BorderLayout.CENTER, buttonPanel); 1164 return panel; 1165 } 1166 1167 /** 1168 * Associates the given JComponent with the PROP_ property identified by the 1169 * given propId 1170 * 1171 * @param propId 1172 * The property 1173 * @param comp 1174 * The gui component that allows the user to set the property 1175 * 1176 * @return Just returns the given comp 1177 */ 1178 protected JComponent addPropComp(String propId, JComponent comp) { 1179 Object oldComp = propToComps.get(propId); 1180 if (oldComp != null) { 1181 throw new IllegalStateException("Already have a component defined:" 1182 + propId); 1183 } 1184 propToComps.put(propId, comp); 1185 return comp; 1186 } 1187 1188 /** 1189 * Should we use the user supplied property 1190 * 1191 * @param propId 1192 * The property 1193 * 1194 * @return Should use the value from the advanced widget 1195 */ 1196 protected boolean usePropFromUser(String propId) { 1197 if (propToComps.get(propId) == null) { 1198 return false; 1199 } 1200 return true; 1201 } 1202 1203 /** 1204 * Get one of the selected times. 1205 * 1206 * @return One of the selected times. 1207 */ 1208 protected AreaDirectory getASelectedTime() { 1209 if (haveTimeSelected()) { 1210 List selected = getSelectedAbsoluteTimes(); 1211 if (selected.size() > 0) { 1212 AddeImageDescriptor aid = (AddeImageDescriptor) selected.get(0); 1213 if (aid != null) { 1214 return aid.getDirectory(); 1215 } 1216 } 1217 } 1218 return null; 1219 } 1220 1221 /** 1222 * Enable or disable the GUI widgets based on what has been selected. 1223 */ 1224 @Override protected void enableWidgets() { 1225 boolean descriptorState = ((getState() == STATE_CONNECTED) && canReadTimes()); 1226 1227 for (int i = 0; i < compsThatNeedDescriptor.size(); i++) { 1228 JComponent comp = (JComponent) compsThatNeedDescriptor.get(i); 1229 GuiUtils.enableTree(comp, descriptorState); 1230 } 1231 1232 boolean timesOk = timesOk(); 1233 if (propPanel != null) { 1234 GuiUtils.enableTree(propPanel, timesOk); 1235 } 1236 1237 // Require times to be selected 1238 GuiUtils.enableTree(loadButton, descriptorState && timesOk); 1239 1240 if (timesOk) { 1241 checkCenterEnabled(); 1242 } 1243 checkTimesLists(); 1244 1245 // TODO: This is temporary... absolute times on Windows makes the local 1246 // servers choke 1247 // Update: this works now, but leave it here as a reminder 1248 // boolean localWindowsServer = isLocalServer() && 1249 // System.getProperty("os.name").startsWith("Windows"); 1250 // setDoAbsoluteTimes(getDoAbsoluteTimes() && !localWindowsServer); 1251 1252 enableAbsoluteTimesList(getDoAbsoluteTimes() && descriptorState); 1253 1254 getRelativeTimesChooser().setEnabled( 1255 !getDoAbsoluteTimes() && descriptorState); 1256 1257 if (drivercbx != null) { 1258// logger.trace("set drivercbx={}", anyTimeDrivers() && descriptorState); 1259 drivercbx.setEnabled(anyTimeDrivers() && descriptorState); 1260 } 1261 revalidate(); 1262 } 1263 1264 /** 1265 * Check if we are using the lat/lon widget 1266 * 1267 * @return true if we are using the lat/lon widget 1268 */ 1269 protected boolean useLatLon() { 1270 return locationPanel.getVisibleIndex() == 0; 1271 } 1272 1273 /** 1274 * Enable or disable the center lat/lon and line/element widgets 1275 */ 1276 protected void checkCenterEnabled() { 1277 // NOT NOW 1278 if (true) { 1279 return; 1280 } 1281 1282 boolean usingLatLon = useLatLon(); 1283 1284 latLonWidget.getLatField().setEnabled(usingLatLon); 1285 latLonWidget.getLonField().setEnabled(usingLatLon); 1286 // centerLatLbl.setEnabled(usingLatLon); 1287 // centerLonLbl.setEnabled(usingLatLon); 1288 1289 centerLineFld.setEnabled(!usingLatLon); 1290 centerElementFld.setEnabled(!usingLatLon); 1291 // centerLineLbl.setEnabled( !usingLatLon); 1292 // centerElementLbl.setEnabled( !usingLatLon); 1293 1294 } 1295 1296 /** 1297 * Get the selected calibration unit. 1298 * 1299 * @return the selected calibration unit 1300 */ 1301 protected String getSelectedUnit() { 1302 if (unitComboBox==null || unitComboBox.getSelectedItem()==null) return ""; 1303 String selection = (String) ((TwoFacedObject) unitComboBox.getSelectedItem()).getId(); 1304 return selection; 1305 } 1306 1307 /** 1308 * Get the data type for this chooser 1309 * 1310 * @return the data type 1311 */ 1312 @Override public String getDataType() { 1313 return "IMAGE"; 1314 } 1315 1316 /** 1317 * Get a description of the currently selected dataset 1318 * 1319 * @return a description of the currently selected dataset 1320 * @deprecated use #getDatasetName() 1321 */ 1322 @Deprecated public String getDatasetDescription() { 1323 return getDatasetName(); 1324 } 1325 1326 /** 1327 * Read the set of image times available for the current server/group/type 1328 * This method is a wrapper, setting the wait cursor and wrapping the call 1329 * to {@link #readTimesInner(boolean)}; in a try/catch block 1330 */ 1331 @Override public void readTimes() { 1332 readTimes(false); 1333 } 1334 1335 public void readTimes(boolean forceAll) { 1336 1337 // Make sure there is a valid entry in the image count text field 1338 if (parseImageCount() < 0) return; 1339 1340 clearTimesList(); 1341 if (!canReadTimes()) { 1342 return; 1343 } 1344 Misc.run(new Runnable() { 1345 public void run() { 1346 updateStatus(); 1347 showWaitCursor(); 1348 try { 1349 readTimesInner(forceAll); 1350 checkSetNav(); 1351 } catch (Exception e) { 1352 handleConnectionError(e); 1353 } 1354 showNormalCursor(); 1355 updateStatus(); 1356 } 1357 }); 1358 } 1359 1360 /** 1361 * _more_ 1362 */ 1363 @Override public void doCancel() { 1364 readTimesTask = null; 1365 setState(STATE_UNCONNECTED); 1366 super.doCancel(); 1367 } 1368 1369 /** locking mutex */ 1370 private Object MUTEX = new Object(); 1371 1372 /** 1373 * Set the list of dates/times based on the image selection 1374 * 1375 */ 1376 1377 protected void readTimesInner(boolean forceAll) { 1378 String descriptor = getDescriptor(); 1379 // String archivePosition = forceAll ? "all" : numTimes; 1380 String archivePosition = numTimes; 1381 String pos = (getDoAbsoluteTimes() || (archiveDay != null)) 1382 ? archivePosition 1383 : "0"; 1384 1385 StringBuffer addeCmdBuff = getGroupUrl(REQ_IMAGEDIR, getGroup()); 1386 String id = getSelectedStation(); 1387 if (id != null) { 1388 appendKeyValue(addeCmdBuff, PROP_ID, id); 1389 } 1390 appendKeyValue(addeCmdBuff, PROP_DESCR, descriptor); 1391 appendKeyValue(addeCmdBuff, PROP_POS, "" + pos); 1392 if (archiveDay != null) { 1393 appendKeyValue(addeCmdBuff, PROP_DAY, archiveDay); 1394 appendKeyValue(addeCmdBuff, PROP_TIME, archiveBegTime + " " + archiveEndTime); 1395 } 1396 String url = addeCmdBuff.toString(); 1397 readTimesTask = startTask(); 1398 updateStatus(); 1399 Object task = readTimesTask; 1400 try { 1401 AreaDirectoryList adir = new AreaDirectoryList(url); 1402 // Make sure no other loads are occurred 1403 boolean ok = stopTaskAndIsOk(task); 1404 if (!Misc.equals(readTimesTask, task) || !ok) { 1405 return; 1406 } 1407 readTimesTask = null; 1408 1409 synchronized (MUTEX) { 1410 // Array of AreaDirectory-s sorted by time 1411 AreaDirectory[][] dirs = adir.getSortedDirs(); 1412 int numImages = dirs.length; 1413 imageDescriptors = new Vector(); 1414 // TODO: Add a setBands method to AreaDirectory to replace bandtable 1415 bandTable = new Hashtable(numImages); 1416 int len = dirs[0].length; 1417 bandDirs = new Hashtable(len); 1418 for (int i = 0; i < len; i++) { 1419 AreaDirectory dir = dirs[0][i]; 1420 int ilen = dirs[0][i].getBands().length; 1421 for(int j = 0; j < ilen; j++){ 1422 int bindex = dirs[0][i].getBands()[j]; 1423 bandDirs.put(bindex, dir); 1424 } 1425 } 1426 lastAD = null; 1427 for (int i = 0; i < numImages; i++) { 1428 int bandIndex = 0; 1429 lastAD = (AreaDirectory) dirs[i][0]; 1430 int[] allBands = new int[MAX_BANDS]; 1431 Vector[] allCals = new Vector[MAX_BANDS]; 1432 for (int j = 0; j < dirs[i].length; j++) { 1433 int nbands = dirs[i][j].getNumberOfBands(); 1434 int[] abands = dirs[i][j].getBands(); 1435 Vector[] vb = dirs[i][j].getCalInfo(); 1436 for (int k = 0; k < nbands; k++) { 1437 allBands[bandIndex] = abands[k]; 1438 allCals[bandIndex++] = vb[k]; 1439 } 1440 } 1441 int[] bands = new int[bandIndex]; 1442 System.arraycopy(allBands, 0, bands, 0, bandIndex); 1443 Vector[] cals = new Vector[bandIndex]; 1444 System.arraycopy(allCals, 0, cals, 0, bandIndex); 1445 lastAD.setCalInfo(cals); 1446 bandTable.put(lastAD, bands); 1447 AddeImageDescriptor aid = new AddeImageDescriptor(lastAD, null); 1448 imageDescriptors.add(aid); 1449 } 1450 1451 Collections.sort(imageDescriptors); 1452 if (getDoAbsoluteTimes()) { 1453 setAbsoluteTimes(imageDescriptors); 1454 } 1455 // revalidate(); 1456 } 1457 setState(STATE_CONNECTED); 1458 } catch (McIDASException e) { 1459 logger.warn("Exception while reading times from server", e); 1460 stopTask(task); 1461 readTimesTask = null; 1462 handleConnectionError("\nError reading times", e); 1463 // you want this step because readTimes() will call updateStatus(), 1464 // and since we already have a server and dataset, all the user needs 1465 // to do is select an image type (descriptor). 1466 setState(STATE_CONNECTED); 1467 } 1468 } 1469 1470 /** 1471 * Set the selected times in the times list based on the input times 1472 * 1473 * @param times Input times. 1474 */ 1475 @Override protected void setSelectedTimes(DateTime[] times) { 1476 if ((times == null) || (times.length == 0)) { 1477 return; 1478 } 1479 DateTime[] imageTimes = new DateTime[times.length]; 1480 1481 if (imageDescriptors != null) { 1482 imageTimes = new DateTime[imageDescriptors.size()]; 1483 for (int idIdx = 0; idIdx < imageDescriptors.size(); idIdx++) { 1484 AddeImageDescriptor aid = (AddeImageDescriptor) imageDescriptors.get(idIdx); 1485 imageTimes[idIdx] = aid.getImageTime(); 1486 } 1487 } else { 1488 imageTimes = times; 1489 } 1490 if (imageTimes.length > 0) { 1491 try { 1492 Gridded1DSet imageSet = DateTime.makeTimeSet(imageTimes); 1493 int numTimes = times.length; 1494 double[][] timesValues = new double[1][numTimes]; 1495 for (int i = 0; i < times.length; i++) { 1496 timesValues[0][i] = times[i].getValue(imageSet.getSetUnits()[0]); 1497 } 1498 setSelectedAbsoluteTimes(imageSet.doubleToIndex(timesValues)); 1499 absoluteTimesSelectionChanged(); 1500 } catch (VisADException ve) { 1501 logException("Unable to set times from display", ve); 1502 } 1503 } 1504 } 1505 1506 /** 1507 * Set the center location portion of the request. If the input from the 1508 * widget is null, use the centerpoint from the image descriptor. 1509 * 1510 * @param aid Image descriptor for the image. 1511 */ 1512 protected void setCenterLocation(AddeImageDescriptor aid) { 1513 String latPoint = ""; 1514 String lonPoint = ""; 1515 if (aid != null) { 1516 AreaDirectory ad = aid.getDirectory(); 1517 latPoint = "" + ad.getCenterLatitude(); 1518 lonPoint = "" + ad.getCenterLongitude(); 1519 } 1520 if (!latPoint.trim().equals("")) { 1521 latLonWidget.setLat(latPoint); 1522 } 1523 if (!lonPoint.trim().equals("")) { 1524 latLonWidget.setLon(lonPoint); 1525 } 1526 } 1527 1528 /** 1529 * get the adde server grup type to use 1530 * 1531 * @return group type 1532 */ 1533 @Override protected String getGroupType() { 1534 return AddeServer.TYPE_IMAGE; 1535 } 1536 1537 /** 1538 * Does this selector have all of its state set to load in data 1539 * 1540 * @return Has the user chosen everything they need to choose to load data 1541 */ 1542 @Override protected boolean getGoodToGo() { 1543 // if(!super.getGoodToGo()) return false; 1544 if (getDoAbsoluteTimes()) { 1545 return getHaveAbsoluteTimesSelected(); 1546 } else { 1547 return canReadTimes() && (lastAD != null); 1548 } 1549 } 1550 1551 /** 1552 * Returns a list of the images to load or null if none have been selected. 1553 * 1554 * @return list get the list of image descriptors 1555 */ 1556 @Override public List getImageList() { 1557 if (!timesOk()) { 1558 return null; 1559 } 1560 List images = new ArrayList(); 1561 String defaultBand = getDefault(PROP_BAND, ALL); 1562 try { 1563 if (getDoRelativeTimes()) { 1564 AddeImageDescriptor firstDescriptor = (AddeImageDescriptor) imageDescriptors.get(0); 1565 AreaDirectory ad = firstDescriptor.getDirectory(); 1566 int[] bands = (int[]) bandTable.get(ad); 1567 bandInfos = makeBandInfos(ad, bands); 1568 int[] relativeTimesIndices = getRelativeTimeIndices(); 1569 for (int i = 0; i < relativeTimesIndices.length; i++) { 1570 AddeImageDescriptor aid = new AddeImageDescriptor(relativeTimesIndices[i], firstDescriptor); 1571 AddeImageInfo aii = makeImageInfo(aid.getDirectory(), true, relativeTimesIndices[i]); 1572 aii.setDebug(EntryStore.isAddeDebugEnabled(false)); 1573 if (aii.getBand() == null) aii.setBand(defaultBand); 1574 aid.setImageInfo(aii); 1575 aid.setSource(aii.getURLString()); 1576 images.add(aid); 1577 } 1578 } else { 1579 List selectedTimes = getSelectedAbsoluteTimes(); 1580 for (int i = 0; i < selectedTimes.size(); i++) { 1581 AddeImageDescriptor aid = new AddeImageDescriptor((AddeImageDescriptor) selectedTimes.get(i)); 1582 AddeImageInfo aii = makeImageInfo(aid.getDirectory(), false, i); 1583 aii.setDebug(EntryStore.isAddeDebugEnabled(false)); 1584 if (aii.getBand() == null) aii.setBand(defaultBand); 1585 aid.setImageInfo(aii); 1586 aid.setSource(aii.getURLString()); 1587 images.add(aid); 1588 } 1589 } 1590 } catch (Exception exc) { 1591 logException("Error occured", exc); 1592 return null; 1593 } 1594 return images; 1595 } 1596 1597 /** 1598 * Process the image defaults resources 1599 */ 1600 protected void initializeAddeDefaults() { 1601 resourceMaps = new ArrayList(); 1602 if (addeDefaults == null) { 1603 return; 1604 } 1605 for (int resourceIdx = 0; resourceIdx < addeDefaults.size(); resourceIdx++) { 1606 Element root = addeDefaults.getRoot(resourceIdx); 1607 if (root == null) { 1608 continue; 1609 } 1610 Hashtable resourceMap = new Hashtable(); 1611 resourceMaps.add(resourceMap); 1612 1613 XmlNodeList defaultNodes = XmlUtil.getElements(root, TAG_DEFAULT); 1614 for (int nodeIdx = 0; nodeIdx < defaultNodes.size(); nodeIdx++) { 1615 Element dfltNode = (Element) defaultNodes.item(nodeIdx); 1616 String pattern = XmlUtil.getAttribute(dfltNode, ATTR_PATTERN, 1617 (String) null); 1618 if (pattern == null) { 1619 pattern = XmlUtil.getAttribute(dfltNode, ATTR_NAME); 1620 } 1621 if (pattern != null) { 1622 pattern = pattern.toLowerCase(); 1623 } 1624 resourceMap.put(pattern, dfltNode); 1625 } 1626 } 1627 } 1628 1629 /** 1630 * Get the default value for a key 1631 * 1632 * @param property 1633 * property (key type) 1634 * @param dflt 1635 * default value 1636 * @return value for key or dflt if not found 1637 */ 1638 protected String getDefault(String property, String dflt) { 1639 if (resourceMaps == null) { 1640 initializeAddeDefaults(); 1641 } 1642 property = property.toLowerCase(); 1643 1644 String userDefault = null; 1645 String server = getServer(); 1646 String group = getGroup(); 1647 String descriptor = getDescriptor(); 1648 String[] keys = { userDefault, server + ":" + group + "/" + descriptor, 1649 group + "/" + descriptor, server + ":" + group + "/*", 1650 group + "/*", server + ":*/" + descriptor, "*/" + descriptor, 1651 descriptor, server + ":*/*", server, "*" }; 1652 1653 if (server != null) { 1654 if (PROP_USER.equals(property)) 1655 return getLastAddedUser(); 1656 if (PROP_PROJ.equals(property)) 1657 return getLastAddedProj(); 1658 } 1659 1660 for (int resourceIdx = 0; resourceIdx < resourceMaps.size(); resourceIdx++) { 1661 Hashtable resourceMap = (Hashtable) resourceMaps.get(resourceIdx); 1662 for (int keyIdx = 0; keyIdx < keys.length; keyIdx++) { 1663 String key = keys[keyIdx]; 1664 if (key == null) { 1665 continue; 1666 } 1667 key = key.toLowerCase(); 1668 Element defaultNode = (Element)resourceMap.get(key); 1669 if (defaultNode == null) { 1670 continue; 1671 } 1672 String value = XmlUtil.getAttribute(defaultNode, property, (String)null); 1673 if (value == null) { 1674 continue; 1675 } 1676 if (value.equals(VALUE_DEFAULT)) { 1677 return dflt; 1678 } else { 1679 return value; 1680 } 1681 } 1682 } 1683 return dflt; 1684 } 1685 1686 /** 1687 * Get the image size string from the directory and defaults 1688 * 1689 * @param ad 1690 * image directory 1691 * @return request size 1692 */ 1693 protected String getSizeString(AreaDirectory ad) { 1694 String retString = MAX_SIZE + " " + MAX_SIZE; 1695 if (ad != null) { 1696 int x = ad.getElements(); 1697 int y = ad.getLines(); 1698 if ((x < MAX_SIZE) && (y < MAX_SIZE)) { 1699 retString = x + " " + y; 1700 } else if ((x >= MAX_SIZE) && (y >= MAX_SIZE)) { 1701 retString = MAX_SIZE + " " + MAX_SIZE; 1702 } else if ((x >= MAX_SIZE) && (y < MAX_SIZE)) { 1703 retString = MAX_SIZE + " " + y; 1704 } else if ((x < MAX_SIZE) && (y >= MAX_SIZE)) { 1705 retString = x + " " + MAX_SIZE; 1706 } 1707 } 1708 return retString; 1709 } 1710 1711 /** 1712 * Check for valid lat/lon values 1713 * 1714 * @return true if values are valid 1715 */ 1716 protected boolean checkForValidValues() { 1717 if (usePropFromUser(PROP_LOC)) { 1718 if (useLatLon()) { 1719 String msg = latLonWidget.isValidValues(); 1720 if ((msg != null) && (msg.length() > 0)) { 1721 LogUtil.userMessage(msg); 1722 return false; 1723 } 1724 } 1725 } 1726 return true; 1727 } 1728 1729 /** 1730 * Get the list of properties for the base URL 1731 * 1732 * @return list of properties 1733 */ 1734 protected String[] getBaseUrlProps() { 1735 return new String[] { PROP_DESCR, PROP_UNIT, PROP_SPAC, PROP_BAND, 1736 PROP_NAV, PROP_USER, PROP_PROJ, }; 1737 } 1738 1739 /** 1740 * A utility that creates the url argument line for the given set of 1741 * properties. 1742 * 1743 * @param props 1744 * The PROP_ properties to make the request string for 1745 * @param ad 1746 * The area directory. 1747 * 1748 * @return The adde request string 1749 */ 1750 protected String makeProps(String[] props, AreaDirectory ad) { 1751 StringBuffer buf = new StringBuffer(); 1752 for (int propIdx = 0; propIdx < props.length; propIdx++) { 1753 appendKeyValue(buf, props[propIdx], 1754 getPropValue(props[propIdx], ad)); 1755 } 1756 return buf.toString(); 1757 } 1758 1759 /** 1760 * Get the value for the given property. This can either be the value 1761 * supplied by the end user through the advanced GUI or is the default 1762 * 1763 * @param prop 1764 * The property 1765 * @param ad 1766 * The AreaDirectory 1767 * 1768 * @return The value of the property to use in the request string 1769 */ 1770 protected String getPropValue(String prop, AreaDirectory ad) { 1771 if (usePropFromUser(prop)) { 1772 return getUserPropValue(prop, ad); 1773 } 1774 1775 // Handle size specially because we really want to get the minimum of 1776 // the default and the ad size 1777 if (PROP_SIZE.equals(prop)) { 1778 int[] size = getSize(ad); 1779 return size[0] + " " + size[1]; 1780 } 1781 1782 return getDefault(prop, getDefaultPropValue(prop, ad, false)); 1783 } 1784 1785 /** 1786 * Get the user supplied property value for the adde request string 1787 * 1788 * @param prop 1789 * The property 1790 * @param ad 1791 * The AreaDirectory 1792 * 1793 * @return The value, supplied by the user, of the property to use in the 1794 * request string 1795 */ 1796 protected String getUserPropValue(String prop, AreaDirectory ad) { 1797 if (PROP_LATLON.equals(prop) && (latLonWidget != null)) { 1798 // apparently the ADDE server can't handle long numbers 1799 return Format.dfrac(latLonWidget.getLat(), 5) + " " 1800 + Format.dfrac(latLonWidget.getLon(), 5); 1801 } 1802 if (PROP_PLACE.equals(prop) && (placeLbl != null)) { 1803 return place; 1804 } 1805 1806 if (PROP_LINELE.equals(prop) && (centerLineFld != null)) { 1807 return centerLineFld.getText().trim() + " " 1808 + centerElementFld.getText().trim(); 1809 } 1810 1811 if (PROP_SIZE.equals(prop) && (numLinesFld != null)) { 1812 return numLinesFld.getText().trim() + " " 1813 + numElementsFld.getText().trim(); 1814 } 1815 if (PROP_MAG.equals(prop) && (lineMagSlider != null)) { 1816 return getLineMagValue() + " " + getElementMagValue(); 1817 } 1818 if (PROP_BAND.equals(prop) && (bandComboBox != null)) { 1819 1820 Object selected = bandComboBox.getSelectedItem(); 1821 if (selected != null) { 1822 if (selected.equals(ALLBANDS)) { 1823 return ALLBANDS.toString(); 1824 } else { 1825 return "" + ((BandInfo) selected).getBandNumber(); 1826 } 1827 } 1828 } 1829 if (PROP_UNIT.equals(prop)) { 1830 return getSelectedUnit(); 1831 } 1832 if (PROP_NAV.equals(prop)) { 1833 return TwoFacedObject.getIdString(navComboBox.getSelectedItem()); 1834 } 1835 1836 if (PROP_USER.equals(prop)) 1837 return getLastAddedUser(); 1838 if (PROP_PROJ.equals(prop)) 1839 return getLastAddedProj(); 1840 1841 return null; 1842 } 1843 1844 /** 1845 * Get the default property value for the adde request string 1846 * 1847 * @param prop 1848 * The property 1849 * @param ad 1850 * The AreaDirectory 1851 * @param forDisplay 1852 * Is this to display to the user in the gui 1853 * 1854 * @return The default of the property to use in the request string 1855 */ 1856 protected String getDefaultPropValue(String prop, AreaDirectory ad, 1857 boolean forDisplay) { 1858 if (PROP_USER.equals(prop)) { 1859 return DEFAULT_USER; 1860 } 1861 if (PROP_USER.equals(prop)) { 1862 return PLACE_CENTER; 1863 } 1864 if (PROP_PROJ.equals(prop)) { 1865 return DEFAULT_PROJ; 1866 } 1867 if (PROP_DESCR.equals(prop)) { 1868 return getDescriptor(); 1869 } 1870 if (PROP_VERSION.equals(prop)) { 1871 return DEFAULT_VERSION; 1872 } 1873 if (PROP_COMPRESS.equals(prop)) { 1874 return "gzip"; 1875 } 1876 if (PROP_PORT.equals(prop)) { 1877 return DEFAULT_PORT; 1878 } 1879 if (PROP_DEBUG.equals(prop)) { 1880// return DEFAULT_DEBUG; 1881 Boolean.toString(EntryStore.isAddeDebugEnabled(false)); 1882 } 1883 if (PROP_SIZE.equals(prop)) { 1884 if (ad != null) { 1885 return ad.getLines() + " " + ad.getElements(); 1886 } 1887 return MAX_SIZE + " " + MAX_SIZE; 1888 } 1889 if (PROP_MAG.equals(prop)) { 1890 return "1 1"; 1891 } 1892 // if (prop.equals(PROP_LOC) || prop.equals(PROP_LINELE)) { 1893 if (PROP_MAG.equals(prop)) { 1894 if (ad == null) { 1895 return "0 0"; 1896 } 1897 return ad.getLines() / 2 + " " + ad.getElements() / 2; 1898 } 1899 // if (prop.equals(PROP_LATLON)) { 1900 if (PROP_LOC.equals(prop) || PROP_LATLON.equals(prop)) { 1901 if (ad == null) { 1902 return "0 0"; 1903 } 1904 return ad.getCenterLatitude() + " " + ad.getCenterLongitude(); 1905 } 1906 if (PROP_BAND.equals(prop)) { 1907 if (bandTable==null) return ""; 1908 if (forDisplay) { 1909 return getBandName(ad, ((int[]) bandTable.get(ad))[0]); 1910 } 1911 return "" + ((int[]) bandTable.get(ad))[0]; 1912 } 1913 if (PROP_SPAC.equals(prop)) { 1914 return getSelectedUnit().equalsIgnoreCase("BRIT") ? "1" : "4"; 1915 } 1916 if (PROP_UNIT.equals(prop)) { 1917 return "X"; 1918 } 1919 if (PROP_NAV.equals(prop)) { 1920 return "X"; 1921 } 1922 return ""; 1923 } 1924 1925 /** 1926 * Set the properties on the AddeImageInfo from the list of properties 1927 * 1928 * @param aii 1929 * The AddeImageInfo 1930 * @param props 1931 * list of props to set 1932 * @param ad 1933 * The AreaDirectory 1934 */ 1935 protected void setImageInfoProps(AddeImageInfo aii, String[] props, AreaDirectory ad) { 1936 for (int i = 0; i < props.length; i++) { 1937 String prop = props[i]; 1938 String value = getPropValue(prop, ad); 1939 if (prop.equals(PROP_USER)) { 1940 aii.setUser(value); 1941 } else if (prop.equals(PROP_PROJ)) { 1942 aii.setProject(Integer.parseInt(value)); 1943 } else if (prop.equals(PROP_DESCR)) { 1944 aii.setDescriptor(value); 1945 } else if (prop.equals(PROP_VERSION)) { 1946 aii.setVersion(value); 1947 } else if (prop.equals(PROP_COMPRESS)) { 1948 int compVal = AddeURL.GZIP; 1949 if (value.equals("none") || value.equals("1")) { 1950 compVal = AddeURL.NO_COMPRESS; 1951 } else if (value.equals("compress") || value.equals("2") || value.equals("true")) { 1952 compVal = AddeURL.COMPRESS; 1953 } 1954 aii.setCompression(compVal); 1955 } else if (prop.equals(PROP_PORT)) { 1956 aii.setPort(Integer.parseInt(value)); 1957 } else if (prop.equals(PROP_DEBUG)) { 1958// aii.setDebug(Boolean.getBoolean(value)); 1959 aii.setDebug(EntryStore.isAddeDebugEnabled(false)); 1960 } else if (prop.equals(PROP_SPAC)) { 1961 aii.setSpacing(Integer.parseInt(value)); 1962 } else if (prop.equals(PROP_UNIT)) { 1963 if (value.equals(ALLUNITS.getId())) { 1964 value = getDefault(prop, getDefaultPropValue(prop, ad, false)); 1965 } 1966 aii.setUnit(value); 1967 } else if (prop.equals(PROP_BAND)) { 1968 if (value.equals(ALLBANDS.toString())) { 1969 value = getDefault(prop, getDefaultPropValue(prop, ad, false)); 1970 } 1971 aii.setBand(value); 1972 } else if (prop.equals(PROP_NAV)) { 1973 aii.setNavType(value); 1974 } else if (prop.equals(PROP_ID)) { 1975 aii.setId(value); 1976 } 1977 } 1978 } 1979 1980 /** 1981 * Get the name of the selected band 1982 * 1983 * @return the name of the band 1984 */ 1985 public String getSelectedBandName() { 1986 return getBandName(propertiesAD, getSelectedBand()); 1987 } 1988 1989 /** 1990 * Clear the properties widgets 1991 */ 1992 protected void clearPropertiesWidgets() { 1993 if (latLonWidget != null) { 1994 latLonWidget.getLatField().setText(""); 1995 latLonWidget.getLonField().setText(""); 1996 } 1997 if (centerLineFld != null) { 1998 centerLineFld.setText(""); 1999 centerElementFld.setText(""); 2000 } 2001 if (numLinesFld != null) { 2002 if (sizeLbl != null) { 2003 sizeLbl.setText(""); 2004 } 2005 numLinesFld.setText(""); 2006 numElementsFld.setText(""); 2007 } 2008 if (unitComboBox != null) { 2009 GuiUtils.setListData(unitComboBox, new Vector()); 2010 } 2011 if (bandComboBox != null) { 2012 GuiUtils.setListData(bandComboBox, new Vector()); 2013 } 2014 2015 setMagSliders(DEFAULT_MAG, DEFAULT_MAG); 2016 2017 if (placeLbl != null) { 2018 changePlace(PLACE_CENTER); 2019 } 2020 2021 if (navComboBox != null) { 2022 checkSetNav(); 2023// navComboBox.setSelectedIndex(0); 2024 } 2025 baseNumLines = 0.0; 2026 baseNumElements = 0.0; 2027 } 2028 2029 /** 2030 * Set the widgets with the state from the given AreaDirectory 2031 * 2032 * @param ad 2033 * AreaDirectory for the image 2034 */ 2035 protected void setPropertiesState(AreaDirectory ad) { 2036 setPropertiesState(ad, false); 2037 } 2038 2039 /** 2040 * _more_ 2041 * 2042 * @param ad 2043 * _more_ 2044 * 2045 * @return _more_ 2046 */ 2047 protected int[] getSize(AreaDirectory ad) { 2048 baseNumLines = ad.getLines(); 2049 baseNumElements = ad.getElements(); 2050 2051 String sizeDefault = getDefault(PROP_SIZE, (String) null); 2052 List toks = ((sizeDefault != null) ? StringUtil.split(sizeDefault, " ", 2053 true, true) : null); 2054 if ((toks == null) || (toks.size() == 0)) { 2055 return new int[] { (int) baseNumLines, (int) baseNumElements }; 2056 } else { 2057 String lines = "" + toks.get(0); 2058 if (lines.equalsIgnoreCase(ALL)) { 2059 lines = "" + (int) baseNumLines; 2060 } 2061 int numLines = new Integer(lines.trim()).intValue(); 2062 2063 String elems = (toks.size() > 1) ? "" + toks.get(1) : "" 2064 + (int) baseNumElements; 2065 if (elems.equalsIgnoreCase(ALL)) { 2066 elems = "" + baseNumElements; 2067 } 2068 int numElements = new Integer(elems.trim()).intValue(); 2069 return new int[] { (int) Math.min(numLines, baseNumLines), 2070 (int) Math.min(numElements, baseNumElements) }; 2071 } 2072 2073 } 2074 2075 /** 2076 * Set the widgets with the state from the given AreaDirectory 2077 * 2078 * @param ad 2079 * AreaDirectory for the image 2080 * @param force 2081 * force an update regardless of the previous invocation 2082 */ 2083 protected void setPropertiesState(AreaDirectory ad, boolean force) { 2084 if (amSettingProperties) 2085 return; 2086 2087 prevPropertiesAD = propertiesAD; 2088 propertiesAD = ad; 2089 if (!force && checkPropertiesEqual(prevPropertiesAD, propertiesAD)) 2090 return; 2091 2092 amSettingProperties = true; 2093 2094 if (ad == null) { 2095 clearPropertiesWidgets(); 2096 amSettingProperties = false; 2097 return; 2098 } 2099 2100 String[] propArray = getAdvancedProps(); 2101 2102 if (numLinesFld != null) { 2103 int[] size = getSize(ad); 2104 numLinesFld.setText("" + size[0]); 2105 numElementsFld.setText("" + size[1]); 2106 if (sizeLbl != null) { 2107 String label = " Raw size: " + ad.getLines() + " X " 2108 + ad.getElements(); 2109 sizeLbl.setText(label); 2110 } 2111 } 2112 if (latLonWidget != null) { 2113 latLonWidget.getLatField().setText("" + ad.getCenterLatitude()); 2114 latLonWidget.getLonField().setText("" + ad.getCenterLongitude()); 2115 } 2116 if (centerLineFld != null) { 2117 centerLineFld.setText("" + ad.getLines() / 2); 2118 centerElementFld.setText("" + ad.getElements() / 2); 2119 } 2120 2121 List<BandInfo> bandList = null; 2122 int[] bands = (int[]) bandTable.get(ad); 2123 if (bands != null) 2124 bandList = makeBandInfos(ad, bands); 2125 bandInfos = bandList; 2126 2127 if (bandComboBox != null) { 2128 List comboList = bandList; 2129 if (bandList.size() > 1) { 2130 comboList = new ArrayList(); 2131 comboList.addAll(bandList); 2132 comboList.add(ALLBANDS); 2133 } 2134 GuiUtils.setListData(bandComboBox, comboList); 2135 } 2136 2137 setAvailableUnits(ad, getSelectedBand()); 2138 2139 for (int propIdx = 0; propIdx < propArray.length; propIdx++) { 2140 String prop = propArray[propIdx]; 2141 String value = getDefault(prop, getDefaultPropValue(prop, ad, false)); 2142 if (value == null) 2143 value = ""; 2144 2145 value = value.trim(); 2146 if (prop.equals(PROP_LOC)) { 2147 String key = getDefault(PROP_KEY, PROP_LATLON); 2148 2149 boolean usingLineElement = key.equals(PROP_LINELE); 2150 if (usingLineElement) { 2151 locationPanel.show(1); 2152 } else { 2153 locationPanel.show(0); 2154 } 2155 if (usingLineElement) { 2156 value = getDefault(PROP_LOC, getDefaultPropValue( 2157 PROP_LINELE, ad, false)); 2158 } else { 2159 value = getDefault(PROP_LOC, getDefaultPropValue( 2160 PROP_LATLON, ad, false)); 2161 } 2162 String[] pair = getPair(value); 2163 if (pair != null) { 2164 if (usingLineElement) { 2165 centerLineFld.setText(pair[0]); 2166 centerElementFld.setText(pair[1]); 2167 } else { 2168 latLonWidget.setLat(pair[0]); 2169 latLonWidget.setLon(pair[1]); 2170 } 2171 } 2172 } else if (prop.equals(PROP_BAND)) { 2173 if (value.equalsIgnoreCase((String) ALLBANDS.getId())) { 2174 bandComboBox.setSelectedItem(ALLBANDS); 2175 } else { 2176 int bandNum = 0; 2177 try { 2178 bandNum = Integer.parseInt(value); 2179 } catch (NumberFormatException nfe) { 2180 } 2181 int index = BandInfo.findIndexByNumber(bandNum, bandList); 2182 if (index != -1) { 2183 bandComboBox.setSelectedIndex(index); 2184 } 2185 } 2186 } else if (prop.equals(PROP_PLACE)) { 2187 changePlace(value); 2188 } else if (prop.equals(PROP_MAG)) { 2189 String[] pair = getPair(value); 2190 if (pair != null) { 2191 setMagSliders(new Integer(pair[0]).intValue(), new Integer( 2192 pair[1]).intValue()); 2193 } else { 2194 setMagSliders(DEFAULT_MAG, DEFAULT_MAG); 2195 } 2196 } else if (prop.equals(PROP_NAV)) { 2197 if (navComboBox != null) { 2198 navComboBox.setSelectedIndex((value 2199 .equalsIgnoreCase("LALO") ? 1 : 0)); 2200 } 2201 checkSetNav(); 2202 } 2203 } 2204 amSettingProperties = false; 2205 2206 } 2207 2208 /** 2209 * Set the mag slider values 2210 * 2211 * @param lineValue 2212 * the line value 2213 * @param elementValue 2214 * the element value 2215 */ 2216 protected void setMagSliders(int lineValue, int elementValue) { 2217 if (lineMagSlider != null) { 2218 if (lineValue > 0) { 2219 lineValue--; 2220 } else if (lineValue < 0) { 2221 lineValue++; 2222 } 2223 if (elementValue > 0) { 2224 elementValue--; 2225 } else if (elementValue < 0) { 2226 elementValue++; 2227 } 2228 2229 lineMagSlider.setValue(lineValue); 2230 elementMagSlider.setValue(elementValue); 2231 lineMagLbl.setText(StringUtil.padLeft("" + getLineMagValue(), 4)); 2232 elementMagLbl.setText(StringUtil.padLeft("" + getElementMagValue(), 2233 4)); 2234 linesToElements = Math.abs(lineValue / (double) elementValue); 2235 if (Double.isNaN(linesToElements)) { 2236 linesToElements = 1.0; 2237 } 2238 } 2239 } 2240 2241 /** 2242 * Get the value of the given magnification slider. 2243 * 2244 * @param slider 2245 * The slider to get the value from 2246 * @return The magnification value 2247 */ 2248 protected int getMagValue(JSlider slider) { 2249 // Value is [-SLIDER_MAX,SLIDER_MAX]. We change 0 and -1 to 1 2250 int value = slider.getValue(); 2251 if (value >= 0) { 2252 return value + 1; 2253 } 2254 return value - 1; 2255 } 2256 2257 /** 2258 * Get a pair of properties 2259 * 2260 * @param v 2261 * a space separated string 2262 * 2263 * @return an array of the two strings 2264 */ 2265 protected String[] getPair(String v) { 2266 if (v == null) { 2267 return null; 2268 } 2269 v = v.trim(); 2270 List toks = StringUtil.split(v, " ", true, true); 2271 if ((toks == null) || (toks.size() == 0)) { 2272 return null; 2273 } 2274 String tok1 = toks.get(0).toString(); 2275 return new String[] { tok1, 2276 ((toks.size() > 1) ? toks.get(1).toString() : tok1) }; 2277 2278 } 2279 2280 /** 2281 * Get the selected band from the advanced chooser 2282 * 2283 * @return selected band number 2284 */ 2285 protected int getSelectedBand() { 2286 2287 Object bi = (bandComboBox == null) ? null : bandComboBox 2288 .getSelectedItem(); 2289 if ((bi == null) || bi.equals(ALLBANDS)) { 2290 return 0; 2291 } 2292 return ((BandInfo) bi).getBandNumber(); 2293 } 2294 2295 /** 2296 * Translate a place name into a human readable form 2297 * 2298 * @param place 2299 * raw name 2300 * 2301 * @return human readable name 2302 */ 2303 protected String translatePlace(String place) { 2304 place = place.toUpperCase(); 2305 if (place.equals(PLACE_ULEFT)) { 2306 return "Upper left"; 2307 } 2308 if (place.equals(PLACE_LLEFT)) { 2309 return "Lower left"; 2310 } 2311 if (place.equals(PLACE_URIGHT)) { 2312 return "Upper right"; 2313 } 2314 if (place.equals(PLACE_LRIGHT)) { 2315 return "Lower right"; 2316 } 2317 if (place.equals(PLACE_CENTER)) { 2318 return "Center"; 2319 } 2320 return place; 2321 } 2322 2323 /** 2324 * Get the band name for a particular area 2325 * 2326 * @param ad 2327 * AreaDirectory 2328 * @param band 2329 * band number 2330 * 2331 * @return name of the band 2332 */ 2333 protected String getBandName(AreaDirectory ad, int band) { 2334 // if (band== 0) return ALLBANDS.toString(); 2335 2336 if (useSatBandInfo) { 2337 if (satBandInfo == null) { 2338 return "Band: " + band; 2339 } 2340 String[] descrs = satBandInfo.getBandDescr(ad.getSensorID(), ad 2341 .getSourceType()); 2342 if (descrs != null) { 2343 if ((band >= 0) && (band < descrs.length)) { 2344 return descrs[band]; 2345 } 2346 } 2347 return "Band: " + band; 2348 } 2349 2350 if (sensorToBandToName == null) { 2351 return "Band: " + band; 2352 } 2353 Hashtable bandToName = (Hashtable) sensorToBandToName.get(new Integer( 2354 ad.getSensorID())); 2355 String name = null; 2356 Integer bandInteger = new Integer(band); 2357 2358 if (bandToName != null) { 2359 name = (String) bandToName.get(bandInteger); 2360 } 2361 if (name == null) { 2362 name = "Band: " + band; 2363 } 2364 /* 2365 * else { name = band + " - " + name.trim(); } 2366 */ 2367 return name; 2368 } 2369 2370 /** 2371 * Set the available units in the unit selector 2372 * 2373 * @param ad 2374 * AreaDirectory for the image 2375 * @param band 2376 * band to use for units 2377 */ 2378 protected void setAvailableUnits(AreaDirectory ad, int band) { 2379 List l = getAvailableUnits(ad, band); 2380 l.add(ALLUNITS); 2381 GuiUtils.setListData(unitComboBox, l); 2382 TwoFacedObject tfo = null; 2383 if ((bandComboBox != null) && (getSelectedBand() == 0)) { 2384 tfo = ALLUNITS; 2385 } else { 2386 String preferredUnit = getDefault(PROP_UNIT, "BRIT"); 2387 tfo = TwoFacedObject.findId(preferredUnit, l); 2388 } 2389 if (tfo != null) { 2390 unitComboBox.setSelectedItem(tfo); 2391 } 2392 } 2393 2394 /** 2395 * Set the available units in the unit selector 2396 * 2397 * @param ad 2398 * AreaDirectory for the image 2399 * @param band 2400 * band to use for units 2401 * 2402 * @return List of available units 2403 */ 2404 protected List<TwoFacedObject> getAvailableUnits(AreaDirectory ad, int band) { 2405 // get Vector array of Calibration types. Layout is 2406 // v[i] = band[i] and for each band, it is a vector of 2407 // strings of calibration names and descriptions 2408 // n = name, n+1 = desc. 2409 // for radar, we only have one band 2410 if (ad == null) { 2411 return new ArrayList<>(); 2412 } 2413 int[] bands = (int[]) bandTable.get(ad); 2414 int index = (bands == null) ? 0 : Arrays.binarySearch(bands, band); 2415 if (index < 0) index = 0; 2416 Vector<TwoFacedObject> l = new Vector<>(); 2417 Vector v = ad.getCalInfo()[index]; 2418 TwoFacedObject tfo = null; 2419 int preferredUnitIndex = 0; 2420 String preferredUnit = getDefault(PROP_UNIT, "BRIT"); 2421 if ((v != null) && (v.size() / 2 > 0)) { 2422 for (int i = 0; i < v.size() / 2; i++) { 2423 String name = (String) v.get(2 * i); 2424 String desc = (String) v.get(2 * i + 1); 2425 desc = StringUtil.camelCase(desc); 2426 tfo = new TwoFacedObject(desc, name); 2427 l.add(tfo); 2428 if (name.equalsIgnoreCase(preferredUnit)) { 2429 preferredUnitIndex = i; 2430 } 2431 } 2432 } else { 2433 l.add(new TwoFacedObject("Raw Value", "RAW")); 2434 } 2435 return l; 2436 } 2437 2438 /** 2439 * Get the band name information from the server 2440 */ 2441 protected void readSatBands() { 2442 satBandInfo = null; 2443 sensorToBandToName = null; 2444 List lines = null; 2445 try { 2446 StringBuffer buff = getUrl(REQ_TEXT); 2447 appendKeyValue(buff, PROP_FILE, FILE_SATBAND); 2448 lines = readTextLines(buff.toString()); 2449 if (lines == null) { 2450 return; 2451 } 2452 if (useSatBandInfo) { 2453 satBandInfo = new AddeSatBands(StringUtil.listToStringArray(lines)); 2454 return; 2455 } 2456 } catch (Exception e) { 2457 return; 2458 } 2459 2460 sensorToBandToName = new Hashtable(); 2461 2462 for (int i = 0; i < lines.size(); i++) { 2463 if (!lines.get(i).toString().startsWith("Sat")) { 2464 continue; 2465 } 2466 List satIds = StringUtil.split(lines.get(i).toString(), " ", true, 2467 true); 2468 satIds.remove(0); 2469 Hashtable bandToName = new Hashtable(); 2470 for (int j = i + 1; j < lines.size(); j++, i++) { 2471 String line = lines.get(i).toString(); 2472 line = line.trim(); 2473 if (line.startsWith("EndSat")) { 2474 break; 2475 } 2476 2477 int idx = line.indexOf(" "); 2478 if (idx < 0) { 2479 continue; 2480 } 2481 String bandTok = line.substring(0, idx); 2482 try { 2483 bandToName.put(Integer.decode(bandTok.trim()), line 2484 .substring(idx).trim()); 2485 } catch (NumberFormatException nfe) { 2486 } 2487 } 2488 for (int j = 0; j < satIds.size(); j++) { 2489 Integer sensorId = new Integer(satIds.get(j).toString()); 2490 sensorToBandToName.put(sensorId, bandToName); 2491 } 2492 } 2493 } 2494 2495 /** 2496 * Make an AddeImageInfo from a URL and an AreaDirectory 2497 * 2498 * @param dir 2499 * AreaDirectory 2500 * @param isRelative 2501 * true if is relative 2502 * @param num 2503 * number (for relative images) 2504 * 2505 * @return corresponding AddeImageInfo 2506 */ 2507 protected AddeImageInfo makeImageInfo(AreaDirectory dir, 2508 boolean isRelative, int num) { 2509 AddeImageInfo info = new AddeImageInfo(getAddeServer().getName(), 2510 AddeImageInfo.REQ_IMAGEDATA, getGroup(), getDescriptor()); 2511 if (isRelative) { 2512 info.setDatasetPosition((num == 0) ? 0 : -num); 2513 } else { 2514 info.setStartDate(dir.getNominalTime()); 2515 } 2516 setImageInfoProps(info, getMiscKeyProps(), dir); 2517 setImageInfoProps(info, getBaseUrlProps(), dir); 2518 2519 String locKey = getDefault(PROP_KEY, PROP_LINELE); 2520 String locValue = null; 2521 if (usePropFromUser(PROP_LOC)) { 2522 if (useLatLon()) { 2523 locKey = PROP_LATLON; 2524 locValue = getUserPropValue(PROP_LATLON, dir); 2525 } else { 2526 locKey = PROP_LINELE; 2527 locValue = getUserPropValue(PROP_LINELE, dir); 2528 } 2529 } else { 2530 locValue = getPropValue(PROP_LOC, dir); 2531 } 2532 info.setLocateKey(locKey); 2533 info.setLocateValue(locValue); 2534 2535 String placeKey = getPropValue(PROP_PLACE, dir); 2536 info.setPlaceValue(placeKey); 2537 2538 String magKey = getPropValue(PROP_MAG, dir); 2539 int lmag = 1; 2540 int emag = 1; 2541 StringTokenizer tok = new StringTokenizer(magKey); 2542 lmag = (int) Misc.parseNumber((String) tok.nextElement()); 2543 if (tok.hasMoreTokens()) { 2544 emag = (int) Misc.parseNumber((String) tok.nextElement()); 2545 } else { 2546 emag = lmag; 2547 } 2548 info.setLineMag(lmag); 2549 info.setElementMag(emag); 2550 2551 int lines = dir.getLines(); 2552 int elems = dir.getElements(); 2553 String sizeKey = getPropValue(PROP_SIZE, dir); 2554 tok = new StringTokenizer(sizeKey); 2555 String size = (String) tok.nextElement(); 2556 if (!size.equalsIgnoreCase("all")) { 2557 lines = (int) Misc.parseNumber(size); 2558 if (tok.hasMoreTokens()) { 2559 elems = (int) Misc.parseNumber((String) tok.nextElement()); 2560 } else { 2561 elems = lines; 2562 } 2563 } 2564 info.setLines(lines); 2565 info.setElements(elems); 2566 /* 2567 * System.out.println("url = " + info.getURLString().toLowerCase() + 2568 * "\n"); 2569 */ 2570 return info; 2571 } 2572 2573 /** 2574 * Check to see if the two Area directories are equal 2575 * 2576 * @param ad1 2577 * first AD (may be null) 2578 * @param ad2 2579 * second AD (may be null) 2580 * 2581 * @return true if they are equal 2582 */ 2583 protected boolean checkPropertiesEqual(AreaDirectory ad1, AreaDirectory ad2) { 2584 if (ad1 == null) { 2585 return false; 2586 } 2587 if (ad2 == null) { 2588 return false; 2589 } 2590 return Misc.equals(ad1, ad2) 2591 || ((ad1.getLines() == ad2.getLines()) 2592 && (ad1.getElements() == ad2.getElements()) && Arrays 2593 .equals(ad1.getBands(), ad2.getBands())); 2594 } 2595 2596 /** 2597 * Get a description of the properties 2598 * 2599 * @return a description 2600 */ 2601 protected String getPropertiesDescription() { 2602 StringBuffer buf = new StringBuffer(); 2603 String[] propArray = getAdvancedProps(); 2604 List list = Misc.toList(propArray); 2605 if (list.contains(PROP_BAND)) { 2606 buf.append(getSelectedBandName()); 2607 buf.append(", "); 2608 } 2609 if (list.contains(PROP_SIZE)) { 2610 buf.append("Size: "); 2611 String sizeKey = getUserPropValue(PROP_SIZE, propertiesAD); 2612 StringTokenizer tok = new StringTokenizer(sizeKey); 2613 if (tok.hasMoreTokens()) { 2614 String size = ((String) tok.nextElement()).trim(); 2615 buf.append(size); 2616 buf.append("x"); 2617 if (!size.equalsIgnoreCase("all")) { 2618 if (tok.hasMoreTokens()) { 2619 buf.append(((String) tok.nextElement()).trim()); 2620 } else { 2621 buf.append(size); 2622 } 2623 } 2624 } 2625 } 2626 return buf.toString(); 2627 } 2628 2629 /** 2630 * Show the given error to the user. If it was an ADDE exception that was 2631 * a bad server error then print out a nice message. 2632 * 2633 * <p>Overridden in McIDAS-V to work with ADDE {@literal "archive"} 2634 * servers (servers that require a {@literal "DAY="} parameter).</p> 2635 * 2636 * @param e Exception to be handled. Cannot be {@code null}. 2637 */ 2638 @Override protected void handleConnectionError(Exception e) { 2639 handleConnectionError("", e); 2640 } 2641 2642 /** 2643 * Show the given error to the user. If it was an ADDE exception that was 2644 * a bad server error then print out a nice message. 2645 * 2646 * <p>Overridden in McIDAS-V to work with ADDE {@literal "archive"} 2647 * servers (servers that require a {@literal "DAY="} parameter).</p> 2648 * 2649 * @param details Details about the context of {@code e}. {@code null} 2650 * will be treated as an empty {@code String}. 2651 * @param e Exception to be handled. Cannot be {@code null}. 2652 */ 2653 @Override protected void handleConnectionError(String details, Exception e) { 2654 if ((e != null) && (e.getMessage() != null)) { 2655 Throwable cause = e.getCause(); 2656 if (cause.getMessage() != null) { 2657 String msg = cause.getMessage().toLowerCase(); 2658 if ((cause instanceof AddeURLException) && msg.contains("must be used with archived datasets")) { 2659 getArchiveDay(); 2660 return; 2661 } 2662 } 2663 } 2664 super.handleConnectionError(details, e); 2665 } 2666 2667 /** 2668 * Get the list of bands for the images 2669 * 2670 * @param ad 2671 * AreaDirectory 2672 * @param bands 2673 * list of bands 2674 * @return list of BandInfos for the selected images 2675 */ 2676 protected List<BandInfo> makeBandInfos(AreaDirectory ad, int[] bands) { 2677 // readSatBands(); 2678 List<BandInfo> l = new ArrayList<>(); 2679 if (ad != null) { 2680 if (bands != null) { 2681 for (int i = 0; i < bands.length; i++) { 2682 int band = bands[i]; 2683 if (band > 0) { 2684 BandInfo bi = new BandInfo(ad.getSensorID(), band); 2685 bi.setBandDescription(getBandName(ad, band)); 2686 bi.setCalibrationUnits(getAvailableUnits(ad, band)); 2687 bi.setPreferredUnit(getDefault(PROP_UNIT, "BRIT")); 2688 l.add(bi); 2689 } 2690 } 2691 } 2692 } 2693 return l; 2694 } 2695 2696 /** 2697 * Get the pregenerated bandInfos 2698 */ 2699 protected List<BandInfo> getBandInfos() { 2700 return bandInfos; 2701 } 2702 2703 /** 2704 * Get the list of BandInfos for the current selected images 2705 * 2706 * @return list of BandInfos 2707 */ 2708 public List<BandInfo> getSelectedBandInfos() { 2709 // update the BandInfo list based on what has been chosen 2710 List selectedBandInfos = new ArrayList<>(); 2711 List selectedUnits = null; 2712 if (unitComboBox != null) { 2713 TwoFacedObject tfo = (TwoFacedObject) unitComboBox.getSelectedItem(); 2714 if (!(tfo.equals(ALLUNITS))) { // specific unit requested 2715 selectedUnits = new ArrayList<>(); 2716 selectedUnits.add(tfo); 2717 } 2718 } 2719 if (getSelectedBand() == 0) { // All bands selected 2720 if (selectedUnits != null) { 2721 for (Iterator iter = bandInfos.iterator(); iter.hasNext();) { 2722 BandInfo newBI = new BandInfo((BandInfo) iter.next()); 2723 newBI.setCalibrationUnits(selectedUnits); 2724 newBI.setPreferredUnit((String) ((TwoFacedObject) selectedUnits.get(0)).getId()); 2725 selectedBandInfos.add(newBI); 2726 } 2727 } else { // else All Bands, AllUnits 2728 selectedBandInfos = bandInfos; 2729 } 2730 } else { // not All selected; 2731 int index = BandInfo.findIndexByNumber(getSelectedBand(), bandInfos); 2732 BandInfo selectedBandInfo = null; 2733 if (index != -1) { 2734 selectedBandInfo = bandInfos.get(index); 2735 } 2736 if (selectedBandInfo != null) { 2737 if (selectedUnits != null) { 2738 BandInfo newBI = new BandInfo(selectedBandInfo); 2739 newBI.setCalibrationUnits(selectedUnits); 2740 newBI.setPreferredUnit((String) ((TwoFacedObject) selectedUnits.get(0)).getId()); 2741 selectedBandInfos.add(newBI); 2742 } else { 2743 selectedBandInfos.add(selectedBandInfo); 2744 } 2745 } 2746 } 2747 return selectedBandInfos; 2748 } 2749 2750 /** 2751 * Get the id for the default display type 2752 * 2753 * @return the display id 2754 */ 2755 @Override protected String getDefaultDisplayType() { 2756 return "imagedisplay"; 2757 } 2758 2759 /** 2760 * User said go, we go. Simply get the list of images from the imageChooser 2761 * and create the ADDE.IMAGE DataSource 2762 * 2763 */ 2764 @Override public void doLoadInThread() { 2765 if (!checkForValidValues()) { 2766 return; 2767 } 2768 if (!getGoodToGo()) { 2769 updateStatus(); 2770 return; 2771 } 2772 2773 List imageList = getImageList(); 2774 if ((imageList == null) || (imageList.isEmpty())) { 2775 return; 2776 } 2777 2778 // Check for size threshold 2779 final int[] dim = { 0, 0 }; 2780 AddeImageDescriptor aid = (AddeImageDescriptor) imageList.get(0); 2781 dim[0] = aid.getImageInfo().getElements(); 2782 dim[1] = aid.getImageInfo().getLines(); 2783 // System.err.println("dim:" + dim[0] + " x " + dim[1] + " # images:" 2784 // + imageList.size()); 2785 int numPixels = dim[0] * dim[1] * imageList.size(); 2786 double megs = (4 * numPixels) / (double) 1000000; 2787 2788 //DAVEP: take this out--it should be warning in the data source, not the chooser 2789 boolean doSizeCheck = false; 2790 if (megs > SIZE_THRESHOLD && doSizeCheck) { 2791 final JCheckBox maintainSize = new JCheckBox( 2792 "Maintain spatial extent", false); 2793 final JLabel sizeLbl = new JLabel(StringUtil.padRight(" " 2794 + ((double) ((int) megs * 100)) / 100.0 + " MB", 14)); 2795 GuiUtils.setFixedWidthFont(sizeLbl); 2796 final List[] listHolder = { imageList }; 2797 final JSlider slider = new JSlider(2, (int) megs, (int) megs); 2798 slider.setMajorTickSpacing((int) (megs - 2) / 10); 2799 slider.setMinorTickSpacing((int) (megs - 2) / 10); 2800 // slider.setPaintTicks(true); 2801 slider.setSnapToTicks(true); 2802 final long timeNow = System.currentTimeMillis(); 2803 ChangeListener sizeListener = new javax.swing.event.ChangeListener() { 2804 public void stateChanged(ChangeEvent evt) { 2805 // A hack so we don't respond to the first event that we get 2806 // from the slider when 2807 // the dialog is first shown 2808 if (System.currentTimeMillis() - timeNow < 500) 2809 return; 2810 JSlider slider = (JSlider) evt.getSource(); 2811 int pixelsPerImage = 1000000 * slider.getValue() 2812 / listHolder[0].size() / 4; 2813 double aspect = dim[1] / (double) dim[0]; 2814 int nx = (int) Math.sqrt(pixelsPerImage / aspect); 2815 int ny = (int) (aspect * nx); 2816 if (maintainSize.isSelected()) { 2817 // doesn't work 2818 lineMagSlider.setValue(getLineMagValue() - 1); 2819 lineMagSliderChanged(true); 2820 } else { 2821 numElementsFld.setText("" + nx); 2822 numLinesFld.setText("" + ny); 2823 } 2824 listHolder[0] = getImageList(); 2825 AddeImageDescriptor aid = (AddeImageDescriptor) listHolder[0] 2826 .get(0); 2827 dim[0] = aid.getImageInfo().getElements(); 2828 dim[1] = aid.getImageInfo().getLines(); 2829 int numPixels = dim[0] * dim[1] * listHolder[0].size(); 2830 double nmegs = (4 * numPixels) / (double) 1000000; 2831 sizeLbl.setText(StringUtil.padRight(" " 2832 + ((double) ((int) nmegs * 100)) / 100.0 + " MB", 2833 14)); 2834 } 2835 }; 2836 slider.addChangeListener(sizeListener); 2837 2838 JComponent msgContents = GuiUtils 2839 .vbox( 2840 new JLabel( 2841 "<html>You are about to load " 2842 + megs 2843 + " MB of imagery.<br>Are you sure you want to do this?<p><hr><p></html>"), 2844 GuiUtils.inset(GuiUtils.leftCenterRight(new JLabel( 2845 "Change Size: "), 2846 GuiUtils.inset(slider, 5), sizeLbl), 5)); 2847 2848 if (!GuiUtils.askOkCancel("Image Size", msgContents)) { 2849 return; 2850 } 2851 imageList = listHolder[0]; 2852 } 2853 2854 ImageDataset ids = new ImageDataset(getDatasetName(), imageList); 2855 // make properties Hashtable to hand the station name 2856 // to the AddeImageDataSource 2857 Hashtable ht = new Hashtable(); 2858 ht.put(DataSelection.PROP_CHOOSERTIMEMATCHING, getDoTimeDrivers()); 2859 getDataSourceProperties(ht); 2860 Object bandName = getSelectedBandName(); 2861 if (bandName != null && !(bandName.equals(ALLBANDS.toString()))) { 2862 ht.put(DATA_NAME_KEY, bandName); 2863 } 2864 ht.put("allBands", bandDirs); 2865 makeDataSource(ids, getDataSourceId(), ht); 2866 saveServerState(); 2867 // uncheck the check box every time click the add source button 2868 drivercbx.setSelected(false); 2869 enableTimeWidgets(); 2870 setDoTimeDrivers(false); 2871 } 2872 2873 /** 2874 * Return the data source ID. Used by extending classes. 2875 */ 2876 @Override protected String getDataSourceId() { 2877 return "ADDE.IMAGE"; 2878 } 2879 2880 /** 2881 * Get the DataSource properties 2882 * 2883 * @param ht 2884 * Hashtable of properties 2885 */ 2886 @Override protected void getDataSourceProperties(Hashtable ht) { 2887 super.getDataSourceProperties(ht); 2888 ht.put(DATASET_NAME_KEY, getDatasetName()); 2889 ht.put(ImageDataSource.PROP_BANDINFO, getSelectedBandInfos()); 2890 } 2891 2892 /** 2893 * _more_ 2894 * 2895 * @return _more_ 2896 */ 2897 protected List processPropertyComponents() { 2898 List bottomComps = new ArrayList(); 2899 getBottomComponents(bottomComps); 2900 for (int i = 0; i < bottomComps.size(); i++) { 2901 addDescComp((JComponent) bottomComps.get(i)); 2902 } 2903 return bottomComps; 2904 } 2905 2906 /** 2907 * Make the UI for this selector. 2908 * 2909 * @return The gui 2910 */ 2911 @Override public JComponent doMakeContents() { 2912 JPanel myPanel = new JPanel(); 2913 2914 JLabel timesLabel = McVGuiUtils.makeLabelRight("Times:"); 2915 addDescComp(timesLabel); 2916 2917 JPanel timesPanel = makeTimesPanel(); 2918 timesPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); 2919 addDescComp(timesPanel); 2920 2921 JLabel imageLabel = McVGuiUtils.makeLabelRight("Other:"); 2922 addDescComp(imageLabel); 2923 2924 List comps = new ArrayList(); 2925 comps.addAll(processPropertyComponents()); 2926 GuiUtils.tmpInsets = GRID_INSETS; 2927 JPanel imagePanel = GuiUtils.doLayout(comps, 2, GuiUtils.WT_NY, GuiUtils.WT_N); 2928 imagePanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); 2929 2930 GroupLayout layout = new GroupLayout(myPanel); 2931 myPanel.setLayout(layout); 2932 layout.setHorizontalGroup(layout.createParallelGroup(LEADING) 2933 .addGroup(layout.createSequentialGroup() 2934 .addGroup(layout.createParallelGroup(LEADING) 2935 .addGroup(layout.createSequentialGroup() 2936 .addComponent(descriptorLabel) 2937 .addGap(GAP_RELATED) 2938 .addComponent(descriptorComboBox)) 2939 .addGroup(layout.createSequentialGroup() 2940 .addComponent(timesLabel) 2941 .addGap(GAP_RELATED) 2942 .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 2943 .addGroup(layout.createSequentialGroup() 2944 .addComponent(imageLabel) 2945 .addGap(GAP_RELATED) 2946 .addComponent(imagePanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))))); 2947 2948 layout.setVerticalGroup(layout.createParallelGroup(LEADING) 2949 .addGroup(layout.createSequentialGroup() 2950 .addGroup(layout.createParallelGroup(BASELINE) 2951 .addComponent(descriptorLabel) 2952 .addComponent(descriptorComboBox)) 2953 .addPreferredGap(RELATED) 2954 .addGroup(layout.createParallelGroup(LEADING) 2955 .addComponent(timesLabel) 2956 .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)) 2957 .addPreferredGap(RELATED) 2958 .addGroup(layout.createParallelGroup(LEADING) 2959 .addComponent(imageLabel) 2960 .addComponent(imagePanel)))); 2961 2962 setInnerPanel(myPanel); 2963 return super.doMakeContents(); 2964 } 2965 2966 public JComponent doMakeContents(boolean doesOverride) { 2967 return doesOverride ? super.doMakeContents() : doMakeContents(); 2968 } 2969 2970}