package nodebox.handle; import nodebox.graphics.GraphicsContext; import nodebox.graphics.Path; import nodebox.graphics.Point; import nodebox.graphics.Rect; public class TranslateHandle extends AbstractHandle { public static final int HANDLE_LENGTH = 100; private enum DragState { NONE, CENTER, HORIZONTAL, VERTICAL } private String translateName; private double px, py; private double ox, oy; private float handleLength = HANDLE_LENGTH; private DragState dragState = DragState.NONE; public TranslateHandle() { this("translate"); } public TranslateHandle(String translateName) { this.translateName = translateName; update(); } @Override public void update() { setVisible(isConnected("shape")); } public void draw(GraphicsContext ctx) { Point cp = (Point) getValue(translateName); double x = cp.x; double y = cp.y; ctx.rectmode(GraphicsContext.RectMode.CENTER); Path p = new Path(); p.setFillColor(HANDLE_COLOR); ctx.stroke(HANDLE_COLOR); p.setStrokeColor(null); ctx.nofill(); drawDot(ctx, x, y); if (dragState == DragState.NONE) { // Horizontal and vertical direction lines. ctx.line(x, y, x + handleLength, y); ctx.line(x, y, x, y + handleLength); // Vertical arrow p.moveto(x, y + handleLength + 3); p.lineto(x - 5, y + handleLength - 3); p.lineto(x + 5, y + handleLength - 3); // Horizontal arrow p.moveto(x + handleLength + 3, y); p.lineto(x + handleLength - 3, y - 5); p.lineto(x + handleLength - 3, y + 5); } else if (dragState == DragState.CENTER) { ctx.line(px, py, x, y); drawDot(ctx, x, y); } else if (dragState == DragState.HORIZONTAL) { double x0, x1; ctx.line(px - handleLength, y, x + handleLength, y); if (x + handleLength > px - handleLength) { // arrow points right x0 = x + handleLength + 3; x1 = x + handleLength - 3; } else { // arrow points left x0 = x + handleLength - 3; x1 = x + handleLength + 3; } p.moveto(x0, y); p.lineto(x1, y - 5); p.lineto(x1, y + 5); } else if (dragState == DragState.VERTICAL) { double y0, y1; ctx.line(x, py - handleLength, x, y + handleLength); if (y + handleLength > py - handleLength) { // arrow points down y0 = y + handleLength + 3; y1 = y + handleLength - 3; } else { // arrow points up y0 = y + handleLength - 3; y1 = y + handleLength + 3; } p.moveto(x, y0); p.lineto(x - 5, y1); p.lineto(x + 5, y1); } ctx.nostroke(); ctx.draw(p); } @Override public boolean mousePressed(Point pt) { px = pt.getX(); py = pt.getY(); Point cp = (Point) getValue(translateName); double x = ox = cp.x; double y = oy = cp.y; Rect centerRect = createHitRectangle(x, y); Rect horRect = createHitRectangle(x + handleLength, y); Rect vertRect = createHitRectangle(x, y + handleLength); if (centerRect.contains(pt)) dragState = DragState.CENTER; else if (horRect.contains(pt)) dragState = DragState.HORIZONTAL; else if (vertRect.contains(pt)) dragState = DragState.VERTICAL; return (dragState != DragState.NONE); } @Override public boolean mouseDragged(Point pt) { if (dragState == DragState.NONE) return false; Point cp = (Point) getValue(translateName); double dx = pt.x - px; double dy = pt.y - py; if (dx == 0 && dy == 0) return false; startCombiningEdits("Set Value"); if (dragState == DragState.CENTER) { silentSet(translateName, new Point(ox + dx, oy + dy)); } else if (dragState == DragState.HORIZONTAL) silentSet(translateName, new Point(ox + dx, cp.y)); else if (dragState == DragState.VERTICAL) silentSet(translateName, new Point(cp.x, oy + dy)); return true; } @Override public boolean mouseReleased(Point pt) { if (dragState == DragState.NONE) return false; dragState = DragState.NONE; stopCombiningEdits(); updateHandle(); return true; } }