
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.*;
import javafx.event.EventHandler;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;


public class MultiTouchSample extends Application {

    private ImageView postView;
    private MultiTouchPane multiTouchPane;

    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root));
        multiTouchPane = new MultiTouchPane();
        root.getChildren().add(multiTouchPane);

    }

    public class MultiTouchPane extends Region {

        public MultiTouchPane() {

            Image img = new Image(MultiTouchSample.class.getResource("square.png").toExternalForm(), false);
            MultiTouchImageView iv = new MultiTouchImageView(img);

            iv.setLayoutX(300);
            iv.setLayoutY(300);

            getChildren().add(iv);

        }

        //@Override protected void layoutChildren() {}
    }

    public class MultiTouchImageView extends StackPane {

        private ImageView imageView;
        private double lastX, lastY, startScale, startRotate;

        public MultiTouchImageView(Image img) {

            imageView = new ImageView(img);
            imageView.setSmooth(true);
            getChildren().add(imageView);

            setOnMousePressed(new EventHandler<MouseEvent>() {
                @Override public void handle(MouseEvent event) {

                    lastX = event.getX();
                    lastY = event.getY();
                    toFront();
                }
            });
            setOnMouseDragged(new EventHandler<MouseEvent>() {
                @Override public void handle(MouseEvent event) {

                    double layoutX = getLayoutX() + (event.getX() - lastX);
                    double layoutY = getLayoutY() + (event.getY() - lastY);

                    if ((layoutX >= 0) && (layoutX <= (getParent().getLayoutBounds().getWidth()))) {
                        setLayoutX(layoutX);
                    }

                    if ((layoutY >= 0) && (layoutY <= (getParent().getLayoutBounds().getHeight()))) {
                        setLayoutY(layoutY);
                    }

                    if ((getLayoutX() + (event.getX() - lastX) <= 0)) {
                        setLayoutX(0);
                    }
                }
            });
            addEventHandler(ZoomEvent.ZOOM_STARTED, new EventHandler<ZoomEvent>() {
                @Override public void handle(ZoomEvent event) {
                    startScale = getScaleX();
                }
            });
            addEventHandler(ZoomEvent.ZOOM, new EventHandler<ZoomEvent>() {
                @Override public void handle(ZoomEvent event) {
                    setScaleX(event.getTotalZoomFactor());
                    setScaleY(event.getTotalZoomFactor());
                }
            });
            addEventHandler(RotateEvent.ROTATION_STARTED, new EventHandler<RotateEvent>() {
                @Override public void handle(RotateEvent event) {
                    startRotate = getRotate();
                }
            });
            addEventHandler(RotateEvent.ROTATE, new EventHandler<RotateEvent>() {
                @Override public void handle(RotateEvent event) {
                    setRotate(event.getTotalAngle());
                }
            });

        }
    }

    @Override public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
        primaryStage.setFullScreen(true);
    }
    public static void main(String[] args) { launch(args); }
}
