/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program 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 this program; if not, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.swing.figure.support;
import com.bc.ceres.swing.figure.AbstractHandle;
import com.bc.ceres.swing.figure.Figure;
import com.bc.ceres.swing.figure.FigureStyle;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
/**
* A {@link com.bc.ceres.swing.figure.Handle Handle} that can be used to rotate figures.
*
* @author Norman Fomferra
* @since Ceres 0.10
*/
public class RotateHandle extends AbstractHandle {
private final double radius;
private double theta;
public RotateHandle(Figure figure, FigureStyle style) {
super(figure, style, style);
radius = 80;
theta = 0;
setLocation();
setShape(createHandleShape(radius, theta));
}
@Override
public void updateLocation() {
setLocation();
}
private void setLocation() {
final Rectangle2D bounds = getFigure().getBounds();
final double centerX = bounds.getCenterX();
final double centerY = bounds.getCenterY();
setLocation(centerX, centerY);
}
@Override
public void move(double dx, double dy) {
setLocation(getX() + dx, getY() + dy);
RectangularShape handleShape = (RectangularShape) getShape();
double ax = handleShape.getCenterX() - getX();
double ay = handleShape.getCenterY() - getY();
final double theta1 = Math.atan2(ay, ax);
ax += dx;
ay += dy;
final double theta2 = Math.atan2(ay, ax);
final double delta = theta2 - theta1;
theta += delta;
getFigure().rotate(getLocation(), delta);
}
@Override
public void drawHandle(Graphics2D g) {
RectangularShape handleShape = (RectangularShape) getShape();
Shape anchorShape = new Ellipse2D.Double(-0.5 * StyleDefaults.ROTATE_ANCHOR_SIZE,
-0.5 * StyleDefaults.ROTATE_ANCHOR_SIZE,
StyleDefaults.ROTATE_ANCHOR_SIZE,
StyleDefaults.ROTATE_ANCHOR_SIZE);
Line2D connectionLine = new Line2D.Double(0.0,
0.0,
handleShape.getCenterX(),
handleShape.getCenterY());
g.setPaint(StyleDefaults.SELECTION_STROKE_PAINT);
g.setStroke(StyleDefaults.SELECTION_STROKE);
g.draw(connectionLine);
g.setPaint(getNormalStyle().getFillPaint());
g.fill(anchorShape);
g.setPaint(getNormalStyle().getStrokePaint());
g.setStroke(getNormalStyle().getStroke());
g.draw(anchorShape);
g.draw(new Line2D.Double(0, 0, 0, 0));
super.drawHandle(g);
}
private static Shape createHandleShape(double radius, double theta) {
Point2D rotateHandleCenter = new Point2D.Double(0, -radius);
rotateHandleCenter = AffineTransform.getRotateInstance(theta).transform(rotateHandleCenter, null);
return new Ellipse2D.Double(rotateHandleCenter.getX() - StyleDefaults.ROTATE_HANDLE_SIZE * 0.5,
rotateHandleCenter.getY() - StyleDefaults.ROTATE_HANDLE_SIZE * 0.5,
StyleDefaults.ROTATE_HANDLE_SIZE,
StyleDefaults.ROTATE_HANDLE_SIZE);
}
}