/** * */ package cz.cuni.mff.peckam.java.origamist.gui.viewer.listing; import java.awt.Color; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.LinkedList; import java.util.List; import java.util.Stack; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import cz.cuni.mff.peckam.java.origamist.files.Category; import cz.cuni.mff.peckam.java.origamist.files.File; import cz.cuni.mff.peckam.java.origamist.files.Listing; import cz.cuni.mff.peckam.java.origamist.services.ServiceLocator; import cz.cuni.mff.peckam.java.origamist.services.interfaces.ConfigurationManager; /** * A JTree displaying the list of loaded files and categories. * * @author Martin Pecka */ public class ListingTree extends JTree { /** */ private static final long serialVersionUID = 7977020048548617471L; /** * The expanded nodes. A hashtable would serve better, but we workaround the unability to use hashcode() of the * changing nodes. */ protected List<TreePath> expanded = new LinkedList<TreePath>(); /** If false, do not fire TreeExpansionListeners' events. */ protected boolean fireTreeExpansionListeners = true; public ListingTree(Listing listing) { this(); setListing(listing); } public ListingTree() { setSelectionModel(new DefaultTreeSelectionModel()); getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); setRootVisible(false); setShowsRootHandles(true); setToolTipText(""); // XXX - don't delete this line, or the tooltips for items won't display :( setCellRenderer(new ListingTreeCellRenderer()); setBackground(new Color(250, 250, 242)); // addTreeSelectionListener(new ListingTreeSelectionListener()); //this is rather done in OrigamiViewer ServiceLocator.get(ConfigurationManager.class).get() .addPropertyChangeListener("diagramLocale", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { invalidate(); repaint(); } }); } /** * Set a new listing that will be displayed by this tree. * * @param listing The listing to display. */ public void setListing(Listing listing) { setModel(new DefaultTreeModel(createStructure(listing))); } /** * Create a structure of DefaultMutableTreeNodes corresponding to the given listing. * * @param listing The listing to generate the structure from. * @return The structure generated from the listing. */ protected DefaultMutableTreeNode createStructure(Listing listing) { if (listing == null) return null; Stack<DefaultMutableTreeNode> categories = new Stack<DefaultMutableTreeNode>(); DefaultMutableTreeNode root = new DefaultMutableTreeNode(listing); if (listing.getCategories() != null) { for (Category cat : listing.getCategories().getCategory()) { DefaultMutableTreeNode node = new DefaultMutableTreeNode(cat); categories.push(node); root.add(node); } } if (listing.getFiles() != null) { for (File file : listing.getFiles().getFile()) { root.add(new DefaultMutableTreeNode(file, false)); } } while (!categories.isEmpty()) { DefaultMutableTreeNode catNode = categories.pop(); Category cat = (Category) catNode.getUserObject(); if (cat.getCategories() != null) { for (Category cat1 : cat.getCategories().getCategory()) { DefaultMutableTreeNode node = new DefaultMutableTreeNode(cat1); categories.push(node); catNode.add(node); } } if (cat.getFiles() != null) { for (File file : cat.getFiles().getFile()) { catNode.add(new DefaultMutableTreeNode(file, false)); } } } return root; } @Override public String getToolTipText(MouseEvent event) { if (getRowForLocation(event.getX(), event.getY()) == -1) return null; TreePath curPath = getPathForLocation(event.getX(), event.getY()); Object comp = curPath.getLastPathComponent(); if (comp instanceof File) { FileRenderer fc = (FileRenderer) getCellRenderer().getTreeCellRendererComponent(this, comp, false, false, true, 0, false); Rectangle entryBounds = this.getPathBounds(curPath); int x = (int) (event.getX() - entryBounds.getX()); int y = (int) (event.getY() - entryBounds.getY()); MouseEvent e = new MouseEvent((Component) event.getSource(), event.getID(), event.getWhen(), event.getModifiers(), x, y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), true, event.getButton()); return fc.getToolTipText(e); } else { return super.getToolTipText(event); } } @Override public Point getToolTipLocation(MouseEvent event) { if (getRowForLocation(event.getX(), event.getY()) == -1) return super.getToolTipLocation(event); TreePath curPath = getPathForLocation(event.getX(), event.getY()); Object comp = ((DefaultMutableTreeNode) curPath.getLastPathComponent()).getUserObject(); if (comp instanceof File) { FileRenderer fc = (FileRenderer) getCellRenderer().getTreeCellRendererComponent(this, curPath.getLastPathComponent(), false, false, true, 0, false); Rectangle entryBounds = this.getPathBounds(curPath); int x = (int) (event.getX() - entryBounds.getX()); int y = (int) (event.getY() - entryBounds.getY()); MouseEvent e = new MouseEvent((Component) event.getSource(), event.getID(), event.getWhen(), event.getModifiers(), x, y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), true, event.getButton()); Point loc = fc.getToolTipLocation(e); if (loc != null) { loc.x += entryBounds.x; loc.y += entryBounds.y; return loc; } } return super.getToolTipLocation(event); } }