001 /*
002 * $Id: ParameterTree.java,v 1.5 2012/02/19 17:35:50 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.ui;
032
033
034 import java.awt.Component;
035 import java.awt.Dimension;
036 import java.awt.event.KeyAdapter;
037 import java.awt.event.KeyEvent;
038 import java.awt.event.MouseAdapter;
039 import java.awt.event.MouseEvent;
040 import java.util.ArrayList;
041 import java.util.Enumeration;
042 import java.util.Hashtable;
043 import java.util.List;
044
045 import javax.swing.ImageIcon;
046 import javax.swing.JComponent;
047 import javax.swing.JFrame;
048 import javax.swing.JMenu;
049 import javax.swing.JMenuBar;
050 import javax.swing.JPanel;
051 import javax.swing.JPopupMenu;
052 import javax.swing.JScrollPane;
053 import javax.swing.JTree;
054 import javax.swing.SwingUtilities;
055 import javax.swing.tree.DefaultMutableTreeNode;
056 import javax.swing.tree.DefaultTreeCellRenderer;
057 import javax.swing.tree.DefaultTreeModel;
058 import javax.swing.tree.TreePath;
059 import javax.swing.tree.TreeSelectionModel;
060
061 import ucar.unidata.idv.IdvPersistenceManager;
062 import ucar.unidata.ui.DndTree;
063 import ucar.unidata.util.GuiUtils;
064 import ucar.unidata.util.LogUtil;
065 import edu.wisc.ssec.mcidasv.ParameterSet;
066 import 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.5 $
075 */
076 public 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