예제 #1
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);
  }
예제 #2
0
  private void shiftDock() {
    long now = System.currentTimeMillis();
    Rectangle2D cfgBounds = Client.getConfiguredBounds();

    // The bounds to work in
    int boundsSize = cfg.isVertical() ? (int) cfgBounds.getHeight() : (int) cfgBounds.getWidth();

    // Total amount to slide
    int value = cfg.sizeProperty().get() - AUTOHIDE_TAB_OPPOSITE_SIZE;

    // How far along the timeline?
    float fac = Math.min(1f, 1f - ((float) (yEnd - now) / (float) AUTOHIDE_DURATION));

    // The amount of movement so far
    float amt = fac * (float) value;

    // The amount to shrink the width (or height when vertical) of the
    // visible 'bar'
    float barSize = (float) boundsSize * fac;

    // If showing, reverse
    final boolean fhidden = hidden;

    if (!hidden) {
      amt = value - amt;
      barSize = (float) boundsSize - barSize;
      if (!pull.isVisible()) pull.setVisible(true);
    }

    // Reveal or hide the pull tab
    dockContent.setOpacity(hidden ? 1f - fac : fac);
    pull.setOpacity((hidden ? fac : 1f - fac) * 0.5f);

    Stage stage = getStage();
    if (stage != null) {
      if (cfg.topProperty().get()) {
        getScene().getRoot().translateYProperty().set(-amt);
        stage.setHeight(cfg.sizeProperty().get() - amt + Client.DROP_SHADOW_SIZE);
        stage.setWidth(Math.max(AUTOHIDE_TAB_SIZE, cfgBounds.getWidth() - barSize));
        stage.setX(cfgBounds.getMinX() + ((cfgBounds.getWidth() - stage.getWidth()) / 2f));
      } else if (cfg.bottomProperty().get()) {
        stage.setY(cfgBounds.getMaxY() + amt);
        stage.setHeight(cfg.sizeProperty().get() - amt + Client.DROP_SHADOW_SIZE);
        stage.setWidth(Math.max(AUTOHIDE_TAB_SIZE, cfgBounds.getWidth() - barSize));
        stage.setX(cfgBounds.getMinX() + ((cfgBounds.getWidth() - stage.getWidth()) / 2f));
      } else if (cfg.leftProperty().get()) {
        getScene().getRoot().translateXProperty().set(-amt);
        stage.setWidth(cfg.sizeProperty().get() - amt);
        stage.setHeight(Math.max(AUTOHIDE_TAB_SIZE, cfgBounds.getHeight() - barSize));
        stage.setY(cfgBounds.getMinY() + ((cfgBounds.getHeight() - stage.getHeight()) / 2f));
      } else if (cfg.rightProperty().get()) {
        stage.setX(cfgBounds.getMaxX() + amt - cfg.sizeProperty().get());
        stage.setWidth(cfg.sizeProperty().get() - amt);
        stage.setHeight(Math.max(AUTOHIDE_TAB_SIZE, cfgBounds.getHeight() - barSize));
        stage.setY(cfgBounds.getMinY() + ((cfgBounds.getHeight() - stage.getHeight()) / 2f));
      } else {
        throw new UnsupportedOperationException();
      }
    }

    // The update or the sign in dialog may have been popped, so make sure
    // it is position correctly
    if (signInPopup != null && signInPopup.isShowing()) {
      signInPopup.sizeToScene();
    }

    // If not fully hidden / revealed, play again
    if (now < yEnd) {
      dockHider.playFromStart();
    } else {
      // Defer this as events may still be coming in
      Platform.runLater(
          new Runnable() {
            @Override
            public void run() {
              if (!fhidden && stage != null) {
                stage.requestFocus();
                pull.setVisible(false);
              }
              hiding = false;
            }
          });
    }
  }