Java resize and move object

Java resize and move object

------------------ Resize.java -----------------

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.canvas.*;
import javafx.scene.transform.*;
import javafx.scene.image.*;
import javafx.beans.property.*;
import javafx.geometry.*;

public class Resize extends Application {

  double a = 6, a2 = a / 2;
  double gridSize = -1;
  double lastX, lastY;
  double lX, lY, sX, sY, sWidth, sHeight;
  Slider slider1, slider2;
  CheckBox checkBox;
  ScrollPane scrollPane;
  Group group, overlay = null;
  Pane zoomPane;
  Rectangle srBnd, srNW, srN, srNE, srE, srSE, srS, srSW, srW;
  Element selectedElement;
  Rectangle2D area = new Rectangle2D(0, 0, 1000, 1000);
  Paint bg1 = Paint.valueOf("linear-gradient(from 0.0% 0.0% to 0.0% 100.0%, 0x90c1eaff 0.0%, 0x5084b0ff 100.0%)");
  BackgroundFill backgroundFill1 = new BackgroundFill(bg1, null, null);
  Canvas canvas = new Canvas();
  SnapshotParameters sp = new SnapshotParameters();

  @Override
  public void start(final Stage stage) {
    BorderPane layout = new BorderPane();
    stage.setScene(new Scene(layout, 500, 300));
    group = new Group(createElement(150, 30, 105, 105, Color.AQUA), createElement(45, 30, 45, 105, Color.VIOLET),
      createElement(45, 180, 45, 45, Color.TAN), createElement(150, 180, 105, 45, Color.LIME));
    zoomPane = new Pane(group);
    zoomPane.setOnMousePressed(me -> select(null));
    Scale scale = new Scale();
    group.getTransforms().add(scale);
    slider1 = new Slider(.1, 5, 1);
    slider1.setMinWidth(150);
    slider1.setMaxWidth(150);
    slider1.setPadding(new Insets(6));
    slider1.setTooltip(new Tooltip("Zoom"));
    slider1.valueProperty().addListener((v, o, n) -> {
      scale.setX(n.doubleValue());
      scale.setY(n.doubleValue());
      updateGrid();
      updateZoomPane();
      updateOverlay();
    });
    slider2 = new Slider(5, 35, 15);
    slider2.setMinWidth(150);
    slider2.setMaxWidth(150);
    slider2.setPadding(new Insets(6));
    slider2.setTooltip(new Tooltip("Grid size"));
    slider2.valueProperty().addListener((v, o, n) -> {
      updateGrid();
    });
    checkBox = new CheckBox();
    checkBox.setPadding(new Insets(6));
    checkBox.setTooltip(new Tooltip("Show grid"));
    checkBox.selectedProperty().addListener((v, o, n) -> {
      slider2.setDisable(!n.booleanValue());
      updateGrid();
    });
    checkBox.setSelected(true);
    scrollPane = new ScrollPane(new Group(zoomPane));
    scrollPane.viewportBoundsProperty().addListener((v, o, n) -> {
      updateZoomPane();
      Platform.runLater(() -> zoomPane.requestLayout());
    });
    layout.setCenter(scrollPane);
    layout.setBottom(new FlowPane(slider1, checkBox, slider2));
    //stage.setOnCloseRequest(e -> System.out.println(group.getChildren().toString()));
    stage.show();
  }

  void updateGrid() {
    double size = slider1.getValue() * slider2.getValue();
    if (!checkBox.isSelected() || size < 4) size = 0;
    if (gridSize != size) {
      if (size <= 0) {
        zoomPane.setBackground(new Background(backgroundFill1));
      } else {
        Paint bg2 = patternTransparent(size);
        BackgroundFill backgroundFill2 = new BackgroundFill(bg2, null, null);
        zoomPane.setBackground(new Background(backgroundFill1, backgroundFill2));
      }
      gridSize = size;
    }
  }

  void updateZoomPane() {
    zoomPane.setPrefWidth(Math.max(scrollPane.getViewportBounds().getWidth(), group.getBoundsInParent().getMaxX()));
    zoomPane.setPrefHeight(Math.max(scrollPane.getViewportBounds().getHeight(), group.getBoundsInParent().getMaxY()));
  }

  ImagePattern patternTransparent(double size) {
    canvas.setHeight(size);
    canvas.setWidth(size);
    GraphicsContext gc = canvas.getGraphicsContext2D();
    gc.clearRect(0, 0, size, size);
    gc.setFill(Color.BLACK);
    //gc.setLineWidth(2);
    gc.strokeLine(0, 0, 0, size);
    gc.strokeLine(1, 0, size, 0);
    sp.setFill(Color.TRANSPARENT);
    WritableImage image = canvas.snapshot(sp, null);
    return new ImagePattern(image, 0, 0, size, size, false);
  }

  Element createElement(double x, double y, double width, double height, Paint fill) {
    Element element = new Element(x, y, width, height, fill);
    element.setOnMousePressed(me -> {
      select(element);
      srBnd.fireEvent(me);
      me.consume();
    });
    element.setOnMouseDragged(me -> srBnd.fireEvent(me));
    element.setOnMouseReleased(me -> srBnd.fireEvent(me));
    element.boundsInParentProperty().addListener((v, o, n) -> updateOverlay());
    return element;
  }

  class Element extends Group {

    Rectangle rectangle = new Rectangle();
    DoubleProperty widthProperty = new SimpleDoubleProperty();
    DoubleProperty heightProperty = new SimpleDoubleProperty();

    Element(double x, double y, double width, double height, Paint fill) {
      widthProperty.addListener((v, o, n) -> { rectangle.setWidth(n.doubleValue()); });
      heightProperty.addListener((v, o, n) -> { rectangle.setHeight(n.doubleValue()); });
      setLayoutX(x);
      setLayoutY(y);
      widthProperty.set(width);
      heightProperty.set(height);
      rectangle.setFill(fill);
      getChildren().add(rectangle);
      //setPickOnBounds(true);
    }
    DoubleProperty widthProperty() { return widthProperty; }
    DoubleProperty heightProperty() { return heightProperty; }
    @Override public String toString() { return "[" + getLayoutX() + ", " + getLayoutY() + ", " + widthProperty.get() + ", " + heightProperty.get() + "]"; }
  }

  void select(Element element) {
    if (overlay == null && element != null) iniOverlay();
    if (element != selectedElement) {
      overlay.setVisible(element != null);
      if (element != null) element.toFront();
      selectedElement = element;
      updateOverlay();
    }
  }

  void iniOverlay() {
    overlay = new Group();
    //overlay.setVisible(false);
    srBnd = new Rectangle();
    srBnd.setStroke(Color.BLACK);
    srBnd.setStrokeType(StrokeType.INSIDE);
    srBnd.setStrokeWidth(1);
    srBnd.getStrokeDashArray().addAll(2d, 4d);
    srBnd.setFill(Color.TRANSPARENT);
    handleMouse(srBnd);
    srNW = srCreate(Cursor.NW_RESIZE);
    srN = srCreate(Cursor.N_RESIZE);
    srNE = srCreate(Cursor.NE_RESIZE);
    srE = srCreate(Cursor.E_RESIZE);
    srSE = srCreate(Cursor.SE_RESIZE);
    srS = srCreate(Cursor.S_RESIZE);
    srSW = srCreate(Cursor.SW_RESIZE);
    srW = srCreate(Cursor.W_RESIZE);
    overlay.getChildren().addAll(srBnd, srNW, srN, srNE, srE, srSE, srS, srSW, srW);
    zoomPane.getChildren().add(overlay);
  }

  void updateOverlay() {
    if (selectedElement != null) {
      double zoom = slider1.getValue();
      srBnd.setX(selectedElement.getLayoutX() * zoom);
      srBnd.setY(selectedElement.getLayoutY() * zoom);
      srBnd.setWidth(selectedElement.widthProperty().get() * zoom);
      srBnd.setHeight(selectedElement.heightProperty().get() * zoom);
      srNW.setX(selectedElement.getLayoutX() * zoom);
      srNW.setY(selectedElement.getLayoutY() * zoom);
      srN.setX((selectedElement.getLayoutX() + selectedElement.widthProperty().get() / 2) * zoom - a2);
      srN.setY(selectedElement.getLayoutY() * zoom);
      srNE.setX((selectedElement.getLayoutX() + selectedElement.widthProperty().get()) * zoom - a);
      srNE.setY(selectedElement.getLayoutY() * zoom);
      srE.setX((selectedElement.getLayoutX() + selectedElement.widthProperty().get()) * zoom - a);
      srE.setY((selectedElement.getLayoutY() + selectedElement.heightProperty().get() / 2) * zoom - a2);
      srSE.setX((selectedElement.getLayoutX() + selectedElement.widthProperty().get()) * zoom - a);
      srSE.setY((selectedElement.getLayoutY() + selectedElement.heightProperty().get()) * zoom - a);
      srS.setX((selectedElement.getLayoutX() + selectedElement.widthProperty().get() / 2) * zoom - a2);
      srS.setY((selectedElement.getLayoutY() + selectedElement.heightProperty().get()) * zoom - a);
      srSW.setX(selectedElement.getLayoutX() * zoom);
      srSW.setY((selectedElement.getLayoutY() + selectedElement.heightProperty().get()) * zoom - a);
      srW.setX(selectedElement.getLayoutX() * zoom);
      srW.setY((selectedElement.getLayoutY() + selectedElement.heightProperty().get() / 2) * zoom - a2);
    }
  }

  Rectangle srCreate(Cursor cursor) {
    Rectangle rectangle = new Rectangle(a, a, Color.BLACK);
    rectangle.setCursor(cursor);
    handleMouse(rectangle);
    return rectangle;
  }

  void handleMouse(Node node) {
    node.setOnMousePressed(me -> {
      lX = me.getX();
      lY = me.getY();
      sX = selectedElement.getLayoutX();
      sY = selectedElement.getLayoutY();
      sWidth = selectedElement.widthProperty().get();
      sHeight = selectedElement.heightProperty().get();
      me.consume();
    });
    node.setOnMouseDragged(me -> {
      double zoom = slider1.getValue();
      double dx = (me.getX() - lX) / zoom;
      double dy = (me.getY() - lY) / zoom;
      Object source = me.getSource();
      if (source == srBnd) relocate(sX + dx, sY + dy);
      else if (source == srNW) { setHSize(sX + dx, true); setVSize(sY + dy, true); }
      else if (source == srN) setVSize(sY + dy, true);
      else if (source == srNE) { setHSize(sX + sWidth + dx, false); setVSize(sY + dy, true); }
      else if (source == srE) setHSize(sX + sWidth + dx, false);
      else if (source == srSE) { setHSize(sX + sWidth + dx, false); setVSize(sY + sHeight + dy, false); }
      else if (source == srS) setVSize(sY + sHeight + dy, false);
      else if (source == srSW) { setHSize(sX + dx, true); setVSize(sY + sHeight + dy, false); }
      else if (source == srW) setHSize(sX + dx, true);
      updateZoomPane();
      me.consume();
    });
    node.setOnMouseReleased(me -> { //snap to grid
      if (checkBox.isSelected() && slider2.getValue() > 0) {
        Object source = me.getSource();
        if (source == srBnd) relocate(snap(selectedElement.getLayoutX()), snap(selectedElement.getLayoutY()));
        else {
          if (source == srNW || source == srN || source == srNE) setVSize(snap(selectedElement.getLayoutY()), true);
          else if (source == srSW || source == srS || source == srSE) setVSize(snap(selectedElement.getLayoutY() + selectedElement.heightProperty().get()), false);
          if (source == srNW || source == srW || source == srSW) setHSize(snap(selectedElement.getLayoutX()), true);
          else if (source == srNE || source == srE || source == srSE) setHSize(snap(selectedElement.getLayoutX() + selectedElement.widthProperty().get()), false);
        }
        updateZoomPane();
      }
      me.consume();
    });
  }

  double snap(double value) {
    double gridSize = slider2.getValue();
    return Math.round(value / gridSize) * gridSize;
  }

  void setHSize(double h, boolean b) {
    double x = selectedElement.getLayoutX(), w = selectedElement.widthProperty().get(), width;
    double as = (a * 3) / slider1.getValue();
    if (h < area.getMinX()) h = area.getMinX();
    if (h > area.getMaxX()) h = area.getMaxX();
    if (b) {
      width = w + x - h;
      if (width < as) { width = as; h = x + w - as; }
      selectedElement.setLayoutX(h);
    } else {
      width = h - x;
      if (width < as) width = as;
    }
    selectedElement.widthProperty().set(width);
  }

  void setVSize(double v, boolean b) {
    double y = selectedElement.getLayoutY(), h = selectedElement.heightProperty().get(), height;
    double as = (a * 3) / slider1.getValue();
    if (v < area.getMinY()) v = area.getMinY();
    if (v > area.getMaxY()) v = area.getMaxY();
    if (b) {
      height = h + y - v;
      if (height < as) { height = as; v = y + h - as; }
      selectedElement.setLayoutY(v);
    } else {
      height = v - y;
      if (height < as) height = as;
    }
    selectedElement.heightProperty().set(height);
  }

  void relocate(double x, double y) {
    double maxX = area.getMaxX() - selectedElement.widthProperty().get();
    double maxY = area.getMaxY() - selectedElement.heightProperty().get();
    if (x < area.getMinX()) x = area.getMinX();
    if (y < area.getMinY()) y = area.getMinY();
    if (x > maxX) x = maxX;
    if (y > maxY) y = maxY;
    selectedElement.setLayoutX(x);
    selectedElement.setLayoutY(y);
  }
}

Download ZIP

Back