All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fife.rsta.ac.SourceTreeNode Maven / Gradle / Ivy

/*
 * 10/09/2011
 *
 * Copyright (C) 2011 Robert Futrell
 * robert_futrell at users.sourceforge.net
 * http://fifesoft.com/rsyntaxtextarea
 *
 * This library is distributed under a modified BSD license.  See the included
 * LICENSE.md file for details.
 */
package org.fife.rsta.ac;

import java.util.*;
import java.util.regex.Pattern;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;

import org.fife.ui.autocomplete.Util;


/**
 * Base class for tree nodes in an {@link AbstractSourceTree}.  They can be
 * sorted and filtered based on user input.
 *
 * @author Robert Futrell
 * @version 1.0
 * @see AbstractSourceTree
 */
public class SourceTreeNode extends DefaultMutableTreeNode
		implements Comparable {

	private boolean sortable;
	private boolean sorted;
	private Pattern pattern;
	private List visibleChildren;
	private int sortPriority;


	/**
	 * Creates an unsorted tree node.
	 *
	 * @param userObject The user data for this tree node.
	 */
	public SourceTreeNode(Object userObject) {
		this(userObject, false);
	}


	/**
	 * Constructor.
	 *
	 * @param userObject The user data for this tree node.
	 * @param sorted Whether any child nodes added to this one should be
	 *        sorted.
	 */
	public SourceTreeNode(Object userObject, boolean sorted) {
		super(userObject);
		visibleChildren = new ArrayList<>();
		setSortable(true);
		setSorted(sorted);
	}


	/**
	 * Overridden to ensure the new child is only made visible if it is
	 * matched by the current filter.
	 *
	 * @param child The child node to add.
	 */
	@Override
	public void add(MutableTreeNode child) {
		//super.add(child);
		if(child!=null && child.getParent()==this) {
			insert(child, super.getChildCount() - 1);
		}
		else {
			insert(child, super.getChildCount());
		}
		if (sortable && sorted) {
			refreshVisibleChildren(); // TODO: Find index and add for performance
		}
	}


	/**
	 * Overridden to operate over visible children only.
	 *
	 * @return The visible children.
	 */
	@Override
	public Enumeration children() {
		return Collections.enumeration(visibleChildren);
	}


	/**
	 * Returns a clone of this tree node.  The clone will not contain any child
	 * nodes.
	 *
	 * @return The clone of this node.
	 * @see #cloneWithChildren()
	 */
	@Override
	public Object clone() {
		SourceTreeNode node = (SourceTreeNode)super.clone();
		// Not based off original, no children!
		node.visibleChildren = new ArrayList<>();
		return node;
	}


	/**
	 * Returns a clone of this tree node and all of its children.
	 *
	 * @return The clone of this node.
	 * @see #clone()
	 */
	public SourceTreeNode cloneWithChildren() {
		SourceTreeNode clone = (SourceTreeNode)clone();
		for (int i=0; iAbstractSourceTree is sorted.  Sorting is done first
	 * by priority, and nodes with equal priority are then sorted by their
	 * string representations, ignoring case.  Subclasses can override this
	 * method if they wish to do more intricate sorting.
	 *
	 * @param stn2 A tree node to compare to.
	 * @return How these tree nodes compare relative to each other.
	 */
	@Override
	public int compareTo(SourceTreeNode stn2) {
		int res = -1;
		if (stn2!=null) {
			res = getSortPriority() - stn2.getSortPriority();
			if (res==0 && ((SourceTreeNode)getParent()).isSorted()) {
				res = toString().compareToIgnoreCase(stn2.toString());
			}
		}
		return res;
	}


	/**
	 * Filters the children of this tree node based on the specified prefix.
	 *
	 * @param pattern The pattern that the child nodes must match.  If this is
	 *        null, all possible children are shown.
	 */
	protected void filter(Pattern pattern) {
		this.pattern = pattern;
		refreshVisibleChildren();
		for (int i=0; inull
	 *         if none.
	 */
	@Override
	public TreeNode getChildAfter(TreeNode child) {
		if (child==null) {
			throw new IllegalArgumentException("child cannot be null");
		}
		int index = getIndex(child);
		if (index==-1) {
			throw new IllegalArgumentException("child node not contained");
		}
		return indexnull
	 *         if none.
	 */
	@Override
	public TreeNode getChildBefore(TreeNode child) {
		if (child==null) {
			throw new IllegalArgumentException("child cannot be null");
		}
		int index = getIndex(child);
		if (index==-1) {
			throw new IllegalArgumentException("child node not contained");
		}
		return index> 0 ? getChildAt(index - 1) : null;
	}


	/**
	 * Overridden to operate over visible children only.
	 *
	 * @return The number of visible child nodes.
	 */
	@Override
	public int getChildCount() {
		return visibleChildren.size();
	}


	/**
	 * Overridden to operate over visible children only.
	 *
	 * @param child The child node.
	 * @return The index of the child, if it is visible.  If the child node is
	 *         not contained in this tree, or is simply not visible,
	 *         -1 is returned.
	 */
	@Override
	public int getIndex(TreeNode child) {
		if (child==null) {
			throw new IllegalArgumentException("child cannot be null");
		}
		for (int i=0; i i=visibleChildren.iterator(); i.hasNext();) {
					TreeNode node = i.next();
					if (node.isLeaf()) {
						String text = node.toString();
						text = Util.stripHtml(text);
						if (!pattern.matcher(text).find()) {
							i.remove();
						}
					}
				}
			}
		}
	}


	/**
	 * Sets whether this particular node's children are sortable.  Usually,
	 * only tree nodes containing only "leaves" should be sorted (for example,
	 * a "types" node).
	 *
	 * @param sortable Whether this node's children are sortable.
	 * @see #isSortable()
	 */
	public void setSortable(boolean sortable) {
		this.sortable = sortable;
	}


	/**
	 * Sets whether this tree node (and any child sortable tree nodes) are
	 * sorting their children.
	 *
	 * @param sorted Whether sorting is enabled.
	 * @see #isSorted()
	 */
	public void setSorted(boolean sorted) {
		if (sorted!=this.sorted) {
			// We must keep this state, even if we're not sortable, so that
			// we can know when to toggle the sortable state of our children.
			this.sorted = sorted;
			// This individual node may not be sortable...
			if (sortable) {
				refreshVisibleChildren();
			}
			// But its children could still be.
			for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy