001/* 002 * $Id: ParameterTree.java,v 1.4 2011/03/24 16:06:34 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 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 031package edu.wisc.ssec.mcidasv.ui; 032 033 034import java.awt.Component; 035import java.awt.Dimension; 036import java.awt.event.KeyAdapter; 037import java.awt.event.KeyEvent; 038import java.awt.event.MouseAdapter; 039import java.awt.event.MouseEvent; 040import java.util.ArrayList; 041import java.util.Enumeration; 042import java.util.Hashtable; 043import java.util.List; 044 045import javax.swing.ImageIcon; 046import javax.swing.JComponent; 047import javax.swing.JFrame; 048import javax.swing.JMenu; 049import javax.swing.JMenuBar; 050import javax.swing.JPanel; 051import javax.swing.JPopupMenu; 052import javax.swing.JScrollPane; 053import javax.swing.JTree; 054import javax.swing.SwingUtilities; 055import javax.swing.tree.DefaultMutableTreeNode; 056import javax.swing.tree.DefaultTreeCellRenderer; 057import javax.swing.tree.DefaultTreeModel; 058import javax.swing.tree.TreePath; 059import javax.swing.tree.TreeSelectionModel; 060 061import ucar.unidata.idv.IdvPersistenceManager; 062import ucar.unidata.ui.DndTree; 063import ucar.unidata.util.GuiUtils; 064import ucar.unidata.util.LogUtil; 065import edu.wisc.ssec.mcidasv.ParameterSet; 066import edu.wisc.ssec.mcidasv.PersistenceManager; 067 068 069/** 070 * Class ParameterTree Gives a tree gui for editing parameter sets 071 * 072 * 073 * @author IDV Development Team 074 * @version $Revision: 1.4 $ 075 */ 076public class ParameterTree extends DndTree { 077 078 /** The window */ 079 private JFrame frame; 080 081 /** What is the type of the parameter set we are showing */ 082 private String parameterType; 083 084 /** The root of the tree */ 085 private DefaultMutableTreeNode treeRoot; 086 087 /** The tree model */ 088 private DefaultTreeModel treeModel; 089 090 /** A mapping from tree node to, either, category or ParameterSet */ 091 private Hashtable nodeToData; 092 093 /** The ui manager */ 094 private UIManager uiManager; 095 096 /** The persistence manager */ 097 private PersistenceManager persistenceManager; 098 099 /** Icon to use for categories */ 100 private ImageIcon categoryIcon; 101 102 /** Icon to use for parameters */ 103 private ImageIcon parameterIcon; 104 105 106 107 108 /** 109 * Create the tree with the given parameter set type 110 * 111 * 112 * @param uiManager The UI manager 113 * @param parameterType The type of the parameter set we are showing 114 */ 115 public ParameterTree(UIManager uiManager, String parameterType) { 116 117 categoryIcon = GuiUtils.getImageIcon("/auxdata/ui/icons/folder.png", 118 getClass()); 119 parameterIcon = GuiUtils.getImageIcon("/auxdata/ui/icons/page.png", 120 getClass()); 121 122 this.uiManager = uiManager; 123 this.persistenceManager = (PersistenceManager)(uiManager.getPersistenceManager()); 124 125 setToolTipText( 126 "<html>Right click to show popup menu.<br>Drag to move parameter sets or categories</html>"); 127 128 this.parameterType = parameterType; 129 treeRoot = new DefaultMutableTreeNode("Parameter Sets"); 130 131 // setRootVisible(false); 132 setShowsRootHandles(true); 133 treeModel = new DefaultTreeModel(treeRoot); 134 setModel(treeModel); 135 DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { 136 public Component getTreeCellRendererComponent(JTree theTree, 137 Object value, boolean sel, boolean expanded, 138 boolean leaf, int row, boolean hasFocus) { 139 140 super.getTreeCellRendererComponent(theTree, value, sel, 141 expanded, leaf, row, hasFocus); 142 if ((nodeToData == null) || (value == null)) { 143 return this; 144 } 145 Object data = nodeToData.get(value); 146 if (data == null) { 147 setIcon(categoryIcon); 148 return this; 149 } 150 if (data instanceof ParameterSet) { 151 setToolTipText( 152 "<html>Right click to show parameter set menu.<br>Drag to move parameter set</html>"); 153 setIcon(parameterIcon); 154 } else { 155 setToolTipText( 156 "<html>Right click to show category menu.<br>Drag to move parameter sets or categories</html><"); 157 setIcon(categoryIcon); 158 } 159 return this; 160 } 161 }; 162 setCellRenderer(renderer); 163 164 165 166 167 addKeyListener(new KeyAdapter() { 168 public void keyPressed(KeyEvent e) { 169 if (e.getKeyCode() == e.VK_DELETE) { 170 deleteSelected(); 171 } 172 } 173 }); 174 175 getSelectionModel().setSelectionMode( 176 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); 177 // TreeSelectionModel.SINGLE_TREE_SELECTION); 178 179 180 addMouseListener(new MouseAdapter() { 181 public void mouseClicked(MouseEvent event) { 182 TreePath path = getPathForLocation(event.getX(), 183 event.getY()); 184 Object data = findDataAtPath(path); 185 if ( !SwingUtilities.isRightMouseButton(event)) { 186// if (event.getClickCount() > 1) { 187// if ((data != null) && (data instanceof SavedBundle)) { 188// doOpen((SavedBundle) data); 189// } 190// } 191 return; 192 } 193 clearSelection(); 194 addSelectionPath(path); 195 final DefaultMutableTreeNode parentNode = 196 (DefaultMutableTreeNode) path.getLastPathComponent(); 197 198 JPopupMenu popup = new JPopupMenu(); 199 if (data == null) { 200 popup.add(GuiUtils.makeMenuItem("Add Subcategory", 201 ParameterTree.this, "addCategory", parentNode)); 202 } else { 203 if (data instanceof ParameterSet) { 204 ParameterSet set = (ParameterSet) data; 205 popup.add(GuiUtils.makeMenuItem("Rename", 206 ParameterTree.this, "doRename", set)); 207 popup.add(GuiUtils.makeMenuItem("Delete", 208 ParameterTree.this, "deleteParameterSet", set)); 209 } else { 210 popup.add(GuiUtils.makeMenuItem("Delete Category", 211 ParameterTree.this, "deleteCategory", 212 data.toString())); 213 popup.add(GuiUtils.makeMenuItem("Add Subcategory", 214 ParameterTree.this, "addCategory", parentNode)); 215 } 216 } 217 popup.show((Component) event.getSource(), event.getX(), 218 event.getY()); 219 } 220 }); 221 loadParameterSets(); 222 223 String title = "Parameter Set Manager"; 224 225 Dimension defaultDimension = new Dimension(300, 400); 226 JScrollPane sp = GuiUtils.makeScrollPane(this, 227 (int) defaultDimension.getWidth(), 228 (int) defaultDimension.getHeight()); 229 sp.setPreferredSize(defaultDimension); 230 231 232 JMenuBar menuBar = new JMenuBar(); 233 JMenu fileMenu = new JMenu("File"); 234 JMenu helpMenu = new JMenu("Help"); 235 menuBar.add(fileMenu); 236 // menuBar.add(helpMenu); 237// fileMenu.add(GuiUtils.makeMenuItem("Export to File", this, 238// "doExport")); 239// fileMenu.add(GuiUtils.makeMenuItem("Export to Plugin", this, 240// "doExportToPlugin")); 241// fileMenu.addSeparator(); 242 fileMenu.add(GuiUtils.makeMenuItem("Close", this, "doClose")); 243 244 245 246 247 JComponent bottom = GuiUtils.wrap(GuiUtils.makeButton("Close", this, 248 "doClose")); 249 250 JPanel contents = GuiUtils.topCenterBottom(menuBar, sp, bottom); 251 frame = GuiUtils.createFrame(title); 252 frame.getContentPane().add(contents); 253 frame.pack(); 254 frame.setLocation(100, 100); 255 } 256 257 /** 258 * close 259 */ 260 public void doClose() { 261 frame.dispose(); 262 } 263 264 265 /** 266 * Get the list of selected parameter sets 267 * 268 * @return The selected parameter sets 269 */ 270 private List getSelectedParameterSets() { 271 TreePath[] paths = getSelectionModel().getSelectionPaths(); 272 if ((paths == null) || (paths.length == 0)) { 273 return new ArrayList(); 274 } 275 List sets = new ArrayList(); 276 for (int i = 0; i < paths.length; i++) { 277 Object data = findDataAtPath(paths[i]); 278 if (data == null) { 279 continue; 280 } 281 if ( !(data instanceof ParameterSet)) { 282 continue; 283 } 284 sets.add(data); 285 } 286 return sets; 287 } 288 289 /** 290 * Show the window 291 */ 292 public void setVisible(boolean visibility) { 293 frame.setVisible(visibility); 294 } 295 296 297 /** 298 * Ok to drag the node 299 * 300 * @param sourceNode The node to drag 301 * 302 * @return Ok to drag 303 */ 304 protected boolean okToDrag(DefaultMutableTreeNode sourceNode) { 305 return sourceNode.getParent() != null; 306 } 307 308 309 /** 310 * Ok to drop the node 311 * 312 * 313 * @param sourceNode The dragged node 314 * @param destNode Where to drop 315 * 316 * @return Ok to drop 317 */ 318 protected boolean okToDrop(DefaultMutableTreeNode sourceNode, 319 DefaultMutableTreeNode destNode) { 320 321 322 //Don't drop a parameter set onto the root. It must be in a category 323 if (sourceNode.getUserObject() instanceof ParameterSet) { 324 if (destNode.getParent() == null) { 325 return false; 326 } 327 } 328 329 if (destNode.getUserObject() instanceof ParameterSet) { 330 return false; 331 } 332 if (destNode == sourceNode.getParent()) { 333 return false; 334 } 335 while (destNode != null) { 336 if (destNode == sourceNode) { 337 return false; 338 } 339 destNode = (DefaultMutableTreeNode) destNode.getParent(); 340 } 341 return true; 342 } 343 344 345 346 /** 347 * Handle the DND drop 348 * 349 * 350 * @param sourceNode The dragged node 351 * @param destNode Where to drop 352 */ 353 protected void doDrop(DefaultMutableTreeNode sourceNode, 354 DefaultMutableTreeNode destNode) { 355 if (sourceNode.getUserObject() instanceof ParameterSet) { 356 persistenceManager.moveParameterSet( 357 parameterType, 358 (ParameterSet) sourceNode.getUserObject(), 359 getCategoryList(destNode)); 360 } else { 361 persistenceManager.moveParameterSetCategory( 362 parameterType, 363 getCategoryList(sourceNode), 364 getCategoryList(destNode)); 365 } 366 367 loadParameterSets(); 368 } 369 370 371 372 373 /** 374 * Create the list of categories 375 * 376 * @param destNode From where 377 * 378 * @return List of String categories 379 */ 380 private List getCategoryList(DefaultMutableTreeNode destNode) { 381 List categories = new ArrayList(); 382 while (destNode.getParent() != null) { 383 categories.add(0, destNode.getUserObject().toString()); 384 destNode = (DefaultMutableTreeNode) destNode.getParent(); 385 } 386 return categories; 387 } 388 389 /** 390 * Load the parameter sets into the tree 391 */ 392 protected void loadParameterSets() { 393 394 Enumeration paths = 395 getExpandedDescendants(new TreePath(treeRoot.getPath())); 396 Hashtable expandedState = 397 GuiUtils.initializeExpandedPathsBeforeChange(this, treeRoot); 398 399 List allCategories = persistenceManager.getAllParameterSetCategories(parameterType); 400 nodeToData = new Hashtable(); 401 treeRoot.removeAllChildren(); 402 Hashtable catNodes = new Hashtable(); 403 Hashtable fakeSets = new Hashtable(); 404 List sets = new ArrayList(); 405 406 //We use a set of fake parameter sets to we include all categories into the tree 407 for (int i = 0; i < allCategories.size(); i++) { 408 List categories = persistenceManager.stringToCategories((String) allCategories.get(i)); 409 ParameterSet fakeSet = new ParameterSet("", categories, parameterType); 410 fakeSets.put(fakeSet, fakeSet); 411 sets.add(fakeSet); 412 } 413 sets.addAll(persistenceManager.getAllParameterSets(parameterType)); 414 for (int i = 0; i < sets.size(); i++) { 415 ParameterSet set = (ParameterSet) sets.get(i); 416 List categories = set.getCategories(); 417 DefaultMutableTreeNode catNode = treeRoot; 418 String fullCat = ""; 419 for (int catIdx = 0; catIdx < categories.size(); catIdx++) { 420 String cat = (String) categories.get(catIdx); 421 if (fullCat.length() > 0) { 422 fullCat = fullCat + IdvPersistenceManager.CATEGORY_SEPARATOR; 423 } 424 fullCat = fullCat + cat; 425 DefaultMutableTreeNode tmpNode = (DefaultMutableTreeNode) catNodes.get(fullCat); 426 if (tmpNode == null) { 427 tmpNode = new DefaultMutableTreeNode(cat); 428 nodeToData.put(tmpNode, fullCat); 429 catNode.add(tmpNode); 430 catNodes.put(fullCat, tmpNode); 431 } 432 catNode = tmpNode; 433 } 434 //Skip over the fake ones 435 if (fakeSets.get(set) == null) { 436 DefaultMutableTreeNode setNode = new DefaultMutableTreeNode(set); 437 nodeToData.put(setNode, set); 438 catNode.add(setNode); 439 } 440 } 441 treeModel.nodeStructureChanged(treeRoot); 442 GuiUtils.expandPathsAfterChange(this, expandedState, treeRoot); 443 } 444 445 446 /** 447 * Find the data (either a ParameterSet or a category) 448 * associated with the given tree path 449 * 450 * @param path The path 451 * 452 * @return The data 453 */ 454 455 private Object findDataAtPath(TreePath path) { 456 if ((path == null) || (nodeToData == null)) { 457 return null; 458 } 459 DefaultMutableTreeNode last = 460 (DefaultMutableTreeNode) path.getLastPathComponent(); 461 if (last == null) { 462 return null; 463 } 464 return nodeToData.get(last); 465 } 466 467 /** 468 * Delete the selected item in the tree 469 */ 470 public void deleteSelected() { 471 System.out.println("deleteSelected"); 472 TreePath[] paths = getSelectionModel().getSelectionPaths(); 473 if ((paths == null) || (paths.length == 0)) { 474 return; 475 } 476 Object data = findDataAtPath(paths[0]); 477 if (data == null) { 478 return; 479 } 480 if (data instanceof ParameterSet) { 481 deleteParameterSet((ParameterSet) data); 482 } else { 483 deleteCategory(data.toString()); 484 } 485 } 486 487 488 /** 489 * Delete the given parameter set 490 * 491 * @param parameterSet The parameter set to delete 492 */ 493 public void deleteParameterSet(ParameterSet parameterSet) { 494 if ( !GuiUtils.askYesNo( 495 "Parameter set delete confirmation", 496 "Are you sure you want to delete the parameter set \"" + parameterSet 497 + "\" ?")) { 498 return; 499 } 500 System.out.println("deleteParameterSet"); 501 persistenceManager.deleteParameterSet(parameterType, parameterSet); 502 loadParameterSets(); 503 } 504 505 506 /** 507 * Delete the given parameter set category 508 * 509 * @param category The category to delete 510 */ 511 public void deleteCategory(String category) { 512 if ( !GuiUtils.askYesNo( 513 "Parameter Set Category Delete Confirmation", 514 "<html>Are you sure you want to delete the category:<p> <center>\"" 515 + category 516 + "\"</center> <br> and all parameter sets and categories under it?</html>")) { 517 return; 518 } 519 System.out.println("deleteCategory"); 520 persistenceManager.deleteParameterSetCategory(parameterType, category); 521 loadParameterSets(); 522 } 523 524 /** 525 * Create a new category under the given node 526 * 527 * @param parentNode The parent tree node 528 */ 529 public void addCategory(DefaultMutableTreeNode parentNode) { 530 String cat = 531 GuiUtils.getInput("Please enter the new category name", 532 "Name: ", ""); 533 if (cat == null) { 534 return; 535 } 536 String parentCat = (String) nodeToData.get(parentNode); 537 String fullCat = ((parentCat == null) 538 ? cat 539 : (parentCat 540 + IdvPersistenceManager.CATEGORY_SEPARATOR 541 + cat)); 542 System.out.println("addCategory"); 543 if ( !persistenceManager.addParameterSetCategory(parameterType, fullCat)) { 544 LogUtil.userMessage( 545 "A category with the given name already exists"); 546 return; 547 } 548 DefaultMutableTreeNode newCatNode = new DefaultMutableTreeNode(cat); 549 nodeToData.put(newCatNode, fullCat); 550 parentNode.add(newCatNode); 551 552 553 Hashtable expandedState = 554 GuiUtils.initializeExpandedPathsBeforeChange(this, treeRoot); 555 treeModel.nodeStructureChanged(treeRoot); 556 GuiUtils.expandPathsAfterChange(this, expandedState, treeRoot); 557 } 558 559 560 /** 561 * Rename the parameter set 562 * @param parameterSet the parameter set 563 */ 564 public void doRename(ParameterSet parameterSet) { 565 System.out.println("doRename"); 566 persistenceManager.renameParameterSet(parameterType, parameterSet); 567 } 568 569} 570