Пример #1
0
  private void showContextMenu(double x, double y) {
    if (contextMenu != null && contextMenu.isShowing()) contextMenu.hide();
    contextMenu = new ContextMenu();
    // contextMenu.getStyleClass().add("background");

    Color bg = cfg.colorProperty().getValue();
    Color fg = bg.getBrightness() < 0.5f ? Color.WHITE : Color.BLACK;

    contextMenu.setStyle(background(bg, true));

    contextMenu.setOnHidden(
        value -> {
          if (cfg.autoHideProperty().get() && !arePopupsOpen()) maybeHideDock();
        });
    if (!cfg.autoHideProperty().get()) {
      MenuItem hide = new MenuItem(resources.getString("menu.hide"));
      hide.setOnAction(value -> getStage().setIconified(true));
      hide.setStyle(textFill(fg));
      contextMenu.getItems().add(hide);
    }
    MenuItem close = new MenuItem(resources.getString("menu.exit"));
    close.setOnAction(
        value -> {
          context.confirmExit();
          maybeHideDock();
        });
    close.setStyle(textFill(fg));
    contextMenu.getItems().add(close);
    Point2D loc = new Point2D(x + getStage().getX(), y + getStage().getY());
    contextMenu.show(dockContent, loc.getX(), loc.getY());
  }
Пример #2
0
  public Rectangle getLocalRectangle() {
    Point2D pos = this.parent.getPosition();
    double x = pos.getX();
    double y = pos.getY();
    outside:
    for (Node node : this.parent.getRootPane().getItems()) {
      if (node != this) {
        y = 0;

        // VerticalなSplitPane
        if (node instanceof DockableAreaGroupPane) {
          DockableAreaGroupPane pane = (DockableAreaGroupPane) node;
          for (DockableTabPane tabPane : pane.getTabPaneList()) {
            if (tabPane != this) {
              y += tabPane.getHeight();
            } else {
              break outside;
            }
          }
          x += pane.getWidth();
        }
      } else {
        break;
      }
    }
    double w = this.getWidth();
    double h = this.getHeight();
    // System.out.println("x:" + x + "  y:" + y + "  w:" + w + "  h:" + h);
    Rectangle rect = new Rectangle();
    rect.x = (int) x;
    rect.y = (int) y;
    rect.width = (int) w;
    rect.height = (int) h;
    return rect;
  }
Пример #3
0
  static enum ShapeType {
    RECTANGLE(gc -> gc.fillRect(0, 0, CIRCLE_RADIUS, CIRCLE_RADIUS)),
    CIRCLE(gc -> gc.fillOval(0, 0, CIRCLE_RADIUS, CIRCLE_RADIUS)),
    ELLIPSE(
        gc ->
            gc.fillOval(
                ELLIPSE_CENTER.getX(),
                ELLIPSE_CENTER.getY(),
                ELLIPSE_RADIUS.getWidth(),
                ELLIPSE_RADIUS.getHeight()));

    ShapeType(Consumer<GraphicsContext> drawAlgorithm) {
      this.drawAlgorithm = drawAlgorithm;
    }

    public void drawWith(GraphicsContext gc) {
      drawAlgorithm.accept(gc);
    }

    public void clearAndDrawWith(GraphicsContext gc) {
      gc.clearRect(0, 0, CIRCLE_RADIUS, CIRCLE_RADIUS);
      gc.setFill(Color.TAN);
      drawAlgorithm.accept(gc);
    }

    private Consumer<GraphicsContext> drawAlgorithm;
  }
Пример #4
0
  protected GameState.SystemSides findSystemSide(
      Point2D point, double rotationAngleInDegrees, double fieldWidth, double fieldHeight) {
    double centerX = point.getX(), centerY = point.getY();
    double angle = (rotationAngleInDegrees + 360) % 360;

    double angleLimits[] = new double[4];
    angleLimits[0] = Math.atan2(-centerY, fieldWidth - centerX);
    angleLimits[1] = Math.atan2(fieldHeight - centerY, fieldWidth - centerX);
    angleLimits[2] = Math.atan2(fieldHeight - centerY, -centerX);
    angleLimits[3] = Math.atan2(-centerY, -centerX);

    for (int i = 0; i < 4; i++) {
      angleLimits[i] = (Math.toDegrees(angleLimits[i]) + 360) % 360;
    }

    if (angle >= angleLimits[0] || angle <= angleLimits[1]) {
      return GameState.SystemSides.Right;
    } else if (angle < angleLimits[2]) {
      return GameState.SystemSides.Down;
    } else if (angle <= angleLimits[3]) {
      return GameState.SystemSides.Left;
    } else {
      return GameState.SystemSides.Up;
    }
  }
Пример #5
0
 private static Bounds translateBounds(Bounds bounds, Point2D offset) {
   return new BoundingBox(
       bounds.getMinX() + offset.getX(),
       bounds.getMinY() + offset.getY(),
       bounds.getWidth(),
       bounds.getHeight());
 }
Пример #6
0
  protected Point2D getCrossPointWithSide(
      Point2D point,
      double rotationAngleInDegrees,
      double fieldWidth,
      double fieldHeight,
      GameState.SystemSides side) {
    double centerX = point.getX(), centerY = point.getY();

    double angle = (rotationAngleInDegrees + 360) % 360;

    if (angle == 90) {
      return new Point2D(centerX, fieldHeight);
    } else if (angle == 270) {
      return new Point2D(centerX, 0);
    }

    double a = Math.tan(Math.toRadians(angle));
    double b = centerY - a * centerX;

    switch (side) {
      case Right:
        return new Point2D(fieldWidth, a * fieldWidth + b);
      case Down:
        return new Point2D((fieldHeight - b) / a, fieldHeight);
      case Left:
        return new Point2D(0, b);
      case Up:
        return new Point2D(-b / a, 0);
      default:
        return new Point2D(0, 0);
    }
  }
 private boolean areWithinDistance(final Optional<Point> pos, final Point2D point) {
   if (pos.isPresent()) {
     final double dx = Math.abs(pos.get().x - point.getX());
     final double dy = Math.abs(pos.get().y - point.getY());
     return dx * dx + dy * dy <= X_RADIUS * X_RADIUS;
   }
   return false;
 }
 public Point2D sceneGraphObjectToDecoration(double x, double y, boolean snapToPixel) {
   Point2D result = sceneGraphObjectToDecoration(x, y);
   if (snapToPixel) {
     final double rx = Math.round(result.getX());
     final double ry = Math.round(result.getY());
     result = new Point2D(rx, ry);
   }
   return result;
 }
Пример #9
0
  /**
   * Traverse the scene graph for all open stages and pick an event target for a dock event based on
   * the location. Once the event target is chosen run the event task with the target and the
   * previous target of the last dock event if one is cached. If an event target is not found fire
   * the explicit dock event on the stage root if one is provided.
   *
   * @param location The location of the dock event in screen coordinates.
   * @param eventTask The event task to be run when the event target is found.
   * @param explicit The explicit event to be fired on the stage root when no event target is found.
   */
  private void pickEventTarget(Point2D location, EventTask eventTask, Event explicit) {
    // RFE for public scene graph traversal API filed but closed:
    // https://bugs.openjdk.java.net/browse/JDK-8133331

    ObservableList<Stage> stages =
        FXCollections.unmodifiableObservableList(StageHelper.getStages());
    // fire the dock over event for the active stages
    for (Stage targetStage : stages) {
      // obviously this title bar does not need to receive its own events
      // though users of this library may want to know when their
      // dock node is being dragged by subclassing it or attaching
      // an event listener in which case a new event can be defined or
      // this continue behavior can be removed
      if (targetStage == this.dockNode.getStage()) continue;

      eventTask.reset();

      Node dragNode = dragNodes.get(targetStage);

      Parent root = targetStage.getScene().getRoot();
      Stack<Parent> stack = new Stack<Parent>();
      if (root.contains(root.screenToLocal(location.getX(), location.getY()))
          && !root.isMouseTransparent()) {
        stack.push(root);
      }
      // depth first traversal to find the deepest node or parent with no children
      // that intersects the point of interest
      while (!stack.isEmpty()) {
        Parent parent = stack.pop();
        // if this parent contains the mouse click in screen coordinates in its local bounds
        // then traverse its children
        boolean notFired = true;
        for (Node node : parent.getChildrenUnmodifiable()) {
          if (node.contains(node.screenToLocal(location.getX(), location.getY()))
              && !node.isMouseTransparent()) {
            if (node instanceof Parent) {
              stack.push((Parent) node);
            } else {
              eventTask.run(node, dragNode);
            }
            notFired = false;
            break;
          }
        }
        // if none of the children fired the event or there were no children
        // fire it with the parent as the target to receive the event
        if (notFired) {
          eventTask.run(parent, dragNode);
        }
      }

      if (explicit != null && dragNode != null && eventTask.getExecutions() < 1) {
        Event.fireEvent(dragNode, explicit.copyFor(this, dragNode));
        dragNodes.put(targetStage, null);
      }
    }
  }
Пример #10
0
 public double getValue(Point2D p) {
   switch (this) {
     case X:
       return p.getX();
     case Y:
       return p.getY();
   }
   assert false;
   return 0;
 }
  public void show(Control ownerControl) {

    Point2D point =
        ownerControl.localToScene(ownerControl.getWidth() / 2, ownerControl.getHeight());
    double x =
        point.getX() + ownerControl.getScene().getX() + ownerControl.getScene().getWindow().getX();
    double y =
        point.getY() + ownerControl.getScene().getY() + ownerControl.getScene().getWindow().getY();
    popup.show(ownerControl, x - getPopoverPointX(), y - getPopoverPointY());
  }
Пример #12
0
  public static Point2D latLongToPixel(
      final Dimension2D MAP_DIMENSION,
      final Point2D UPPER_LEFT,
      final Point2D LOWER_RIGHT,
      final Point2D LOCATION) {
    final double LATITUDE = LOCATION.getX();
    final double LONGITUDE = LOCATION.getY();
    final double MAP_WIDTH = MAP_DIMENSION.getWidth();
    final double MAP_HEIGHT = MAP_DIMENSION.getHeight();

    final double WORLD_MAP_WIDTH =
        ((MAP_WIDTH / (LOWER_RIGHT.getY() - UPPER_LEFT.getY())) * 360) / (2 * Math.PI);
    final double MAP_OFFSET_Y =
        (WORLD_MAP_WIDTH
            / 2
            * Math.log10(
                (1 + Math.sin(Math.toRadians(LOWER_RIGHT.getX())))
                    / (1 - Math.sin(Math.toRadians(LOWER_RIGHT.getX())))));

    final double X =
        (LONGITUDE - UPPER_LEFT.getY()) * (MAP_WIDTH / (LOWER_RIGHT.getY() - UPPER_LEFT.getY()));
    final double Y =
        MAP_HEIGHT
            - ((WORLD_MAP_WIDTH
                    / 2
                    * Math.log10(
                        (1 + Math.sin(Math.toRadians(LATITUDE)))
                            / (1 - Math.sin(Math.toRadians(LATITUDE)))))
                - MAP_OFFSET_Y);

    return new Point2D(X, Y);
  }
Пример #13
0
 public void moveTo(Robot robot, Node visual, double localX, double localY)
     throws InterruptedException {
   Point2D localToScene = visual.localToScene(localX, localY);
   double x = scene.getWindow().getX() + localToScene.getX();
   double y = scene.getWindow().getY() + localToScene.getY();
   EventSynchronizer<MouseEvent> synchronizer =
       new EventSynchronizer<MouseEvent>(visual, MouseEvent.MOUSE_ENTERED);
   synchronizer.register();
   robot.mouseMove((int) x, (int) y);
   synchronizer.await();
 }
Пример #14
0
    public Shape getReflectionClip() {
      if (reflection == null || !getSkinnable().getClipReflections()) {
        return null;
      }

      return new Polygon(
          ulReflection2d.getX(), ulReflection2d.getY(),
          urReflection2d.getX(), urReflection2d.getY(),
          perspectiveTransform.getLrx(), perspectiveTransform.getLry(),
          perspectiveTransform.getLlx(), perspectiveTransform.getLly());
    }
Пример #15
0
 protected void refreshHandleLocation(Node hostVisual) {
   // position vbox top-right next to the host
   Bounds hostBounds = hostVisual.getBoundsInParent();
   Parent parent = hostVisual.getParent();
   if (parent != null) {
     hostBounds = parent.localToScene(hostBounds);
   }
   Point2D location =
       getVisual().getParent().sceneToLocal(hostBounds.getMaxX(), hostBounds.getMinY());
   getVisual().setLayoutX(location.getX());
   getVisual().setLayoutY(location.getY());
 }
  /**
   * Check if the provided mouse location would select the annotation
   *
   * @param point Location of mouse on screen
   * @return <code>true</code> if this annotation gets selected at that mouse location
   */
  boolean isSelected(final Point2D point) {
    final Optional<Rectangle> rect = screen_box;
    if (rect.isPresent() && rect.get().contains(point.getX(), point.getY())) {
      selected = Selection.Body;
      return true;
    }

    if (areWithinDistance(screen_pos, point)) {
      selected = Selection.Reference;
      return true;
    }

    return false;
  }
 /*     */ public WCPoint screenToWindow(WCPoint paramWCPoint) {
   /* 108 */ WebView localWebView = this.accessor.getView();
   /* 109 */ Scene localScene = localWebView.getScene();
   /* 110 */ Window localWindow = null;
   /*     */
   /* 112 */ if ((localScene != null) && ((localWindow = localScene.getWindow()) != null))
   /*     */ {
     /* 115 */ Point2D localPoint2D =
         localWebView.sceneToLocal(
             paramWCPoint.getX() - localWindow.getX() - localScene.getX(),
             paramWCPoint.getY() - localWindow.getY() - localScene.getY());
     /*     */
     /* 118 */ return new WCPoint((float) localPoint2D.getX(), (float) localPoint2D.getY());
     /*     */ }
   /* 120 */ return new WCPoint(0.0F, 0.0F);
   /*     */ }
 /*     */ public WCPoint windowToScreen(WCPoint paramWCPoint) /*     */ {
   /* 125 */ WebView localWebView = this.accessor.getView();
   /* 126 */ Scene localScene = localWebView.getScene();
   /* 127 */ Window localWindow = null;
   /*     */
   /* 129 */ if ((localScene != null) && ((localWindow = localScene.getWindow()) != null))
   /*     */ {
     /* 132 */ Point2D localPoint2D =
         localWebView.localToScene(paramWCPoint.getX(), paramWCPoint.getY());
     /* 133 */ return new WCPoint(
         (float) (localPoint2D.getX() + localScene.getX() + localWindow.getX()),
         (float) (localPoint2D.getY() + localScene.getY() + localWindow.getY()));
     /*     */ }
   /*     */
   /* 136 */ return new WCPoint(0.0F, 0.0F);
   /*     */ }
  /** Update the popup location below the anchor node. */
  @Override
  protected void updatePopupLocation() {
    final Bounds anchorBounds = getAnchor().getLayoutBounds();
    Point2D popupLocation;

    assert anchorBounds != null;

    // At exit time, closeRequestHandler() is not always called.
    // So this method can be invoked after the anchor has been removed the
    // scene. This looks like a bug in FX...
    // Anway we protect ourself by checking.
    if (getAnchor().getScene() != null) {
      popupLocation = getAnchor().localToScreen(anchorBounds.getMinX(), anchorBounds.getMaxY());
      getPopup().setX(popupLocation.getX());
      getPopup().setY(popupLocation.getY());
    }
  }
Пример #20
0
  /**
   * calculate the layout point for a popup window based on the two points, windowPoint from popup
   * window and parentPoint from parent node
   *
   * @param window the popup window
   * @param windowPoint align point inside popup window
   * @param parent parent node with which the popup window try to align
   * @param parentPoint align point inside parent node
   * @return the Point2D
   */
  public static Point2D pointRelativeTo(
      PopupWindow window, Point2D windowPoint, Node parent, Point2D parentPoint) {
    if (parent == null || window == null) {
      return null;
    }

    double anchorWidth = window.getWidth();
    double anchorHeight = window.getHeight();

    Point2D point2D =
        Utils.pointRelativeTo(parent, anchorWidth, anchorHeight, HPos.CENTER, VPos.BOTTOM, false);
    //        Rectangle2D screenBounds = JideFXUtilities.getScreenBounds(new Point2D(0,
    // parentPoint.getY()));
    //        if (screenBounds.getMaxX() >= point2D.getX() + anchorWidth + parentPoint.getX() -
    // windowPoint.getX()) {
    //            point2D = point2D.add(parentPoint.getX() - windowPoint.getX(), 0);
    //        }
    //        if (screenBounds.getMaxY() >= point2D.getY() + anchorHeight + parentPoint.getY() -
    // parent.getLayoutBounds().getMaxY() - windowPoint.getY()) {
    //            point2D = point2D.add(0, parentPoint.getY() - parent.getLayoutBounds().getMaxY() +
    // windowPoint.getY());
    //        }

    point2D =
        new Point2D(
            point2D.getX() + parentPoint.getX() - windowPoint.getX(),
            point2D.getY()
                + parentPoint.getY()
                - parent.getLayoutBounds().getMaxY()
                + windowPoint.getY());

    return point2D;
  }
Пример #21
0
 /**
  * @param node
  * @return
  */
 public static Tooltip create(Node node) {
   Tooltip tooltip = new Tooltip();
   node.setOnMouseEntered(
       (MouseEvent event) -> {
         Point2D p =
             node.localToScreen(
                 node.getLayoutBounds().getMaxX() / 2,
                 node.getLayoutBounds().getMaxY()
                     + 5); // I position the tooltip at bottom right of the node (see below for
         // explanation)
         tooltip.show(node, p.getX(), p.getY());
       });
   node.setOnMouseExited(
       (MouseEvent event) -> {
         tooltip.hide();
       });
   return tooltip;
 }
Пример #22
0
  private int getMiddle(int v1, Point2D p1, int v2, Point2D p2) {
    String key = "" + Math.min(v1, v2) + "_" + Math.max(v1, v2);
    if (map.get(key) != null) {
      return map.get(key);
    }

    texCoord1.add(p1.add(p2).multiply(0.5f));

    map.put(key, index.get());
    return index.getAndIncrement();
  }
Пример #23
0
  public void update(Point2D center, Dimension2D dim) {
    moveTo1.setX(center.getX() - 10);
    moveTo1.setY(center.getY());

    lineTo1.setX(center.getX() + 10);
    lineTo1.setY(center.getY());

    moveTo2.setX(center.getX());
    moveTo2.setY(center.getY() - 10);

    lineTo2.setX(center.getX());
    lineTo2.setY(center.getY() + 10);
  }
Пример #24
0
 protected FxRobot moveTo(Node node) {
   baseFXRobot.waitForIdle();
   double x;
   double y;
   do {
     try {
       Thread.sleep(100);
     } catch (InterruptedException ignored) {
     }
     Point2D position = robot.point(node).getPosition();
     x = position.getX();
     y = position.getY();
     robot.moveTo(node);
     try {
       Thread.sleep(100);
     } catch (InterruptedException ignored) {
     }
     baseFXRobot.waitForIdle();
   } while (hasMoved(node, x, y));
   return robot.moveTo(node);
 }
Пример #25
0
 private Point2D validateCoordinate(Point2D possibleNewLocation) {
   double maxY = armyAllegiance.getScene().getHeight();
   double maxX = armyAllegiance.getScene().getWidth();
   double myX = possibleNewLocation.getX();
   double myY = possibleNewLocation.getY();
   double newX = 0.0;
   double newY = 0.0;
   if ((myX < 0) && (myY < 0)) {
     newX = SingletonRandom.instance.getNormalDistribution(0.0, (0.25 * maxX), 2.0);
     newY = SingletonRandom.instance.getNormalDistribution(0.0, (0.25 * maxY), 2.0);
     return new Point2D(newX, newY);
   } else if ((0 < myX) && (myX < maxX) && (myY < 0)) {
     newY = SingletonRandom.instance.getNormalDistribution(0.0, (0.25 * maxY), 2.0);
     return new Point2D(myX, newY);
   } else if ((myX > maxX) && (myY < 0)) {
     newX = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxX), 2.0);
     newY = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxY), 2.0);
     return new Point2D(newX, newY);
   } else if ((0 < myX) && (myY < maxY) && (myY > 0)) {
     newX = SingletonRandom.instance.getNormalDistribution(0.0, (0.25 * maxX), 2.0);
     return new Point2D(newX, myY);
   } else if ((myX > maxX) && (myY < maxY) && (myY > 0)) {
     newX = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxX), 2.0);
     return new Point2D(newX, myY);
   }
   if ((myX < 0) && (myY > maxY)) {
     newX = SingletonRandom.instance.getNormalDistribution(0.0, (0.25 * maxX), 2.0);
     newY = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxY), 2.0);
     return new Point2D(newX, newY);
   } else if ((0 < myX) && (myX < maxX) && (myY > maxY)) {
     newY = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxY), 2.0);
     return new Point2D(myX, newY);
   } else if ((myX > maxX) && (myY > maxY)) {
     newX = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxX), 2.0);
     newY = SingletonRandom.instance.getNormalDistribution(0.0, (0.75 * maxY), 2.0);
     return new Point2D(newX, newY);
   } else {
     return new Point2D(myX, myY);
   }
 }
 private void updatePopup() {
   if (getText() == null) {
     return;
   }
   LinkedList<String> searchResult = new LinkedList<>();
   searchResult.addAll(
       entries.stream().filter(x -> x.startsWith(getText())).collect(Collectors.toList()));
   if (entries.size() > 0) {
     populatePopup(searchResult);
     if (!popup.isShowing()) {
       Point2D p = this.localToScene(0.0, 0.0);
       double x = p.getX() + this.getScene().getX() + this.getScene().getWindow().getX();
       double y =
           p.getY()
               + this.getScene().getY()
               + this.getScene().getWindow().getY()
               + this.getHeight();
       popup.show(AutoCompleteTextField.this, x, y);
     }
   } else {
     popup.hide();
   }
 }
Пример #27
0
    @Override
    public Point2D getScenePosition() {
      Scene scene;

      if (source instanceof Node) {
        scene = ((Node) source).getScene();
      } else if (source instanceof Scene) {
        scene = (Scene) source;
      } else {
        return null;
      }

      return screenPos.subtract(
          scene.getX() + scene.getWindow().getX(), scene.getY() + scene.getWindow().getY());
    }
  private SequentialTransition createTransition(
      final Point2D pntStartPoint, final Point2D pntEndPoint, ImageView imView) {

    imView =
        new ImageView(
            new Image(getClass().getResourceAsStream("/res/img/b1fh.png"), 75, 75, true, true));

    imView.setX(pntStartPoint.getX());
    imView.setY(pntStartPoint.getY() - 30);

    APMainScreen.getChildren().add(imView);

    TranslateTransition translateTransition = new TranslateTransition(Duration.millis(300), imView);
    translateTransition.setFromX(0);
    translateTransition.setToX(pntEndPoint.getX() - pntStartPoint.getX());
    translateTransition.setFromY(0);
    translateTransition.setToY(pntEndPoint.getY() - pntStartPoint.getY());

    translateTransition.setCycleCount(1);
    translateTransition.setAutoReverse(false);

    int rnd = randInt(1, 3);

    RotateTransition rotateTransition = new RotateTransition(Duration.millis(150), imView);
    rotateTransition.setByAngle(90F);
    rotateTransition.setCycleCount(rnd);
    rotateTransition.setAutoReverse(false);

    ParallelTransition parallelTransition = new ParallelTransition();
    parallelTransition.getChildren().addAll(translateTransition, rotateTransition);

    SequentialTransition seqTrans = new SequentialTransition();
    seqTrans.getChildren().addAll(parallelTransition);

    final ImageView ivRemove = imView;
    seqTrans.setOnFinished(
        new EventHandler<ActionEvent>() {

          @Override
          public void handle(ActionEvent arg0) {
            APMainScreen.getChildren().remove(ivRemove);
          }
        });

    return seqTrans;
  }
Пример #29
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);
  }
Пример #30
0
 private static double hypot(Point2D p1, Point2D p2) {
   return Math.hypot(p1.getX() - p2.getX(), p1.getY() - p2.getY());
 }