Package de.chris_soft.utilities.swing.tree

Source Code of de.chris_soft.utilities.swing.tree.DynamicTree

/**
* NanoDoA - File based document archive
*
* Copyright (C) 2011-2012 Christian Packenius, christian.packenius@googlemail.com
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.utilities.swing.tree;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import de.chris_soft.utilities.LogUtils;
import de.chris_soft.utilities.swing.SwingUtils;

/**
* Dynamic JTree with a possibility of single selection.
* @author Christian Packenius.
*/
public class DynamicTree extends JPanel {
  /**
   * serialVersionUID.
   */
  private static final long serialVersionUID = -1532733139607975119L;

  /**
   * Physical tree for tree displaying.
   */
  final JTree tree;

  /**
   * Tree model.
   */
  public final DefaultTreeModel treeModel;

  /**
   * Root node of this tree.
   */
  public final DefaultMutableTreeNode rootNode;

  final Map<Object, DefaultMutableTreeNode> obj2node = new HashMap<Object, DefaultMutableTreeNode>();

  /**
   * User object for root node.
   */
  public final Object rootObject;

  /**
   * Constructor.
   * @param rootObject Title of the root.
   */
  public DynamicTree(Object rootObject) {
    super(new BorderLayout());
    this.rootObject = rootObject;
    rootNode = new DefaultMutableTreeNode(rootObject);
    obj2node.put(rootObject, rootNode);
    treeModel = new DefaultTreeModel(rootNode);
    tree = createTreeComposite();
    DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
    renderer.setBackgroundNonSelectionColor(getBackground());
    JScrollPane scrollPane = new JScrollPane(tree);
    add(scrollPane);
  }

  private JTree createTreeComposite() {
    JTree tree = new JTree(treeModel);
    tree.setBackground(getBackground());
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setShowsRootHandles(true);
    tree.setExpandsSelectedPaths(true);
    tree.setRootVisible(true);
    return tree;
  }

  /**
   * Removes all nodes from tree (except root node).
   */
  public void removeAllNodes() {
    removeAllChildren(rootNode);
    treeModel.reload();
  }

  /**
   * Removes the current node from tree if possible.
   */
  public void removeCurrentNode() {
    TreePath selection = tree.getSelectionPath();
    if (selection != null) {
      DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) selection.getLastPathComponent();
      MutableTreeNode parent = (MutableTreeNode) currentNode.getParent();
      if (parent != null) {
        treeModel.removeNodeFromParent(currentNode);
      }
    }
  }

  /**
   * Removes a node from the tree.
   * @param obj Object of the node to remove.
   */
  public void removeNode(Object obj) {
    DefaultMutableTreeNode node = obj2node.get(obj);
    if (node != null) {
      treeModel.removeNodeFromParent(node);
    }
  }

  /**
   * Refreshed a node on the tree.
   * @param obj Object of the node to refresh.
   */
  public void refreshNode(Object obj) {
    DefaultMutableTreeNode node = obj2node.get(obj);
    if (node != null) {
      treeModel.reload(node);
    }
  }

  /**
   * Adds a child node to a parent node.
   * @param parentObject Parent node. May be <i>null</i> for root as parent.
   * @param childObject Child object with data for child node.
   */
  public void addNode(final Object parentObject, final Object childObject) {
    Runnable doRun = new Runnable() {
      @Override
      public void run() {
        DefaultMutableTreeNode parentNode = getParentNodeFromParentObject(parentObject);
        DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(childObject);
        obj2node.put(childObject, childNode);
        int childIndex = getNewChildIndex(childObject, parentNode);
        treeModel.insertNodeInto(childNode, parentNode, childIndex);
        if (parentObject == null) {
          tree.expandPath(new TreePath(new Object[] {rootNode}));
        }
      }

      private DefaultMutableTreeNode getParentNodeFromParentObject(final Object parentObject) {
        DefaultMutableTreeNode parentNode;
        if (parentObject == null) {
          parentNode = rootNode;
        }
        else {
          parentNode = obj2node.get(parentObject);
        }
        return parentNode;
      }

      private int getNewChildIndex(final Object childObject, DefaultMutableTreeNode parentNode) {
        int childIndex = parentNode.getChildCount();
        for (int i = 0; i < childIndex; i++) {
          TreeNode child = parentNode.getChildAt(i);
          if (child.toString().compareToIgnoreCase(childObject.toString()) > 0) {
            childIndex = i;
          }
        }
        return childIndex;
      }
    };
    try {
      SwingUtils.runInGuiNow(doRun);
    } catch (Exception exception) {
      LogUtils.log(exception);
    }
  }

  /**
   * Returns the object of the current node.
   * @return Objekt of the current node or <i>null</i> if there is no current node (or if the root node is selected).
   */
  public Object getCurrentNode() {
    TreePath selection = tree.getSelectionPath();
    if (selection != null) {
      DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) selection.getLastPathComponent();
      if (currentNode != null) {
        return currentNode.getUserObject();
      }
    }
    return null;
  }

  /**
   * Sets the current node.
   * @param obj Object of the node to set to.
   * @return <i>true</i> if the node is set.
   */
  public boolean setCurrentNode(Object obj) {
    DefaultMutableTreeNode node = obj2node.get(obj);
    if (node != null) {
      tree.setSelectionPath(new TreePath(node.getPath()));
      tree.scrollPathToVisible(new TreePath(node.getPath()));
      return true;
    }
    return false;
  }

  /**
   * Tells if there is a node with the given object.
   * @param obj Object.
   * @return <i>true</i> if there is a node with this object.
   */
  public boolean hasNode(Object obj) {
    return obj2node.containsKey(obj);
  }

  /**
   * Returns one by one all node objects.
   * @param obj Object of the previous node (or null for getting root object).
   * @return Next object or root object if <i>null</i>.
   */
  public Object getNextNode(Object obj) {
    if (obj == null) {
      return rootNode.getUserObject();
    }
    DefaultMutableTreeNode node = obj2node.get(obj);
    DefaultMutableTreeNode nextNode = node.getNextNode();
    if (nextNode == null) {
      return null;
    }
    return nextNode.getUserObject();
  }

  /**
   * Removes all children of a tree element.
   * @param parentNode Parent node of the children to remove.
   */
  public void removeAllChildren(DefaultMutableTreeNode parentNode) {
    innerChildRemoval(parentNode);
    parentNode.removeAllChildren();
  }

  private void innerChildRemoval(DefaultMutableTreeNode parentNode) {
    Enumeration<?> children = parentNode.children();
    while (children.hasMoreElements()) {
      Object oChild = children.nextElement();
      DefaultMutableTreeNode nChild = (DefaultMutableTreeNode) oChild;
      innerChildRemoval(nChild);
    }
    obj2node.remove(parentNode.getUserObject());
  }

  /**
   * Adds a tree selection listener to the tree.
   * @param listener Tree selection listener.
   */
  public void addTreeSelectionListener(TreeSelectionListener listener) {
    tree.addTreeSelectionListener(listener);
  }

  /**
   * Adds a tree expansion listener to the tree.
   * @param listener Tree expansion listener.
   */
  public void addTreeExpansionListener(TreeExpansionListener listener) {
    tree.addTreeExpansionListener(listener);
  }

  /**
   * Returns a list of all user objects of the corresponding parent tree node.
   * @param parentUserObject User object of the corresponding parent tree node.
   * @return List of all childrens user objects.
   */
  public List<Object> getChildUserObjects(Object parentUserObject) {
    DefaultMutableTreeNode parent = obj2node.get(parentUserObject);
    List<Object> list = new ArrayList<Object>();
    if (parent != null) {
      Enumeration<?> children = parent.children();
      while (children.hasMoreElements()) {
        DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
        list.add(child.getUserObject());
      }
    }
    return list;
  }

  /**
   * Returns the JTree component.
   * @return JTree component of this dynamic tree.
   */
  public JTree getTree() {
    return tree;
  }

  /**
   * Set a child node of the current node with the given user object.
   * @param userObject User object of the child node.
   */
  public void setCurrentChild(Object userObject) {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getSelectionPath().getLastPathComponent();
    Enumeration<?> children = node.children();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
      Object childObject = child.getUserObject();
      if (childObject.equals(userObject)) {
        setCurrentNode(childObject);
      }
    }
  }

  /**
   * Removes the last node of the given path of user objects.
   * @param objects User Objects, starting with root object (not <i>null</i>!).
   */
  public void removeUserObjectPath(Object[] objects) {
    DefaultMutableTreeNode node = rootNode;
    for (int i = 1; i < objects.length && node != null; i++) {
      Enumeration<?> en = node.children();
      boolean found = false;
      while (en.hasMoreElements() && !found) {
        DefaultMutableTreeNode child = (DefaultMutableTreeNode) en.nextElement();
        if (child.getUserObject().equals(objects[i])) {
          node = child;
          found = true;
        }
      }
      if (!found) {
        return;
      }
    }
    treeModel.removeNodeFromParent(node);
  }
}
TOP

Related Classes of de.chris_soft.utilities.swing.tree.DynamicTree

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.