/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2008 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.agents.metadata.browser; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.swing.Icon; import javax.swing.tree.DefaultMutableTreeNode; import org.openmicroscopy.shoola.agents.util.EditorUtil; import omero.gateway.model.DatasetData; import omero.gateway.model.ExperimenterData; import omero.gateway.model.ImageData; import omero.gateway.model.PlateData; import omero.gateway.model.ProjectData; import omero.gateway.model.ScreenData; import omero.gateway.model.TagAnnotationData; /** * Represents a component in the composite structure used to visualize an * image hierarchy. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME3.0 */ public abstract class TreeBrowserDisplay extends DefaultMutableTreeNode { /** * Back pointer to the parent node or <code>null</code> if this is the root. */ private TreeBrowserDisplay parentDisplay; /** * The set of nodes that have been added to this node. * Will always be empty for a leaf node. */ protected Set<TreeBrowserDisplay> childrenDisplay; /** Indicates if the node is expanded or not. */ private boolean expanded; /** The default icon associated to this node. */ private Icon defaultIcon; /** Flag indicating that the node is for a menu. */ private boolean menuNode; /** * Returns the name of the node. * * @return See above. */ private String getNodeName() { Object obj = getUserObject(); if (obj instanceof ProjectData) return ((ProjectData) obj).getName(); else if (obj instanceof DatasetData) return ((DatasetData) obj).getName(); else if (obj instanceof ImageData) return ((ImageData) obj).getName(); else if (obj instanceof ExperimenterData) { ExperimenterData exp = (ExperimenterData) obj; return EditorUtil.formatExperimenter(exp); } else if (obj instanceof ScreenData) return ((ScreenData) obj).getName(); else if (obj instanceof PlateData) return ((PlateData) obj).getName(); else if (obj instanceof TagAnnotationData) return ((TagAnnotationData) obj).getTagValue(); else if (obj instanceof String) return (String) obj; return ""; } /** * Constructor used by subclasses. * * @param hierarchyObject The original object in the image hierarchy which * is visualized by this node. * Never pass <code>null</code>. */ protected TreeBrowserDisplay(Object hierarchyObject) { this(hierarchyObject, null, false); } /** * Constructor used by subclasses. * * @param hierarchyObject The original object in the image hierarchy which * is visualized by this node. * Never pass <code>null</code>. * @param defaultIcon The default icon associated to this node. * @param menuNode Pass <code>true</code> to indicate that the node * is a menu node, <code>false</code> otherwise. */ protected TreeBrowserDisplay(Object hierarchyObject, Icon defaultIcon, boolean menuNode) { super(); if (hierarchyObject == null) throw new NullPointerException("No hierarchy object."); setUserObject(hierarchyObject); childrenDisplay = new HashSet<TreeBrowserDisplay>(); this.defaultIcon = defaultIcon; this.menuNode = menuNode; } /** * Returns <code>true</code> to indicate that the node is part of a * menu, <code>false</code> otherwise. * * @return See above. */ public boolean isMenuNode() { return menuNode; } /** * Returns the default icon associated to this node. * * @return See above. */ public Icon getDefaultIcon() { return defaultIcon; } /** * Returns <code>true</code> if the nodes contain children, * <code>false</code> otherwise. * * @return See above. */ public boolean hasChildrenDisplay() { return (childrenDisplay.size() != 0); } /** * Returns the parent node to this node in the visualization tree. * * @return The parent node or <code>null</code> if this node has no parent. * This can happen if this node hasn't been linked yet or if it's * the root node. */ public TreeBrowserDisplay getParentDisplay() { return parentDisplay; } /** * Returns all the child nodes to this node in the visualization tree. * Note that, although never <code>null</code>, the returned set may be * empty. In particular, this is always the case for a leaf node — * that is an {@link TreeBrowserNode}. * * @return A <i>read-only</i> set containing all the child nodes. */ public Set getChildrenDisplay() { return Collections.unmodifiableSet(childrenDisplay); } /** * Adds a node to the visualization tree as a child of this node. * The <code>child</code>'s parent is set to be this node. If <code> * child</code> is currently a child to another node <code>n</code>, * then <code>child</code> is first * {@link #removeChildDisplay(TreeBrowserDisplay) removed} from <code>n</code> * and then added to this node. * * @param child The node to add. Mustn't be <code>null</code>. * @see DefaultMutableTreeNode */ public void addChildDisplay(TreeBrowserDisplay child) { if (child == null) throw new NullPointerException("No child."); if (childrenDisplay.contains(child)) return; if (child.parentDisplay != null) //Was the child of another node. child.parentDisplay.removeChildDisplay(child); child.parentDisplay = this; childrenDisplay.add(child); } /** * Removes the specified <code>child</code> node. * If <code>child</code> is not among the children of this node, no action * is taken. Otherwise, it is removed from the children set and orphaned. * That is, its parent (which is this node) is set to <code>null</code>. * * @param child The node to remove. Mustn't be <code>null</code>. */ public void removeChildDisplay(TreeBrowserDisplay child) { if (child == null) throw new NullPointerException("No child."); if (childrenDisplay.contains(child)) { //NOTE: parentDisplay != null b/c child has been added through //the add method. child.parentDisplay.childrenDisplay.remove(child); child.parentDisplay = null; } } /** Removes all <code>children</code> nodes from the children set. */ public void removeAllChildrenDisplay() { Iterator i = childrenDisplay.iterator(); Set<Object> toRemove = new HashSet<Object>(childrenDisplay.size()); while (i.hasNext()) toRemove.add(i.next()); i = toRemove.iterator(); while (i.hasNext()) removeChildDisplay((TreeBrowserDisplay) i.next()); } /** * Removes the children contained in the passed collection. * * @param children The collection to handle. */ public void removeChildrenDisplay(List children) { if (children == null) return; Iterator i = children.iterator(); while (i.hasNext()) removeChildDisplay((TreeBrowserDisplay) i.next()); } /** * Returns <code>true</code> is the node is expanded, * <code>false</code> otherwise. * * @return See above */ public boolean isExpanded() { return expanded; } /** * Sets to <code>true</code> if the node is expanded, * <code>false</code> otherwise. * * @param expanded The value to set. */ public void setExpanded(boolean expanded) { this.expanded = expanded; } /** * Overridden to return the name of the hierarchy object. * @see Object#toString() */ public String toString() { return getNodeName(); } /** * Made final to ensure objects are compared by reference so that the * {@link #addChildDisplay(TreeBrowserDisplay) addChildDisplay} and * {@link #removeChildDisplay(TreeBrowserDisplay) removeChildDisplay} methods * will work fine. * @see Object#equals(Object) */ public final boolean equals(Object x) { return (this == x); } /** * Implemented by subclasses to call the right version of the <code>visit * </code> method on the specified <code>visitor</code>. * This method is called during * the nodes iteration. Subclasses will just call the <code>visit</code> * method passing a reference to <code>this</code>. * * @param visitor The visitor. Will never be <code>null</code>. */ protected abstract void doAccept(TreeBrowserVisitor visitor); /** * Tells if the children of this node were requested. * * @return <code>true</code> if the children were requested, * <code>false</code> otherwise. */ public abstract boolean isChildrenLoaded(); /** * Indicates if the children were requested for this node. * * @param childrenLoaded The value to set. */ public abstract void setChildrenLoaded(Boolean childrenLoaded); }