xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="210mm"
- height="297mm"
+ width="11.567822"
+ height="9.8627777"
id="svg1901"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
- sodipodi:docname="arrowHead.svg"
+ sodipodi:docname="loop.svg"
version="1.1">
<defs
id="defs1903">
<marker
inkscape:stockid="TriangleInL"
orient="auto"
- refY="0.0"
- refX="0.0"
+ refY="0"
+ refX="0"
id="TriangleInL"
style="overflow:visible">
<path
id="path4265"
- d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
- transform="scale(-0.8)" />
+ d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="scale(-0.8,-0.8)"
+ inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
- refY="0.0"
- refX="0.0"
+ refY="0"
+ refX="0"
id="Arrow2Lend"
- style="overflow:visible;">
+ style="overflow:visible">
<path
id="path4153"
- style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- transform="scale(1.1) rotate(180) translate(1,0)" />
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
- refY="0.0"
- refX="0.0"
+ refY="0"
+ refX="0"
id="Arrow2Lstart"
style="overflow:visible">
<path
id="path4150"
- style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- transform="scale(1.1) translate(1,0)" />
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(1.1,0,0,1.1,1.1,0)"
+ inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
- refY="0.0"
- refX="0.0"
+ refY="0"
+ refX="0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path4132"
- d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
- transform="scale(0.8) translate(12.5,0)" />
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(0.8,0,0,0.8,10,0)"
+ inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
- refY="0.0"
- refX="0.0"
+ refY="0"
+ refX="0"
id="Arrow1Mstart"
style="overflow:visible">
<path
id="path4138"
- d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
- transform="scale(0.4) translate(10,0)" />
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(0.4,0,0,0.4,4,0)"
+ inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
- refY="0.0"
- refX="0.0"
+ refY="0"
+ refX="0"
id="Arrow1Lend"
- style="overflow:visible;">
+ style="overflow:visible">
<path
id="path4135"
- d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
- transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="0.70710678"
- inkscape:cx="26.330076"
- inkscape:cy="194.93962"
+ inkscape:zoom="32"
+ inkscape:cx="-1.9642866"
+ inkscape:cy="-2.7672376"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:window-width="1006"
inkscape:window-x="1428"
inkscape:window-y="52"
showgrid="false"
- inkscape:window-maximized="0" />
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
<metadata
id="metadata1906">
<rdf:RDF>
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
inkscape:label="Taso 1"
inkscape:groupmode="layer"
id="layer1"
- style="opacity:1">
+ transform="translate(-0.13537823,-1042.2366)">
<path
sodipodi:type="star"
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
inkscape:randomized="0"
d="m 148.57144,345.21932 230.49908,-204.50728 61.85896,301.8717 z"
inkscape:transform-center-y="-0.37884722"
- transform="matrix(0.00747689,-0.00472065,0.00249533,0.01414476,7.2395258,1043.2168)" />
+ transform="matrix(0.00747689,-0.00472065,0.00249533,0.01414476,2.177026,1048.1856)" />
<path
sodipodi:type="arc"
style="fill:none;stroke:#000000;stroke-width:0.88339353;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:none"
sodipodi:rx="21.785715"
sodipodi:ry="13.121153"
d="m 59.821428,1014.4158 a 21.785715,13.121153 0 1 1 -22.182754,-13.119"
- transform="matrix(0.23486318,0,0,0.36599586,-3.551648,675.89564)"
+ transform="matrix(0.23486318,0,0,0.36599586,-8.614148,680.86439)"
sodipodi:start="0"
sodipodi:end="4.6941632"
sodipodi:open="true" />
package org.simantics.sysdyn.ui.elements;\r
\r
import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Paint;\r
import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
import java.awt.geom.Arc2D;\r
import java.awt.geom.Path2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.awt.geom.RectangularShape;\r
import java.util.Collection;\r
\r
import org.simantics.db.ReadGraph;\r
import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
import org.simantics.db.common.utils.NameUtils;\r
import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.elements.ITextListener;\r
+import org.simantics.diagram.elements.TextNode;\r
import org.simantics.diagram.stubs.G2DResource;\r
import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
import org.simantics.g2d.diagram.IDiagram;\r
import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.SceneGraphNodeKey;\r
+import org.simantics.g2d.element.handler.HandleMouseEvent;\r
import org.simantics.g2d.element.handler.impl.BoundsOutline;\r
import org.simantics.g2d.element.handler.impl.DefaultTransform;\r
+import org.simantics.g2d.element.handler.impl.HoverImpl;\r
import org.simantics.g2d.element.handler.impl.ObjectTerminal;\r
import org.simantics.g2d.element.handler.impl.OutlinePick;\r
import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
import org.simantics.g2d.image.Image;\r
import org.simantics.g2d.image.impl.ShapeImage;\r
import org.simantics.g2d.svg.SVGImage;\r
+import org.simantics.g2d.utils.Alignment;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.scenegraph.g2d.nodes.SVGNode;\r
+import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.properties.LoopTab;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintListener;\r
+import org.simantics.utils.datastructures.hints.IHintObservable;\r
\r
/**\r
+ * Factory for loops.\r
+ * \r
* @author Tuomas Miettinen\r
*/\r
public class LoopFactory extends SysdynElementFactory {\r
\r
- public static final Image LOOP_STATIC_IMAGE = new ShapeImage(getLoopShape(), null, new BasicStroke(1), true);\r
-\r
- @Override\r
- public ElementClass create(ReadGraph graph, ICanvasContext canvas,\r
- IDiagram diagram, Resource elementType) throws DatabaseException {\r
- \r
- G2DResource g2d = G2DResource.getInstance(graph);\r
- String svgDoc = graph.getPossibleRelatedValue(elementType, g2d.HasSVGDocument);\r
- Image image = null;\r
- String id = "TextElement: " + NameUtils.getSafeName(graph, elementType);\r
- if (svgDoc != null)\r
- image = new SVGImage(id+".svg", svgDoc);\r
- else\r
- image = DefaultImages.ERROR_DECORATOR.get();\r
- \r
- return ElementClass.compile(\r
- SimpleElementLayers.INSTANCE,\r
- OutlinePick.INSTANCE,\r
- TextImpl.INSTANCE,\r
- TextColorImpl.BLACK,\r
- TextFontImpl.DEFAULT,\r
- DefaultTransform.INSTANCE,\r
- new StaticSymbolImpl(image),\r
- new StaticImageElementHandler(image),\r
- new StaticObjectAdapter(elementType),\r
- StaticSymbolImageInitializer.INSTANCE,\r
- //new HoverTextElementHandler(0, 0, Alignment.LEADING, 0, 1.5, 1.5, true),\r
- BoundsOutline.INSTANCE\r
- ).setId(LoopFactory.class.getSimpleName());\r
- }\r
-\r
- static Shape getLoopShape() {\r
- Path2D loop = new Path2D.Double();\r
- loop.moveTo(1, 2);\r
- loop.lineTo(0, 0);\r
- loop.lineTo(-1, 2);\r
- loop.closePath();\r
- \r
- loop.append(new Arc2D.Double(-10, -3, 10, 10, 0, -270, Arc2D.OPEN), false);\r
- return loop;\r
- }\r
+ public static final Image LOOP_STATIC_IMAGE = new ShapeImage(getLoopShape(), null, new BasicStroke(1), true);\r
+ private static Image image = null;\r
+\r
+ @Override\r
+ public ElementClass create(ReadGraph graph, ICanvasContext canvas,\r
+ IDiagram diagram, Resource elementType) throws DatabaseException {\r
+\r
+ // Create the loop symbol svg image\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ String svgDoc = graph.getPossibleRelatedValue(elementType, g2d.HasSVGDocument);\r
+ String id = "TextElement: " + NameUtils.getSafeName(graph, elementType);\r
+ if (svgDoc != null)\r
+ image = new SVGImage(id+".svg", svgDoc);\r
+ else\r
+ image = DefaultImages.ERROR_DECORATOR.get();\r
+\r
+ return ElementClass.compile(\r
+ SimpleElementLayers.INSTANCE,\r
+ OutlinePick.INSTANCE,\r
+ TextImpl.INSTANCE,\r
+ TextColorImpl.BLACK,\r
+ TextFontImpl.DEFAULT,\r
+ DefaultTransform.INSTANCE,\r
+ new StaticObjectAdapter(elementType),\r
+ new StaticSymbolImpl(image),\r
+ StaticSymbolImageInitializer.INSTANCE,\r
+ new LoopImageSceneGraph(image),\r
+ HoverImpl.INSTANCE,\r
+ LoopSceneGraph.INSTANCE,\r
+ BoundsOutline.INSTANCE\r
+ ).setId(LoopFactory.class.getSimpleName());\r
+ }\r
+\r
+ static Shape getLoopShape() {\r
+ // Used in shortcut.\r
+ Path2D loop = new Path2D.Double();\r
+ loop.moveTo(1, 2);\r
+ loop.lineTo(0, 0);\r
+ loop.lineTo(-1, 2);\r
+ loop.closePath();\r
+\r
+ loop.append(new Arc2D.Double(-10, -3, 10, 10, 0, -270, Arc2D.OPEN), false);\r
+ return loop;\r
+ }\r
+\r
+ @Override\r
+ protected String getText(ReadGraph graph, Resource element) throws DatabaseException {\r
+ // Get loop comment instead of loop name.\r
+ SysdynResource sr = SysdynResource.getInstance(graph); \r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ Resource component = graph.getPossibleObject(element, mr.ElementToComponent);\r
+ String text = null;\r
+ if (component != null) {\r
+ text = (String) graph.getPossibleRelatedValue(component, sr.Loop_Comment);\r
+ }\r
+ if (text == null || LoopTab.AUTO.equals(text))\r
+ text = "";\r
+ return text;\r
+ }\r
\r
@Override\r
protected ElementClass compileElementClass(Resource elementType,\r
Collection<ObjectTerminal> terminals) {\r
- // TODO Auto-generated method stub\r
return null;\r
}\r
\r
+ /**\r
+ * Handling for the loop image on diagram.\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+ public static class LoopImageSceneGraph extends StaticImageElementHandler {\r
+\r
+ private static final long serialVersionUID = -185893525553743589L;\r
+ \r
+ private IHintListener hoverHintListener;\r
+ \r
+ private static final Key NODE = new SceneGraphNodeKey(HoverShapeNode.class, "LOOP_NODE");\r
+\r
+ public LoopImageSceneGraph(Image i) {\r
+ super(i);\r
+ }\r
+\r
+ @Override\r
+ public void init(IElement e, G2DParentNode parent) {\r
+ super.init(e, parent);\r
+\r
+ // Create new hover shape node for the loop image\r
+ final HoverShapeNode node = ElementUtils.getOrCreateNode(e, parent, NODE, "loopHover", HoverShapeNode.class);\r
+ \r
+ // Set the shape of the shape node to match the shape of the image\r
+ SVGNode image = e.getHint(getNodeKey());\r
+ RectangularShape bounds = (RectangularShape)image.getBounds().clone();\r
+ node.setShape(bounds);\r
+\r
+ // Set the shape node transparent\r
+ Paint paint = new Color(0,0,0,0);\r
+ node.setColor(paint);\r
+ \r
+ // Handle hover\r
+ Boolean hover = e.getHint(ElementHints.KEY_HOVER); \r
+ node.setHover(hover != null ? hover : false);\r
+ hoverHintListener = new IHintListener() {\r
+\r
+ @Override\r
+ public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {\r
+ }\r
+\r
+ @Override\r
+ public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
+ IElement e = (IElement)sender;\r
+ HoverShapeNode shape = (HoverShapeNode) e.getHint(NODE);\r
+ if(shape == null) {\r
+ return;\r
+ }\r
+ boolean hover = ElementUtils.isHovering(e);\r
+ shape.setHover(hover);\r
+ }\r
+ };\r
+ e.addHintListener(hoverHintListener);\r
+ }\r
+\r
+ @Override\r
+ public void cleanup(IElement e) {\r
+ super.cleanup(e);\r
+ e.removeHintListener(hoverHintListener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Handling for the text box of loop in diagram.\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+ public static class LoopSceneGraph extends HoverTextElementNoBounds implements HandleMouseEvent {\r
+\r
+ private static final long serialVersionUID = -5093461687773246286L;\r
+\r
+ public static final LoopSceneGraph INSTANCE = new LoopSceneGraph();\r
+ \r
+ private static final Key NODE = new SceneGraphNodeKey(ShapeNode.class, "LOOP_COMMENT_NODE");\r
+ \r
+ public LoopSceneGraph() {\r
+ super(0, 0, Alignment.CENTER, 0, 1, 1, true);\r
+ }\r
+ \r
+ @Override\r
+ public void init(IElement e, G2DParentNode parent) {\r
+ super.init(e, parent);\r
+ \r
+ // Move the text box into (around) the middle of the loop image\r
+ AffineTransform at = ElementUtils.getTransform(e);\r
+ final HoverShapeNode node = ElementUtils.getOrCreateNode(e, parent, NODE, "loopComment", HoverShapeNode.class);\r
+\r
+ if(at != null) {\r
+ node.setTransform(at);\r
+\r
+ TextNode name = (TextNode) e.getHint(SG_NODE);\r
+ if(name != null) {\r
+ AffineTransform at2 = (AffineTransform) at.clone();\r
+ at2.translate(getXCoordShift(e), getYCoordShift(e));\r
+\r
+ Alignment alignment = Alignment.CENTER;\r
+\r
+ name.setTransform(at2);\r
+ if(alignment != null)\r
+ name.setHorizontalAlignment((byte) alignment.ordinal());\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ private static double getXCoordShift(IElement e) {\r
+ //String location = e.getHint(SysdynElementHints.KEY_LOCATION);\r
+ return 0.4;\r
+ }\r
+\r
+ private static double getYCoordShift(IElement e) {\r
+ //String location = e.getHint(SysdynElementHints.KEY_LOCATION);\r
+ return 10.7;\r
+ }\r
+\r
+ @Override\r
+ protected <T extends HoverTextNode> Callback<T> getCallback(final IElement e, G2DParentNode parent, Class<T> nodeClass) {\r
+ return new Callback<T>() {\r
+ @Override\r
+ public void run(T node) {\r
+ node.setTextListener(new ITextListener() {\r
+\r
+ Resource component;\r
+\r
+ @Override\r
+ public void textChanged() {\r
+ }\r
+\r
+ @Override\r
+ public void textEditingStarted() {\r
+ if(component != null) return;\r
+\r
+ Object o = e.getHint(ElementHints.KEY_OBJECT);\r
+ if(o != null && o instanceof Resource) {\r
+ final Resource element = (Resource)o;\r
+ SimanticsUI.getSession().asyncRequest(new ReadRequest() {\r
+\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ component = graph.getPossibleObject(element, ModelingResources.getInstance(graph).ElementToComponent);\r
+ }\r
+ });\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void textEditingCancelled() {\r
+ TextNode node = (TextNode) e.getHint(SG_NODE);\r
+ if (node != null) {\r
+ endEdit(node);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void textEditingEnded() {\r
+ TextNode node = (TextNode) e.getHint(SG_NODE);\r
+ if (node == null)\r
+ return;\r
+\r
+ // Write the changed comment of the loop\r
+ final String text = node.getText();\r
+ try {\r
+ SimanticsUI.getSession().syncRequest(new WriteRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph)\r
+ throws DatabaseException {\r
+ if (component != null) {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ graph.deny(component, sr.Loop_Comment);\r
+ graph.claimLiteral(component, sr.Loop_Comment, text);\r
+ }\r
+ }\r
+\r
+ });\r
+ } catch (DatabaseException e1) {\r
+ e1.printStackTrace();\r
+ }\r
+\r
+ IDiagram diagram = ElementUtils.getDiagram(e);\r
+ DiagramUtils.synchronizeHintsToBackend(diagram, e);\r
+ endEdit(node);\r
+ }\r
+ });\r
+ }\r
+ };\r
+ }\r
+\r
+ }\r
+\r
+\r
}\r