X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fg2d%2Fnodes%2FTransformableSelectionNode.java;fp=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fg2d%2Fnodes%2FTransformableSelectionNode.java;h=3cb77242800a5395acdfb51a92ec8f819adfdf60;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=8bf623c0b737b2ccbecc8985604e278b4146f698;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformableSelectionNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformableSelectionNode.java index 8bf623c0b..3cb772428 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformableSelectionNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TransformableSelectionNode.java @@ -1,367 +1,367 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.scenegraph.g2d.nodes; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.geom.Path2D; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import org.simantics.scenegraph.g2d.G2DNode; -import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.IG2DNode; -import org.simantics.scenegraph.g2d.IdentityAffineTransform; -import org.simantics.scenegraph.g2d.events.EventTypes; -import org.simantics.scenegraph.g2d.events.MouseEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; -import org.simantics.scenegraph.utils.GeometryUtils; -import org.simantics.scenegraph.utils.NodeUtil; - -/** - * @author J-P Laine - * @author Tuukka Lehtonen - */ -public class TransformableSelectionNode extends G2DNode { - - public static interface TransformCallback { - public void moved(Point2D delta); - public void resized(Point2D delta); - } - - private static final long serialVersionUID = -2879575230419873230L; - - private static final int HEADER_HEIGHT = 10; - - public transient static final BasicStroke SELECTION_STROKE = new BasicStroke(1.0f, - BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, - new float[] { 5.0f, 5.0f }, 0.0f); - - protected Rectangle2D bounds = null; - protected Color color = null; - protected Boolean resizeable = Boolean.FALSE; - - protected double minWidth = 7; - protected double minHeight = 7; - - protected transient Point2D dragDelta = null; - protected transient Point2D orig = null; - protected transient Boolean resize = null; - - protected transient Point2D temp = new Point2D.Double(); - protected transient Path2D path = new Path2D.Double(); - protected transient Rectangle2D rect = new Rectangle2D.Double(); - - protected transient TransformCallback transformCallback = null; - - @Override - public void init() { - super.init(); - addEventHandler(this); - } - - @Override - public void cleanup() { - removeEventHandler(this); - super.cleanup(); - } - - @SyncField({"transform", "bounds", "color", "resizeable", "minWidth", "minHeight"}) - public void init(AffineTransform transform, Rectangle2D bounds, Color color, boolean resizeable, double minWidth, double minHeight) { -// System.out.println("init("+transform+", "+bounds+", "+color+", "+resizeable+")"); - this.transform = transform; - this.bounds = bounds; - this.color = color; - this.resizeable = resizeable; - this.minWidth = minWidth; - this.minHeight = minHeight; - } - - @SyncField({"transform", "bounds", "color", "resizeable"}) - public void init(AffineTransform transform, Rectangle2D bounds, Color color, boolean resizeable) { -// System.out.println("init("+transform+", "+bounds+", "+color+", "+resizeable+")"); - this.transform = transform; - this.bounds = bounds; - this.color = color; - this.resizeable = resizeable; - } - - @SyncField({"transform", "bounds", "color"}) - public void init(AffineTransform transform, Rectangle2D bounds, Color color) { -// System.out.println("init("+transform+", "+bounds+", "+color+")"); - this.transform = transform; - this.bounds = bounds; - this.color = color; - } - - @Override - public void render(Graphics2D g) { - if (bounds == null) - return; - AffineTransform ot = g.getTransform(); - - g.setColor(color); - g.transform(transform); - - AffineTransform tx = g.getTransform(); - //System.out.println("tx: " + tx); - double scale = GeometryUtils.getScale(tx); - //System.out.println("scale: " + scale); - double scaleRecip = 1.0 / scale; - //System.out.println("scale: " + scaleRecip); - - BasicStroke scaledStroke = GeometryUtils.scaleStroke( SELECTION_STROKE, (float) scaleRecip); - g.setStroke(scaledStroke); - - double padding = 0.0 * scaleRecip; - double paddingX = padding; - double paddingY = padding; - - g.draw(new Rectangle2D.Double(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY, - bounds.getWidth() + 2.0*paddingX, bounds.getHeight() + 2.0*paddingY)); - - double right = (bounds.getMinX() - paddingX + bounds.getWidth() + 2.0*paddingX); - double bottom = (bounds.getMinY() - paddingY + bounds.getHeight() + 2.0*paddingY); - - if (resizeable) { - Path2D corner = new Path2D.Double(); - corner.moveTo(right-8-paddingX, bottom); - corner.lineTo(right, bottom - 8 - paddingY); - corner.lineTo(right, bottom); - corner.closePath(); - g.setColor(new Color(20, 20, 20, 120)); - g.fill(corner); - - g.setColor(color); - g.draw(new Line2D.Double(right-8-paddingX, bottom, right, bottom - 8 - paddingY)); - } - - Rectangle2D header = new Rectangle2D.Double(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY, bounds.getWidth() + 2.0*paddingX, HEADER_HEIGHT); - g.setColor(new Color(20, 20, 20, 120)); - g.fill(header); - - g.setColor(color); - g.draw(new Line2D.Double(bounds.getMinX(), bounds.getMinY()+HEADER_HEIGHT, right, bounds.getMinY()+HEADER_HEIGHT)); - - g.setTransform(ot); - } - - @Override - public Rectangle2D getBoundsInLocal() { - return bounds; - } - - public void setTransformCallback(TransformCallback transformCallback) { - this.transformCallback = transformCallback; - } - - @ServerSide - protected void resized(Point2D size) { - if (transformCallback != null) { - transformCallback.resized(size); - } - } - - @ServerSide - protected void moved(Point2D location) { - if (transformCallback != null) { - transformCallback.moved(location); - } - } - - @Override - public boolean mouseMoved(MouseMovedEvent e) { - boolean consume = false; - - Point2D scale = getScale(temp); - final double sx = scale.getX(); - final double sy = scale.getY(); - - Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, temp); - final double mx = localPos.getX(); - final double my = localPos.getY(); - - AffineTransform i = AffineTransform.getTranslateInstance(-transform.getTranslateX()*sx, -transform.getTranslateY()*sy); - Point2D p = i.transform(new Point2D.Double(sx*mx, sy*my), null); - - boolean dragging = (e.buttons & MouseEvent.LEFT_MASK) != 0; - - if (dragging && dragDelta != null) { - double x = (p.getX() - dragDelta.getX())/sx;// /transform.getScaleX(); - double y = (p.getY() - dragDelta.getY())/sy;// /transform.getScaleY(); - if (Boolean.TRUE.equals(resize)) { - - double width; - double pointX; - if (bounds.getWidth() + x < minWidth) { - width = minWidth; - pointX = dragDelta.getX(); - } else { - width = bounds.getWidth() + x; - pointX = p.getX(); - } - - double height; - double pointY; - if (bounds.getHeight() + y < minHeight) { - height = minHeight; - pointY = dragDelta.getY(); - } else { - height = bounds.getHeight() + y; - pointY = p.getY(); - } - -// System.out.println("bounds.getX()=" + bounds.getX() + " bounds.getY())=" + bounds.getY()); -// System.out.println("width=" + width + " height=" + height); - - bounds.setFrame(bounds.getX(), bounds.getY(), width, height); - dragDelta = new Point2D.Double(pointX, pointY); // TODO .. - - } else if (Boolean.FALSE.equals(resize)) { - if (transform == IdentityAffineTransform.INSTANCE) - transform = AffineTransform.getTranslateInstance(x, y); - else - transform.translate(x, y); - } - - //dragDelta = new Point2D.Double(me.getPoint().getX(), me.getPoint().getY()); - repaint(); - } else { - final double paddingX = 0.0; - final double paddingY = 0.0; - - Path2D corner = createCorner(path, bounds, paddingX, paddingY, sx, sy); - Rectangle2D header = createRectangle(rect, bounds, paddingX, paddingY, sx, sy); - - if (corner.contains(p)) { - setCursor(Cursor.HAND_CURSOR); - //consume = true; - } else if (header.contains(p)) { - setCursor(Cursor.HAND_CURSOR); - //consume = true; - } else { - setCursor(Cursor.DEFAULT_CURSOR); - } - } - - return consume; - } - - @Override - protected boolean mouseButtonPressed(MouseButtonPressedEvent e) { - boolean consume = false; - - if (e.button == MouseEvent.LEFT_BUTTON && !e.hasAnyModifier(MouseEvent.ALL_MODIFIERS_MASK)) { - Point2D scale = getScale(temp); - final double sx = scale.getX(); - final double sy = scale.getY(); - - Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, temp); - final double mx = localPos.getX(); - final double my = localPos.getY(); - - AffineTransform i = AffineTransform.getTranslateInstance(-transform.getTranslateX()*sx, -transform.getTranslateY()*sy); - Point2D p = i.transform(new Point2D.Double(sx*mx, sy*my), null); - - final double paddingX = 0.0; - final double paddingY = 0.0; - - Path2D corner = createCorner(path, bounds, paddingX, paddingY, sx, sy); - Rectangle2D header = createRectangle(rect, bounds, paddingX, paddingY, sx, sy); - - if (corner.contains(p)) {// me.getPoint().getX() > right-5-paddingX && me.getPoint().getY() > bottom - 5 - paddingY) { - if (orig == null) - orig = new Point2D.Double(bounds.getWidth(), bounds.getHeight()); - resize = Boolean.TRUE; - setCursor(Cursor.SE_RESIZE_CURSOR); - consume = true; - } else if (header.contains(p)) {// me.getPoint().getY() < bounds.getMinY()+8) { - if (orig == null) - orig = new Point2D.Double(transform.getTranslateX(), transform.getTranslateY()); - resize = Boolean.FALSE; - setCursor(Cursor.MOVE_CURSOR); - consume = true; - } else { - resize = null; - } - - dragDelta = new Point2D.Double(p.getX(), p.getY()); - - repaint(); - } - return consume; - } - - @Override - protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) { - if (orig != null) { - setCursor(Cursor.DEFAULT_CURSOR); - if (resize) { - Point2D delta = new Point2D.Double(bounds.getWidth() - orig.getX(), bounds.getHeight() - orig.getY()); - resized(delta); - } else { - Point2D delta = new Point2D.Double((transform.getTranslateX() - orig.getX()), (transform.getTranslateY() - orig.getY())); - moved(delta); - } - orig = null; - return true; - } - return false; - } - - @Override - public int getEventMask() { - return EventTypes.MouseButtonPressedMask | EventTypes.MouseButtonReleasedMask | EventTypes.MouseMovedMask; - } - - private Point2D getScale(Point2D result) { - double sx = 1.0, sy = 1.0; - IG2DNode node = (IG2DNode) this.getParent(); - while (node != null) { - sx *= node.getTransform().getScaleX(); - sy *= node.getTransform().getScaleY(); - // FIXME: it should be G2DParentNode but you can never be sure - node = (G2DParentNode) node.getParent(); - } - result.setLocation(sx, sy); - return result; - } - - private static Rectangle2D createRectangle(Rectangle2D result, Rectangle2D bounds, - double paddingX, double paddingY, double sx, double sy) { - result.setFrame( - (bounds.getMinX() - paddingX)*sx, - (bounds.getMinY() - paddingY)*sy, - (bounds.getWidth() + 2.0 * paddingX) * sx, - HEADER_HEIGHT*sy); - return result; - } - - private static Path2D createCorner(Path2D result, Rectangle2D bounds, - double paddingX, double paddingY, double sx, double sy) { - final double right = (bounds.getMinX() - paddingX + bounds.getWidth() + 2.0 * paddingX); - final double bottom = (bounds.getMinY() - paddingY + bounds.getHeight() + 2.0 * paddingY); - result.reset(); - result.moveTo((right - 8 - paddingX) * sx, bottom * sy); - result.lineTo(right * sx, (bottom - 8 - paddingY) * sy); - result.lineTo(right * sx, bottom * sy); - result.closePath(); - return result; - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.g2d.nodes; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.scenegraph.g2d.G2DNode; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.IG2DNode; +import org.simantics.scenegraph.g2d.IdentityAffineTransform; +import org.simantics.scenegraph.g2d.events.EventTypes; +import org.simantics.scenegraph.g2d.events.MouseEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; +import org.simantics.scenegraph.utils.GeometryUtils; +import org.simantics.scenegraph.utils.NodeUtil; + +/** + * @author J-P Laine + * @author Tuukka Lehtonen + */ +public class TransformableSelectionNode extends G2DNode { + + public static interface TransformCallback { + public void moved(Point2D delta); + public void resized(Point2D delta); + } + + private static final long serialVersionUID = -2879575230419873230L; + + private static final int HEADER_HEIGHT = 10; + + public transient static final BasicStroke SELECTION_STROKE = new BasicStroke(1.0f, + BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, + new float[] { 5.0f, 5.0f }, 0.0f); + + protected Rectangle2D bounds = null; + protected Color color = null; + protected Boolean resizeable = Boolean.FALSE; + + protected double minWidth = 7; + protected double minHeight = 7; + + protected transient Point2D dragDelta = null; + protected transient Point2D orig = null; + protected transient Boolean resize = null; + + protected transient Point2D temp = new Point2D.Double(); + protected transient Path2D path = new Path2D.Double(); + protected transient Rectangle2D rect = new Rectangle2D.Double(); + + protected transient TransformCallback transformCallback = null; + + @Override + public void init() { + super.init(); + addEventHandler(this); + } + + @Override + public void cleanup() { + removeEventHandler(this); + super.cleanup(); + } + + @SyncField({"transform", "bounds", "color", "resizeable", "minWidth", "minHeight"}) + public void init(AffineTransform transform, Rectangle2D bounds, Color color, boolean resizeable, double minWidth, double minHeight) { +// System.out.println("init("+transform+", "+bounds+", "+color+", "+resizeable+")"); + this.transform = transform; + this.bounds = bounds; + this.color = color; + this.resizeable = resizeable; + this.minWidth = minWidth; + this.minHeight = minHeight; + } + + @SyncField({"transform", "bounds", "color", "resizeable"}) + public void init(AffineTransform transform, Rectangle2D bounds, Color color, boolean resizeable) { +// System.out.println("init("+transform+", "+bounds+", "+color+", "+resizeable+")"); + this.transform = transform; + this.bounds = bounds; + this.color = color; + this.resizeable = resizeable; + } + + @SyncField({"transform", "bounds", "color"}) + public void init(AffineTransform transform, Rectangle2D bounds, Color color) { +// System.out.println("init("+transform+", "+bounds+", "+color+")"); + this.transform = transform; + this.bounds = bounds; + this.color = color; + } + + @Override + public void render(Graphics2D g) { + if (bounds == null) + return; + AffineTransform ot = g.getTransform(); + + g.setColor(color); + g.transform(transform); + + AffineTransform tx = g.getTransform(); + //System.out.println("tx: " + tx); + double scale = GeometryUtils.getScale(tx); + //System.out.println("scale: " + scale); + double scaleRecip = 1.0 / scale; + //System.out.println("scale: " + scaleRecip); + + BasicStroke scaledStroke = GeometryUtils.scaleStroke( SELECTION_STROKE, (float) scaleRecip); + g.setStroke(scaledStroke); + + double padding = 0.0 * scaleRecip; + double paddingX = padding; + double paddingY = padding; + + g.draw(new Rectangle2D.Double(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY, + bounds.getWidth() + 2.0*paddingX, bounds.getHeight() + 2.0*paddingY)); + + double right = (bounds.getMinX() - paddingX + bounds.getWidth() + 2.0*paddingX); + double bottom = (bounds.getMinY() - paddingY + bounds.getHeight() + 2.0*paddingY); + + if (resizeable) { + Path2D corner = new Path2D.Double(); + corner.moveTo(right-8-paddingX, bottom); + corner.lineTo(right, bottom - 8 - paddingY); + corner.lineTo(right, bottom); + corner.closePath(); + g.setColor(new Color(20, 20, 20, 120)); + g.fill(corner); + + g.setColor(color); + g.draw(new Line2D.Double(right-8-paddingX, bottom, right, bottom - 8 - paddingY)); + } + + Rectangle2D header = new Rectangle2D.Double(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY, bounds.getWidth() + 2.0*paddingX, HEADER_HEIGHT); + g.setColor(new Color(20, 20, 20, 120)); + g.fill(header); + + g.setColor(color); + g.draw(new Line2D.Double(bounds.getMinX(), bounds.getMinY()+HEADER_HEIGHT, right, bounds.getMinY()+HEADER_HEIGHT)); + + g.setTransform(ot); + } + + @Override + public Rectangle2D getBoundsInLocal() { + return bounds; + } + + public void setTransformCallback(TransformCallback transformCallback) { + this.transformCallback = transformCallback; + } + + @ServerSide + protected void resized(Point2D size) { + if (transformCallback != null) { + transformCallback.resized(size); + } + } + + @ServerSide + protected void moved(Point2D location) { + if (transformCallback != null) { + transformCallback.moved(location); + } + } + + @Override + public boolean mouseMoved(MouseMovedEvent e) { + boolean consume = false; + + Point2D scale = getScale(temp); + final double sx = scale.getX(); + final double sy = scale.getY(); + + Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, temp); + final double mx = localPos.getX(); + final double my = localPos.getY(); + + AffineTransform i = AffineTransform.getTranslateInstance(-transform.getTranslateX()*sx, -transform.getTranslateY()*sy); + Point2D p = i.transform(new Point2D.Double(sx*mx, sy*my), null); + + boolean dragging = (e.buttons & MouseEvent.LEFT_MASK) != 0; + + if (dragging && dragDelta != null) { + double x = (p.getX() - dragDelta.getX())/sx;// /transform.getScaleX(); + double y = (p.getY() - dragDelta.getY())/sy;// /transform.getScaleY(); + if (Boolean.TRUE.equals(resize)) { + + double width; + double pointX; + if (bounds.getWidth() + x < minWidth) { + width = minWidth; + pointX = dragDelta.getX(); + } else { + width = bounds.getWidth() + x; + pointX = p.getX(); + } + + double height; + double pointY; + if (bounds.getHeight() + y < minHeight) { + height = minHeight; + pointY = dragDelta.getY(); + } else { + height = bounds.getHeight() + y; + pointY = p.getY(); + } + +// System.out.println("bounds.getX()=" + bounds.getX() + " bounds.getY())=" + bounds.getY()); +// System.out.println("width=" + width + " height=" + height); + + bounds.setFrame(bounds.getX(), bounds.getY(), width, height); + dragDelta = new Point2D.Double(pointX, pointY); // TODO .. + + } else if (Boolean.FALSE.equals(resize)) { + if (transform == IdentityAffineTransform.INSTANCE) + transform = AffineTransform.getTranslateInstance(x, y); + else + transform.translate(x, y); + } + + //dragDelta = new Point2D.Double(me.getPoint().getX(), me.getPoint().getY()); + repaint(); + } else { + final double paddingX = 0.0; + final double paddingY = 0.0; + + Path2D corner = createCorner(path, bounds, paddingX, paddingY, sx, sy); + Rectangle2D header = createRectangle(rect, bounds, paddingX, paddingY, sx, sy); + + if (corner.contains(p)) { + setCursor(Cursor.HAND_CURSOR); + //consume = true; + } else if (header.contains(p)) { + setCursor(Cursor.HAND_CURSOR); + //consume = true; + } else { + setCursor(Cursor.DEFAULT_CURSOR); + } + } + + return consume; + } + + @Override + protected boolean mouseButtonPressed(MouseButtonPressedEvent e) { + boolean consume = false; + + if (e.button == MouseEvent.LEFT_BUTTON && !e.hasAnyModifier(MouseEvent.ALL_MODIFIERS_MASK)) { + Point2D scale = getScale(temp); + final double sx = scale.getX(); + final double sy = scale.getY(); + + Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, temp); + final double mx = localPos.getX(); + final double my = localPos.getY(); + + AffineTransform i = AffineTransform.getTranslateInstance(-transform.getTranslateX()*sx, -transform.getTranslateY()*sy); + Point2D p = i.transform(new Point2D.Double(sx*mx, sy*my), null); + + final double paddingX = 0.0; + final double paddingY = 0.0; + + Path2D corner = createCorner(path, bounds, paddingX, paddingY, sx, sy); + Rectangle2D header = createRectangle(rect, bounds, paddingX, paddingY, sx, sy); + + if (corner.contains(p)) {// me.getPoint().getX() > right-5-paddingX && me.getPoint().getY() > bottom - 5 - paddingY) { + if (orig == null) + orig = new Point2D.Double(bounds.getWidth(), bounds.getHeight()); + resize = Boolean.TRUE; + setCursor(Cursor.SE_RESIZE_CURSOR); + consume = true; + } else if (header.contains(p)) {// me.getPoint().getY() < bounds.getMinY()+8) { + if (orig == null) + orig = new Point2D.Double(transform.getTranslateX(), transform.getTranslateY()); + resize = Boolean.FALSE; + setCursor(Cursor.MOVE_CURSOR); + consume = true; + } else { + resize = null; + } + + dragDelta = new Point2D.Double(p.getX(), p.getY()); + + repaint(); + } + return consume; + } + + @Override + protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) { + if (orig != null) { + setCursor(Cursor.DEFAULT_CURSOR); + if (resize) { + Point2D delta = new Point2D.Double(bounds.getWidth() - orig.getX(), bounds.getHeight() - orig.getY()); + resized(delta); + } else { + Point2D delta = new Point2D.Double((transform.getTranslateX() - orig.getX()), (transform.getTranslateY() - orig.getY())); + moved(delta); + } + orig = null; + return true; + } + return false; + } + + @Override + public int getEventMask() { + return EventTypes.MouseButtonPressedMask | EventTypes.MouseButtonReleasedMask | EventTypes.MouseMovedMask; + } + + private Point2D getScale(Point2D result) { + double sx = 1.0, sy = 1.0; + IG2DNode node = (IG2DNode) this.getParent(); + while (node != null) { + sx *= node.getTransform().getScaleX(); + sy *= node.getTransform().getScaleY(); + // FIXME: it should be G2DParentNode but you can never be sure + node = (G2DParentNode) node.getParent(); + } + result.setLocation(sx, sy); + return result; + } + + private static Rectangle2D createRectangle(Rectangle2D result, Rectangle2D bounds, + double paddingX, double paddingY, double sx, double sy) { + result.setFrame( + (bounds.getMinX() - paddingX)*sx, + (bounds.getMinY() - paddingY)*sy, + (bounds.getWidth() + 2.0 * paddingX) * sx, + HEADER_HEIGHT*sy); + return result; + } + + private static Path2D createCorner(Path2D result, Rectangle2D bounds, + double paddingX, double paddingY, double sx, double sy) { + final double right = (bounds.getMinX() - paddingX + bounds.getWidth() + 2.0 * paddingX); + final double bottom = (bounds.getMinY() - paddingY + bounds.getHeight() + 2.0 * paddingY); + result.reset(); + result.moveTo((right - 8 - paddingX) * sx, bottom * sy); + result.lineTo(right * sx, (bottom - 8 - paddingY) * sy); + result.lineTo(right * sx, bottom * sy); + result.closePath(); + return result; + } + +}