/**
   * Lays out the ribbons in a bundled style. Basically, this means doing a series of phased
   * depth-first traversals on each of the top-level category nodes.
   *
   * @param minX The left bound of the display space.
   * @param maxX The right bound of the display space.
   */
  public void doLayoutBundled(int minX, int maxX, BarState currentState) {

    root.setWidth(maxX - minX);

    // Set all the layout and completeness flags to false.
    resetForBundling(root);

    // If there are no connections, return.
    if (!root.getChildren().isEmpty()) {

      // While the root is not set to complete...
      while (!root.isComplete()) {

        // Iterate through each of the invisible nodes, each of
        // which represents a top-level category bar. At each
        // step, lay out the leftmost incomplete branch of the
        // top-level node.
        for (VisualConnection invisible : root.getChildren()) {

          if (!invisible.isComplete()) layoutBranch(invisible, currentState, (maxX - minX));

          // If this node is complete and is the last of the root's
          // children, then we're done.
          else if (invisible == root.getChildren().get(root.getChildren().size() - 1))
            root.setComplete(true);
        }
      }
    }
    setColors(root);
  }
  /**
   * Lay out the leftmost incomplete branch of this connection node.
   *
   * @param connectionNode
   */
  public boolean layoutBranch(
      VisualConnection connectionNode, BarState currentState, int totalWidth) {

    // If this node isn't laid out already, lay it out.
    if (!connectionNode.isLaidOut()) {

      connectionNode.layout(connectionNode.getParent().getWidth());
      connectionNode.setLaidOut(true);

      // If this is a leaf, this node is completed.
      if (connectionNode.getChildren().isEmpty()) {
        connectionNode.setComplete(true);
        return true;
      }
    }

    // If this is not a leaf, call layoutBranch on this node's
    // leftmost incomplete child.
    for (VisualConnection child : connectionNode.getChildren())
      if (!child.isComplete())
        if (layoutBranch(child, currentState, totalWidth) == false) return false;

    // If all of the children are complete, this node is
    // completed.
    connectionNode.setComplete(true);

    return true;
  }