/* * Copyright 2016 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.tools; import pixelitor.gui.ImageComponent; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** * Represents the mouse drag on the image made by the user while using a tool. * The coordinates are in image coordinates. */ public class UserDrag { private double startX; private double startY; private double endX; private double endY; private boolean startFromCenter; private double oldEndX; private double oldEndY; private boolean constrainPoints = false; // the normal constructor public UserDrag() { } public UserDrag(double startX, double startY, double endX, double endY) { this.startX = startX; this.startY = startY; this.endX = endX; this.endY = endY; } public void setStartFromMouseEvent(MouseEvent e, ImageComponent ic) { startX = ic.componentXToImageSpace(e.getX()); startY = ic.componentYToImageSpace(e.getY()); } public void setEndFromMouseEvent(MouseEvent e, ImageComponent ic) { endX = ic.componentXToImageSpace(e.getX()); endY = ic.componentYToImageSpace(e.getY()); if (constrainPoints) { double dx = Math.abs(endX - startX); double dy = Math.abs(endY - startY); if (dx > dy) { endY = startY; } else { endX = startX; } } } public void setConstrainPoints(boolean constrainPoints) { this.constrainPoints = constrainPoints; } public double getStartX() { return startX; } public double getStartY() { return startY; } public double getStartXFromCenter() { if (startFromCenter) { return startX - (endX - startX); } else { return startX; } } public double getStartYFromCenter() { if (startFromCenter) { return startY - (endY - startY); } else { return startY; } } public double getEndX() { return endX; } public double getEndY() { return endY; } public Point2D.Double getStartPoint() { return new Point2D.Double(startX, startY); } public Point2D.Double getEndPoint() { return new Point2D.Double(endX, endY); } public double getDistance() { double dx = startX - endX; double dy = startY - endY; return Math.sqrt(dx * dx + dy * dy); } public double getStartDistanceFrom(double x, double y) { double dx = startX - x; double dy = startY - y; return Math.sqrt(dx * dx + dy * dy); } public double getDrawAngle() { return Math.atan2(endX - startX, endY - startY); // between -PI and PI } public double getAngleFromStartTo(double x, double y) { return Math.atan2(x - startX, y - startY); } public void drawLine(Graphics2D g) { g.draw(asLine()); } public Line2D asLine() { return new Line2D.Double(startX, startY, endX, endY); } public void saveEndValues() { oldEndX = endX; oldEndY = endY; } public void adjustStartForSpaceDownMove() { double dx = endX - oldEndX; double dy = endY - oldEndY; startX += dx; startY += dy; } public double getDX() { return endX - startX; } public double getDY() { return endY - startY; } /** * Creates a Rectangle where the sign of with/height indicate the direction of drawing * * @return a Rectangle where the width and height can be < 0 */ public Rectangle2D createPossiblyEmptyRect() { double x; double y; double width; double height; if (startFromCenter) { double halfWidth = endX - startX; // can be negative double halfHeight = endY - startY; // can be negative x = startX - halfWidth; y = startY - halfHeight; width = 2 * halfWidth; height = 2 * halfHeight; } else { x = startX; y = startY; width = endX - startX; height = endY - startY; } return new Rectangle2D.Double(x, y, width, height); } /** * Creates a Rectangle where the width/height are >=0 independently of the direction of the drawing * * @return a Rectangle where the width and height are >= 0 */ public Rectangle2D createPositiveRect() { double x; double y; double width; double height; if (startFromCenter) { double halfWidth; // positive or zero if (endX > startX) { halfWidth = endX - startX; x = startX - halfWidth; } else { halfWidth = startX - endX; x = endX; } double halfHeight; // positive or zero if (endY > startY) { halfHeight = endY - startY; y = startY - halfHeight; } else { halfHeight = startY - endY; y = endY; } width = 2 * halfWidth; height = 2 * halfHeight; } else { double tmpEndX; if (endX > startX) { x = startX; tmpEndX = endX; } else { x = endX; tmpEndX = startX; } double tmpEndY; if (endY > startY) { y = startY; tmpEndY = endY; } else { y = endY; tmpEndY = startY; } width = tmpEndX - x; height = tmpEndY - y; } return new Rectangle2D.Double(x, y, width, height); } public Point2D getCenterPoint() { double cx = (startX + endX) / 2.0; double cy = (startY + endY) / 2.0; return new Point2D.Double(cx, cy); } public void setStartFromCenter(boolean startFromCenter) { this.startFromCenter = startFromCenter; } // public Rectangle getAffectedStrokedRect(int thickness) { // Rectangle r = createPositiveRect(); // if (thickness == 0) { // return r; // } // // int halfThickness = thickness / 2 + 1; // int sizeEnlargement = thickness + 2; // // r.setBounds(r.x - halfThickness, r.y - halfThickness, r.width + sizeEnlargement, r.height + sizeEnlargement); // return r; // } public boolean isClick() { return ((startX == endX) && (startY == endY)); } public boolean isStartFromCenter() { return startFromCenter; } @Override public String toString() { return "UserDrag{" + "startX=" + startX + ", startY=" + startY + ", endX=" + endX + ", endY=" + endY + '}'; } public double taxiCabMetric(int x, int y) { return Math.abs(x - startX) + Math.abs(y - startY); } }