X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fg2d%2FG2DNode.java;h=477b95517cfb26d6aaa95347ccc6bed4285dd394;hp=a558aa308d68dec22bba2c63942293ffc90d789d;hb=5b16b1d94b0c046803f8b246d32b74f289eca646;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java index a558aa308..477b95517 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java @@ -1,399 +1,408 @@ -/******************************************************************************* - * 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; - -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import org.simantics.scenegraph.INode; -import org.simantics.scenegraph.Node; -import org.simantics.scenegraph.ParentNode; -import org.simantics.scenegraph.g2d.events.Event; -import org.simantics.scenegraph.g2d.events.EventTypes; -import org.simantics.scenegraph.g2d.events.FocusEvent; -import org.simantics.scenegraph.g2d.events.IEventHandler; -import org.simantics.scenegraph.g2d.events.KeyEvent; -import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent; -import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent; -import org.simantics.scenegraph.g2d.events.NodeEventHandler; -import org.simantics.scenegraph.g2d.events.TimeEvent; -import org.simantics.scenegraph.g2d.events.command.CommandEvent; -import org.simantics.scenegraph.utils.GeometryUtils; -import org.simantics.scenegraph.utils.NodeUtil; - -public abstract class G2DNode extends Node implements IG2DNode { - - private static final long serialVersionUID = 8283264115992894707L; - - protected int z = 0; - protected AffineTransform transform = IdentityAffineTransform.INSTANCE; - - @SyncField("z") - public void setZIndex(int z) { - if (z != this.z) { - G2DParentNode parent = (G2DParentNode) getParent(); - if (parent != null) - parent.invalidateChildOrder(); - this.z = z; - } - } - - public int getZIndex() { - return z; - } - - public boolean validate() { - return true; - } - - @Override - public void cleanup() { - retractMapping(); - repaint(); - } - - public void repaint() { - INode parent = getParent(); - while(parent != null && !(parent instanceof G2DSceneGraph)) - parent = parent.getParent(); - if(parent == null || ((G2DSceneGraph)parent).getRootPane() == null) return; - ((G2DSceneGraph)parent).getRootPane().repaint(); - } - - - // Bounds and transformation - - public AffineTransform getTransform() { - return transform; - } - - @PropertySetter("Transform") - @SyncField("transform") - public void setTransform(AffineTransform transform) { - assert(transform != null); - if (transform.isIdentity()) - this.transform = IdentityAffineTransform.INSTANCE; - else - this.transform = transform; - } - - /** - * Return bounds transformed with local transformation - * - * @return transformed bounds - */ - public Rectangle2D getBounds() { - Rectangle2D local = getBoundsInLocal(); - if (local == null) - return null; - // TODO: potential spot for CPU/memory allocation optimization - // by using more specialized implementations - return transform.createTransformedShape(local).getBounds2D(); - } - - /** - * Return bounds in local coordinates - * - * @return bounds - */ - abstract public Rectangle2D getBoundsInLocal(); - - public Rectangle2D getBoundsInLocal(boolean ignoreNulls) { - return getBoundsInLocal(); - } - - // Helper methods for bounds checking - - public boolean contains(Point2D point) { - Rectangle2D bounds = getBounds(); - if(bounds == null) return false; - return bounds.contains(point); - } - - public boolean containsLocal(Point2D localPoint) { - Rectangle2D bounds = getBoundsInLocal(); - if(bounds == null) return false; - return bounds.contains(localPoint); - } - - public boolean intersects(Rectangle2D b) { - if (b == null) - return true; - Rectangle2D a = getBounds(); - if (a == null) - return true; - /* - * Compared to Rectangle2D.intersects, this - * intersects closed (not open) shapes. - */ - double ax = a.getX(); - double ay = a.getY(); - double aw = a.getWidth(); - double ah = a.getHeight(); - double bx = b.getX(); - double by = b.getY(); - double bw = b.getWidth(); - double bh = b.getHeight(); - return (ax + aw >= bx && - ay + ah >= by && - ax <= bx + bw && - ay <= by + bh); - } - - public Point2D localToParent(Point2D point) { - return transform.transform(point, null); - } - - public Rectangle2D localToParent(Rectangle2D rect) { - return transform.createTransformedShape(rect).getBounds2D(); - } - - public Point2D parentToLocal(Point2D point) { - AffineTransform inverse = null; - try { - inverse = transform.createInverse(); - return inverse.transform(point, null); - } catch (NoninvertibleTransformException e) { - e.printStackTrace(); // FIXME - } - return point; - } - - public Point2D parentToLocal(Point2D src, Point2D dst) { - AffineTransform inverse = null; - try { - inverse = transform.createInverse(); - return inverse.transform(src, dst); - } catch (NoninvertibleTransformException e) { - e.printStackTrace(); // FIXME - } - return src; - } - - public Rectangle2D parentToLocal(Rectangle2D rect) { - AffineTransform inverse = null; - try { - inverse = transform.createInverse(); - return inverse.createTransformedShape(rect).getBounds2D(); - } catch (NoninvertibleTransformException e) { - e.printStackTrace(); // FIXME - } - return rect; - } - - public Point2D localToControl(Point2D point) { - IG2DNode node = this; - while(node != null) { - point = node.getTransform().transform(point, null); - node = (G2DParentNode)node.getParent(); // FIXME: it should be G2DParentNode but you can never be sure - } - return point; - } - - public Rectangle2D localToControl(Rectangle2D rect) { - Shape shape = rect; - IG2DNode node = this; - while(node != null) { - shape = node.getTransform().createTransformedShape(shape); - node = (G2DParentNode)node.getParent(); // FIXME: it should be G2DParentNode but you can never be sure - } - - return shape.getBounds2D(); - } - - public Point2D controlToLocal(Point2D point) { - AffineTransform at = NodeUtil.getGlobalToLocalTransform(this, null); - if (at == null) - return point; - return at.transform(point, null); - } - - public Rectangle2D controlToLocal(Rectangle2D rect) { - AffineTransform at = NodeUtil.getGlobalToLocalTransform(this, null); - if (at == null) - return rect; - return GeometryUtils.transformRectangle(at, rect); - } - - @Override - public String toString() { - return super.toString() + " [z=" + z + ",transform=" + transform + "]"; - } - - /** - * @see org.simantics.scenegraph.g2d.IG2DNode#getRootNode() - */ - public G2DSceneGraph getRootNode2D() { - ParentNode root = getRootNode(); - return (G2DSceneGraph) root; - } - - @Override - public boolean hasFocus() { - return getFocusNode() == this; - } - - @Override - public IG2DNode getFocusNode() { - return getRootNode2D().getFocusNode(); - } - - @Override - public void setFocusNode(IG2DNode node) { - getRootNode2D().setFocusNode(node); - } - - protected NodeEventHandler getEventHandler() { - return NodeUtil.getNodeEventHandler(this); - } - - protected void addEventHandler(IEventHandler handler) { - getEventHandler().add(handler); - } - - protected void removeEventHandler(IEventHandler handler) { - getEventHandler().remove(handler); - } - - @Override - public int getEventMask() { - return 0; - } - - @Override - public boolean handleEvent(Event e) { - int eventType = EventTypes.toType(e); - switch (eventType) { - case EventTypes.Command: - return handleCommand((CommandEvent) e); - - case EventTypes.FocusGained: - case EventTypes.FocusLost: - return handleFocusEvent((FocusEvent) e); - - case EventTypes.KeyPressed: - return keyPressed((KeyPressedEvent) e); - case EventTypes.KeyReleased: - return keyReleased((KeyReleasedEvent) e); - - case EventTypes.MouseButtonPressed: - return mouseButtonPressed((MouseButtonPressedEvent) e); - case EventTypes.MouseButtonReleased: - return mouseButtonReleased((MouseButtonReleasedEvent) e); - case EventTypes.MouseClick: - return mouseClicked((MouseClickEvent) e); - case EventTypes.MouseDoubleClick: - return mouseDoubleClicked((MouseDoubleClickedEvent) e); - case EventTypes.MouseMoved: - return mouseMoved((MouseMovedEvent) e); - case EventTypes.MouseDragBegin: - return mouseDragged((MouseDragBegin) e); - case EventTypes.MouseEnter: - return mouseEntered((MouseEnterEvent) e); - case EventTypes.MouseExit: - return mouseExited((MouseExitEvent) e); - case EventTypes.MouseWheel: - return mouseWheelMoved((MouseWheelMovedEvent) e); - - case EventTypes.Time: - return handleTimeEvent((TimeEvent) e); - } - return false; - } - - protected boolean keyReleased(KeyReleasedEvent e) { - return false; - } - - protected boolean keyPressed(KeyPressedEvent e) { - return false; - } - - protected boolean handleCommand(CommandEvent e) { - return false; - } - - protected boolean handleFocusEvent(FocusEvent e) { - return false; - } - - protected boolean handleKeyEvent(KeyEvent e) { - return false; - } - - protected boolean mouseButtonPressed(MouseButtonPressedEvent e) { - return false; - } - - protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) { - return false; - } - - protected boolean mouseClicked(MouseClickEvent e) { - return false; - } - - protected boolean mouseDoubleClicked(MouseDoubleClickedEvent e) { - return false; - } - - protected boolean mouseMoved(MouseMovedEvent e) { - return false; - } - - protected boolean mouseDragged(MouseDragBegin e) { - return false; - } - - protected boolean mouseEntered(MouseEnterEvent e) { - return false; - } - - protected boolean mouseExited(MouseExitEvent e) { - return false; - } - - protected boolean mouseWheelMoved(MouseWheelMovedEvent e) { - return false; - } - - protected boolean handleTimeEvent(TimeEvent e) { - return false; - } - - protected void setCursor(int cursorType) { - Component rootPane = NodeUtil.findRootPane(this); - if (rootPane != null) - rootPane.setCursor(Cursor.getPredefinedCursor(cursorType)); - } - - protected void setCursor(Cursor cursor) { - Component rootPane = NodeUtil.findRootPane(this); - if (rootPane != null) - rootPane.setCursor(cursor); - } - -} +/******************************************************************************* + * 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; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.Node; +import org.simantics.scenegraph.ParentNode; +import org.simantics.scenegraph.g2d.events.Event; +import org.simantics.scenegraph.g2d.events.EventTypes; +import org.simantics.scenegraph.g2d.events.FocusEvent; +import org.simantics.scenegraph.g2d.events.IEventHandler; +import org.simantics.scenegraph.g2d.events.KeyEvent; +import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent; +import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent; +import org.simantics.scenegraph.g2d.events.NodeEventHandler; +import org.simantics.scenegraph.g2d.events.TimeEvent; +import org.simantics.scenegraph.g2d.events.command.CommandEvent; +import org.simantics.scenegraph.utils.GeometryUtils; +import org.simantics.scenegraph.utils.NodeUtil; + +public abstract class G2DNode extends Node implements IG2DNode { + + private static final long serialVersionUID = 8283264115992894707L; + + protected int z = 0; + protected AffineTransform transform = IdentityAffineTransform.INSTANCE; + + @SyncField("z") + public void setZIndex(int z) { + if (z != this.z) { + G2DParentNode parent = (G2DParentNode) getParent(); + if (parent != null) + parent.invalidateChildOrder(); + this.z = z; + } + } + + public int getZIndex() { + return z; + } + + public boolean validate() { + return true; + } + + @Override + public void refresh() { + } + + @Override + public void cleanup() { + retractMapping(); + repaint(); + } + + public void repaint() { + INode parent = getParent(); + while(parent != null && !(parent instanceof G2DSceneGraph)) + parent = parent.getParent(); + if(parent == null || ((G2DSceneGraph)parent).getRootPane() == null) return; + ((G2DSceneGraph)parent).getRootPane().repaint(); + } + + + // Bounds and transformation + + public AffineTransform getTransform() { + return transform; + } + + @PropertySetter("Transform") + @SyncField("transform") + public void setTransform(AffineTransform transform) { + assert(transform != null); + if (transform.isIdentity()) + this.transform = IdentityAffineTransform.INSTANCE; + else + this.transform = transform; + } + + /** + * Return bounds transformed with local transformation + * + * @return transformed bounds + */ + public Rectangle2D getBounds() { + Rectangle2D local = getBoundsInLocal(); + if (local == null) + return null; + // TODO: potential spot for CPU/memory allocation optimization + // by using more specialized implementations + return transform.createTransformedShape(local).getBounds2D(); + } + + /** + * Return bounds in local coordinates + * + * @return bounds + */ + abstract public Rectangle2D getBoundsInLocal(); + + public Rectangle2D getBoundsInLocal(boolean ignoreNulls) { + return getBoundsInLocal(); + } + + // Helper methods for bounds checking + + public boolean contains(Point2D point) { + Rectangle2D bounds = getBounds(); + if(bounds == null) return false; + return bounds.contains(point); + } + + public boolean containsLocal(Point2D localPoint) { + Rectangle2D bounds = getBoundsInLocal(); + if(bounds == null) return false; + return bounds.contains(localPoint); + } + + public boolean intersects(Rectangle2D b) { + if (b == null) + return true; + Rectangle2D a = getBounds(); + if (a == null) + return true; + /* + * Compared to Rectangle2D.intersects, this + * intersects closed (not open) shapes. + */ + double ax = a.getX(); + double ay = a.getY(); + double aw = a.getWidth(); + double ah = a.getHeight(); + double bx = b.getX(); + double by = b.getY(); + double bw = b.getWidth(); + double bh = b.getHeight(); + return (ax + aw >= bx && + ay + ah >= by && + ax <= bx + bw && + ay <= by + bh); + } + + public Point2D localToParent(Point2D point) { + return transform.transform(point, null); + } + + public Rectangle2D localToParent(Rectangle2D rect) { + return transform.createTransformedShape(rect).getBounds2D(); + } + + public Point2D parentToLocal(Point2D point) { + AffineTransform inverse = null; + try { + inverse = transform.createInverse(); + return inverse.transform(point, null); + } catch (NoninvertibleTransformException e) { + e.printStackTrace(); // FIXME + } + return point; + } + + public Point2D parentToLocal(Point2D src, Point2D dst) { + AffineTransform inverse = null; + try { + inverse = transform.createInverse(); + return inverse.transform(src, dst); + } catch (NoninvertibleTransformException e) { + e.printStackTrace(); // FIXME + } + return src; + } + + public Rectangle2D parentToLocal(Rectangle2D rect) { + AffineTransform inverse = null; + try { + inverse = transform.createInverse(); + return inverse.createTransformedShape(rect).getBounds2D(); + } catch (NoninvertibleTransformException e) { + e.printStackTrace(); // FIXME + } + return rect; + } + + public Point2D localToControl(Point2D point) { + IG2DNode node = this; + while(node != null) { + point = node.getTransform().transform(point, null); + node = (G2DParentNode)node.getParent(); // FIXME: it should be G2DParentNode but you can never be sure + } + return point; + } + + public Rectangle2D localToControl(Rectangle2D rect) { + Shape shape = rect; + IG2DNode node = this; + while(node != null) { + shape = node.getTransform().createTransformedShape(shape); + node = (G2DParentNode)node.getParent(); // FIXME: it should be G2DParentNode but you can never be sure + } + + return shape.getBounds2D(); + } + + public Point2D controlToLocal(Point2D point) { + AffineTransform at = NodeUtil.getGlobalToLocalTransform(this, null); + if (at == null) + return point; + return at.transform(point, null); + } + + public Rectangle2D controlToLocal(Rectangle2D rect) { + AffineTransform at = NodeUtil.getGlobalToLocalTransform(this, null); + if (at == null) + return rect; + return GeometryUtils.transformRectangle(at, rect); + } + + @Override + public String toString() { + return super.toString() + " [z=" + z + ",transform=" + transform + "]"; + } + + /** + * @see org.simantics.scenegraph.g2d.IG2DNode#getRootNode() + */ + public G2DSceneGraph getRootNode2D() { + ParentNode root = getRootNode(); + return (G2DSceneGraph) root; + } + + @Override + public boolean hasFocus() { + return getFocusNode() == this; + } + + @Override + public IG2DNode getFocusNode() { + return getRootNode2D().getFocusNode(); + } + + @Override + public void setFocusNode(IG2DNode node) { + getRootNode2D().setFocusNode(node); + } + + protected NodeEventHandler getEventHandler() { + return NodeUtil.getNodeEventHandler(this); + } + + protected void addEventHandler(IEventHandler handler) { + getEventHandler().add(handler); + } + + protected void removeEventHandler(IEventHandler handler) { + getEventHandler().remove(handler); + } + + @Override + public int getEventMask() { + return 0; + } + + @Override + public boolean handleEvent(Event e) { + int eventType = EventTypes.toType(e); + switch (eventType) { + case EventTypes.Command: + return handleCommand((CommandEvent) e); + + case EventTypes.FocusGained: + case EventTypes.FocusLost: + return handleFocusEvent((FocusEvent) e); + + case EventTypes.KeyPressed: + return keyPressed((KeyPressedEvent) e); + case EventTypes.KeyReleased: + return keyReleased((KeyReleasedEvent) e); + + case EventTypes.MouseButtonPressed: + return mouseButtonPressed((MouseButtonPressedEvent) e); + case EventTypes.MouseButtonReleased: + return mouseButtonReleased((MouseButtonReleasedEvent) e); + case EventTypes.MouseClick: + return mouseClicked((MouseClickEvent) e); + case EventTypes.MouseDoubleClick: + return mouseDoubleClicked((MouseDoubleClickedEvent) e); + case EventTypes.MouseMoved: + return mouseMoved((MouseMovedEvent) e); + case EventTypes.MouseDragBegin: + return mouseDragged((MouseDragBegin) e); + case EventTypes.MouseEnter: + return mouseEntered((MouseEnterEvent) e); + case EventTypes.MouseExit: + return mouseExited((MouseExitEvent) e); + case EventTypes.MouseWheel: + return mouseWheelMoved((MouseWheelMovedEvent) e); + + case EventTypes.Time: + return handleTimeEvent((TimeEvent) e); + } + return false; + } + + protected boolean keyReleased(KeyReleasedEvent e) { + return false; + } + + protected boolean keyPressed(KeyPressedEvent e) { + return false; + } + + protected boolean handleCommand(CommandEvent e) { + return false; + } + + protected boolean handleFocusEvent(FocusEvent e) { + return false; + } + + protected boolean handleKeyEvent(KeyEvent e) { + return false; + } + + protected boolean mouseButtonPressed(MouseButtonPressedEvent e) { + return false; + } + + protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) { + return false; + } + + protected boolean mouseClicked(MouseClickEvent e) { + return false; + } + + protected boolean mouseDoubleClicked(MouseDoubleClickedEvent e) { + return false; + } + + protected boolean mouseMoved(MouseMovedEvent e) { + return false; + } + + protected boolean mouseDragged(MouseDragBegin e) { + return false; + } + + protected boolean mouseEntered(MouseEnterEvent e) { + return false; + } + + protected boolean mouseExited(MouseExitEvent e) { + return false; + } + + protected boolean mouseWheelMoved(MouseWheelMovedEvent e) { + return false; + } + + protected boolean handleTimeEvent(TimeEvent e) { + return false; + } + + protected void setCursor(int cursorType) { + Component rootPane = NodeUtil.findRootPane(this); + if (rootPane != null) + rootPane.setCursor(Cursor.getPredefinedCursor(cursorType)); + } + + protected void setCursor(Cursor cursor) { + Component rootPane = NodeUtil.findRootPane(this); + if (rootPane != null) + rootPane.setCursor(cursor); + } + + public void accept(IG2DNodeVisitor visitor) { + visitor.enter(this); + visitor.leave(this); + } + +}