/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
/**
* @(#)AbstractRotateHandle.java 4.0 2008-05-11
*
* Copyright (c) 1996-2008 by the original authors of JHotDraw
* and all its contributors.
* All rights reserved.
*
* The copyright of this software is owned by the authors and
* contributors of the JHotDraw project ("the copyright holders").
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* the copyright holders. For details see accompanying license terms.
*/
package org.jhotdraw.draw;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.geom.*;
import org.jhotdraw.geom.*;
import org.jhotdraw.util.*;
/**
* AbstractRotateHandle.
*
* @author Werner Randelshofer
* @version 4.0 2008-05-11 Handle attributes are now retrieved from
* DrawingEditor.
* <br>3.0.1 2007-12-22 Werner Randelshofer: Fixed computation of current
* theta.
* <br>3.0 2007-11-28 Huw Jones: Split up into an AbstractRotateHandle class
* and a concrete default RotateHandle class.
* <br>2.0 2007-04-14 Werner Randelshofer: Added support for AttributeKeys.TRANSFORM.
* <br>1.0 2006-06-12 Werner Randelshofer: Created.
*/
public abstract class AbstractRotateHandle extends AbstractHandle {
private Point location;
private Object restoreData;
private AffineTransform transform;
private Point2D.Double center;
private double startTheta;
private double startLength;
/** Creates a new instance. */
public AbstractRotateHandle(Figure owner) {
super(owner);
}
@Override
public boolean isCombinableWith(Handle h) {
return false;
}
@Override
public String getToolTipText(Point p) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
return labels.getString("handle.rotate.toolTipText");
}
/**
* Draws this handle.
*/
@Override
public void draw(Graphics2D g) {
if (getEditor().getTool().supportsHandleInteraction()) {
drawCircle(g,
(Color) getEditor().getHandleAttribute(HandleAttributeKeys.ROTATE_HANDLE_FILL_COLOR),
(Color) getEditor().getHandleAttribute(HandleAttributeKeys.ROTATE_HANDLE_STROKE_COLOR));
} else {
drawCircle(g,
(Color) getEditor().getHandleAttribute(HandleAttributeKeys.ROTATE_HANDLE_FILL_COLOR_DISABLED),
(Color) getEditor().getHandleAttribute(HandleAttributeKeys.ROTATE_HANDLE_STROKE_COLOR_DISABLED));
}
}
@Override
protected Rectangle basicGetBounds() {
Rectangle r = new Rectangle(getLocation());
int h = getHandlesize();
r.x -= h / 2;
r.y -= h / 2;
r.width = r.height = h;
return r;
}
public Point getLocation() {
if (location == null) {
return view.drawingToView(getOrigin());
}
return location;
}
protected Rectangle2D.Double getTransformedBounds() {
Figure owner = getOwner();
Rectangle2D.Double bounds = owner.getBounds();
if (AttributeKeys.TRANSFORM.get(owner) != null) {
Rectangle2D r = AttributeKeys.TRANSFORM.get(owner).
createTransformedShape(bounds).getBounds2D();
bounds.x = r.getX();
bounds.y = r.getY();
bounds.width = r.getWidth();
bounds.height = r.getHeight();
}
return bounds;
}
protected Object getRestoreData() {
return restoreData;
}
protected double getStartTheta() {
return startTheta;
}
protected abstract Point2D.Double getOrigin();
protected abstract Point2D.Double getCenter();
public void trackStart(Point anchor, int modifiersEx) {
location = new Point(anchor.x, anchor.y);
restoreData = getOwner().getTransformRestoreData();
transform = new AffineTransform();
center = getCenter();
Point2D.Double anchorPoint = view.viewToDrawing(anchor);
startTheta = Geom.angle(center.x, center.y, anchorPoint.x, anchorPoint.y);
startLength = Geom.length(center.x, center.y, anchorPoint.x, anchorPoint.y);
}
public void trackStep(Point anchor, Point lead, int modifiersEx) {
location = new Point(lead.x, lead.y);
Point2D.Double leadPoint = view.viewToDrawing(lead);
double stepTheta = Geom.angle(center.x, center.y, leadPoint.x, leadPoint.y);
double stepLength = Geom.length(center.x, center.y, leadPoint.x, leadPoint.y);
double currentTheta = view.getConstrainer().constrainAngle(stepTheta - startTheta);
transform.setToIdentity();
transform.translate(center.x, center.y);
transform.rotate(currentTheta);
transform.translate(-center.x, -center.y);
getOwner().willChange();
getOwner().restoreTransformTo(restoreData);
getOwner().transform(transform);
getOwner().changed();
}
public void trackEnd(Point anchor, Point lead, int modifiersEx) {
view.getDrawing().fireUndoableEditHappened(
new RestoreDataEdit(getOwner(), restoreData));
fireAreaInvalidated(getDrawingArea());
location = null;
invalidate();
fireAreaInvalidated(getDrawingArea());
}
@Override
public void keyPressed(KeyEvent evt) {
Figure f = getOwner();
center = getCenter();
if (f.isTransformable()) {
AffineTransform tx = new AffineTransform();
switch (evt.getKeyCode()) {
case KeyEvent.VK_UP:
case KeyEvent.VK_LEFT:
tx.rotate(-1d / 180d * Math.PI, center.x, center.y);
evt.consume();
break;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_RIGHT:
tx.rotate(1d / 180d * Math.PI, center.x, center.y);
evt.consume();
break;
}
f.willChange();
f.transform(tx);
f.changed();
fireUndoableEditHappened(
new TransformEdit(f, tx));
}
}
}