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 }