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