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