package edu.colostate.vchill.gui; import edu.colostate.vchill.Config; import edu.colostate.vchill.*; import edu.colostate.vchill.bookmark.Bookmark; import edu.colostate.vchill.bookmark.BookmarkControl; import edu.colostate.vchill.chill.ChillMomentFieldScale; import javax.swing.*; import javax.swing.event.MouseInputAdapter; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import java.awt.*; import java.awt.event.MouseEvent; import java.util.Enumeration; /** * This is a "bookmark browser" that can be used to visually represent bookmarks * by categories and names. It creates a JTree, adds the selection handling, * sets some options and renders it. The BookmarkTreeModel is responsible for * most of the internal workings. * * @author Justin Carlson * @author Jochen Deyke * @author Alexander Deyke * @author jpont * @version 2010-08-30 */ public class ViewBookmarkBrowser extends JPanel { /** * */ private static final long serialVersionUID = 2609212773365339587L; private static final WindowManager wm = WindowManager.getInstance(); private static final ViewControl vc = ViewControl.getInstance(); private static final Config config = Config.getInstance(); private static final ScaleManager sm = ScaleManager.getInstance(); private final JTree tree; private final ViewBookmarkBrowserPopup popup; private static final ViewBookmarkBrowser vbb = new ViewBookmarkBrowser(); private static enum Match { /** * match only the beginning of the string */ BEGINNING, /** * match anywhere in the string */ MIDDLE, /** * match only the end of the string */ END, /** * match the entire string */ ENTIRE, } /** * Constructor for the ViewBookmarkBrowser object */ private ViewBookmarkBrowser() { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); this.tree = new JTree(BookmarkControl.getInstance().getModel()); this.popup = new ViewBookmarkBrowserPopup(this.tree); this.tree.addMouseListener(new MouseInputAdapter() { private Bookmark getBookmark(final TreePath click) { if (click == null) return null; Object[] pathObjects = click.getPath(); if (!tree.isPathSelected(click)) tree.setSelectionPath(click); if (tree.getSelectionPaths() == null || tree.getSelectionPaths().length > 1) return null; DefaultMutableTreeNode node = (DefaultMutableTreeNode) click.getLastPathComponent(); if (node == null || !node.isLeaf()) return null; return BookmarkControl.getInstance().getBookmark( pathObjects[1].toString(), pathObjects[2].toString()); } @Override public void mouseClicked(final MouseEvent e) { TreePath click = tree.getPathForLocation(e.getX(), e.getY()); switch (e.getButton()) { case MouseEvent.BUTTON1: //left click setBookmark(getBookmark(click)); break; case MouseEvent.BUTTON2: //middle click Bookmark bookmark = getBookmark(click); if (bookmark != null) DialogUtil.showHelpDialog("Bookmark comment", bookmark.comment); break; case MouseEvent.BUTTON3: //right click if (!tree.isPathSelected(click)) tree.setSelectionPath(click); popup.show(e.getComponent(), e.getX(), e.getY()); break; } } }); //this.tree.setEditable(true); this.tree.setEditable(false); this.tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); this.tree.setShowsRootHandles(true); this.tree.setCellRenderer(new DefaultTreeCellRenderer() { /** * */ private static final long serialVersionUID = -3738819540553277433L; @Override public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel, final boolean expanded, final boolean leaf, final int row, final boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; switch (node.getLevel()) { case 0: setIcon(new ImageIcon(Loader.getResource("icons/top" + (expanded ? "Open" : "Closed") + ".gif"))); break; case 1: setIcon(new ImageIcon(Loader.getResource("icons/dir" + (expanded ? "Open" : "Closed") + ".gif"))); break; case 2: setIcon(new ImageIcon(Loader.getResource("icons/bookmark.png"))); break; } return this; } }); JScrollPane scrollPane = new JScrollPane(this.tree); add(scrollPane); } /** * Set view characteristics to those specified by the given bookmark * * @param bookmark The bookmark to load */ public static void setBookmark(final Bookmark bookmark) { if (bookmark == null) return; System.out.println("Loading bookmark: " + bookmark.toString()); EventQueue.invokeLater(new Runnable() { public void run() { wm.setMode(bookmark.scan_type, false); //do not force config.setMaxPlotHeight(bookmark.rhi_height); //km config.setGridSpacing(bookmark.ring); //km config.setPlotRange(bookmark.range); //km for (String type : sm.getTypes()) { //each type Bookmark.Scale bmScale = bookmark.scale.get(type); if (bmScale == null) continue; if (bmScale.autoscale) { //use default vs custom scale ChillMomentFieldScale scale = sm.getScale(type); vc.setPlotInterval(type, String.valueOf(scale.maxValue), String.valueOf(scale.minValue)); } else { vc.setPlotInterval(type, bmScale.maxval, bmScale.minval); } } ViewRemotePanel.getInstance().update(); config.setCenterX(bookmark.x); config.setCenterY(bookmark.y); ViewFileBrowserActions actions = ViewFileBrowser.getInstance().getActions(); ControlMessage message = bookmark.getControlMessage(); message = actions.findSweep(message); if (message != null) { //we found the bookmark sweep System.out.println("FOUND BOOKMARK: bookmark control message: " + message); actions.changeSelection(message); //this triggers plot } else { System.out.println("BookMark Not Found Correctly"); } wm.setCenterInKm(); DialogUtil.showHelpDialog("Bookmark comment", bookmark.comment); } }); } /** * Tries to select the specified bookmark. * If it exists, it will also be set as per setBookmark(). * * @param category the (end of) the category to select * @param name the (start of) the name of the bookmark to select */ public void selectBookmark(final String category, final String name) { TreePath newPath = getTreePath(category, name); tree.scrollPathToVisible(newPath.getParentPath()); tree.scrollPathToVisible(newPath); tree.clearSelection(); tree.setSelectionPath(newPath); Object[] pathObjs = newPath.getPath(); if (pathObjs.length != 3) return; //bookmarks, category, bookmark String foundCategory = (String) ((DefaultMutableTreeNode) pathObjs[1]).getUserObject(); String foundBookmark = (String) ((DefaultMutableTreeNode) pathObjs[2]).getUserObject(); Bookmark bookmark = BookmarkControl.getInstance().getBookmark(foundCategory, foundBookmark); if (bookmark != null) setBookmark(bookmark); } /** * @param category the (end of) the category to select * @param name the (start of) the name of the bookmark to select * @return the path to the specified bookmark if it exists, a partial path if it does not. */ public TreePath getTreePath(final String category, final String name) { DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot(); TreePath path = new TreePath(root); tree.expandPath(path); if (category == null) return path; DefaultMutableTreeNode categoryNode = searchNodeForString(root, category, Match.END); if (categoryNode == null) return path; path = path.pathByAddingChild(categoryNode); tree.expandPath(path); if (name == null) return path; DefaultMutableTreeNode bookmarkNode = searchNodeForString(categoryNode, name, Match.BEGINNING); if (bookmarkNode == null) return path; path = path.pathByAddingChild(bookmarkNode); tree.expandPath(path); return path; } /** * @param node the node in whose children to search for the named node * @param toFind the name (userObject) of the child node to find * @param match whether the beginning, end, or entire string must match * @return the child node with the specified name if it exists, null if it does not */ private static DefaultMutableTreeNode searchNodeForString(final DefaultMutableTreeNode node, final String toFind, final Match match) { Enumeration children = node.children(); while (children.hasMoreElements()) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement(); String nodeName = (String) child.getUserObject(); switch (match) { case BEGINNING: if (nodeName.startsWith(toFind)) return child; break; case MIDDLE: if (nodeName.contains(toFind)) return child; break; case END: if (nodeName.endsWith(toFind)) return child; break; case ENTIRE: if (nodeName.equals(toFind)) return child; break; } } return null; } public static ViewBookmarkBrowser getInstance() { return vbb; } }