001 /*
002 * $Id: ImagePlanViewControl.java,v 1.23 2012/02/19 17:35:38 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2012
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 *
012 * All Rights Reserved
013 *
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.
016 *
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 *
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025 * GNU Lesser Public License for more details.
026 *
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program. If not, see http://www.gnu.org/licenses.
029 */
030
031 package edu.wisc.ssec.mcidasv.control;
032
033 import java.awt.BorderLayout;
034 import java.awt.Color;
035 import java.awt.Component;
036 import java.awt.Container;
037 import java.awt.Dimension;
038 import java.awt.event.ActionEvent;
039 import java.awt.event.ActionListener;
040 import java.awt.event.MouseEvent;
041 import java.rmi.RemoteException;
042 import java.util.ArrayList;
043 import java.util.Hashtable;
044 import java.util.List;
045
046 import javax.swing.JButton;
047 import javax.swing.JComponent;
048 import javax.swing.JFrame;
049 import javax.swing.JLabel;
050 import javax.swing.JMenu;
051 import javax.swing.JMenuItem;
052 import javax.swing.JPanel;
053 import javax.swing.JPopupMenu;
054 import javax.swing.JTabbedPane;
055 import javax.swing.JTextField;
056 import javax.swing.event.ChangeEvent;
057 import javax.swing.event.ChangeListener;
058
059 import org.slf4j.Logger;
060 import org.slf4j.LoggerFactory;
061 import org.w3c.dom.Document;
062 import org.w3c.dom.Element;
063 import org.w3c.dom.Node;
064
065 import visad.Data;
066 import visad.DateTime;
067 import visad.FieldImpl;
068 import visad.FlatField;
069 import visad.VisADException;
070 import visad.meteorology.ImageSequenceImpl;
071
072 import ucar.unidata.data.DataChoice;
073 import ucar.unidata.data.DataSelection;
074 import ucar.unidata.data.DataSourceImpl;
075 import ucar.unidata.data.imagery.AddeImageDescriptor;
076 import ucar.unidata.data.imagery.BandInfo;
077 import ucar.unidata.idv.ControlContext;
078 import ucar.unidata.idv.IdvResourceManager;
079 import ucar.unidata.idv.control.ColorTableWidget;
080 import ucar.unidata.idv.control.DisplayControlImpl;
081 import ucar.unidata.ui.XmlTree;
082 import ucar.unidata.util.ColorTable;
083 import ucar.unidata.util.GuiUtils;
084 import ucar.unidata.util.Range;
085 import ucar.unidata.xml.XmlResourceCollection;
086 import ucar.unidata.xml.XmlUtil;
087
088 import edu.wisc.ssec.mcidasv.PersistenceManager;
089 import edu.wisc.ssec.mcidasv.chooser.ImageParameters;
090 import edu.wisc.ssec.mcidasv.data.ComboDataChoice;
091 import edu.wisc.ssec.mcidasv.data.adde.AddeImageParameterDataSource;
092
093 /**
094 * {@link ucar.unidata.idv.control.ImagePlanViewControl} with some McIDAS-V
095 * specific extensions. Namely parameter sets and support for inverted
096 * parameter defaults.
097 */
098 public class ImagePlanViewControl extends ucar.unidata.idv.control.ImagePlanViewControl {
099
100 private static final Logger logger = LoggerFactory.getLogger(ImagePlanViewControl.class);
101
102 private static final String TAG_FOLDER = "folder";
103 private static final String TAG_DEFAULT = "default";
104 private static final String ATTR_NAME = "name";
105 private static final String ATTR_SERVER = "server";
106 private static final String ATTR_POS = "POS";
107 private static final String ATTR_DAY = "DAY";
108 private static final String ATTR_TIME = "TIME";
109 private static final String ATTR_UNIT = "UNIT";
110
111 /** Command for connecting */
112 protected static final String CMD_NEWFOLDER = "cmd.newfolder";
113 protected static final String CMD_NEWPARASET = "cmd.newparaset";
114
115 /** save parameter set */
116 private JFrame saveWindow;
117
118 private static String newFolder;
119
120 private XmlTree xmlTree;
121
122 /** Install new folder fld */
123 private JTextField folderFld;
124
125 /** Holds the current save set tree */
126 private JPanel treePanel;
127
128 /** The user imagedefaults xml root */
129 private static Element imageDefaultsRoot;
130
131 /** The user imagedefaults xml document */
132 private static Document imageDefaultsDocument;
133
134 /** Holds the ADDE servers and groups*/
135 private static XmlResourceCollection imageDefaults;
136
137 private Node lastCat;
138
139 private static Element lastClicked;
140
141 private JButton newFolderBtn;
142
143 private JButton newSetBtn;
144
145 private String newCompName = "";
146
147 /** Shows the status */
148 private JLabel statusLabel;
149
150 /** Status bar component */
151 private JComponent statusComp;
152
153 private JPanel contents;
154
155 private DataSourceImpl dataSource;
156
157 private FlatField image;
158
159 private McIDASVHistogramWrapper histoWrapper;
160
161 public ImagePlanViewControl() {
162 super();
163 logger.trace("created new imageplanviewcontrol={}", Integer.toHexString(hashCode()));
164 this.imageDefaults = getImageDefaults();
165 }
166
167 @Override public boolean init(DataChoice dataChoice)
168 throws VisADException, RemoteException
169 {
170 // this.dataChoice = (DataChoice)this.getDataChoices().get(0);
171 boolean result = super.init((DataChoice)this.getDataChoices().get(0));
172 return result;
173 }
174
175 /**
176 * Get the xml resource collection that defines the image default xml
177 *
178 * @return Image defaults resources
179 */
180 protected XmlResourceCollection getImageDefaults() {
181 XmlResourceCollection ret = null;
182 try {
183 ControlContext controlContext = getControlContext();
184 if (controlContext != null) {
185 IdvResourceManager irm = controlContext.getResourceManager();
186 ret=irm.getXmlResources( IdvResourceManager.RSC_IMAGEDEFAULTS);
187 if (ret.hasWritableResource()) {
188 imageDefaultsDocument =
189 ret.getWritableDocument("<imagedefaults></imagedefaults>");
190 imageDefaultsRoot =
191 ret.getWritableRoot("<imagedefaults></imagedefaults>");
192 }
193 }
194 } catch (Exception e) {
195 System.out.println("e=" + e);
196 }
197 return ret;
198 }
199
200
201 /**
202 * Called by doMakeWindow in DisplayControlImpl, which then calls its
203 * doMakeMainButtonPanel(), which makes more buttons.
204 *
205 * @return container of contents
206 */
207 public Container doMakeContents() {
208 try {
209 JTabbedPane tab = new MyTabbedPane();
210 tab.add("Settings",
211 GuiUtils.inset(GuiUtils.top(doMakeWidgetComponent()), 5));
212 tab.add("Histogram", GuiUtils.inset(getHistogramTabComponent(),5));
213 //Set this here so we don't get odd crud on the screen
214 //When the MyTabbedPane goes to paint itself the first time it
215 //will set the tab back to 0
216 tab.setSelectedIndex(1);
217 GuiUtils.handleHeavyWeightComponentsInTabs(tab);
218 // ColorTableWidget ctw = getColorTableWidget(getRange());
219 Range range = getRange();
220 // int lo = (int)range.getMin();
221 // int hi = (int)range.getMax();
222 double lo = range.getMin();
223 double hi = range.getMax();
224 boolean flag = histoWrapper.modifyRange(lo, hi);
225 ((MyTabbedPane)tab).setPopupFlag(!flag);
226 histoWrapper.setHigh(hi);
227 histoWrapper.setLow(lo);
228 return tab;
229 } catch (Exception exc) {
230 logException("doMakeContents", exc);
231 }
232 return null;
233 }
234
235 protected JComponent getHistogramTabComponent() {
236 List choices = new ArrayList();
237 if (datachoice == null) {
238 datachoice = getDataChoice();
239 }
240 choices.add(datachoice);
241 histoWrapper = new McIDASVHistogramWrapper("histo", choices, (DisplayControlImpl)this);
242 dataSource = getDataSource();
243
244 if (dataSource == null) {
245 try {
246 image = (FlatField)((ComboDataChoice)datachoice).getData();
247 histoWrapper.loadData(image);
248 } catch (Exception e) {
249
250 }
251 } else {
252 Hashtable props = dataSource.getProperties();
253 try {
254 // this.dataSelection = dataChoice.getDataSelection();
255 DataSelection testSelection = datachoice.getDataSelection();
256 DataSelection realSelection = getDataSelection();
257 if (testSelection == null) {
258 datachoice.setDataSelection(realSelection);
259 }
260 ImageSequenceImpl seq = null;
261 if (dataSelection == null)
262 dataSelection = dataSource.getDataSelection();
263 if (dataSelection == null) {
264 image = (FlatField)dataSource.getData(datachoice, null, props);
265 if (image == null) {
266 image = (FlatField)datachoice.getData(null);
267 }
268 } else {
269 // if (dataChoice.getDataSelection() == null) {
270 // dataChoice.setDataSelection(dataSelection)
271 // }
272 Data data = dataSource.getData(datachoice, null, dataSelection, props);
273 if (data instanceof ImageSequenceImpl) {
274 seq = (ImageSequenceImpl) data;
275 } else if (data instanceof FlatField) {
276 image = (FlatField) data;
277 } else if (data instanceof FieldImpl) {
278 image = (FlatField) ((FieldImpl)data).getSample(0, false);
279 }
280 else {
281 throw new Exception("Histogram must be made from a FlatField");
282 }
283 }
284 if (seq != null) {
285 if (seq.getImageCount() > 0)
286 image = (FlatField)seq.getImage(0);
287 }
288 histoWrapper.loadData(image);
289 /*
290 double lo = histoWrapper.getLow();
291 double hi = histoWrapper.getHigh();
292 contrastStretch(lo, hi);
293 */
294 } catch (Exception e) {
295 //System.out.println("Histo e=" + e);
296 }
297 }
298
299 JComponent histoComp = histoWrapper.doMakeContents();
300 JButton resetButton = new JButton("Reset");
301 resetButton.addActionListener(new ActionListener() {
302 public void actionPerformed(ActionEvent ae) {
303 resetColorTable();
304 }
305 });
306 JPanel resetPanel =
307 GuiUtils.center(GuiUtils.inset(GuiUtils.wrap(resetButton), 4));
308 return GuiUtils.centerBottom(histoComp, resetPanel);
309 }
310
311 protected void contrastStretch(double low, double high) {
312 ColorTable ct = getColorTable();
313 if (ct != null) {
314 Range range = new Range(low, high);
315 try {
316 setRange(ct.getName(), range);
317 } catch (Exception e) {
318 System.out.println("contrast stretch e=" + e);
319 }
320 }
321 }
322
323 @Override public boolean setData(DataChoice dataChoice) throws VisADException, RemoteException {
324 boolean result = super.setData(dataChoice);
325 logger.trace("result: {}, dataChoice: {}", result, dataChoice);
326 return result;
327 }
328
329 @Override public void setRange(final Range newRange) throws RemoteException, VisADException {
330 logger.trace("newRange: {} [avoiding NPE!]", newRange);
331 super.setRange(newRange);
332 }
333
334 public void resetColorTable() {
335 try {
336 revertToDefaultColorTable();
337 revertToDefaultRange();
338 histoWrapper.resetPlot();
339 } catch (Exception e) {
340 System.out.println("resetColorTable e=" + e);
341 }
342 }
343
344 protected void getSaveMenuItems(List items, boolean forMenuBar) {
345 super.getSaveMenuItems(items, forMenuBar);
346
347 // DAVEP: Remove the parameter set save options for now...
348 // items.add(GuiUtils.makeMenuItem("Save Image Parameter Set (TEST)", this,
349 // "popupPersistImageParameters"));
350 //
351 // items.add(GuiUtils.makeMenuItem("Save Image Parameter Set", this,
352 // "popupSaveImageParameters"));
353
354 items.add(GuiUtils.makeMenuItem("Save As Local Data Source", this,
355 "saveDataToLocalDisk"));
356 }
357
358 public void popupPersistImageParameters() {
359 PersistenceManager pm = (PersistenceManager)getIdv().getPersistenceManager();
360 pm.saveParameterSet("addeimagery", makeParameterValues());
361 }
362
363 private Hashtable makeParameterValues() {
364 Hashtable parameterValues = new Hashtable();
365 // Document doc = XmlUtil.makeDocument();
366 // Element newChild = doc.createElement(TAG_DEFAULT);
367
368 if (datachoice == null) {
369 datachoice = getDataChoice();
370 }
371 dataSource = getDataSource();
372 if (!(dataSource.getClass().isInstance(new AddeImageParameterDataSource()))) {
373 System.err.println("dataSource not a AddeImageParameterDataSource");
374 return parameterValues;
375 }
376 AddeImageParameterDataSource testDataSource = (AddeImageParameterDataSource)dataSource;
377 List imageList = testDataSource.getDescriptors(datachoice, this.dataSelection);
378 int numImages = imageList.size();
379 List dateTimes = new ArrayList();
380 DateTime thisDT = null;
381 if (!(imageList == null)) {
382 AddeImageDescriptor aid = null;
383 for (int imageNo=0; imageNo<numImages; imageNo++) {
384 aid = (AddeImageDescriptor)(imageList.get(imageNo));
385 thisDT = aid.getImageTime();
386 if (!(dateTimes.contains(thisDT))) {
387 if (thisDT != null) {
388 dateTimes.add(thisDT);
389 }
390 }
391 }
392
393 // Set the date and time for later reference
394 String dateS = "";
395 String timeS = "";
396 if (!(dateTimes.isEmpty())) {
397 thisDT = (DateTime)dateTimes.get(0);
398 dateS = thisDT.dateString();
399 timeS = thisDT.timeString();
400 if (dateTimes.size() > 1) {
401 for (int img=1; img<dateTimes.size(); img++) {
402 thisDT = (DateTime)dateTimes.get(img);
403 String str = "," + thisDT.dateString();
404 String newString = new String(dateS + str);
405 dateS = newString;
406 str = "," + thisDT.timeString();
407 newString = new String(timeS + str);
408 timeS = newString;
409 }
410 }
411 }
412
413 // Set the unit for later reference
414 String unitS = "";
415 if (!(datachoice.getId() instanceof BandInfo)) {
416 System.err.println("dataChoice ID not a BandInfo");
417 return parameterValues;
418 }
419 BandInfo bi = (BandInfo)datachoice.getId();
420 unitS = bi.getPreferredUnit();
421
422 if (aid != null) {
423 String displayUrl = testDataSource.getDisplaySource();
424 ImageParameters ip = new ImageParameters(displayUrl);
425 List props = ip.getProperties();
426 List vals = ip.getValues();
427 String server = ip.getServer();
428 parameterValues.put(ATTR_SERVER, server);
429 // newChild.setAttribute(ATTR_SERVER, server);
430 int num = props.size();
431 if (num > 0) {
432 String attr = "";
433 String val = "";
434 for (int i=0; i<num; i++) {
435 attr = (String)(props.get(i));
436 if (attr.equals(ATTR_POS)) {
437 val = new Integer(numImages - 1).toString();
438 } else if (attr.equals(ATTR_DAY)) {
439 val = dateS;
440 } else if (attr.equals(ATTR_TIME)) {
441 val = timeS;
442 } else if (attr.equals(ATTR_UNIT)) {
443 val = unitS;
444 } else {
445 val = (String)(vals.get(i));
446 }
447 parameterValues.put(attr, val);
448 }
449 }
450 }
451 }
452 return parameterValues;
453 }
454
455 public void saveDataToLocalDisk() {
456 getDataSource().saveDataToLocalDisk();
457 }
458
459 public void popupSaveImageParameters() {
460 if (saveWindow == null) {
461 showSaveDialog();
462 return;
463 }
464 saveWindow.setVisible(true);
465 GuiUtils.toFront(saveWindow);
466 }
467
468 private void showSaveDialog() {
469 if (saveWindow == null) {
470 saveWindow = GuiUtils.createFrame("Save Image Parameter Set");
471 }
472 if (statusComp == null) {
473 statusLabel = new JLabel();
474 statusComp = GuiUtils.inset(statusLabel, 2);
475 statusComp.setBackground(new Color(255, 255, 204));
476 statusLabel.setOpaque(true);
477 statusLabel.setBackground(new Color(255, 255, 204));
478 }
479 JPanel statusPanel = GuiUtils.inset(GuiUtils.top( GuiUtils.vbox(new JLabel(" "),
480 GuiUtils.hbox(GuiUtils.rLabel("Status: "), statusComp),
481 new JLabel(" "))), 6);
482 JPanel sPanel = GuiUtils.topCenter(statusPanel, GuiUtils.filler());
483
484 List newComps = new ArrayList();
485 final JTextField newName = new JTextField(20);
486 newName.addActionListener(new ActionListener() {
487 public void actionPerformed(ActionEvent ae) {
488 setStatus("Click New Folder or New ParameterSet button");
489 newCompName = newName.getText().trim();
490 }
491 });
492 newComps.add(newName);
493 newComps.add(GuiUtils.filler());
494 newFolderBtn = new JButton("New Folder");
495 newFolderBtn.addActionListener(new ActionListener() {
496 public void actionPerformed(ActionEvent ae) {
497 newFolder = newName.getText().trim();
498 if (newFolder.length() == 0) {
499 newComponentError("folder");
500 return;
501 }
502 Element exists = XmlUtil.findElement(imageDefaultsRoot, "folder", ATTR_NAME, newFolder);
503 if (!(exists == null)) {
504 if (!GuiUtils.askYesNo("Verify Replace Folder",
505 "Do you want to replace the folder " +
506 "\"" + newFolder + "\"?" +
507 "\nNOTE: All parameter sets it contains will be deleted.")) return;
508 imageDefaultsRoot.removeChild(exists);
509 }
510 newName.setText("");
511 Node newEle = makeNewFolder();
512 makeXmlTree();
513 xmlTree.selectElement((Element)newEle);
514 lastCat = newEle;
515 lastClicked = null;
516 newSetBtn.setEnabled(true);
517 setStatus("Please enter a name for the new parameter set");
518 }
519 });
520 newComps.add(newFolderBtn);
521 newComps.add(GuiUtils.filler());
522 newName.setEnabled(true);
523 newFolderBtn.setEnabled(true);
524 newSetBtn = new JButton("New Parameter Set");
525 newSetBtn.setActionCommand(CMD_NEWPARASET);
526 newSetBtn.addActionListener(new ActionListener() {
527 public void actionPerformed(ActionEvent ae) {
528 newCompName = newName.getText().trim();
529 if (newCompName.length() == 0) {
530 newComponentError("parameter set");
531 return;
532 }
533 newName.setText("");
534 Element newEle = saveParameterSet();
535 if (newEle == null) return;
536 xmlTree.selectElement(newEle);
537 lastClicked = newEle;
538 }
539 });
540 newComps.add(newSetBtn);
541 newSetBtn.setEnabled(false);
542
543 JPanel newPanel = GuiUtils.top(GuiUtils.left(GuiUtils.hbox(newComps)));
544 JPanel topPanel = GuiUtils.topCenter(sPanel, newPanel);
545
546 treePanel = new JPanel();
547 treePanel.setLayout(new BorderLayout());
548 makeXmlTree();
549 ActionListener listener = new ActionListener() {
550 public void actionPerformed(ActionEvent event) {
551 String cmd = event.getActionCommand();
552 if (cmd.equals(GuiUtils.CMD_CANCEL)) {
553 if (lastClicked != null) {
554 removeNode(lastClicked);
555 lastClicked = null;
556 }
557 saveWindow.setVisible(false);
558 saveWindow = null;
559 } else {
560 saveWindow.setVisible(false);
561 saveWindow = null;
562 }
563 }
564 };
565 JPanel bottom =
566 GuiUtils.inset(GuiUtils.makeApplyCancelButtons(listener), 5);
567 contents =
568 GuiUtils.topCenterBottom(topPanel, treePanel, bottom);
569
570 saveWindow.getContentPane().add(contents);
571 saveWindow.pack();
572 saveWindow.setLocation(200, 200);
573
574 saveWindow.setVisible(true);
575 GuiUtils.toFront(saveWindow);
576 setStatus("Please select a folder from tree, or create a new folder");
577 }
578
579 private void newComponentError(String comp) {
580 JLabel label = new JLabel("Please enter " + comp +" name");
581 JPanel contents = GuiUtils.top(GuiUtils.inset(label, 24));
582 GuiUtils.showOkCancelDialog(null, "Make Component Error", contents, null);
583 }
584
585 private void setStatus(String msg) {
586 statusLabel.setText(msg);
587 contents.paintImmediately(0,0,contents.getWidth(),
588 contents.getHeight());
589 }
590
591 private void removeNode(Element node) {
592 if (imageDefaults == null) {
593 imageDefaults = getImageDefaults();
594 }
595 Node parent = node.getParentNode();
596 parent.removeChild(node);
597 makeXmlTree();
598 try {
599 imageDefaults.writeWritable();
600 } catch (Exception e) {
601 System.out.println("write error e=" + e);
602 }
603 imageDefaults.setWritableDocument(imageDefaultsDocument,
604 imageDefaultsRoot);
605 }
606
607 private Node makeNewFolder() {
608 if (imageDefaults == null) {
609 imageDefaults = getImageDefaults();
610 }
611 if (newFolder.length() == 0) {
612 return null;
613 }
614 List newChild = new ArrayList();
615 Node newEle = imageDefaultsDocument.createElement(TAG_FOLDER);
616 lastCat = newEle;
617 String[] newAttrs = { ATTR_NAME, newFolder };
618 XmlUtil.setAttributes((Element)newEle, newAttrs);
619 newChild.add(newEle);
620 XmlUtil.addChildren(imageDefaultsRoot, newChild);
621 try {
622 imageDefaults.writeWritable();
623 } catch (Exception e) {
624 System.out.println("write error e=" + e);
625 }
626 imageDefaults.setWritableDocument(imageDefaultsDocument,
627 imageDefaultsRoot);
628 return newEle;
629 }
630
631 /**
632 * Just creates an empty XmlTree
633 */
634 private void makeXmlTree() {
635 if (imageDefaults == null) {
636 imageDefaults = getImageDefaults();
637 }
638 xmlTree = new XmlTree(imageDefaultsRoot, true, "") {
639 public void doClick(XmlTree theTree, XmlTree.XmlTreeNode node,
640 Element element) {
641 Element clicked = xmlTree.getSelectedElement();
642 String lastTag = clicked.getTagName();
643 if ("folder".equals(lastTag)) {
644 lastCat = clicked;
645 lastClicked = null;
646 setStatus("Please enter a name for the new parameter set");
647 newSetBtn.setEnabled(true);
648 } else {
649 lastCat = clicked.getParentNode();
650 lastClicked = clicked;
651 }
652 }
653
654 public void doRightClick(XmlTree theTree,
655 XmlTree.XmlTreeNode node,
656 Element element, MouseEvent event) {
657 JPopupMenu popup = new JPopupMenu();
658 if (makePopupMenu(theTree, element, popup)) {
659 popup.show((Component) event.getSource(), event.getX(),
660 event.getY());
661 }
662 }
663 };
664 List tagList = new ArrayList();
665 tagList.add(TAG_FOLDER);
666 tagList.add(TAG_DEFAULT);
667 xmlTree.addTagsToProcess(tagList);
668 xmlTree.defineLabelAttr(TAG_FOLDER, ATTR_NAME);
669 addToContents(GuiUtils.inset(GuiUtils.topCenter(new JPanel(),
670 xmlTree.getScroller()), 5));
671 return;
672 }
673
674 private List getFolders() {
675 return XmlUtil.findChildren(imageDefaultsRoot, TAG_FOLDER);
676 }
677
678
679 private void doDeleteRequest(Node node) {
680 if (node == null) {
681 return;
682 }
683 Element ele = (Element)node;
684 String tagName = ele.getTagName();
685 if (tagName.equals("folder")) {
686 if (!GuiUtils.askYesNo("Verify Delete Folder",
687 "Do you want to delete the folder " +
688 "\"" + ele.getAttribute("name") + "\"?" +
689 "\nNOTE: All parameter sets it contains will be deleted.")) return;
690 XmlUtil.removeChildren(ele);
691 } else if (tagName.equals("default")) {
692 if (!GuiUtils.askYesNo("Verify Delete", "Do you want to delete " +
693 "\"" + ele.getAttribute(ATTR_NAME) + "\"?")) return;
694 } else { return; }
695 removeNode(ele);
696 }
697 /**
698 * Create and popup a command menu for when the user has clicked on the given xml node.
699 *
700 * @param theTree The XmlTree object displaying the current xml document.
701 * @param node The xml node the user clicked on.
702 * @param popup The popup menu to put the menu items in.
703 * @return Did we add any items into the menu
704 */
705 private boolean makePopupMenu(final XmlTree theTree, final Element node,
706 JPopupMenu popup)
707 {
708 theTree.selectElement(node);
709 String tagName = node.getTagName();
710 final Element parent = (Element)node.getParentNode();
711 boolean didone = false;
712 JMenuItem mi;
713
714 if (tagName.equals("default")) {
715 lastClicked = node;
716 JMenu moveMenu = new JMenu("Move to");
717 List folders = getFolders();
718 for (int i = 0; i < folders.size(); i++) {
719 final Element newFolder = (Element)folders.get(i);
720 if (!newFolder.isSameNode(parent)) {
721 String name = newFolder.getAttribute(ATTR_NAME);
722 mi = new JMenuItem(name);
723 mi.addActionListener(new ActionListener() {
724 public void actionPerformed(ActionEvent ae) {
725 moveParameterSet(parent, newFolder);
726 }
727 });
728 moveMenu.add(mi);
729 }
730 }
731 popup.add(moveMenu);
732 popup.addSeparator();
733 didone = true;
734 }
735
736 mi = new JMenuItem("Rename...");
737 mi.addActionListener(new ActionListener() {
738 public void actionPerformed(ActionEvent ae) {
739 doRename(node);
740 }
741 });
742 popup.add(mi);
743 didone = true;
744
745 mi = new JMenuItem("Delete");
746 mi.addActionListener(new ActionListener() {
747 public void actionPerformed(ActionEvent ae) {
748 doDeleteRequest(node);
749 }
750 });
751 popup.add(mi);
752 didone = true;
753
754 return didone;
755 }
756
757 public void moveParameterSet(Element parent, Element newFolder) {
758 if (imageDefaults == null) {
759 imageDefaults = getImageDefaults();
760 }
761 if (lastClicked == null) {
762 return;
763 }
764 Node copyNode = lastClicked.cloneNode(true);
765 newFolder.appendChild(copyNode);
766 parent.removeChild(lastClicked);
767 lastCat = newFolder;
768 makeXmlTree();
769 try {
770 imageDefaults.writeWritable();
771 } catch (Exception e) {
772 System.out.println("write error e=" + e);
773 }
774 imageDefaults.setWritableDocument(imageDefaultsDocument, imageDefaultsRoot);
775 }
776
777 private void doRename(Element node) {
778 if (imageDefaults == null) {
779 imageDefaults = getImageDefaults();
780 }
781 if (!node.hasAttribute(ATTR_NAME)) return;
782 JLabel label = new JLabel("New name: ");
783 JTextField nameFld = new JTextField("", 20);
784 JComponent contents = GuiUtils.doLayout(new Component[] {
785 GuiUtils.rLabel("New name: "), nameFld, }, 2,
786 GuiUtils.WT_N, GuiUtils.WT_N);
787 contents = GuiUtils.center(contents);
788 contents = GuiUtils.inset(contents, 10);
789 if (!GuiUtils.showOkCancelDialog(null, "Rename \"" +
790 node.getAttribute("name") + "\"", contents, null)) return;
791 String newName = nameFld.getText().trim();
792 String tagName = node.getTagName();
793 Element root = imageDefaultsRoot;
794 if (tagName.equals("default")) {
795 root = (Element)node.getParentNode();
796 }
797 Element exists = XmlUtil.findElement(root, tagName, ATTR_NAME, newName);
798 if (!(exists == null)) {
799 if (!GuiUtils.askYesNo("Name Already Exists",
800 "Do you want to replace " + node.getAttribute("name") + " with" +
801 "\"" + newName + "\"?")) return;
802 }
803 node.removeAttribute(ATTR_NAME);
804 node.setAttribute(ATTR_NAME, newName);
805 makeXmlTree();
806 try {
807 imageDefaults.writeWritable();
808 } catch (Exception e) {
809 System.out.println("write error e=" + e);
810 }
811 imageDefaults.setWritableDocument(imageDefaultsDocument,
812 imageDefaultsRoot);
813 }
814
815 /**
816 * Remove the currently display gui and insert the given one.
817 *
818 * @param comp The new gui.
819 */
820 private void addToContents(JComponent comp) {
821 treePanel.removeAll();
822 comp.setPreferredSize(new Dimension(200, 300));
823 treePanel.add(comp, BorderLayout.CENTER);
824 if (contents != null) {
825 contents.invalidate();
826 contents.validate();
827 contents.repaint();
828 }
829 }
830
831 public DataSourceImpl getDataSource() {
832 DataSourceImpl ds = null;
833 List dataSources = getDataSources();
834 if (!dataSources.isEmpty()) {
835 ds = (DataSourceImpl)dataSources.get(0);
836 }
837 return ds;
838 }
839
840 public Element saveParameterSet() {
841 if (imageDefaults == null) {
842 imageDefaults = getImageDefaults();
843 }
844 if (newCompName.length() == 0) {
845 newComponentError("parameter set");
846 return null;
847 }
848 Element newChild = imageDefaultsDocument.createElement(TAG_DEFAULT);
849 newChild.setAttribute(ATTR_NAME, newCompName);
850
851 if (datachoice == null) {
852 datachoice = getDataChoice();
853 }
854 dataSource = getDataSource();
855 if (!(dataSource.getClass().isInstance(new AddeImageParameterDataSource()))) {
856 return newChild;
857 }
858 AddeImageParameterDataSource testDataSource = (AddeImageParameterDataSource)dataSource;
859 List imageList = testDataSource.getDescriptors(datachoice, this.dataSelection);
860 int numImages = imageList.size();
861 List dateTimes = new ArrayList();
862 DateTime thisDT = null;
863 if (!(imageList == null)) {
864 AddeImageDescriptor aid = null;
865 for (int imageNo = 0; imageNo < numImages; imageNo++) {
866 aid = (AddeImageDescriptor)(imageList.get(imageNo));
867 thisDT = aid.getImageTime();
868 if (!(dateTimes.contains(thisDT))) {
869 if (thisDT != null) {
870 dateTimes.add(thisDT);
871 }
872 }
873 }
874 String dateS = "";
875 String timeS = "";
876 if (!(dateTimes.isEmpty())) {
877 thisDT = (DateTime)dateTimes.get(0);
878 dateS = thisDT.dateString();
879 timeS = thisDT.timeString();
880 if (dateTimes.size() > 1) {
881 for (int img = 1; img < dateTimes.size(); img++) {
882 thisDT = (DateTime)dateTimes.get(img);
883 String str = ',' + thisDT.dateString();
884 String newString = new String(dateS + str);
885 dateS = newString;
886 str = ',' + thisDT.timeString();
887 newString = new String(timeS + str);
888 timeS = newString;
889 }
890 }
891 }
892 if (aid != null) {
893 String displayUrl = testDataSource.getDisplaySource();
894 ImageParameters ip = new ImageParameters(displayUrl);
895 List props = ip.getProperties();
896 List vals = ip.getValues();
897 String server = ip.getServer();
898 newChild.setAttribute(ATTR_SERVER, server);
899 int num = props.size();
900 if (num > 0) {
901 String attr = "";
902 String val = "";
903 for (int i = 0; i < num; i++) {
904 attr = (String)(props.get(i));
905 if (attr.equals(ATTR_POS)) {
906 val = new Integer(numImages - 1).toString();
907 } else if (attr.equals(ATTR_DAY)) {
908 val = dateS;
909 } else if (attr.equals(ATTR_TIME)) {
910 val = timeS;
911 } else {
912 val = (String)(vals.get(i));
913 }
914 newChild.setAttribute(attr, val);
915 }
916 }
917 }
918 }
919 Element parent = xmlTree.getSelectedElement();
920 if (parent == null) {
921 parent = (Element)lastCat;
922 }
923 if (parent != null) {
924 Element exists = XmlUtil.findElement(parent, "default", ATTR_NAME, newCompName);
925 if (!(exists == null)) {
926 JLabel label = new JLabel("Replace \"" + newCompName + "\"?");
927 JPanel contents = GuiUtils.top(GuiUtils.inset(label, newCompName.length()+12));
928 if (!GuiUtils.showOkCancelDialog(null, "Parameter Set Exists", contents, null)) {
929 return newChild;
930 }
931 parent.removeChild(exists);
932 }
933 parent.appendChild(newChild);
934 makeXmlTree();
935 }
936 try {
937 imageDefaults.writeWritable();
938 } catch (Exception e) {
939 System.out.println("write error e=" + e);
940 }
941 imageDefaults.setWritableDocument(imageDefaultsDocument, imageDefaultsRoot);
942 return newChild;
943 }
944
945 /**
946 * Holds a JFreeChart histogram of image values.
947 */
948 private class MyTabbedPane extends JTabbedPane implements ChangeListener {
949 /** Have we been painted */
950 boolean painted = false;
951
952 boolean popupFlag = false;
953
954 /**
955 * Creates a new {@code MyTabbedPane} that gets immediately registered
956 * as a {@link javax.swing.event.ChangeListener} for its own events.
957 */
958 public MyTabbedPane() {
959 addChangeListener(this);
960 }
961 /**
962 *
963 * Handle when the tab has changed. When we move to tab 1 then hide the heavy
964 * component. Show it on change to tab 0.
965 *
966 * @param e The event
967 */
968 public void stateChanged(ChangeEvent e) {
969 if (!getActive() || !getHaveInitialized()) {
970 return;
971 }
972 if ((getSelectedIndex() == 1) && popupFlag) {
973 JLabel label = new JLabel("Can't make a histogram");
974 JPanel contents = GuiUtils.top(GuiUtils.inset(label, label.getText().length() + 12));
975 GuiUtils.showOkDialog(null, "Data Unavailable", contents, null);
976 setPopupFlag(false);
977 }
978 }
979
980 private void setPopupFlag(boolean flag) {
981 this.popupFlag = flag;
982 }
983
984 /**
985 * The first time we paint toggle the selected index. This seems to get rid of
986 * screen crud
987 *
988 * @param g graphics
989 */
990 public void paint(java.awt.Graphics g) {
991 if (!painted) {
992 painted = true;
993 setSelectedIndex(1);
994 setSelectedIndex(0);
995 repaint();
996 }
997 super.paint(g);
998 }
999 }
1000 }