-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.scenegraph.g2d.nodes;\r
-\r
-import java.awt.BasicStroke;\r
-import java.awt.Color;\r
-import java.awt.Cursor;\r
-import java.awt.Graphics2D;\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.Line2D;\r
-import java.awt.geom.Path2D;\r
-import java.awt.geom.Point2D;\r
-import java.awt.geom.Rectangle2D;\r
-\r
-import org.simantics.scenegraph.g2d.G2DNode;\r
-import org.simantics.scenegraph.g2d.G2DParentNode;\r
-import org.simantics.scenegraph.g2d.IG2DNode;\r
-import org.simantics.scenegraph.g2d.IdentityAffineTransform;\r
-import org.simantics.scenegraph.g2d.events.EventTypes;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
-import org.simantics.scenegraph.utils.GeometryUtils;\r
-import org.simantics.scenegraph.utils.NodeUtil;\r
-\r
-/**\r
- * @author J-P Laine\r
- * @author Tuukka Lehtonen\r
- */\r
-public class TransformableSelectionNode extends G2DNode {\r
-\r
- public static interface TransformCallback {\r
- public void moved(Point2D delta);\r
- public void resized(Point2D delta);\r
- }\r
-\r
- private static final long serialVersionUID = -2879575230419873230L;\r
-\r
- private static final int HEADER_HEIGHT = 10;\r
-\r
- public transient static final BasicStroke SELECTION_STROKE = new BasicStroke(1.0f,\r
- BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f,\r
- new float[] { 5.0f, 5.0f }, 0.0f);\r
-\r
- protected Rectangle2D bounds = null;\r
- protected Color color = null;\r
- protected Boolean resizeable = Boolean.FALSE;\r
-\r
- protected double minWidth = 7;\r
- protected double minHeight = 7;\r
-\r
- protected transient Point2D dragDelta = null;\r
- protected transient Point2D orig = null;\r
- protected transient Boolean resize = null;\r
-\r
- protected transient Point2D temp = new Point2D.Double();\r
- protected transient Path2D path = new Path2D.Double();\r
- protected transient Rectangle2D rect = new Rectangle2D.Double();\r
-\r
- protected transient TransformCallback transformCallback = null;\r
-\r
- @Override\r
- public void init() {\r
- super.init();\r
- addEventHandler(this);\r
- }\r
-\r
- @Override\r
- public void cleanup() {\r
- removeEventHandler(this);\r
- super.cleanup();\r
- }\r
-\r
- @SyncField({"transform", "bounds", "color", "resizeable", "minWidth", "minHeight"})\r
- public void init(AffineTransform transform, Rectangle2D bounds, Color color, boolean resizeable, double minWidth, double minHeight) {\r
-// System.out.println("init("+transform+", "+bounds+", "+color+", "+resizeable+")");\r
- this.transform = transform;\r
- this.bounds = bounds;\r
- this.color = color;\r
- this.resizeable = resizeable;\r
- this.minWidth = minWidth;\r
- this.minHeight = minHeight;\r
- }\r
-\r
- @SyncField({"transform", "bounds", "color", "resizeable"})\r
- public void init(AffineTransform transform, Rectangle2D bounds, Color color, boolean resizeable) {\r
-// System.out.println("init("+transform+", "+bounds+", "+color+", "+resizeable+")");\r
- this.transform = transform;\r
- this.bounds = bounds;\r
- this.color = color;\r
- this.resizeable = resizeable;\r
- }\r
-\r
- @SyncField({"transform", "bounds", "color"})\r
- public void init(AffineTransform transform, Rectangle2D bounds, Color color) {\r
-// System.out.println("init("+transform+", "+bounds+", "+color+")");\r
- this.transform = transform;\r
- this.bounds = bounds;\r
- this.color = color;\r
- }\r
-\r
- @Override\r
- public void render(Graphics2D g) {\r
- if (bounds == null)\r
- return;\r
- AffineTransform ot = g.getTransform();\r
-\r
- g.setColor(color);\r
- g.transform(transform);\r
-\r
- AffineTransform tx = g.getTransform();\r
- //System.out.println("tx: " + tx);\r
- double scale = GeometryUtils.getScale(tx);\r
- //System.out.println("scale: " + scale);\r
- double scaleRecip = 1.0 / scale;\r
- //System.out.println("scale: " + scaleRecip);\r
-\r
- BasicStroke scaledStroke = GeometryUtils.scaleStroke( SELECTION_STROKE, (float) scaleRecip);\r
- g.setStroke(scaledStroke);\r
-\r
- double padding = 0.0 * scaleRecip;\r
- double paddingX = padding;\r
- double paddingY = padding;\r
-\r
- g.draw(new Rectangle2D.Double(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY,\r
- bounds.getWidth() + 2.0*paddingX, bounds.getHeight() + 2.0*paddingY));\r
-\r
- double right = (bounds.getMinX() - paddingX + bounds.getWidth() + 2.0*paddingX);\r
- double bottom = (bounds.getMinY() - paddingY + bounds.getHeight() + 2.0*paddingY);\r
-\r
- if (resizeable) {\r
- Path2D corner = new Path2D.Double();\r
- corner.moveTo(right-8-paddingX, bottom);\r
- corner.lineTo(right, bottom - 8 - paddingY);\r
- corner.lineTo(right, bottom);\r
- corner.closePath();\r
- g.setColor(new Color(20, 20, 20, 120));\r
- g.fill(corner);\r
-\r
- g.setColor(color);\r
- g.draw(new Line2D.Double(right-8-paddingX, bottom, right, bottom - 8 - paddingY));\r
- }\r
-\r
- Rectangle2D header = new Rectangle2D.Double(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY, bounds.getWidth() + 2.0*paddingX, HEADER_HEIGHT);\r
- g.setColor(new Color(20, 20, 20, 120));\r
- g.fill(header);\r
-\r
- g.setColor(color);\r
- g.draw(new Line2D.Double(bounds.getMinX(), bounds.getMinY()+HEADER_HEIGHT, right, bounds.getMinY()+HEADER_HEIGHT));\r
-\r
- g.setTransform(ot);\r
- }\r
-\r
- @Override\r
- public Rectangle2D getBoundsInLocal() {\r
- return bounds;\r
- }\r
-\r
- public void setTransformCallback(TransformCallback transformCallback) {\r
- this.transformCallback = transformCallback;\r
- }\r
-\r
- @ServerSide\r
- protected void resized(Point2D size) {\r
- if (transformCallback != null) {\r
- transformCallback.resized(size);\r
- }\r
- }\r
-\r
- @ServerSide\r
- protected void moved(Point2D location) {\r
- if (transformCallback != null) {\r
- transformCallback.moved(location);\r
- }\r
- }\r
-\r
- @Override\r
- public boolean mouseMoved(MouseMovedEvent e) {\r
- boolean consume = false;\r
-\r
- Point2D scale = getScale(temp);\r
- final double sx = scale.getX();\r
- final double sy = scale.getY();\r
-\r
- Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, temp);\r
- final double mx = localPos.getX();\r
- final double my = localPos.getY();\r
-\r
- AffineTransform i = AffineTransform.getTranslateInstance(-transform.getTranslateX()*sx, -transform.getTranslateY()*sy);\r
- Point2D p = i.transform(new Point2D.Double(sx*mx, sy*my), null);\r
-\r
- boolean dragging = (e.buttons & MouseEvent.LEFT_MASK) != 0;\r
-\r
- if (dragging && dragDelta != null) {\r
- double x = (p.getX() - dragDelta.getX())/sx;// /transform.getScaleX();\r
- double y = (p.getY() - dragDelta.getY())/sy;// /transform.getScaleY();\r
- if (Boolean.TRUE.equals(resize)) {\r
-\r
- double width;\r
- double pointX;\r
- if (bounds.getWidth() + x < minWidth) {\r
- width = minWidth;\r
- pointX = dragDelta.getX();\r
- } else {\r
- width = bounds.getWidth() + x;\r
- pointX = p.getX();\r
- }\r
-\r
- double height;\r
- double pointY;\r
- if (bounds.getHeight() + y < minHeight) {\r
- height = minHeight;\r
- pointY = dragDelta.getY();\r
- } else {\r
- height = bounds.getHeight() + y;\r
- pointY = p.getY();\r
- }\r
-\r
-// System.out.println("bounds.getX()=" + bounds.getX() + " bounds.getY())=" + bounds.getY());\r
-// System.out.println("width=" + width + " height=" + height);\r
-\r
- bounds.setFrame(bounds.getX(), bounds.getY(), width, height);\r
- dragDelta = new Point2D.Double(pointX, pointY); // TODO ..\r
-\r
- } else if (Boolean.FALSE.equals(resize)) {\r
- if (transform == IdentityAffineTransform.INSTANCE)\r
- transform = AffineTransform.getTranslateInstance(x, y);\r
- else\r
- transform.translate(x, y);\r
- }\r
-\r
- //dragDelta = new Point2D.Double(me.getPoint().getX(), me.getPoint().getY());\r
- repaint();\r
- } else {\r
- final double paddingX = 0.0;\r
- final double paddingY = 0.0;\r
-\r
- Path2D corner = createCorner(path, bounds, paddingX, paddingY, sx, sy);\r
- Rectangle2D header = createRectangle(rect, bounds, paddingX, paddingY, sx, sy);\r
-\r
- if (corner.contains(p)) {\r
- setCursor(Cursor.HAND_CURSOR);\r
- //consume = true;\r
- } else if (header.contains(p)) {\r
- setCursor(Cursor.HAND_CURSOR);\r
- //consume = true;\r
- } else {\r
- setCursor(Cursor.DEFAULT_CURSOR);\r
- }\r
- }\r
-\r
- return consume;\r
- }\r
-\r
- @Override\r
- protected boolean mouseButtonPressed(MouseButtonPressedEvent e) {\r
- boolean consume = false;\r
-\r
- if (e.button == MouseEvent.LEFT_BUTTON && !e.hasAnyModifier(MouseEvent.ALL_MODIFIERS_MASK)) {\r
- Point2D scale = getScale(temp);\r
- final double sx = scale.getX();\r
- final double sy = scale.getY();\r
-\r
- Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, temp);\r
- final double mx = localPos.getX();\r
- final double my = localPos.getY();\r
-\r
- AffineTransform i = AffineTransform.getTranslateInstance(-transform.getTranslateX()*sx, -transform.getTranslateY()*sy);\r
- Point2D p = i.transform(new Point2D.Double(sx*mx, sy*my), null);\r
-\r
- final double paddingX = 0.0;\r
- final double paddingY = 0.0;\r
-\r
- Path2D corner = createCorner(path, bounds, paddingX, paddingY, sx, sy);\r
- Rectangle2D header = createRectangle(rect, bounds, paddingX, paddingY, sx, sy);\r
-\r
- if (corner.contains(p)) {// me.getPoint().getX() > right-5-paddingX && me.getPoint().getY() > bottom - 5 - paddingY) {\r
- if (orig == null)\r
- orig = new Point2D.Double(bounds.getWidth(), bounds.getHeight());\r
- resize = Boolean.TRUE;\r
- setCursor(Cursor.SE_RESIZE_CURSOR);\r
- consume = true;\r
- } else if (header.contains(p)) {// me.getPoint().getY() < bounds.getMinY()+8) {\r
- if (orig == null)\r
- orig = new Point2D.Double(transform.getTranslateX(), transform.getTranslateY());\r
- resize = Boolean.FALSE;\r
- setCursor(Cursor.MOVE_CURSOR);\r
- consume = true;\r
- } else {\r
- resize = null;\r
- }\r
-\r
- dragDelta = new Point2D.Double(p.getX(), p.getY());\r
-\r
- repaint();\r
- }\r
- return consume;\r
- }\r
-\r
- @Override\r
- protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) {\r
- if (orig != null) {\r
- setCursor(Cursor.DEFAULT_CURSOR);\r
- if (resize) {\r
- Point2D delta = new Point2D.Double(bounds.getWidth() - orig.getX(), bounds.getHeight() - orig.getY());\r
- resized(delta);\r
- } else {\r
- Point2D delta = new Point2D.Double((transform.getTranslateX() - orig.getX()), (transform.getTranslateY() - orig.getY()));\r
- moved(delta);\r
- }\r
- orig = null;\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- @Override\r
- public int getEventMask() {\r
- return EventTypes.MouseButtonPressedMask | EventTypes.MouseButtonReleasedMask | EventTypes.MouseMovedMask;\r
- }\r
-\r
- private Point2D getScale(Point2D result) {\r
- double sx = 1.0, sy = 1.0;\r
- IG2DNode node = (IG2DNode) this.getParent();\r
- while (node != null) {\r
- sx *= node.getTransform().getScaleX();\r
- sy *= node.getTransform().getScaleY();\r
- // FIXME: it should be G2DParentNode but you can never be sure\r
- node = (G2DParentNode) node.getParent();\r
- }\r
- result.setLocation(sx, sy);\r
- return result;\r
- }\r
-\r
- private static Rectangle2D createRectangle(Rectangle2D result, Rectangle2D bounds,\r
- double paddingX, double paddingY, double sx, double sy) {\r
- result.setFrame(\r
- (bounds.getMinX() - paddingX)*sx,\r
- (bounds.getMinY() - paddingY)*sy,\r
- (bounds.getWidth() + 2.0 * paddingX) * sx,\r
- HEADER_HEIGHT*sy);\r
- return result;\r
- }\r
-\r
- private static Path2D createCorner(Path2D result, Rectangle2D bounds,\r
- double paddingX, double paddingY, double sx, double sy) {\r
- final double right = (bounds.getMinX() - paddingX + bounds.getWidth() + 2.0 * paddingX);\r
- final double bottom = (bounds.getMinY() - paddingY + bounds.getHeight() + 2.0 * paddingY);\r
- result.reset();\r
- result.moveTo((right - 8 - paddingX) * sx, bottom * sy);\r
- result.lineTo(right * sx, (bottom - 8 - paddingY) * sy);\r
- result.lineTo(right * sx, bottom * sy);\r
- result.closePath();\r
- return result;\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * 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;
+ }
+
+}