Beispiel #1
0
  protected void setPosition(Node node, NodePosition position) {
    if (node == null || position == null) {
      throw new IllegalArgumentException();
    }

    unsetPosition(node);

    if (_nodeByPosition.containsKey(position) == true) {
      unsetPosition(_nodeByPosition.get(position));
    }

    NodePosition parentPosition = position.getParent();
    int level = position.getLevel();

    _positionByNode.put(node, position);
    _nodeByPosition.put(position, node);

    if (_nodeByParentPosition.containsKey(parentPosition) == false) {
      _nodeByParentPosition.put(parentPosition, new HashSet<Node>());
    }

    _nodeByParentPosition.get(parentPosition).add(node);

    if (_nodeByLevel.containsKey(level) == false) {
      _nodeByLevel.put(level, new HashSet<Node>());
    }

    _nodeByLevel.get(level).add(node);
  }
Beispiel #2
0
  protected void unsetPosition(Node node) {
    if (node == null) {
      throw new IllegalArgumentException();
    }

    if (_positionByNode.containsKey(node) == false) {
      return;
    }

    NodePosition position = _positionByNode.get(node);

    _positionByNode.remove(node);
    _nodeByPosition.remove(position);
    _nodeByParentPosition.get(position.getParent()).remove(node);
    _nodeByLevel.get(position.getLevel()).remove(node);
  }
Beispiel #3
0
  @Override
  protected void layoutChildren() {
    super.layoutChildren();

    if (_nodeByPosition.isEmpty()) {
      adjustLineCount(0);

      setPrefWidth(0);
      setPrefHeight(0);

      return;
    }

    // Calculate width per position based on layout bounds
    Map<NodePosition, Double> widthByPosition = new HashMap<>();
    Map<Integer, Double> levelHeight = new HashMap<>();

    Map<Integer, Set<NodePosition>> positionsByLevel = new HashMap<>();
    Map<NodePosition, Set<NodePosition>> positionsByParentPosition = new HashMap<>();

    int maxLevel = Collections.max(_nodeByLevel.keySet());

    for (int curLevel = maxLevel; curLevel >= 0; --curLevel) {
      levelHeight.put(curLevel, 0.0);

      positionsByLevel.put(curLevel, new HashSet<NodePosition>());
    }

    for (int curLevel = maxLevel; curLevel >= 0; --curLevel) {
      // Get bounds of nodes on current level
      Set<Node> curLevelNodes = _nodeByLevel.get(curLevel);

      if (curLevelNodes != null) {
        // Get node bounds
        for (Node node : curLevelNodes) {
          // Node data
          NodePosition nodePosition = _positionByNode.get(node);
          Bounds nodeBounds = node.getLayoutBounds();

          // Get bounds
          widthByPosition.put(nodePosition, nodeBounds.getWidth() + this.getXAxisSpacing());
          levelHeight.put(
              curLevel,
              Math.max(levelHeight.get(curLevel), nodeBounds.getHeight() + this.getYAxisSpacing()));

          // Register positions
          positionsByLevel.get(curLevel).add(nodePosition);

          if (curLevel > 0) {
            positionsByLevel.get(curLevel - 1).add(nodePosition.getParent());
          }
        }
      }

      // Calculate position widths of current level
      for (NodePosition position : positionsByLevel.get(curLevel)) {
        // Register positions
        if (position.getLevel() > 0) {
          NodePosition parentPosition = position.getParent();

          positionsByLevel.get(position.getLevel() - 1).add(parentPosition);

          if (positionsByParentPosition.containsKey(parentPosition) == false) {
            positionsByParentPosition.put(parentPosition, new HashSet<NodePosition>());
          }

          positionsByParentPosition.get(parentPosition).add(position);
        }

        // Get width of children
        double widthOfChildren = 0;

        Set<NodePosition> parentPositions = positionsByParentPosition.get(position);

        if (parentPositions != null) {
          for (NodePosition childPosition : parentPositions) {
            if (widthByPosition.containsKey(childPosition) == true) {
              widthOfChildren += widthByPosition.get(childPosition);
            }
          }
        }

        // Get maximum of node bound and sum of child node bounds
        if (widthByPosition.containsKey(position) == false) {
          widthByPosition.put(position, widthOfChildren);
        } else {
          widthByPosition.put(position, Math.max(widthByPosition.get(position), widthOfChildren));
        }
      }
    }

    // Calculate position boxes
    Map<NodePosition, Rectangle2D> boxesByPosition = new HashMap<>();

    if (positionsByLevel.containsKey(0) == false || positionsByLevel.get(0).size() != 1) {
      throw new IllegalStateException();
    }

    boxesByPosition.put(
        NodePosition.ROOT,
        new Rectangle2D(0, 0, widthByPosition.get(NodePosition.ROOT), levelHeight.get(0)));

    for (int curLevel = 0; curLevel <= maxLevel; ++curLevel) {
      for (NodePosition position : positionsByLevel.get(curLevel)) {
        Rectangle2D positionBox = boxesByPosition.get(position);

        List<NodePosition> childPositions = new ArrayList<>();

        if (positionsByParentPosition.containsKey(position)) {
          childPositions.addAll(positionsByParentPosition.get(position));
        }

        Collections.sort(childPositions);

        double childX = positionBox.getMinX();

        for (NodePosition childPosition : childPositions) {
          double childWidth = widthByPosition.get(childPosition);

          boxesByPosition.put(
              childPosition,
              new Rectangle2D(
                  childX,
                  positionBox.getMaxY(),
                  childWidth,
                  levelHeight.get(childPosition.getLevel())));

          childX += childWidth;
        }
      }
    }

    // Position nodes
    Map<NodePosition, Double> xCenterHintByPosition = new HashMap<>();
    Map<NodePosition, Double> yCenterHintByPosition = new HashMap<>();

    for (int curLevel = maxLevel; curLevel >= 0; --curLevel) {
      for (NodePosition position : positionsByLevel.get(curLevel)) {
        // Calculate center hints
        Rectangle2D positionBox = boxesByPosition.get(position);

        double xCenterHint = (positionBox.getMinX() + positionBox.getMaxX()) / 2;

        if (xCenterHintByPosition.containsKey(position) == true) {
          xCenterHint = xCenterHintByPosition.get(position);
        }

        double yCenterHint = (positionBox.getMinY() + positionBox.getMaxY()) / 2;

        xCenterHintByPosition.put(position, xCenterHint);
        yCenterHintByPosition.put(position, yCenterHint);

        // Position node
        if (_nodeByPosition.containsKey(position)) {
          Node node = _nodeByPosition.get(position);
          Bounds nodeBounds = node.getLayoutBounds();

          node.relocate(
              xCenterHint - nodeBounds.getWidth() / 2, yCenterHint - nodeBounds.getHeight() / 2);
        }

        // Update parent node position hint
        NodePosition parentPosition = position.getParent();

        if (xCenterHintByPosition.containsKey(parentPosition)) {
          xCenterHintByPosition.put(
              parentPosition, (xCenterHintByPosition.get(parentPosition) + xCenterHint) / 2);
        } else {
          xCenterHintByPosition.put(parentPosition, xCenterHint);
        }
      }
    }

    // Update lines
    if (this.getShowLines() == true) {
      adjustLineCount(boxesByPosition.size() - 1);

      int currentLine = 0;

      for (NodePosition position : boxesByPosition.keySet()) {
        if (positionsByParentPosition.containsKey(position) == false) {
          continue;
        }

        for (NodePosition childPosition : positionsByParentPosition.get(position)) {
          Bounds fromBounds =
              _nodeByPosition.containsKey(position)
                  ? _nodeByPosition.get(position).getLayoutBounds()
                  : null;
          Bounds toBounds =
              _nodeByPosition.containsKey(childPosition)
                  ? _nodeByPosition.get(childPosition).getLayoutBounds()
                  : null;

          Point2D lineFrom =
              new Point2D(
                  xCenterHintByPosition.get(position),
                  yCenterHintByPosition.get(position)
                      + (fromBounds != null ? (fromBounds.getHeight() / 2) : 0)
                      + this.getLineSpacing());

          Point2D lineTo =
              new Point2D(
                  xCenterHintByPosition.get(childPosition),
                  yCenterHintByPosition.get(childPosition)
                      - (toBounds != null ? (toBounds.getHeight() / 2) : 0)
                      - this.getLineSpacing());

          Line l = _lines.get(currentLine);

          l.setStartX(lineFrom.getX());
          l.setStartY(lineFrom.getY());

          l.setEndX(lineTo.getX());
          l.setEndY(lineTo.getY());

          ++currentLine;
        }
      }
    } else {
      adjustLineCount(0);
    }

    // Update preferred size
    double totalHeight = 0;
    for (Double h : levelHeight.values()) {
      totalHeight += h;
    }

    setPrefWidth(widthByPosition.get(NodePosition.ROOT));
    setPrefHeight(totalHeight);
  }