package nodebox.handle;
import nodebox.graphics.GraphicsContext;
import nodebox.graphics.Point;
import nodebox.graphics.Rect;
public class ScaleHandle extends AbstractHandle {
public static final int HANDLE_WIDTH = 100;
public static final int HANDLE_HEIGHT = 100;
private enum DragState {
NONE, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
}
private String scaleName;
private double px, py;
private double ox, oy;
private double handleWidth = HANDLE_WIDTH;
private double handleHeight = HANDLE_HEIGHT;
private boolean scaleHorizontal = true;
private boolean scaleVertical = true;
private DragState dragState = DragState.NONE;
public ScaleHandle() {
this("scale");
}
public ScaleHandle(String scaleName) {
this.scaleName = scaleName;
update();
}
@Override
public void update() {
setVisible(isConnected("shape"));
}
public void draw(GraphicsContext ctx) {
ctx.nofill();
ctx.stroke(HANDLE_COLOR);
double halfWidth = handleWidth / 2;
double halfHeight = handleHeight / 2;
ctx.rectmode(GraphicsContext.RectMode.CENTER);
ctx.rect(0, 0, handleWidth, handleHeight);
drawDot(ctx, -halfWidth, -halfHeight);
drawDot(ctx, halfWidth, -halfHeight);
drawDot(ctx, -halfWidth, halfHeight);
drawDot(ctx, halfWidth, halfHeight);
}
@Override
public boolean mousePressed(Point pt) {
double left = -handleWidth / 2;
double right = handleWidth / 2;
double top = -handleHeight / 2;
double bottom = handleHeight / 2;
Rect topLeft = createHitRectangle(left, top);
Rect topRight = createHitRectangle(right, top);
Rect bottomLeft = createHitRectangle(left, bottom);
Rect bottomRight = createHitRectangle(right, bottom);
px = pt.getX();
py = pt.getY();
Point op = (Point) getValue(scaleName);
ox = op.x;
oy = op.y;
if (topLeft.contains(pt))
dragState = DragState.TOP_LEFT;
else if (topRight.contains(pt))
dragState = DragState.TOP_RIGHT;
else if (bottomLeft.contains(pt))
dragState = DragState.BOTTOM_LEFT;
else if (bottomRight.contains(pt))
dragState = DragState.BOTTOM_RIGHT;
else
dragState = DragState.NONE;
return (dragState != DragState.NONE);
}
@Override
public boolean mouseDragged(Point pt) {
if (dragState == DragState.NONE) return false;
double x = pt.getX();
double y = pt.getY();
double dx = x - px;
double dy = y - py;
if (dx == 0 && dy == 0) return false;
startCombiningEdits("Set Value");
if (dragState == DragState.TOP_LEFT) {
handleWidth = HANDLE_WIDTH - dx * 2;
handleHeight = HANDLE_HEIGHT - dy * 2;
} else if (dragState == DragState.TOP_RIGHT) {
handleWidth = HANDLE_WIDTH + dx * 2;
handleHeight = HANDLE_HEIGHT - dy * 2;
} else if (dragState == DragState.BOTTOM_LEFT) {
handleWidth = HANDLE_WIDTH - dx * 2;
handleHeight = HANDLE_HEIGHT + dy * 2;
} else if (dragState == DragState.BOTTOM_RIGHT) {
handleWidth = HANDLE_WIDTH + dx * 2;
handleHeight = HANDLE_HEIGHT + dy * 2;
}
double pctX = handleWidth / HANDLE_WIDTH;
double pctY = handleHeight / HANDLE_HEIGHT;
Point op = (Point) getValue(scaleName);
if (scaleHorizontal)
op = new Point(ox * pctX, op.y);
else
handleWidth = HANDLE_WIDTH;
if (scaleVertical)
op = new Point(op.x, oy * pctY);
else
handleHeight = HANDLE_HEIGHT;
silentSet(scaleName, op);
return true;
}
@Override
public boolean mouseReleased(Point pt) {
if (dragState == DragState.NONE) return false;
handleWidth = HANDLE_WIDTH;
handleHeight = HANDLE_HEIGHT;
dragState = DragState.NONE;
stopCombiningEdits();
updateHandle();
return true;
}
@Override
public boolean keyPressed(int keyCode, int modifiers) {
if ((modifiers & SHIFT_DOWN) != 0) scaleVertical = false;
else if ((modifiers & META_DOWN) != 0) scaleHorizontal = false;
return true;
}
@Override
public boolean keyReleased(int keyCode, int modifiers) {
scaleHorizontal = true;
scaleVertical = true;
return false;
}
}