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