Package com.kodcu.fxdecorate

Source Code of com.kodcu.fxdecorate.FxDecorateController$MoveNodeDraggedEventHandler

/*
* This file is part of FxDecorate.
*
* Copyright (c) 2013 narrowtux <http://www.narrowtux.com/>
* FxDecorate is licensed under the GNU Lesser General Public License.
*
* FxDecorate is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FxDecorate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.kodcu.fxdecorate;

import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.stage.Screen;
import javafx.stage.Stage;

import java.util.LinkedList;
import java.util.List;

//https://github.com/rahmanusta/FxDecorate
public class FxDecorateController {
    private final class ResizeNodeDraggedHandler implements EventHandler<MouseEvent> {
        private final Node handle;

        private ResizeNodeDraggedHandler(Node handle) {
            this.handle = handle;
        }

        public void handle(MouseEvent e) {
            if (currentResizeHandle.equals(handle.getCursor())) {
                double dX = e.getScreenX() - moveStartPoint.getX();
                double dY = e.getScreenY() - moveStartPoint.getY();
                Stage stage = getScene().getStage();
                if (currentResizeHandle == Cursor.W_RESIZE || currentResizeHandle == Cursor.NW_RESIZE || currentResizeHandle == Cursor.SW_RESIZE) {
                    if (setWindowWidth(startWidth - dX)) {
                        stage.setX(startX + dX);
                    }
                }
                if (currentResizeHandle == Cursor.N_RESIZE || currentResizeHandle == Cursor.NW_RESIZE || currentResizeHandle == Cursor.NE_RESIZE) {
                    if (setWindowHeight(startHeight - dY)) {
                        stage.setY(startY + dY);
                    }
                }
                if (currentResizeHandle == Cursor.E_RESIZE || currentResizeHandle == Cursor.SE_RESIZE || currentResizeHandle == Cursor.NE_RESIZE) {
                    setWindowWidth(startWidth + dX);
                }
                if (currentResizeHandle == Cursor.S_RESIZE || currentResizeHandle == Cursor.SE_RESIZE || currentResizeHandle == Cursor.SW_RESIZE) {
                    setWindowHeight(startHeight + dY);
                }
                e.consume();
            }

        }
    }

    private final class MoveNodeDraggedEventHandler implements EventHandler<MouseEvent> {
        private final Node added;

        private MoveNodeDraggedEventHandler(Node added) {
            this.added = added;
        }

        public void handle(MouseEvent e) {
            if (currentMoveNode.equals(added)) {
                Point2D delta = new Point2D(e.getScreenX() - moveStartPoint.getX(), e.getScreenY() - moveStartPoint.getY());
                double stageX = getScene().getWindow().getX();
                double stageY = getScene().getWindow().getY();

                stageX += delta.getX();
                stageY += delta.getY();

                Rectangle2D newBounds = new Rectangle2D(stageX, stageY, getScene().getWindow().getWidth(), getScene().getWindow().getHeight());

                // check screen bounds
                for (Screen screen : Screen.getScreensForRectangle(newBounds)) {
                    // Limit dragging over menu bar
                    if (screen.getVisualBounds().equals(Screen.getPrimary().getVisualBounds())
                            && OperatingSystem.getOS().isMac()
                            && stageY < screen.getVisualBounds().getMinY()) {
                        stageY = screen.getVisualBounds().getMinY();
                    }
                }

                getScene().getWindow().setX(stageX);
                getScene().getWindow().setY(stageY);
                moveStartPoint = new Point2D(e.getScreenX(), e.getScreenY());
                e.consume();
            }
        }
    }

    private List<Node> moveNodes = new LinkedList<Node>();
    private Node primaryMoveNode = null;
    private FxDecorateScene scene;
    private Node currentMoveNode = null;
    private Point2D moveStartPoint = null;

    FxDecorateController(FxDecorateScene scene) {
        this.scene = scene;
    }

    public void addMoveNode(final Node added) {
        if (primaryMoveNode == null) {
            primaryMoveNode = added;
        }
        moveNodes.add(added);
        added.setOnMousePressed(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent e) {
                currentMoveNode = added;
                moveStartPoint = new Point2D(e.getScreenX(), e.getScreenY());
                e.consume();
            }
        });

        added.setOnMouseDragged(new MoveNodeDraggedEventHandler(added));

        added.setOnMouseReleased(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent e) {
                if (currentMoveNode.equals(added)) {
                    currentMoveNode = null;
                    // checkScreenEdges();
                    e.consume();
                }
            }
        });
    }

    public void removeMoveNode(final Node removed) {
        moveNodes.remove(removed);
        removed.setOnMouseMoved(null);
        removed.setOnMousePressed(null);
        removed.setOnMouseReleased(null);
    }

    public FxDecorateScene getScene() {
        return scene;
    }

    public void centerOnScreen() {
        Screen primary = Screen.getPrimary();
        Rectangle2D bounds = primary.getVisualBounds();
        double width = getScene().getStage().getWidth();
        double height = getScene().getStage().getHeight();
        double x = bounds.getMinX() + (bounds.getWidth() - width) / 2d;
        double y = bounds.getMinY() + (bounds.getHeight() - height) / 2d;

        getScene().getWindow().setX(x);
        getScene().getWindow().setY(y);
    }

    /**
     * checks if the primary move node is off screen and if so, resets the
     * window so it is visible again.
     */
    public void checkScreenEdges() {
        if (primaryMoveNode == null) {
            return;
        }

        double minX = Double.MAX_VALUE;
        double maxX = Double.MIN_VALUE;
        double minY = Double.MAX_VALUE;
        double maxY = Double.MIN_VALUE;

        for (Screen screen : Screen.getScreens()) {
            minX = Math.min(minX, screen.getVisualBounds().getMinX());
            minY = Math.min(minY, screen.getVisualBounds().getMinY());

            maxX = Math.max(maxX, screen.getVisualBounds().getMaxX());
            maxY = Math.max(maxY, screen.getVisualBounds().getMaxY());
        }

        Rectangle2D bounds = getScreenBounds(primaryMoveNode);
        Rectangle2D valid = bounds;
        if (!isValidBounds(bounds)) {
            if (bounds.getMinY() < minY || bounds.getMaxY() > maxY) {
                int dir = 1;
                if (bounds.getMaxY() > maxY) {
                    dir = -1;
                }
                for (double y = minX; y <= maxY && y >= minY; y += dir) {
                    Rectangle2D test = cloneRect(bounds, null, y, null, null);
                    if (isValidBounds(test)) {
                        valid = test;
                    }
                }
            }
        }
        // TODO handle when new bounds were found
    }

    private double startX, startY, startWidth, startHeight;
    private Cursor currentResizeHandle = null;

    void setResizeableHandle(final Node handle) {
        handle.setOnMousePressed(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent e) {
                if (currentResizeHandle == null) {
                    startX = getScene().getWindow().getX();
                    startY = getScene().getWindow().getY();
                    startWidth = getScene().getWindow().getWidth();
                    startHeight = getScene().getWindow().getHeight();
                    moveStartPoint = new Point2D(e.getScreenX(), e.getScreenY());
                    currentResizeHandle = handle.getCursor();
                    e.consume();
                }
            }
        });
        handle.setOnMouseDragged(new ResizeNodeDraggedHandler(handle));
        handle.setOnMouseReleased(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent e) {
                currentResizeHandle = null;
                moveStartPoint = null;
                e.consume();
            }
        });
    }

    private boolean setWindowHeight(double height) {
        if (height > getScene().getStage().getMaxWidth()) {
            return false;
        }
        if (height < getScene().getStage().getMinHeight()) {
            return false;
        }
        getScene().getStage().setHeight(height);
        return true;
    }

    private boolean setWindowWidth(double width) {
        if (width > getScene().getStage().getMaxWidth()) {
            return false;
        }
        if (width < getScene().getStage().getMinWidth()) {
            return false;
        }
        getScene().getStage().setWidth(width);
        return true;
    }

    /**
     * Returns if the given rectangle has a valid position for a primary move
     * node.<br/>
     * Conditions are:
     * <ul>
     * <li>at least 10 vertical pixels must be visible</li>
     * <li>the whole height must be visible</li>
     * </ul>
     *
     * @param bounds the rectangle that should be checked
     * @return
     */
    public boolean isValidBounds(Rectangle2D bounds) {
        ObservableList<Screen> screens = Screen.getScreensForRectangle(bounds);
        if (screens.size() == 0) {
            return false;
        }
        for (Screen screen : Screen.getScreensForRectangle(bounds)) {
            Rectangle2D vis = screen.getVisualBounds();
            if (bounds.getMinY() < vis.getMinY() || bounds.getMaxY() > vis.getMaxY()) {
                return false;
            }
        }
        return true;
    }

    /**
     * Manually sets the primary move node.<br/>
     * It will be made sure that this node is always available to be dragged so
     * the user can't move it off screen and have no possibility to drag it.
     *
     * @param primaryMoveNode
     */
    public void setPrimaryMoveNode(Node primaryMoveNode) {
        this.primaryMoveNode = primaryMoveNode;
    }

    public Node getPrimaryMoveNode() {
        return primaryMoveNode;
    }

    private static Rectangle2D getScreenBounds(Node node) {
        double windowX = node.getScene().getWindow().getX();
        double windowY = node.getScene().getWindow().getY();

        Point2D scenepos = node.localToScene(0, 0);

        windowX += scenepos.getX();
        windowY += scenepos.getY();

        return new Rectangle2D(windowX, windowY, node.getLayoutBounds().getWidth(), node.getLayoutBounds().getHeight());
    }

    private static Rectangle2D cloneRect(Rectangle2D c, Double x, Double y, Double width, Double height) {
        return new Rectangle2D(x != null ? x : c.getMinX(), y != null ? y : c.getMinY(), width != null ? width : c.getWidth(), height != null ? height : c.getHeight());
    }
}
TOP

Related Classes of com.kodcu.fxdecorate.FxDecorateController$MoveNodeDraggedEventHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.