org.simantics.issues.common;bundle-version="1.1.0",
org.simantics.scenegraph.profile;bundle-version="1.0.0",
org.simantics.trend;bundle-version="1.0.0",
- org.simantics.history;bundle-version="1.0.0"
+ org.simantics.history;bundle-version="1.0.0",
+ org.simantics.utils.thread.swt;bundle-version="1.1.0"
Bundle-Activator: org.simantics.sysdyn.ui.Activator
Bundle-ActivationPolicy: lazy
Export-Package: org.simantics.sysdyn.ui.browser.nodes
</description>\r
</view>\r
<view\r
- class="org.simantics.sysdyn.ui.trend.ChartPane"\r
+ class="org.simantics.sysdyn.ui.trend.ChartPanel"\r
icon="platform:/plugin/com.famfamfam.silk/icons/chart_line.png"\r
- id="org.simantics.sysdyn.ui.chartPane"\r
- name="Chart Pane"\r
+ id="org.simantics.sysdyn.ui.chartPanel"\r
+ name="Chart Panel"\r
restorable="true">\r
</view>\r
</extension>\r
relative="org.simantics.browsing.ui.graph.propertyView">\r
</view>\r
<view\r
- id="org.simantics.sysdyn.ui.chartPane"\r
+ id="org.simantics.sysdyn.ui.chartPanel"\r
minimized="false"\r
ratio="0.25"\r
relationship="right"\r
import org.simantics.g2d.participant.KeyUtil;\r
import org.simantics.g2d.participant.MouseUtil;\r
import org.simantics.g2d.participant.TransformUtil;\r
-import org.simantics.g2d.routing.algorithm2.Router4;\r
import org.simantics.g2d.utils.GeometryUtils;\r
import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\r
import org.simantics.scenegraph.g2d.events.MouseEvent;\r
import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
import org.simantics.sysdyn.ui.editor.participant.SysdynElementClassProviders.ISysdynElementClassProvider;\r
import org.simantics.sysdyn.ui.editor.routing.DependencyRouter;\r
+import org.simantics.sysdyn.ui.editor.routing.FlowRouter;\r
import org.simantics.sysdyn.ui.elements2.AuxiliaryFactory;\r
import org.simantics.sysdyn.ui.elements2.CloudFactory;\r
import org.simantics.sysdyn.ui.elements2.InputFactory;\r
if(id.equals(AuxiliaryFactory.class.getSimpleName())\r
|| id.equals(InputFactory.class.getSimpleName())\r
|| id.equals(ModuleFactory.class.getSimpleName())) return false;\r
-// diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new FlowRouter(false));\r
- diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new Router4(false));\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new FlowRouter(false));\r
diagram.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, true);\r
ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.FLOW));\r
} \r
else if (me.button == MouseEvent.RIGHT_BUTTON) {\r
// Start connection out of thin air, without a terminal.\r
-// diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new FlowRouter(false));\r
- diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new Router4(false));\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new FlowRouter(false));\r
diagram.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, true);\r
ISysdynElementClassProvider secp = (ISysdynElementClassProvider)elementClassProvider;\r
secp.put(ElementClasses.CONNECTION, elementClassProvider.get(ConnectionClasses.FLOW));\r
import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
import org.simantics.g2d.element.impl.Element;\r
-import org.simantics.g2d.elementclass.BranchPoint;\r
import org.simantics.g2d.elementclass.BranchPointClass;\r
import org.simantics.g2d.elementclass.FlagClass;\r
import org.simantics.g2d.routing.Constants;\r
import org.simantics.g2d.routing.IConnection;\r
import org.simantics.g2d.routing.IRouter2;\r
import org.simantics.g2d.routing.TrivialRouter2;\r
-import org.simantics.g2d.utils.GeometryUtils;\r
import org.simantics.scenegraph.g2d.G2DParentNode;\r
import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;\r
import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
import org.simantics.structural2.modelingRules.ConnectionJudgement;\r
import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.sysdyn.ui.editor.routing.FlowRouter;\r
+import org.simantics.sysdyn.ui.elements2.CloudFactory;\r
import org.simantics.sysdyn.ui.elements2.ValveFactory.ValveSceneGraph;\r
import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
import org.simantics.ui.SimanticsUI;\r
}\r
} else if (ti != null && ti == startFlag) {\r
c.parentObstacle = org.simantics.scenegraph.utils.GeometryUtils.transformRectangle(AffineTransform.getTranslateInstance(c.x, c.y),\r
- ElementUtils.getElementBoundsOnDiagram(ti.e).getBounds2D());\r
+ ElementUtils.getElementBoundsOnDiagram(ti.e).getBounds2D());\r
+ } else if (isEndingInFlag() && ti.e != null) {\r
+ c.parentObstacle = org.simantics.scenegraph.utils.GeometryUtils.transformRectangle(AffineTransform.getTranslateInstance(c.x, c.y),\r
+ CloudFactory.CLOUD_IMAGE.getBounds());\r
} else {\r
c.parentObstacle = org.simantics.scenegraph.utils.GeometryUtils.transformRectangle(AffineTransform.getTranslateInstance(c.x, c.y),\r
BranchPointClass.DEFAULT_IMAGE2.getBounds());\r
- \r
}\r
\r
return c;\r
((Segment) seg).path = (Path2D) path.clone();\r
}\r
\r
- private int toAllowedDirections(BranchPoint.Direction direction) {\r
- switch (direction) {\r
- case Any:\r
- return 0xf;\r
- case Horizontal:\r
- return Constants.EAST_FLAG | Constants.WEST_FLAG;\r
- case Vertical:\r
- return Constants.NORTH_FLAG | Constants.SOUTH_FLAG;\r
- default:\r
- throw new IllegalArgumentException("unrecognized direction: " + direction);\r
- }\r
- }\r
+// private int toAllowedDirections(BranchPoint.Direction direction) {\r
+// switch (direction) {\r
+// case Any:\r
+// return 0xf;\r
+// case Horizontal:\r
+// return Constants.EAST_FLAG | Constants.WEST_FLAG;\r
+// case Vertical:\r
+// return Constants.NORTH_FLAG | Constants.SOUTH_FLAG;\r
+// default:\r
+// throw new IllegalArgumentException("unrecognized direction: " + direction);\r
+// }\r
+// }\r
});\r
\r
// Combine the routed paths\r
package org.simantics.sysdyn.ui.editor.routing;\r
\r
-import gnu.trove.TObjectIntHashMap;\r
-\r
import java.awt.geom.AffineTransform;\r
import java.awt.geom.Path2D;\r
import java.awt.geom.PathIterator;\r
import org.simantics.g2d.routing.IConnection;\r
import org.simantics.g2d.routing.IConnection.Connector;\r
import org.simantics.g2d.routing.IRouter2;\r
+import org.simantics.sysdyn.ui.elements2.connections.Flows;\r
\r
public class FlowRouter implements IRouter2{\r
\r
SysdynLocalRouter localRouter;\r
\r
- public static final double OFFSET = 1.0;\r
+ public static final float OFFSET = 1.0f;\r
\r
public FlowRouter() {\r
this(false);\r
}\r
\r
localRouter.route();\r
- return localRouter.path;\r
- /*\r
- Path2D completePath = new Path2D.Double();\r
\r
- double[] coordinates = new double[localRouter.points.size()];\r
- for(int i = 0; i < localRouter.points.size() ; i++)\r
- coordinates[i] = localRouter.points.get(i);\r
+ Path2D completePath = new Path2D.Double();\r
\r
- boolean vertical = false;\r
+ completePath = Flows.createOffsetPath(localRouter.path, OFFSET);\r
+ completePath.append(Flows.createOffsetPath(localRouter.path, -OFFSET), false);\r
\r
- if(coordinates.length > 3) {\r
- if(coordinates[0] == coordinates[2]) {\r
- // starts to south or north\r
- double[] tempCoordinates = new double[coordinates.length - 1];\r
- for(int i = 0; i < coordinates.length - 1 ; i++)\r
- tempCoordinates[i] = coordinates[i + 1];\r
- \r
- coordinates = new double[tempCoordinates.length];\r
- for(int i = 0; i < tempCoordinates.length ; i++)\r
- coordinates[i] = tempCoordinates[i];\r
- vertical = true;\r
- }\r
- } \r
-\r
- Flows.createOffsetLine(completePath, vertical, OFFSET, coordinates);\r
- Flows.createOffsetLine(completePath, vertical, -OFFSET, coordinates);\r
-// return localRouter.path;\r
- \r
-// Flows.createLines(completePath, false, beginObstacle, endObstacle);\r
return completePath;\r
- */\r
}\r
\r
@Override\r
public void route(IConnection connection) {\r
- Collection<?> segments = connection.getSegments();\r
- if(segments.size() == 1)\r
- for(Object seg : segments) {\r
- Connector begin = connection.getBegin(seg);\r
- Connector end = connection.getEnd(seg);\r
-\r
- double bestLength = Double.POSITIVE_INFINITY;\r
- Path2D bestPath = null;\r
-\r
- for(int sDir : Constants.POSSIBLE_DIRECTIONS[begin.allowedDirections])\r
- for(int tDir : Constants.POSSIBLE_DIRECTIONS[end.allowedDirections]) {\r
- Path2D path = route(begin.x, begin.y, sDir, begin.parentObstacle,\r
- end.x, end.y, tDir, end.parentObstacle);\r
-\r
- double length = pathCost(path);\r
- if(length < bestLength) {\r
- bestLength = length;\r
- bestPath = localRouter.path;\r
- }\r
- }\r
-\r
- if(bestPath != null)\r
- connection.setPath(seg, bestPath);\r
- }\r
- else {\r
- TObjectIntHashMap<Connector> leftSegments = new TObjectIntHashMap<Connector>();\r
- TObjectIntHashMap<Connector> rightSegments = new TObjectIntHashMap<Connector>();\r
- TObjectIntHashMap<Connector> upSegments = new TObjectIntHashMap<Connector>();\r
- TObjectIntHashMap<Connector> downSegments = new TObjectIntHashMap<Connector>();\r
- TObjectIntHashMap<Connector> horizontalCount = new TObjectIntHashMap<Connector>();\r
- for(Object seg : segments) {\r
- Connector begin = connection.getBegin(seg);\r
- Connector end = connection.getEnd(seg);\r
- if(begin.x < end.x) {\r
- leftSegments.adjustOrPutValue(end, 1, 1);\r
- rightSegments.adjustOrPutValue(begin, 1, 1);\r
- }\r
- else {\r
- leftSegments.adjustOrPutValue(begin, 1, 1);\r
- rightSegments.adjustOrPutValue(end, 1, 1);\r
- }\r
- if(begin.y < end.y) {\r
- upSegments.adjustOrPutValue(end, 1, 1);\r
- downSegments.adjustOrPutValue(begin, 1, 1);\r
- }\r
- else {\r
- upSegments.adjustOrPutValue(begin, 1, 1);\r
- downSegments.adjustOrPutValue(end, 1, 1);\r
- }\r
- if((begin.allowedDirections & 5) != 0)\r
- horizontalCount.adjustOrPutValue(end, 1, 1);\r
- if((begin.allowedDirections & 10) != 0)\r
- horizontalCount.adjustOrPutValue(end, -1, -1);\r
- if((end.allowedDirections & 5) != 0)\r
- horizontalCount.adjustOrPutValue(begin, 1, 1);\r
- if((end.allowedDirections & 10) != 0)\r
- horizontalCount.adjustOrPutValue(begin, -1, -1);\r
- }\r
- for(Object seg : segments) {\r
- Connector begin = connection.getBegin(seg);\r
- Connector end = connection.getEnd(seg);\r
- int allowedBegin = begin.allowedDirections;\r
- int allowedEnd = end.allowedDirections;\r
-\r
- if(horizontalCount.get(begin) + horizontalCount.get(end) >= 0) {\r
- //System.out.println("horizontal");\r
- if(begin.x < end.x) {\r
- if(allowedBegin == 0xf) {\r
- if(rightSegments.get(begin) <= 1)\r
- allowedBegin = 1;\r
- else\r
- allowedBegin = 11;\r
- }\r
- if(allowedEnd == 0xf) {\r
- if(leftSegments.get(end) <= 1)\r
- allowedEnd = 4;\r
- else\r
- allowedEnd = 14;\r
- }\r
- }\r
- else {\r
- if(allowedBegin == 0xf) {\r
- if(leftSegments.get(begin) <= 1)\r
- allowedBegin = 4;\r
- else\r
- allowedBegin = 14;\r
- }\r
- if(allowedEnd == 0xf) {\r
- if(rightSegments.get(end) <= 1)\r
- allowedEnd = 1;\r
- else\r
- allowedEnd = 11;\r
- }\r
- }\r
- }\r
- else {\r
- //System.out.println("vertical");\r
- if(begin.y < end.y) {\r
- if(allowedBegin == 0xf) {\r
- if(downSegments.get(begin) <= 1)\r
- allowedBegin = 2;\r
- else\r
- allowedBegin = 7;\r
- }\r
- if(allowedEnd == 0xf) {\r
- if(upSegments.get(end) <= 1)\r
- allowedEnd = 8;\r
- else\r
- allowedEnd = 13;\r
- }\r
- }\r
- else {\r
- if(allowedBegin == 0xf) {\r
- if(upSegments.get(begin) <= 1)\r
- allowedBegin = 8;\r
- else\r
- allowedBegin = 13;\r
- }\r
- if(allowedEnd == 0xf) {\r
- if(downSegments.get(end) <= 1)\r
- allowedEnd = 2;\r
- else\r
- allowedEnd = 7;\r
- }\r
- }\r
- }\r
-\r
- //System.out.println(allowedBegin + " " + allowedEnd);\r
-\r
- double bestLength = Double.POSITIVE_INFINITY;\r
- Path2D bestPath = null;\r
-\r
- for(int sDir : Constants.POSSIBLE_DIRECTIONS[allowedBegin])\r
- for(int tDir : Constants.POSSIBLE_DIRECTIONS[allowedEnd]) {\r
- Path2D path = route(begin.x, begin.y, sDir, begin.parentObstacle,\r
- end.x, end.y, tDir, end.parentObstacle);\r
-\r
- double length = pathCost(path);\r
- if(length < bestLength) {\r
- bestLength = length;\r
- bestPath = localRouter.path;\r
- }\r
- }\r
-\r
- if(bestPath != null)\r
- connection.setPath(seg, bestPath);\r
- }\r
- }\r
- }\r
-\r
- /*\r
- @Override\r
- public void route(IConnection connection) {\r
- \r
- if(!(connection instanceof SysdynConnection)) {\r
- return;\r
- }\r
Collection<?> segments = connection.getSegments();\r
if(segments.size() == 1)\r
for(Object seg : segments) {\r
connection.setPath(seg, bestPath);\r
}\r
}\r
- */\r
+ \r
\r
final static AffineTransform IDENTITY = new AffineTransform();\r
\r
y = temp[1];\r
it.next();\r
}\r
- //return length * (6.0 + bendCount);\r
return bendCount - 1.0 / length;\r
}\r
\r
* share Y-Axis at some point 3. Obstacles don't share axis => Have to\r
* make corners.\r
*/ \r
- if (\r
- aMinX > bMinX && aMinX < bMaxX ||\r
- aMaxX > bMinX && aMaxX < bMaxX ||\r
- aMinX < bMinX && aMaxX > bMaxX) {\r
- // Obstacles share x-axis => no corner\r
- double minX = aMinX > bMinX ? aMinX : bMinX;\r
- double maxX = aMaxX < bMaxX ? aMaxX : bMaxX;\r
- double middle = minX + (maxX - minX) / 2;\r
- sx = middle;\r
- tx = middle;\r
- if (sy > ty) {\r
- sy = aMinY;\r
- ty = bMaxY;\r
- } else {\r
- sy = aMaxY;\r
- ty = bMinY;\r
- }\r
- } else if (\r
- aMinY > bMinY && aMinY < bMaxY || \r
- aMaxY > bMinY && aMaxY < bMaxY ||\r
- aMinY < bMinY && aMaxY > bMaxY) {\r
- // Obstacles share y-axis => no corner\r
- double minY = aMinY > bMinY ? aMinY : bMinY;\r
- double maxY = aMaxY < bMaxY ? aMaxY : bMaxY;\r
- double middle = minY + (maxY - minY) / 2;\r
- sy = middle;\r
- ty = middle;\r
- if (sx > tx) {\r
- sx = aMinX;\r
- tx = bMaxX;\r
- } else {\r
- sx = aMaxX;\r
- tx = bMinX;\r
- }\r
- } else {\r
+// if (\r
+// aMinX > bMinX && aMinX < bMaxX ||\r
+// aMaxX > bMinX && aMaxX < bMaxX ||\r
+// aMinX < bMinX && aMaxX > bMaxX) {\r
+// // Obstacles share x-axis => no corner\r
+// double minX = aMinX > bMinX ? aMinX : bMinX;\r
+// double maxX = aMaxX < bMaxX ? aMaxX : bMaxX;\r
+// double middle = minX + (maxX - minX) / 2;\r
+// sx = middle;\r
+// tx = middle;\r
+// if (sy > ty) {\r
+// sy = aMinY;\r
+// ty = bMaxY;\r
+// } else {\r
+// sy = aMaxY;\r
+// ty = bMinY;\r
+// }\r
+// } else if (\r
+// aMinY > bMinY && aMinY < bMaxY || \r
+// aMaxY > bMinY && aMaxY < bMaxY ||\r
+// aMinY < bMinY && aMaxY > bMaxY) {\r
+// // Obstacles share y-axis => no corner\r
+// double minY = aMinY > bMinY ? aMinY : bMinY;\r
+// double maxY = aMaxY < bMaxY ? aMaxY : bMaxY;\r
+// double middle = minY + (maxY - minY) / 2;\r
+// sy = middle;\r
+// ty = middle;\r
+// if (sx > tx) {\r
+// sx = aMinX;\r
+// tx = bMaxX;\r
+// } else {\r
+// sx = aMaxX;\r
+// tx = bMinX;\r
+// }\r
+// } else {\r
sx = aMinX + (aMaxX - aMinX) / 2;\r
sy = aMinY + (aMaxY - aMinY) / 2;\r
tx = bMinX + (bMaxX - bMinX) / 2;\r
ty = bMaxY;\r
break;\r
}\r
- }\r
+// }\r
\r
path = new Path2D.Double();\r
points = new ArrayList<Double>();\r
import java.awt.Graphics2D;\r
import java.awt.Stroke;\r
import java.awt.geom.Path2D;\r
-import java.awt.geom.PathIterator;\r
-import java.io.Serializable;\r
\r
-import org.simantics.diagram.connection.rendering.ConnectionStyle;\r
+import org.simantics.diagram.connection.rendering.BasicConnectionStyle;\r
\r
-public class FlowConnectionStyle implements ConnectionStyle, Serializable {\r
+public class FlowConnectionStyle extends BasicConnectionStyle {\r
\r
private static final long serialVersionUID = 2777194644079591357L;\r
\r
Stroke lineStroke;\r
\r
public FlowConnectionStyle(Color lineColor, Stroke lineStroke) {\r
+ super(lineColor, Color.BLACK, 0.5, lineStroke, lineStroke, 0.8);\r
this.lineColor = lineColor;\r
this.lineStroke = lineStroke;\r
}\r
if (lineStroke != null)\r
g.setStroke(lineStroke);\r
\r
- Path2D p1 = createOffsetPath(g, path, 1);\r
- Path2D p2 = createOffsetPath(g, path, -1);\r
+ Path2D p1 = Flows.createOffsetPath(path, 1);\r
+ Path2D p2 = Flows.createOffsetPath(path, -1);\r
p1.append(p2, false);\r
g.draw(p1);\r
}\r
return 0;\r
}\r
\r
- private static int x = 0;\r
- private static int y = 1;\r
- private Path2D createOffsetPath(Graphics2D g, Path2D originalPath, float offset) {\r
- PathIterator pi = originalPath.getPathIterator(null);\r
- Path2D newPath = new Path2D.Double();\r
- double[] previous = new double[6];\r
- double[] current = new double[6];\r
- double[] next = new double[6];\r
- boolean vertical = false;\r
- pi.currentSegment(current);\r
- pi.next();\r
- pi.currentSegment(next);\r
- \r
- Direction direction = getDirection(current, next);\r
-\r
- int i = 0;\r
- if(direction == Direction.SOUTH || direction == Direction.NORTH) {\r
- // First line vertical\r
- vertical = true;\r
- current[x] += offset;\r
- newPath.moveTo(current[x], current[y]);\r
- \r
- if(direction == Direction.SOUTH)\r
- offset = -offset;\r
- } else {\r
- // First line horizontal\r
- current[y] += offset;\r
- i = 1;\r
- newPath.moveTo(current[x], current[y]);\r
- if(direction == Direction.WEST)\r
- offset = -offset;\r
- }\r
- \r
-\r
- previous[x] = current[x];\r
- previous[y] = current[y];\r
- current[x] = next[x];\r
- current[y] = next[y];\r
-\r
- while(!pi.isDone()) {\r
- pi.next();\r
- pi.currentSegment(next);\r
- if(previous[i] < next[i] ^ (i&1)==1) {\r
- if(vertical) {\r
- if(!pi.isDone()) current[y] += offset;\r
- newPath.lineTo(previous[x], current[y]);\r
- } else {\r
- if(!pi.isDone()) current[x] += offset;\r
- newPath.lineTo(current[x], previous[y]);\r
- }\r
- } else {\r
- if(vertical) {\r
- if(!pi.isDone()) current[y] -= offset;\r
- newPath.lineTo(previous[x], current[y]);\r
- } else {\r
- if(!pi.isDone()) current[x] -= offset;\r
- newPath.lineTo(current[x], previous[y]);\r
- }\r
- }\r
- \r
- previous[x] = current[x];\r
- previous[y] = current[y];\r
- current[x] = next[x];\r
- current[y] = next[y];\r
- vertical = !vertical;\r
- i = (i + 1) % 2;\r
- }\r
- return newPath;\r
- }\r
- \r
- private enum Direction {NORTH, SOUTH, EAST, WEST};\r
-\r
- private Direction getDirection(double[] current, double[] next) {\r
- if(current[x] == next[x]) {\r
- // move vertically\r
- if(current[y] < next[y])\r
- return Direction.SOUTH;\r
- else\r
- return Direction.NORTH;\r
- } else {\r
- //move horizontally\r
- if(current[x] < next[x])\r
- return Direction.EAST;\r
- else\r
- return Direction.WEST;\r
- }\r
- }\r
-\r
}\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
- * 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.sysdyn.ui.elements2.connections;\r
-\r
-import java.awt.Shape;\r
-import java.awt.Stroke;\r
-\r
-public class FlowStroke implements Stroke {\r
- private Stroke stroke1, stroke2;\r
-\r
- public FlowStroke( Stroke stroke1, Stroke stroke2 ) {\r
- this.stroke1 = stroke1;\r
- this.stroke2 = stroke2;\r
- }\r
-\r
- public Shape createStrokedShape( Shape shape ) {\r
- return stroke2.createStrokedShape( stroke1.createStrokedShape( shape ) );\r
- }\r
- \r
-}\r
package org.simantics.sysdyn.ui.elements2.connections;\r
\r
import java.awt.geom.Path2D;\r
+import java.awt.geom.PathIterator;\r
import java.awt.geom.Rectangle2D;\r
\r
public class Flows {\r
return createLine(path, vertical, newCoordinats);\r
}\r
\r
+ \r
+ private static int x = 0;\r
+ private static int y = 1;\r
+ public static Path2D createOffsetPath(Path2D originalPath, float offset) {\r
+ PathIterator pi = originalPath.getPathIterator(null);\r
+ Path2D newPath = new Path2D.Double();\r
+ double[] previous = new double[6];\r
+ double[] current = new double[6];\r
+ double[] next = new double[6];\r
+ boolean vertical = false;\r
+ pi.currentSegment(current);\r
+ pi.next();\r
+ pi.currentSegment(next);\r
+ \r
+ Direction direction = getDirection(current, next);\r
+\r
+ int i = 0;\r
+ if(direction == Direction.SOUTH || direction == Direction.NORTH) {\r
+ // First line vertical\r
+ vertical = true;\r
+ current[x] += offset;\r
+ newPath.moveTo(current[x], current[y]);\r
+ \r
+ if(direction == Direction.SOUTH)\r
+ offset = -offset;\r
+ } else {\r
+ // First line horizontal\r
+ current[y] += offset;\r
+ i = 1;\r
+ newPath.moveTo(current[x], current[y]);\r
+ if(direction == Direction.WEST)\r
+ offset = -offset;\r
+ }\r
+ \r
+\r
+ previous[x] = current[x];\r
+ previous[y] = current[y];\r
+ current[x] = next[x];\r
+ current[y] = next[y];\r
+\r
+ while(!pi.isDone()) {\r
+ pi.next();\r
+ pi.currentSegment(next);\r
+ if(previous[i] < next[i] ^ (i&1)==1) {\r
+ if(vertical) {\r
+ if(!pi.isDone()) current[y] += offset;\r
+ newPath.lineTo(previous[x], current[y]);\r
+ } else {\r
+ if(!pi.isDone()) current[x] += offset;\r
+ newPath.lineTo(current[x], previous[y]);\r
+ }\r
+ } else {\r
+ if(vertical) {\r
+ if(!pi.isDone()) current[y] -= offset;\r
+ newPath.lineTo(previous[x], current[y]);\r
+ } else {\r
+ if(!pi.isDone()) current[x] -= offset;\r
+ newPath.lineTo(current[x], previous[y]);\r
+ }\r
+ }\r
+ \r
+ previous[x] = current[x];\r
+ previous[y] = current[y];\r
+ current[x] = next[x];\r
+ current[y] = next[y];\r
+ vertical = !vertical;\r
+ i = (i + 1) % 2;\r
+ }\r
+ return newPath;\r
+ }\r
+ \r
+ private static enum Direction {NORTH, SOUTH, EAST, WEST};\r
+\r
+ private static Direction getDirection(double[] current, double[] next) {\r
+ if(current[x] == next[x]) {\r
+ // move vertically\r
+ if(current[y] < next[y])\r
+ return Direction.SOUTH;\r
+ else\r
+ return Direction.NORTH;\r
+ } else {\r
+ //move horizontally\r
+ if(current[x] < next[x])\r
+ return Direction.EAST;\r
+ else\r
+ return Direction.WEST;\r
+ }\r
+ }\r
+ \r
}\r
import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.request.Read;\r
import org.simantics.layer0.Layer0;\r
import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.sysdyn.ui.properties.widgets.ValveOrientationGroup;\r
import org.simantics.sysdyn.ui.properties.widgets.ValveTextLocationGroup;\r
import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory;\r
import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
\r
-public class VariableInformationTab extends LabelPropertyTabContributor {\r
-\r
+public class VariableInformationTab extends LabelPropertyTabContributor implements Widget {\r
+ Composite orientationComposite;\r
+ WidgetSupport support;\r
+ \r
@Override\r
public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) {\r
+ this.support = support;\r
+ support.register(this);\r
+ \r
Composite composite = new Composite(body, SWT.NONE);\r
GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
- GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
\r
Group informationGroup = new Group(composite, SWT.SHADOW_ETCHED_IN);\r
informationGroup.setText("Information");\r
information.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasDescription));\r
GridDataFactory.fillDefaults().grab(true, true).applyTo(information.getWidget());\r
\r
+ orientationComposite = new Composite(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(1, 2).applyTo(orientationComposite);\r
+ GridLayoutFactory.fillDefaults().margins(3,3).applyTo(orientationComposite);\r
+ \r
Group rangeGroup = new Group(composite, SWT.SHADOW_ETCHED_IN);\r
rangeGroup.setText("Range");\r
GridDataFactory.fillDefaults().applyTo(rangeGroup);\r
rangeStep.setInputValidator(new DoubleValidator());\r
GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeStep.getWidget());\r
\r
- Composite valveComposite = new Composite(composite, SWT.NONE);\r
- GridDataFactory.fillDefaults().applyTo(valveComposite);\r
- GridLayoutFactory.fillDefaults().numColumns(2).margins(3,3).applyTo(valveComposite);\r
- new ValveOrientationGroup(valveComposite, context, support, SWT.NONE);\r
- new ValveTextLocationGroup(valveComposite, context, support, SWT.NONE);\r
+\r
\r
}\r
\r
}\r
}\r
\r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ final Resource valve = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ Boolean isValve = false;\r
+ try {\r
+ isValve = context.getSession().syncRequest(new Read<Boolean>() {\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph graph) throws DatabaseException {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ return graph.isInstanceOf(valve, sr.Valve);\r
+ }\r
+\r
+ });\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ if(isValve) {\r
+ ValveOrientationGroup vog = new ValveOrientationGroup(orientationComposite, context, support, SWT.NONE);\r
+ vog.setInput(context, input);\r
+ ValveTextLocationGroup vtlg = new ValveTextLocationGroup(orientationComposite, context, support, SWT.NONE);\r
+ vtlg.setInput(context, input);\r
+ orientationComposite.getParent().layout();\r
+ }\r
+ }\r
}\r
\r
public ValveOrientationGroup(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
super(support);\r
- support.register(this);\r
group = new Group(parent, SWT.NONE);\r
group.setText("Valve orientation");\r
GridDataFactory.fillDefaults().applyTo(group);\r
\r
@Override\r
public void setInput(ISessionContext context, Object input) {\r
- \r
- \r
+ horizontal.setInput(context, input);\r
+ vertical.setInput(context, input);\r
}\r
\r
@Override\r
\r
@Override\r
public void setInput(ISessionContext context, Object input) {\r
- // TODO Auto-generated method stub\r
- \r
+ top.setInput(context, input);\r
+ bottom.setInput(context, input);\r
+ left.setInput(context, input);\r
+ right.setInput(context, input);\r
}\r
\r
@Override\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
- * 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.sysdyn.ui.trend;\r
-\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.ui.part.ViewPart;\r
-import org.simantics.g2d.chassis.SWTChassis;\r
-\r
-public class ChartPane extends ViewPart {\r
-\r
- \r
- @Override\r
- public void createPartControl(Composite parent) {\r
- SWTChassis canvas = new SWTChassis(parent, SWT.NONE);\r
- canvas.syncPopulate();\r
- }\r
- \r
-\r
- @Override\r
- public void setFocus() {\r
- }\r
-\r
-}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.sysdyn.ui.trend;\r
+\r
+import java.awt.Frame;\r
+import java.text.SimpleDateFormat;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.awt.SWT_AWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.events.ControlAdapter;\r
+import org.eclipse.swt.events.ControlEvent;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.PaintEvent;\r
+import org.eclipse.swt.events.PaintListener;\r
+import org.eclipse.swt.graphics.Cursor;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.graphics.Transform;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.widgets.Canvas;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Listener;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.ui.part.ViewPart;\r
+import org.jfree.chart.ChartFactory;\r
+import org.jfree.chart.ChartFrame;\r
+import org.jfree.chart.JFreeChart;\r
+import org.jfree.chart.axis.DateAxis;\r
+import org.jfree.chart.plot.XYPlot;\r
+import org.jfree.data.time.Day;\r
+import org.jfree.data.time.TimeSeries;\r
+import org.jfree.data.time.TimeSeriesCollection;\r
+import org.simantics.g2d.chassis.SWTChassis;\r
+import org.simantics.utils.threads.SWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+import org.simantics.utils.ui.SWTAWTComponent;\r
+\r
+public class ChartPanel extends ViewPart {\r
+\r
+ ScrolledComposite sc;\r
+ Composite composite;\r
+\r
+ @Override\r
+ public void createPartControl(Composite parent) {\r
+ Composite c = new Composite(parent, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().applyTo(c);\r
+\r
+ sc = new ScrolledComposite(c, SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+ GridLayoutFactory.fillDefaults().applyTo(sc);\r
+ \r
+ composite = new Composite(sc, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().numColumns(6).applyTo(composite);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+ \r
+ \r
+ sc.setContent(composite);\r
+ sc.setExpandHorizontal(true);\r
+ sc.setExpandVertical(true);\r
+ sc.getVerticalBar().setIncrement(30);\r
+ sc.getVerticalBar().setPageIncrement(200);\r
+ sc.addControlListener( new ControlAdapter() {\r
+ @Override\r
+ public void controlResized(ControlEvent e) {\r
+ //System.out.println("ScrolledComposite resized: " + sc.getSize());\r
+ refreshScrolledComposite();\r
+ }\r
+ });\r
+ \r
+ final Canvas canvas = new Canvas(composite, SWT.BORDER);\r
+ // Create a paint handler for the canvas\r
+ canvas.addPaintListener(new PaintListener() {\r
+ public void paintControl(PaintEvent e) {\r
+ int canvasHeight = canvas.getSize().y;\r
+ String text = "Module1.Variable2[index3]";\r
+ Transform t = new Transform(e.display);\r
+ t.rotate(-90);\r
+ t.translate(- (canvasHeight - 10), 0);\r
+ e.gc.setTransform(t);\r
+ e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_BLACK));\r
+ e.gc.drawText(text, 0, 0);\r
+ }\r
+ });\r
+ GridDataFactory.fillDefaults().hint(20, SWT.DEFAULT).grab(false, true).applyTo(canvas);\r
+ canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_HAND));\r
+ canvas.addMouseListener(new NewTrendListener());\r
+ ToolTipListener ttl = new ToolTipListener(canvas);\r
+ canvas.addListener(SWT.Dispose, ttl);\r
+ canvas.addListener(SWT.KeyDown, ttl);\r
+ canvas.addListener(SWT.MouseMove, ttl);\r
+ canvas.addListener(SWT.MouseHover, ttl);\r
+ \r
+ Composite swtComposite = new Composite(composite,\r
+ SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
+ GridDataFactory.fillDefaults().hint(200, 200).applyTo(swtComposite);\r
+ Frame frame = SWT_AWT.new_Frame(swtComposite);\r
+ setChart(frame);\r
+ }\r
+\r
+\r
+ @Override\r
+ public void setFocus() {\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+\r
+ }\r
+ \r
+ \r
+ void refreshScrolledComposite() {\r
+ // Execute asynchronously to give the UI events triggering this method\r
+ // call time to run through before actually doing any resizing.\r
+ // Otherwise the result will lag behind reality when scrollbar\r
+ // visibility is toggled by the toolkit.\r
+ ThreadUtils.asyncExec(SWTThread.getThreadAccess(composite.getDisplay()), new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ if (sc.isDisposed())\r
+ return;\r
+ syncRefreshScrolledComposite();\r
+ }\r
+ });\r
+ }\r
+\r
+ void syncRefreshScrolledComposite() {\r
+ // Execute asynchronously to give the UI events triggering this method\r
+ // call time to run through before actually doing any resizing.\r
+ // Otherwise the result will lag behind reality when scrollbar\r
+ // visibility is toggled by the toolkit.\r
+ Rectangle r = sc.getClientArea();\r
+ Point contentSize = composite.computeSize(r.width, SWT.DEFAULT);\r
+ //System.out.println("[" + Thread.currentThread() + "] computed content size: " + contentSize + ", " + r);\r
+ composite.setSize(contentSize);\r
+ }\r
+ \r
+ private class NewTrendListener implements MouseListener {\r
+\r
+ @Override\r
+ public void mouseUp(MouseEvent e) {\r
+ final Canvas canvas = new Canvas(composite, SWT.BORDER);\r
+ // Create a paint handler for the canvas\r
+ canvas.addPaintListener(new PaintListener() {\r
+ public void paintControl(PaintEvent e) {\r
+ int canvasHeight = canvas.getSize().y;\r
+ String text = "Module1.Variable2[index3]";\r
+ Transform t = new Transform(e.display);\r
+ t.rotate(-90);\r
+ t.translate(- (canvasHeight - 10), 0);\r
+ e.gc.setTransform(t);\r
+ e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_BLACK));\r
+ e.gc.drawText(text, 0, 0);\r
+ }\r
+ });\r
+ GridDataFactory.fillDefaults().hint(20, SWT.DEFAULT).grab(false, true).applyTo(canvas);\r
+ composite.layout();\r
+ canvas.addMouseListener(this);\r
+ canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_HAND));\r
+ ToolTipListener ttl = new ToolTipListener(canvas);\r
+ canvas.addListener(SWT.Dispose, ttl);\r
+ canvas.addListener(SWT.KeyDown, ttl);\r
+ canvas.addListener(SWT.MouseMove, ttl);\r
+ canvas.addListener(SWT.MouseHover, ttl);\r
+ \r
+ Composite swtComposite = new Composite(composite,\r
+ SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
+ Frame frame = SWT_AWT.new_Frame(swtComposite);\r
+ GridDataFactory.fillDefaults().hint(200, 200).applyTo(swtComposite);\r
+ setChart(frame);\r
+ syncRefreshScrolledComposite();\r
+ }\r
+\r
+ @Override\r
+ public void mouseDown(MouseEvent e) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+\r
+ @Override\r
+ public void mouseDoubleClick(MouseEvent e) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+ }\r
+ \r
+ \r
+ private void setChart(Frame frame) {\r
+ TimeSeries population = new TimeSeries("Indian Population");\r
+ population.add(new Day(1, 3, 1961), 439234771);\r
+ population.add(new Day(1, 3, 1971), 548159652);\r
+ population.add(new Day(1, 3, 1981), 683329097);\r
+ population.add(new Day(1, 3, 1991), 843387888);\r
+ population.add(new Day(1, 3, 2001), 1028610328);\r
+ population.add(new Day(1, 3, 2011), 1210193422);\r
+ TimeSeriesCollection dataset = new TimeSeriesCollection(population);\r
+ \r
+ // Create the chart\r
+ JFreeChart chart = ChartFactory.createTimeSeriesChart(\r
+ "Population of India", "Date", "Population", dataset,\r
+ true, true, false);\r
+ \r
+ //Get the plot and set date format\r
+ XYPlot plot = chart.getXYPlot();\r
+ DateAxis axis = (DateAxis) plot.getDomainAxis();\r
+ axis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy"));\r
+\r
+ // Render the frame\r
+ org.jfree.chart.ChartPanel panel = new org.jfree.chart.ChartPanel(chart);\r
+ panel.setSize(200, 200);\r
+ frame.add(panel);\r
+ }\r
+\r
+ \r
+ \r
+ private class ToolTipListener implements Listener {\r
+ Shell tip = null;\r
+ Label label = null;\r
+ Composite composite;\r
+ \r
+ public ToolTipListener(Composite composite) {\r
+ this.composite = composite;\r
+ }\r
+\r
+ public void handleEvent(Event event) {\r
+ switch (event.type) {\r
+ case SWT.Dispose:\r
+ case SWT.KeyDown:\r
+ case SWT.MouseMove: {\r
+ if (tip == null)\r
+ break;\r
+ tip.dispose();\r
+ tip = null;\r
+ label = null;\r
+ break;\r
+ }\r
+ case SWT.MouseHover: {\r
+ if(composite.isDisposed())\r
+ return;\r
+ if (tip != null && !tip.isDisposed())\r
+ tip.dispose();\r
+ Display display = composite.getDisplay();\r
+ tip = new Shell(display, SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);\r
+ tip.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));\r
+ FillLayout layout = new FillLayout();\r
+ layout.marginWidth = 2;\r
+ tip.setLayout(layout);\r
+ label = new Label(tip, SWT.NONE);\r
+ label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));\r
+ label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));\r
+ label.setText("Module1.Variable2[index3]");\r
+// label.addListener(SWT.MouseExit, labelListener);\r
+// label.addListener(SWT.MouseDown, labelListener);\r
+ Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ Point pt = composite.toDisplay(event.x, event.y);\r
+ tip.setBounds(pt.x, pt.y, size.x, size.y);\r
+ tip.setVisible(true);\r
+ }\r
+ }\r
+ }\r
+ };\r
+}\r
\r
<product name="Simantics System Dynamic Tool" uid="org.simantics.sysdyn.product.Sysdyn" id="org.simantics.sysdyn.ui.product" application="org.simantics.workbench.application" version="1.5" useFeatures="true" includeLaunchers="true">\r
\r
-\r
<configIni use="default">\r
</configIni>\r
\r
</win>\r
</launcher>\r
\r
-\r
<vm>\r
+ <windows include="false">org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6</windows>\r
</vm>\r
\r
<license>\r