Ejemplo n.º 1
0
    /**
     * Creates a new node to represent <code>userObject</code>. This does NOT check to ensure there
     * isn't already a child node to manage <code>userObject</code>.
     */
    protected FHTreeStateNode createChildFor(Object userObject) {
      int newChildIndex = treeModel.getIndexOfChild(getUserObject(), userObject);

      if (newChildIndex < 0) return null;

      FHTreeStateNode aNode;
      FHTreeStateNode child = createNodeForValue(userObject, newChildIndex);
      int childRow;

      if (isVisible()) {
        childRow = getRowToModelIndex(newChildIndex);
      } else {
        childRow = -1;
      }
      child.row = childRow;
      for (int counter = 0, maxCounter = getChildCount(); counter < maxCounter; counter++) {
        aNode = (FHTreeStateNode) getChildAt(counter);
        if (aNode.childIndex > newChildIndex) {
          insert(child, counter);
          return child;
        }
      }
      add(child);
      return child;
    }
Ejemplo n.º 2
0
  /** Sent to completely rebuild the visible tree. All nodes are collapsed. */
  private void rebuild(boolean clearSelection) {
    Object rootUO;

    treePathMapping.clear();
    if (treeModel != null && (rootUO = treeModel.getRoot()) != null) {
      root = createNodeForValue(rootUO, 0);
      root.path = new TreePath(rootUO);
      addMapping(root);
      if (isRootVisible()) {
        rowCount = 1;
        root.row = 0;
      } else {
        rowCount = 0;
        root.row = -1;
      }
      root.expand();
    } else {
      root = null;
      rowCount = 0;
    }
    if (clearSelection && treeSelectionModel != null) {
      treeSelectionModel.clearSelection();
    }
    this.visibleNodesChanged();
  }
Ejemplo n.º 3
0
    /**
     * Updates <code>nextIndex</code> returning false if it is beyond the number of children of
     * parent.
     */
    protected boolean updateNextIndex() {
      // nextIndex == -1 identifies receiver, make sure is expanded
      // before descend.
      if (nextIndex == -1 && !parent.isExpanded()) {
        return false;
      }

      // Check that it can have kids
      if (childCount == 0) {
        return false;
      }
      // Make sure next index not beyond child count.
      else if (++nextIndex >= childCount) {
        return false;
      }

      FHTreeStateNode child = parent.getChildAtModelIndex(nextIndex);

      if (child != null && child.isExpanded()) {
        parent = child;
        nextIndex = -1;
        childCount = treeModel.getChildCount(child.getUserObject());
      }
      return true;
    }
Ejemplo n.º 4
0
  /** Returns true if the value identified by row is currently expanded. */
  public boolean isExpanded(TreePath path) {
    if (path != null) {
      FHTreeStateNode lastNode = getNodeForPath(path, true, false);

      return (lastNode != null && lastNode.isExpanded());
    }
    return false;
  }
Ejemplo n.º 5
0
    protected TreePath getPath() {
      if (node == null) return null;

      if (isNodeParentNode)
        return node.getTreePath()
            .pathByAddingChild(treeModel.getChild(node.getUserObject(), childIndex));
      return node.path;
    }
Ejemplo n.º 6
0
    /** Messaged to set the user object. This resets the path. */
    public void setUserObject(Object o) {
      super.setUserObject(o);
      if (path != null) {
        FHTreeStateNode parent = (FHTreeStateNode) getParent();

        if (parent != null) resetChildrenPaths(parent.getTreePath());
        else resetChildrenPaths(null);
      }
    }
Ejemplo n.º 7
0
    /**
     * Messaged when the node has expanded. This updates all of the receivers children rows, as well
     * as the total row count.
     */
    protected void didExpand() {
      int nextRow = setRowAndChildren(row);
      FHTreeStateNode parent = (FHTreeStateNode) getParent();
      int childRowCount = nextRow - row - 1;

      if (parent != null) {
        parent.adjustRowBy(childRowCount, parent.getIndex(this) + 1);
      }
      adjustRowCountBy(childRowCount);
    }
Ejemplo n.º 8
0
  /**
   * Invoked after a node (or a set of siblings) has changed in some way. The node(s) have not
   * changed locations in the tree or altered their children arrays, but other attributes have
   * changed and may affect presentation. Example: the name of a file has changed, but it is in the
   * same location in the file system.
   *
   * <p>e.path() returns the path the parent of the changed node(s).
   *
   * <p>e.childIndices() returns the index(es) of the changed node(s).
   */
  public void treeNodesChanged(TreeModelEvent e) {
    if (e != null) {
      int changedIndexs[];
      FHTreeStateNode changedParent =
          getNodeForPath(SwingUtilities2.getTreePath(e, getModel()), false, false);
      int maxCounter;

      changedIndexs = e.getChildIndices();
      /* Only need to update the children if the node has been
      expanded once. */
      // PENDING(scott): make sure childIndexs is sorted!
      if (changedParent != null) {
        if (changedIndexs != null && (maxCounter = changedIndexs.length) > 0) {
          Object parentValue = changedParent.getUserObject();

          for (int counter = 0; counter < maxCounter; counter++) {
            FHTreeStateNode child = changedParent.getChildAtModelIndex(changedIndexs[counter]);

            if (child != null) {
              child.setUserObject(treeModel.getChild(parentValue, changedIndexs[counter]));
            }
          }
          if (changedParent.isVisible() && changedParent.isExpanded()) visibleNodesChanged();
        }
        // Null for root indicates it changed.
        else if (changedParent == root && changedParent.isVisible() && changedParent.isExpanded()) {
          visibleNodesChanged();
        }
      }
    }
  }
Ejemplo n.º 9
0
    /**
     * Returns the number of children that are expanded to <code>stopIndex</code>. This does not
     * include the number of children that the child at <code>stopIndex</code> might have.
     */
    protected int getNumExpandedChildrenTo(int stopIndex) {
      FHTreeStateNode aChild;
      int retCount = stopIndex;

      for (int counter = 0, maxCounter = getChildCount(); counter < maxCounter; counter++) {
        aChild = (FHTreeStateNode) getChildAt(counter);
        if (aChild.childIndex >= stopIndex) return retCount;
        else {
          retCount += aChild.getTotalChildCount();
        }
      }
      return retCount;
    }
Ejemplo n.º 10
0
    /**
     * Asks all the children of the receiver for their totalChildCount and returns this value (plus
     * stopIndex).
     */
    protected int getCountTo(int stopIndex) {
      FHTreeStateNode aChild;
      int retCount = stopIndex + 1;

      for (int counter = 0, maxCounter = getChildCount(); counter < maxCounter; counter++) {
        aChild = (FHTreeStateNode) getChildAt(counter);
        if (aChild.childIndex >= stopIndex) counter = maxCounter;
        else retCount += aChild.getTotalChildCount();
      }
      if (parent != null) return retCount + ((FHTreeStateNode) getParent()).getCountTo(childIndex);
      if (!isRootVisible()) return (retCount - 1);
      return retCount;
    }
Ejemplo n.º 11
0
  /**
   * Invoked after nodes have been removed from the tree. Note that if a subtree is removed from the
   * tree, this method may only be invoked once for the root of the removed subtree, not once for
   * each individual set of siblings removed.
   *
   * <p>e.path() returns the former parent of the deleted nodes.
   *
   * <p>e.childIndices() returns the indices the nodes had before they were deleted in ascending
   * order.
   */
  public void treeNodesRemoved(TreeModelEvent e) {
    if (e != null) {
      int changedIndexs[];
      int maxCounter;
      TreePath parentPath = SwingUtilities2.getTreePath(e, getModel());
      FHTreeStateNode changedParentNode = getNodeForPath(parentPath, false, false);

      changedIndexs = e.getChildIndices();
      // PENDING(scott): make sure that changedIndexs are sorted in
      // ascending order.
      if (changedParentNode != null
          && changedIndexs != null
          && (maxCounter = changedIndexs.length) > 0) {
        Object[] children = e.getChildren();
        boolean isVisible = (changedParentNode.isVisible() && changedParentNode.isExpanded());

        for (int counter = maxCounter - 1; counter >= 0; counter--) {
          changedParentNode.removeChildAtModelIndex(changedIndexs[counter], isVisible);
        }
        if (isVisible) {
          if (treeSelectionModel != null) treeSelectionModel.resetRowSelection();
          if (treeModel.getChildCount(changedParentNode.getUserObject()) == 0
              && changedParentNode.isLeaf()) {
            // Node has become a leaf, collapse it.
            changedParentNode.collapse(false);
          }
          visibleNodesChanged();
        } else if (changedParentNode.isVisible()) visibleNodesChanged();
      }
    }
  }
Ejemplo n.º 12
0
    /**
     * Adjusts this node, its child, and its parent starting at an index of <code>index</code> index
     * is the index of the child to start adjusting from, which is not necessarily the model index.
     */
    protected void adjustRowBy(int amount, int startIndex) {
      // Could check isVisible, but probably isn't worth it.
      if (isExpanded) {
        // children following startIndex.
        for (int counter = getChildCount() - 1; counter >= startIndex; counter--)
          ((FHTreeStateNode) getChildAt(counter)).adjustRowBy(amount);
      }
      // Parent
      FHTreeStateNode parent = (FHTreeStateNode) getParent();

      if (parent != null) {
        parent.adjustRowBy(amount, parent.getIndex(this) + 1);
      }
    }
Ejemplo n.º 13
0
 /**
  * Determines whether or not the root node from the TreeModel is visible.
  *
  * @param rootVisible true if the root node of the tree is to be displayed
  * @see #rootVisible
  */
 public void setRootVisible(boolean rootVisible) {
   if (isRootVisible() != rootVisible) {
     super.setRootVisible(rootVisible);
     if (root != null) {
       if (rootVisible) {
         rowCount++;
         root.adjustRowBy(1);
       } else {
         rowCount--;
         root.adjustRowBy(-1);
       }
       visibleNodesChanged();
     }
   }
 }
Ejemplo n.º 14
0
  /**
   * Messages getTreeNodeForPage(path, onlyIfVisible, shouldCreate, path.length) as long as path is
   * non-null and the length is {@literal >} 0. Otherwise returns null.
   */
  private FHTreeStateNode getNodeForPath(
      TreePath path, boolean onlyIfVisible, boolean shouldCreate) {
    if (path != null) {
      FHTreeStateNode node;

      node = getMapping(path);
      if (node != null) {
        if (onlyIfVisible && !node.isVisible()) return null;
        return node;
      }
      if (onlyIfVisible) return null;

      // Check all the parent paths, until a match is found.
      Stack<TreePath> paths;

      if (tempStacks.size() == 0) {
        paths = new Stack<TreePath>();
      } else {
        paths = tempStacks.pop();
      }

      try {
        paths.push(path);
        path = path.getParentPath();
        node = null;
        while (path != null) {
          node = getMapping(path);
          if (node != null) {
            // Found a match, create entries for all paths in
            // paths.
            while (node != null && paths.size() > 0) {
              path = paths.pop();
              node = node.createChildFor(path.getLastPathComponent());
            }
            return node;
          }
          paths.push(path);
          path = path.getParentPath();
        }
      } finally {
        paths.removeAllElements();
        tempStacks.push(paths);
      }
      // If we get here it means they share a different root!
      return null;
    }
    return null;
  }
Ejemplo n.º 15
0
  /** Marks the path <code>path</code> expanded state to <code>isExpanded</code>. */
  public void setExpandedState(TreePath path, boolean isExpanded) {
    if (isExpanded) ensurePathIsExpanded(path, true);
    else if (path != null) {
      TreePath parentPath = path.getParentPath();

      // YECK! Make the parent expanded.
      if (parentPath != null) {
        FHTreeStateNode parentNode = getNodeForPath(parentPath, false, true);
        if (parentNode != null) parentNode.makeVisible();
      }
      // And collapse the child.
      FHTreeStateNode childNode = getNodeForPath(path, true, false);

      if (childNode != null) childNode.collapse(true);
    }
  }
Ejemplo n.º 16
0
  /**
   * Returns the row that the last item identified in path is visible at. Will return -1 if any of
   * the elements in path are not currently visible.
   */
  public int getRowForPath(TreePath path) {
    if (path == null || root == null) return -1;

    FHTreeStateNode node = getNodeForPath(path, true, false);

    if (node != null) return node.getRow();

    TreePath parentPath = path.getParentPath();

    node = getNodeForPath(parentPath, true, false);
    if (node != null && node.isExpanded()) {
      return node.getRowToModelIndex(
          treeModel.getIndexOfChild(
              parentPath.getLastPathComponent(), path.getLastPathComponent()));
    }
    return -1;
  }
Ejemplo n.º 17
0
 /** Returns the path for passed in row. If row is not visible null is returned. */
 public TreePath getPathForRow(int row) {
   if (row >= 0 && row < getRowCount()) {
     if (root.getPathForRow(row, getRowCount(), info)) {
       return info.getPath();
     }
   }
   return null;
 }
Ejemplo n.º 18
0
  /**
   * Returns the bounds for the given node. If <code>childIndex</code> is -1, the bounds of <code>
   * parent</code> are returned, otherwise the bounds of the node at <code>childIndex</code> are
   * returned.
   */
  private Rectangle getBounds(FHTreeStateNode parent, int childIndex, Rectangle placeIn) {
    boolean expanded;
    int level;
    int row;
    Object value;

    if (childIndex == -1) {
      // Getting bounds for parent
      row = parent.getRow();
      value = parent.getUserObject();
      expanded = parent.isExpanded();
      level = parent.getLevel();
    } else {
      row = parent.getRowToModelIndex(childIndex);
      value = treeModel.getChild(parent.getUserObject(), childIndex);
      expanded = false;
      level = parent.getLevel() + 1;
    }

    Rectangle bounds = getNodeDimensions(value, row, level, expanded, boundsBuffer);
    // No node dimensions, bail.
    if (bounds == null) return null;

    if (placeIn == null) placeIn = new Rectangle();

    placeIn.x = bounds.x;
    placeIn.height = getRowHeight();
    placeIn.y = row * placeIn.height;
    placeIn.width = bounds.width;
    return placeIn;
  }
Ejemplo n.º 19
0
    /**
     * Finds the next valid parent, this should be called when nextIndex is beyond the number of
     * children of the current parent.
     */
    protected boolean findNextValidParent() {
      if (parent == root) {
        // mark as invalid!
        parent = null;
        return false;
      }
      while (parent != null) {
        FHTreeStateNode newParent = (FHTreeStateNode) parent.getParent();

        if (newParent != null) {
          nextIndex = parent.childIndex;
          parent = newParent;
          childCount = treeModel.getChildCount(parent.getUserObject());
          if (updateNextIndex()) return true;
        } else parent = null;
      }
      return false;
    }
Ejemplo n.º 20
0
    /**
     * Removes the child at <code>modelIndex</code>. <code>isChildVisible</code> should be true if
     * the receiver is visible and expanded.
     */
    protected void removeChildAtModelIndex(int modelIndex, boolean isChildVisible) {
      FHTreeStateNode childNode = getChildAtModelIndex(modelIndex);

      if (childNode != null) {
        int row = childNode.getRow();
        int index = getIndex(childNode);

        childNode.collapse(false);
        remove(index);
        adjustChildIndexs(index, -1);
        childCount--;
        if (isChildVisible) {
          // Adjust the rows.
          resetChildrenRowsFrom(row, index, modelIndex);
        }
      } else {
        int maxCounter = getChildCount();
        FHTreeStateNode aChild;

        for (int counter = 0; counter < maxCounter; counter++) {
          aChild = (FHTreeStateNode) getChildAt(counter);
          if (aChild.childIndex >= modelIndex) {
            if (isChildVisible) {
              adjustRowBy(-1, counter);
              adjustRowCountBy(-1);
            }
            // Since matched and children are always sorted by
            // index, no need to continue testing with the
            // above.
            for (; counter < maxCounter; counter++)
              ((FHTreeStateNode) getChildAt(counter)).childIndex--;
            childCount--;
            return;
          }
        }
        // No children to adjust, but it was a child, so we still need
        // to adjust nodes after this one.
        if (isChildVisible) {
          adjustRowBy(-1, maxCounter);
          adjustRowCountBy(-1);
        }
        childCount--;
      }
    }
Ejemplo n.º 21
0
  /**
   * Returns a rectangle giving the bounds needed to draw path.
   *
   * @param path a TreePath specifying a node
   * @param placeIn a Rectangle object giving the available space
   * @return a Rectangle object specifying the space to be used
   */
  public Rectangle getBounds(TreePath path, Rectangle placeIn) {
    if (path == null) return null;

    FHTreeStateNode node = getNodeForPath(path, true, false);

    if (node != null) return getBounds(node, -1, placeIn);

    // node hasn't been created yet.
    TreePath parentPath = path.getParentPath();

    node = getNodeForPath(parentPath, true, false);
    if (node != null && node.isExpanded()) {
      int childIndex =
          treeModel.getIndexOfChild(parentPath.getLastPathComponent(), path.getLastPathComponent());

      if (childIndex != -1) return getBounds(node, childIndex, placeIn);
    }
    return null;
  }
Ejemplo n.º 22
0
  /**
   * Ensures that all the path components in path are expanded, accept for the last component which
   * will only be expanded if expandLast is true. Returns true if succesful in finding the path.
   */
  private boolean ensurePathIsExpanded(TreePath aPath, boolean expandLast) {
    if (aPath != null) {
      // Make sure the last entry isn't a leaf.
      if (treeModel.isLeaf(aPath.getLastPathComponent())) {
        aPath = aPath.getParentPath();
        expandLast = true;
      }
      if (aPath != null) {
        FHTreeStateNode lastNode = getNodeForPath(aPath, false, true);

        if (lastNode != null) {
          lastNode.makeVisible();
          if (expandLast) lastNode.expand();
          return true;
        }
      }
    }
    return false;
  }
Ejemplo n.º 23
0
  /**
   * Returns an Enumerator that increments over the visible paths starting at the passed in
   * location. The ordering of the enumeration is based on how the paths are displayed.
   */
  public Enumeration<TreePath> getVisiblePathsFrom(TreePath path) {
    if (path == null) return null;

    FHTreeStateNode node = getNodeForPath(path, true, false);

    if (node != null) {
      return new VisibleFHTreeStateNodeEnumeration(node);
    }
    TreePath parentPath = path.getParentPath();

    node = getNodeForPath(parentPath, true, false);
    if (node != null && node.isExpanded()) {
      return new VisibleFHTreeStateNodeEnumeration(
          node,
          treeModel.getIndexOfChild(
              parentPath.getLastPathComponent(), path.getLastPathComponent()));
    }
    return null;
  }
Ejemplo n.º 24
0
    /**
     * Adds newChild to this nodes children at the appropriate location. The location is determined
     * from the childIndex of newChild.
     */
    protected void addNode(FHTreeStateNode newChild) {
      boolean added = false;
      int childIndex = newChild.getChildIndex();

      for (int counter = 0, maxCounter = getChildCount(); counter < maxCounter; counter++) {
        if (((FHTreeStateNode) getChildAt(counter)).getChildIndex() > childIndex) {
          added = true;
          insert(newChild, counter);
          counter = maxCounter;
        }
      }
      if (!added) add(newChild);
    }
Ejemplo n.º 25
0
    /**
     * Returns the number of children in the receiver by descending all expanded nodes and messaging
     * them with getTotalChildCount.
     */
    public int getTotalChildCount() {
      if (isExpanded()) {
        FHTreeStateNode parent = (FHTreeStateNode) getParent();
        int pIndex;

        if (parent != null && (pIndex = parent.getIndex(this)) + 1 < parent.getChildCount()) {
          // This node has a created sibling, to calc total
          // child count directly from that!
          FHTreeStateNode nextSibling = (FHTreeStateNode) parent.getChildAt(pIndex + 1);

          return nextSibling.row - row - (nextSibling.childIndex - childIndex);
        } else {
          int retCount = childCount;

          for (int counter = getChildCount() - 1; counter >= 0; counter--) {
            retCount += ((FHTreeStateNode) getChildAt(counter)).getTotalChildCount();
          }
          return retCount;
        }
      }
      return 0;
    }
Ejemplo n.º 26
0
    /**
     * Sets the receivers row to <code>nextRow</code> and recursively updates all the children of
     * the receivers rows. The index the next row is to be placed as is returned.
     */
    protected int setRowAndChildren(int nextRow) {
      row = nextRow;

      if (!isExpanded()) return row + 1;

      int lastRow = row + 1;
      int lastModelIndex = 0;
      FHTreeStateNode child;
      int maxCounter = getChildCount();

      for (int counter = 0; counter < maxCounter; counter++) {
        child = (FHTreeStateNode) getChildAt(counter);
        lastRow += (child.childIndex - lastModelIndex);
        lastModelIndex = child.childIndex + 1;
        if (child.isExpanded) {
          lastRow = child.setRowAndChildren(lastRow);
        } else {
          child.row = lastRow++;
        }
      }
      return lastRow + childCount - lastModelIndex;
    }
Ejemplo n.º 27
0
  /**
   * Invoked after nodes have been inserted into the tree.
   *
   * <p>e.path() returns the parent of the new nodes
   *
   * <p>e.childIndices() returns the indices of the new nodes in ascending order.
   */
  public void treeNodesInserted(TreeModelEvent e) {
    if (e != null) {
      int changedIndexs[];
      FHTreeStateNode changedParent =
          getNodeForPath(SwingUtilities2.getTreePath(e, getModel()), false, false);
      int maxCounter;

      changedIndexs = e.getChildIndices();
      /* Only need to update the children if the node has been
      expanded once. */
      // PENDING(scott): make sure childIndexs is sorted!
      if (changedParent != null
          && changedIndexs != null
          && (maxCounter = changedIndexs.length) > 0) {
        boolean isVisible = (changedParent.isVisible() && changedParent.isExpanded());

        for (int counter = 0; counter < maxCounter; counter++) {
          changedParent.childInsertedAtModelIndex(changedIndexs[counter], isVisible);
        }
        if (isVisible && treeSelectionModel != null) treeSelectionModel.resetRowSelection();
        if (changedParent.isVisible()) this.visibleNodesChanged();
      }
    }
  }
Ejemplo n.º 28
0
    // This can be rather expensive, but is needed for the collapse
    // case this is resulting from a remove (although I could fix
    // that by having instances of FHTreeStateNode hold a ref to
    // the number of children). I prefer this though, making determing
    // the row of a particular node fast is very nice!
    protected void resetChildrenRowsFrom(int newRow, int childIndex, int modelIndex) {
      int lastRow = newRow;
      int lastModelIndex = modelIndex;
      FHTreeStateNode node;
      int maxCounter = getChildCount();

      for (int counter = childIndex; counter < maxCounter; counter++) {
        node = (FHTreeStateNode) getChildAt(counter);
        lastRow += (node.childIndex - lastModelIndex);
        lastModelIndex = node.childIndex + 1;
        if (node.isExpanded) {
          lastRow = node.setRowAndChildren(lastRow);
        } else {
          node.row = lastRow++;
        }
      }
      lastRow += childCount - lastModelIndex;
      node = (FHTreeStateNode) getParent();
      if (node != null) {
        node.resetChildrenRowsFrom(lastRow, node.getIndex(this) + 1, this.childIndex + 1);
      } else { // This is the root, reset total ROWCOUNT!
        rowCount = lastRow;
      }
    }
Ejemplo n.º 29
0
    /** @return next visible TreePath. */
    public TreePath nextElement() {
      if (!hasMoreElements()) throw new NoSuchElementException("No more visible paths");

      TreePath retObject;

      if (nextIndex == -1) retObject = parent.getTreePath();
      else {
        FHTreeStateNode node = parent.getChildAtModelIndex(nextIndex);

        if (node == null)
          retObject =
              parent
                  .getTreePath()
                  .pathByAddingChild(treeModel.getChild(parent.getUserObject(), nextIndex));
        else retObject = node.getTreePath();
      }
      updateNextObject();
      return retObject;
    }
Ejemplo n.º 30
0
    /** Invokes <code>expandParentAndReceiver</code> on the parent, and expands the receiver. */
    protected void expandParentAndReceiver() {
      FHTreeStateNode parent = (FHTreeStateNode) getParent();

      if (parent != null) parent.expandParentAndReceiver();
      expand();
    }