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
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 *{ 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; i AbstractSourceTree 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 index null * 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; ii=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