@MOD.terminalRelation SYSDYN.IsTailOf
SYSDYN.SysdynTerminal <T DIA.Terminal
+ @L0.assert DIA.Terminal.AllowedDirections 0
//#####################################################################
SYSDYN.Valve <T STR.Component
@MOD.connection SYSDYN.IsTailOf
@MOD.connection SYSDYN.IsHeadOf
+
+SYSDYN.HasValveOrientation <R L0.HasProperty : L0.FunctionalRelation
+ L0.HasRange L0.Boolean
+
+SYSDYN.Orientation <T L0.Entity
+SYSDYN.Horizontal <T SYSDYN.Orientation
+SYSDYN.Vertical <T SYSDYN.Orientation
SYSDYN.ValveSymbol <T DIA.FontProvider <T DIA.ColorProvider
@MOD.defSymbol "Valve" SYSDYN.Valve
+ @L0.assert SYSDYN.Orientation SYSDYN.Horizontal
L0.IsDependencyOf BasicSymbols
STR.IsDefinedBy _ : DIA.Composite <R L0.HasNext
@L0.orderedSet
SYSDYN.PolarityLocation <R L0.HasProperty : L0.FunctionalRelation
L0.HasRange L0.String
-SYSDYN.FlowConnection <T DIA.Connection
+SYSDYN.FlowConnection <T DIA.RouteGraphConnection
MOD.DiagramConnectionTypeToConnectionType
SYSDYN.Flow
public final Resource HasTolerance_Inverse;\r
public final Resource HasUnit;\r
public final Resource HasUnit_Inverse;\r
+ public final Resource HasValveOrientation;\r
+ public final Resource HasValveOrientation_Inverse;\r
public final Resource HistoryRealization;\r
+ public final Resource Horizontal;\r
public final Resource ImportModuleTree;\r
public final Resource ImportedOntologies;\r
public final Resource IndependentVariable;\r
public final Resource Module;\r
public final Resource ModuleSymbol;\r
public final Resource NormalExpression;\r
+ public final Resource Orientation;\r
public final Resource ParameterExpression;\r
public final Resource PlaybackExperiment;\r
public final Resource Polarity;\r
public final Resource Variable;\r
public final Resource Variable_Type;\r
public final Resource Variable_Type_Inverse;\r
+ public final Resource Vertical;\r
public final Resource WithLookupExpression;\r
public final Resource angle;\r
public final Resource angle_Inverse;\r
public static final String HasTolerance_Inverse = "http://www.simantics.org/Sysdyn-1.1/HasTolerance/Inverse";\r
public static final String HasUnit = "http://www.simantics.org/Sysdyn-1.1/HasUnit";\r
public static final String HasUnit_Inverse = "http://www.simantics.org/Sysdyn-1.1/HasUnit/Inverse";\r
+ public static final String HasValveOrientation = "http://www.simantics.org/Sysdyn-1.1/HasValveOrientation";\r
+ public static final String HasValveOrientation_Inverse = "http://www.simantics.org/Sysdyn-1.1/HasValveOrientation/Inverse";\r
public static final String HistoryRealization = "http://www.simantics.org/Sysdyn-1.1/HistoryRealization";\r
+ public static final String Horizontal = "http://www.simantics.org/Sysdyn-1.1/Horizontal";\r
public static final String ImportModuleTree = "http://www.simantics.org/Sysdyn-1.1/ImportModuleTree";\r
public static final String ImportedOntologies = "http://www.simantics.org/Sysdyn-1.1/ImportedOntologies";\r
public static final String IndependentVariable = "http://www.simantics.org/Sysdyn-1.1/IndependentVariable";\r
public static final String Module = "http://www.simantics.org/Sysdyn-1.1/Module";\r
public static final String ModuleSymbol = "http://www.simantics.org/Sysdyn-1.1/ModuleSymbol";\r
public static final String NormalExpression = "http://www.simantics.org/Sysdyn-1.1/NormalExpression";\r
+ public static final String Orientation = "http://www.simantics.org/Sysdyn-1.1/Orientation";\r
public static final String ParameterExpression = "http://www.simantics.org/Sysdyn-1.1/ParameterExpression";\r
public static final String PlaybackExperiment = "http://www.simantics.org/Sysdyn-1.1/PlaybackExperiment";\r
public static final String Polarity = "http://www.simantics.org/Sysdyn-1.1/Polarity";\r
public static final String Variable = "http://www.simantics.org/Sysdyn-1.1/Variable";\r
public static final String Variable_Type = "http://www.simantics.org/Sysdyn-1.1/Variable/Type";\r
public static final String Variable_Type_Inverse = "http://www.simantics.org/Sysdyn-1.1/Variable/Type/Inverse";\r
+ public static final String Vertical = "http://www.simantics.org/Sysdyn-1.1/Vertical";\r
public static final String WithLookupExpression = "http://www.simantics.org/Sysdyn-1.1/WithLookupExpression";\r
public static final String angle = "http://www.simantics.org/Sysdyn-1.1/angle";\r
public static final String angle_Inverse = "http://www.simantics.org/Sysdyn-1.1/angle/Inverse";\r
HasTolerance_Inverse = getResourceOrNull(graph, URIs.HasTolerance_Inverse);\r
HasUnit = getResourceOrNull(graph, URIs.HasUnit);\r
HasUnit_Inverse = getResourceOrNull(graph, URIs.HasUnit_Inverse);\r
+ HasValveOrientation = getResourceOrNull(graph, URIs.HasValveOrientation);\r
+ HasValveOrientation_Inverse = getResourceOrNull(graph, URIs.HasValveOrientation_Inverse);\r
HistoryRealization = getResourceOrNull(graph, URIs.HistoryRealization);\r
+ Horizontal = getResourceOrNull(graph, URIs.Horizontal);\r
ImportModuleTree = getResourceOrNull(graph, URIs.ImportModuleTree);\r
ImportedOntologies = getResourceOrNull(graph, URIs.ImportedOntologies);\r
IndependentVariable = getResourceOrNull(graph, URIs.IndependentVariable);\r
Module = getResourceOrNull(graph, URIs.Module);\r
ModuleSymbol = getResourceOrNull(graph, URIs.ModuleSymbol);\r
NormalExpression = getResourceOrNull(graph, URIs.NormalExpression);\r
+ Orientation = getResourceOrNull(graph, URIs.Orientation);\r
ParameterExpression = getResourceOrNull(graph, URIs.ParameterExpression);\r
PlaybackExperiment = getResourceOrNull(graph, URIs.PlaybackExperiment);\r
Polarity = getResourceOrNull(graph, URIs.Polarity);\r
Variable = getResourceOrNull(graph, URIs.Variable);\r
Variable_Type = getResourceOrNull(graph, URIs.Variable_Type);\r
Variable_Type_Inverse = getResourceOrNull(graph, URIs.Variable_Type_Inverse);\r
+ Vertical = getResourceOrNull(graph, URIs.Vertical);\r
WithLookupExpression = getResourceOrNull(graph, URIs.WithLookupExpression);\r
angle = getResourceOrNull(graph, URIs.angle);\r
angle_Inverse = getResourceOrNull(graph, URIs.angle_Inverse);\r
VTT Technical Research Centre of Finland - initial API and implementation\r
-->\r
-<adapters>\r\r <target interface="org.simantics.db.layer0.adapter.Realization">\r <type uri="http://www.simantics.org/Sysdyn-0.0/Module"\r class="org.simantics.structural2.realization.StructuralRealization">\r <this />\r </type>\r </target>\r\r<!-- \r <target interface="org.simantics.db.layer0.variable.Variable">\r <type uri="http://www.simantics.org/Sysdyn-0.0/HistoryRealization"\r class="org.simantics.sysdyn.ui.project.HistoryVariable" >\r <this />\r </type>\r <type uri="http://www.simantics.org/Sysdyn-0.0/DefaultRealization"\r class="org.simantics.sysdyn.ui.project.DefaultVariable" >\r <this />\r </type>\r </target>\r -->\r\r <target interface="org.simantics.layer0.utils.triggers.ITrigger">\r <type uri = "http://www.simantics.org/Sysdyn-0.0/DiagramToCompositeMapping"\r class = "org.simantics.sysdyn.ui.editor.DiagramToCompositeMapping3">\r <graph/>\r <this />\r </type>\r </target>\r \r <target interface="org.simantics.structural.ui.modelBrowser.nodes.AbstractNode">\r <type uri="http://www.simantics.org/Sysdyn-0.0/SysdynModel"\r class="org.simantics.structural.ui.modelBrowser.nodes.ModelNode">\r <this />\r </type>\r </target> \r \r\r <target\r interface="org.simantics.browsing.ui.common.node.AbstractNode">\r <type\r uri="http://www.simantics.org/Sysdyn-0.0/SysdynModel"\r class="org.simantics.sysdyn.ui.browser.nodes.ModelNode">\r <this />\r </type>\r\r <resource\r uri="http://www.simantics.org/Sysdyn-0.0/ModuleSymbol"\r class="org.simantics.sysdyn.ui.browser.nodes.SymbolNode">\r <this />\r </resource>\r\r <type\r uri="http://www.simantics.org/Simulation-1.0/Experiment"\r class="org.simantics.sysdyn.ui.browser.nodes.ExperimentNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Sysdyn-0.0/Result"\r class="org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode">\r <this />\r </type>\r \r </target>\r\r <!-- Inject default connection routing algorithm for sysdyn diagrams -->\r <target interface="org.simantics.g2d.diagram.DiagramClass">\r <adapter uri="http://www.simantics.org/Sysdyn-0.0/ConfigurationDiagram"\r adapterClass="org.simantics.sysdyn.ui.elements2.ConfigurationDiagramClassAdapter" />\r </target>\r\r <!-- Sysdyn symbols -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ModuleSymbol"\r class="org.simantics.sysdyn.ui.elements2.ModuleFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/InputSymbol"\r class="org.simantics.sysdyn.ui.elements2.InputFactory" />\r\r <type uri="http://www.simantics.org/Sysdyn-0.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/ModuleSymbol"\r class="org.simantics.sysdyn.ui.elements2.ModuleFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/InputSymbol"\r class="org.simantics.sysdyn.ui.elements2.InputFactory" /> \r </target>\r \r <!-- Sysdyn connections -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <!-- Edges -->\r <resource uri="http://www.simantics.org/Sysdyn-0.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.FlowEdgeFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.DependencyEdgeFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.FlowEdgeFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.DependencyEdgeFactory" />\r <!-- : SYSDYN.Connection-->\r <type uri="http://www.simantics.org/Sysdyn-0.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.FlowConnectionFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.DependencyConnectionFactory" />\r </target>\r \r <target interface="org.simantics.g2d.connection.EdgeVisualsConfigurer">\r <baseType uri="http://www.simantics.org/Diagram-0.0/HasConnector" />\r <resource uri="http://www.simantics.org/Diagram-0.0/HasPlainConnector"\r class="org.simantics.diagram.content.ArrowConfigurer">\r <string>none 0</string>\r </resource>\r <resource uri="http://www.simantics.org/Diagram-0.0/HasArrowConnector"\r class="org.simantics.diagram.content.ArrowConfigurer">\r <string>fill 1</string>\r </resource>\r </target>\r \r <!-- ModelBrowser2 -->\r \r <target interface="org.simantics.browsing.ui.model.children.ChildRule">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectBrowseContext/ModuleTypeChildRule"\r class="org.simantics.sysdyn.ui.browser.childrules.ModuleTypeChildRule"/>\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectBrowseContext/ModuleContentChildRule"\r class="org.simantics.sysdyn.ui.browser.childrules.ModuleContentChildRule"/> \r </target>\r \r <target interface="org.simantics.browsing.ui.model.visuals.VisualsRule">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectBrowseContext/ModuleTypeLabelRule"\r class="org.simantics.sysdyn.ui.browser.labelrules.ModuleTypeLabelRule"/>\r </target> \r \r <target interface="org.simantics.db.layer0.adapter.ActionFactory">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewModuleType"\r class="org.simantics.sysdyn.ui.browser.actions.NewModuleTypeAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewEnumeration"\r class="org.simantics.sysdyn.ui.browser.actions.NewEnumerationAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/OpenWorkbook"\r class="org.simantics.sysdyn.ui.browser.actions.OpenWorkbookAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewFunction"\r class="org.simantics.sysdyn.ui.browser.actions.NewFunctionAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewFunctionLibrary"\r class="org.simantics.sysdyn.ui.browser.actions.NewFunctionLibraryAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewSharedFunctionLibrary"\r class="org.simantics.sysdyn.ui.browser.actions.NewSharedFunctionLibraryAction" /> \r </target> \r \r <!-- PROFILES -->\r <target interface="org.simantics.scenegraph.profile.Style">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/SimulationPlaybackStyle"\r class="org.simantics.sysdyn.ui.elements2.profiles.SimulationPlaybackStyle">\r </resource>\r <resource uri="http://www.simantics.org/Sysdyn-0.0/IssueStyle"\r class="org.simantics.sysdyn.ui.elements2.profiles.IssueDecorationStyle">\r </resource>\r </target>\r
+<adapters>\r\r <target interface="org.simantics.db.layer0.adapter.Realization">\r <type uri="http://www.simantics.org/Sysdyn-0.0/Module"\r class="org.simantics.structural2.realization.StructuralRealization">\r <this />\r </type>\r </target>\r\r<!-- \r <target interface="org.simantics.db.layer0.variable.Variable">\r <type uri="http://www.simantics.org/Sysdyn-0.0/HistoryRealization"\r class="org.simantics.sysdyn.ui.project.HistoryVariable" >\r <this />\r </type>\r <type uri="http://www.simantics.org/Sysdyn-0.0/DefaultRealization"\r class="org.simantics.sysdyn.ui.project.DefaultVariable" >\r <this />\r </type>\r </target>\r -->\r\r <target interface="org.simantics.layer0.utils.triggers.ITrigger">\r <type uri = "http://www.simantics.org/Sysdyn-0.0/DiagramToCompositeMapping"\r class = "org.simantics.sysdyn.ui.editor.DiagramToCompositeMapping3">\r <graph/>\r <this />\r </type>\r </target>\r \r <target interface="org.simantics.structural.ui.modelBrowser.nodes.AbstractNode">\r <type uri="http://www.simantics.org/Sysdyn-0.0/SysdynModel"\r class="org.simantics.structural.ui.modelBrowser.nodes.ModelNode">\r <this />\r </type>\r </target> \r \r\r <target\r interface="org.simantics.browsing.ui.common.node.AbstractNode">\r <type\r uri="http://www.simantics.org/Sysdyn-0.0/SysdynModel"\r class="org.simantics.sysdyn.ui.browser.nodes.ModelNode">\r <this />\r </type>\r\r <resource\r uri="http://www.simantics.org/Sysdyn-0.0/ModuleSymbol"\r class="org.simantics.sysdyn.ui.browser.nodes.SymbolNode">\r <this />\r </resource>\r\r <type\r uri="http://www.simantics.org/Simulation-1.0/Experiment"\r class="org.simantics.sysdyn.ui.browser.nodes.ExperimentNode">\r <this />\r </type>\r \r <type\r uri="http://www.simantics.org/Sysdyn-0.0/Result"\r class="org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode">\r <this />\r </type>\r \r </target>\r\r <!-- Inject default connection routing algorithm for sysdyn diagrams -->\r <target interface="org.simantics.g2d.diagram.DiagramClass">\r <adapter uri="http://www.simantics.org/Sysdyn-0.0/ConfigurationDiagram"\r adapterClass="org.simantics.sysdyn.ui.elements2.ConfigurationDiagramClassAdapter" />\r </target>\r\r <!-- Sysdyn symbols -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ModuleSymbol"\r class="org.simantics.sysdyn.ui.elements2.ModuleFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/InputSymbol"\r class="org.simantics.sysdyn.ui.elements2.InputFactory" />\r\r <type uri="http://www.simantics.org/Sysdyn-0.0/StockSymbol"\r class="org.simantics.sysdyn.ui.elements2.StockFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/ModuleSymbol"\r class="org.simantics.sysdyn.ui.elements2.ModuleFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/ValveSymbol"\r class="org.simantics.sysdyn.ui.elements2.ValveFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/AuxiliarySymbol"\r class="org.simantics.sysdyn.ui.elements2.AuxiliaryFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/CloudSymbol"\r class="org.simantics.sysdyn.ui.elements2.CloudFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/InputSymbol"\r class="org.simantics.sysdyn.ui.elements2.InputFactory" /> \r </target>\r \r <!-- Sysdyn connections -->\r <target interface="org.simantics.diagram.adapter.ElementFactory">\r <!-- Edges --> \r <resource uri="http://www.simantics.org/Sysdyn-0.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.RouteFlowEdgeFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.RouteFlowEdgeFactory" /> \r <type uri="http://www.simantics.org/Sysdyn-0.0/FlowConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.RouteFlowConnectionFactory">\r <graph/>\r </type> \r \r <resource uri="http://www.simantics.org/Sysdyn-0.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.DependencyEdgeFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.DependencyEdgeFactory" />\r <type uri="http://www.simantics.org/Sysdyn-0.0/DependencyConnection"\r class="org.simantics.sysdyn.ui.elements2.connections.DependencyConnectionFactory" />\r </target>\r \r <target interface="org.simantics.g2d.connection.EdgeVisualsConfigurer">\r <baseType uri="http://www.simantics.org/Diagram-0.0/HasConnector" />\r <resource uri="http://www.simantics.org/Diagram-0.0/HasPlainConnector"\r class="org.simantics.diagram.content.ArrowConfigurer">\r <string>none 0</string>\r </resource>\r <resource uri="http://www.simantics.org/Diagram-0.0/HasArrowConnector"\r class="org.simantics.diagram.content.ArrowConfigurer">\r <string>fill 1</string>\r </resource>\r </target>\r \r <!-- ModelBrowser2 -->\r \r <target interface="org.simantics.browsing.ui.model.children.ChildRule">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectBrowseContext/ModuleTypeChildRule"\r class="org.simantics.sysdyn.ui.browser.childrules.ModuleTypeChildRule"/>\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectBrowseContext/ModuleContentChildRule"\r class="org.simantics.sysdyn.ui.browser.childrules.ModuleContentChildRule"/> \r </target>\r \r <target interface="org.simantics.browsing.ui.model.visuals.VisualsRule">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectBrowseContext/ModuleTypeLabelRule"\r class="org.simantics.sysdyn.ui.browser.labelrules.ModuleTypeLabelRule"/>\r </target> \r \r <target interface="org.simantics.db.layer0.adapter.ActionFactory">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewModuleType"\r class="org.simantics.sysdyn.ui.browser.actions.NewModuleTypeAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewEnumeration"\r class="org.simantics.sysdyn.ui.browser.actions.NewEnumerationAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/OpenWorkbook"\r class="org.simantics.sysdyn.ui.browser.actions.OpenWorkbookAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewFunction"\r class="org.simantics.sysdyn.ui.browser.actions.NewFunctionAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewFunctionLibrary"\r class="org.simantics.sysdyn.ui.browser.actions.NewFunctionLibraryAction" />\r <resource uri="http://www.simantics.org/Sysdyn-0.0/ProjectActionContext/Actions/NewSharedFunctionLibrary"\r class="org.simantics.sysdyn.ui.browser.actions.NewSharedFunctionLibraryAction" /> \r </target> \r \r <!-- PROFILES -->\r <target interface="org.simantics.scenegraph.profile.Style">\r <resource uri="http://www.simantics.org/Sysdyn-0.0/SimulationPlaybackStyle"\r class="org.simantics.sysdyn.ui.elements2.profiles.SimulationPlaybackStyle">\r </resource>\r <resource uri="http://www.simantics.org/Sysdyn-0.0/IssueStyle"\r class="org.simantics.sysdyn.ui.elements2.profiles.IssueDecorationStyle">\r </resource>\r </target>\r
</adapters>
\ No newline at end of file
import org.simantics.sysdyn.ui.elements2.SysdynElementClasses;\r
import org.simantics.sysdyn.ui.elements2.SysdynElementFactory;\r
import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses;\r
+import org.simantics.sysdyn.ui.elements2.connections.RouteFlowEdgeClass;\r
import org.simantics.sysdyn.ui.elements2.connections.SysdynConnectionClass;\r
import org.simantics.sysdyn.ui.properties.SysdynPropertyPage;\r
import org.simantics.ui.workbench.IPropertyPage;\r
protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
SysdynResource sr = SysdynResource.getInstance(graph);\r
ElementClass dependencyClass = SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection));\r
+ ElementClass flowClass = RouteFlowEdgeClass.FLOW_CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection));\r
return SysdynElementClassProviders.mappedProvider(\r
ElementClasses.CONNECTION, dependencyClass,\r
ElementClasses.FLAG, CloudFactory.createElementClass(sr.CloudSymbol, SysdynElementFactory.createTerminals(graph, sr.CloudSymbol)),\r
- ConnectionClasses.FLOW, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)),\r
+ ConnectionClasses.FLOW, flowClass,\r
ConnectionClasses.DEPENDENCY, dependencyClass,\r
SysdynElementClasses.VALVE, CloudFactory.createElementClass(sr.ValveSymbol, SysdynElementFactory.createTerminals(graph, sr.ValveSymbol))\r
);\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.MouseEvent;\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
*\r
* @author Toni Kalajainen\r
*/\r
-public class PointerInteractor extends org.simantics.g2d.diagram.participant.pointertool.PointerInteractor {\r
+public class PointerInteractor extends org.simantics.diagram.participant.PointerInteractor2 {\r
\r
@Dependency Selection selection;\r
@Dependency KeyUtil keys;\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 FlowRouter(false));\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new Router4(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 FlowRouter(false));\r
+ diagram.setHint(DiagramHints.ROUTE_ALGORITHM, new Router4(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
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.editor.participant.SysdynConnectTool.SysdynConnection;\r
-import org.simantics.sysdyn.ui.elements2.connections.Flows;\r
\r
public class FlowRouter implements IRouter2{\r
\r
}\r
\r
localRouter.route();\r
-\r
+ return localRouter.path;\r
+ /*\r
Path2D completePath = new Path2D.Double();\r
\r
double[] coordinates = new double[localRouter.points.size()];\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
connection.setPath(seg, bestPath);\r
}\r
}\r
+ */\r
\r
final static AffineTransform IDENTITY = new AffineTransform();\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.elements2;\r
+\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.ElementHandler;\r
+\r
+public class Orientation implements ElementHandler {\r
+\r
+ private static final long serialVersionUID = 958120463924210936L;\r
+ \r
+ public static final Orientation INSTANCE = new Orientation();\r
+ \r
+ public String getOrientation(IElement e) {\r
+ return e.getHint(SysdynElementHints.KEY_ORIENTATION);\r
+ }\r
+\r
+ \r
+ public void setOrientation(IElement e, String orientation) {\r
+ if (orientation != null)\r
+ e.setHint(SysdynElementHints.KEY_ORIENTATION, orientation);\r
+ else\r
+ e.removeHint(SysdynElementHints.KEY_ORIENTATION);\r
+ }\r
+}\r
+ \r
/*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 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
public class SysdynElementHints {\r
\r
public static final Key KEY_INPUT_REFERENCE = new KeyOf(String.class, "INPUT_REFERENCE");\r
+ public static final Key KEY_ORIENTATION = new KeyOf(String.class, "ORIENTATION"); \r
\r
}\r
/*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 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
\r
public class SysdynElementUtils {\r
\r
- \r
+\r
public static void setInputReference(IElement e, String inputReference)\r
{\r
Input i = e.getElementClass().getSingleItem(Input.class);\r
- i.setInputReference(e, inputReference);\r
+ if(i != null)\r
+ i.setInputReference(e, inputReference);\r
}\r
\r
public static String getInputReference(IElement e)\r
{\r
Input i = e.getElementClass().getSingleItem(Input.class);\r
- return i.getInputReference(e);\r
+ if(i != null)\r
+ return i.getInputReference(e);\r
+ else\r
+ return null;\r
+ }\r
+\r
+ public static void setOrientation(IElement e, String orientation)\r
+ {\r
+ Orientation o = e.getElementClass().getSingleItem(Orientation.class);\r
+ if(o != null)\r
+ o.setOrientation(e, orientation);\r
}\r
- \r
+\r
+ public static String getOrientation(IElement e)\r
+ {\r
+ Orientation o = e.getElementClass().getSingleItem(Orientation.class);\r
+ if(o != null)\r
+ return o.getOrientation(e);\r
+ else\r
+ return null;\r
+ }\r
+\r
}\r
/*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 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
import java.awt.geom.Rectangle2D;\r
import java.util.Collection;\r
\r
+import org.simantics.db.ReadGraph;\r
import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
import org.simantics.diagram.elements.TextNode;\r
+import org.simantics.g2d.canvas.ICanvasContext;\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.utils.Alignment;\r
import org.simantics.scenegraph.g2d.G2DParentNode;\r
import org.simantics.scenegraph.g2d.nodes.ShapeNode;\r
-import org.simantics.utils.datastructures.hints.IHintListener;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\r
+import org.simantics.sysdyn.SysdynResource;\r
import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
+import org.simantics.utils.datastructures.hints.IHintListener;\r
+import org.simantics.utils.datastructures.hints.IHintObservable;\r
\r
\r
public class ValveFactory extends SysdynElementFactory {\r
HoverImpl.INSTANCE,\r
ValveSceneGraph.INSTANCE,\r
BoundsOutline.INSTANCE,\r
+ Orientation.INSTANCE,\r
new WholeElementTerminals(terminals)\r
).setId(ValveFactory.class.getSimpleName());\r
}\r
\r
+ @Override\r
+ public void load(ReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource element, final IElement e) throws DatabaseException {\r
+ super.load(graph, canvas, diagram, element, e);\r
+ \r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ \r
+ Resource orientation = graph.getPossibleObject(element, sr.HasValveOrientation);\r
+ \r
+ String orientationText;\r
+ if(orientation != null && sr.Vertical.equals(orientation)) {\r
+ orientationText = "Vertical";\r
+ } else {\r
+ orientationText = "Horizontal";\r
+ } \r
+ SysdynElementUtils.setOrientation(e, orientationText);\r
+ \r
+ }\r
+ \r
/**\r
* @param valveSize\r
* @param rotated <code>true</code> for vertical valve, <code>false</code>\r
node.setStroke(STROKE);\r
node.setScaleStroke(true);\r
node.setColor(Color.BLACK);\r
- node.setShape(createShape(VALVE_SIZE, Boolean.TRUE.equals(e.getHint(KEY_ROTATED))));\r
+ boolean rotated = false;\r
+ String orientation = SysdynElementUtils.getOrientation(e);\r
+ if(orientation != null && orientation.equals("Vertical"))\r
+ rotated = true;\r
+ node.setShape(createShape(VALVE_SIZE, Boolean.TRUE.equals(rotated)));\r
Boolean hover = e.getHint(ElementHints.KEY_HOVER); \r
node.setHover(hover != null ? hover : false);\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.elements2.connections;\r
+\r
+import java.awt.Color;\r
+import java.awt.Graphics2D;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.io.Serializable;\r
+import java.util.StringTokenizer;\r
+\r
+import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;\r
+\r
+\r
+/**\r
+ * Copied from ArrowLLineEndStyle\r
+ */\r
+public class FlowArrowLineStyle implements ILineEndStyle, Serializable {\r
+\r
+ private static final long serialVersionUID = 5348566089660986479L;\r
+\r
+ public static enum ArrowType { None, Stroke, Fill }\r
+\r
+ public static final double length = 8.0;\r
+ public static final double width = 4.0;\r
+ public static final double space = 0.0;\r
+\r
+ protected ArrowType type;\r
+ protected Path2D path;\r
+ protected double lineEndLength;\r
+ \r
+ protected Rectangle2D bounds = new Rectangle2D.Double();\r
+ \r
+ public FlowArrowLineStyle(String desc, Rectangle2D bounds) {\r
+ this.type = ArrowType.None;\r
+ this.lineEndLength = 0.0;\r
+\r
+ double l = length;\r
+ double w = width;\r
+ double s = space;\r
+ this.bounds = bounds;\r
+\r
+ StringTokenizer tokenizer = new StringTokenizer(desc);\r
+ if (tokenizer.hasMoreTokens()) {\r
+ String type = tokenizer.nextToken();\r
+ this.type = parseType(type);\r
+\r
+ if (tokenizer.hasMoreTokens()) {\r
+ String ls = tokenizer.nextToken();\r
+ l = parseSize(ls, length);\r
+\r
+ if (tokenizer.hasMoreTokens()) {\r
+ String ws = tokenizer.nextToken();\r
+ w = parseSize(ws, width);\r
+\r
+ if (tokenizer.hasMoreTokens()) {\r
+ String ss = tokenizer.nextToken();\r
+ s = parseSize(ss, space);\r
+ }\r
+ }\r
+ }\r
+ if (this.type != ArrowType.None) {\r
+ this.path = arrow(l, w, s);\r
+ lineEndLength = l+s;\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void render(Graphics2D g, double x, double y, int dir) {\r
+ if (type == ArrowType.None || path == null)\r
+ return;\r
+ // Calculate coordinates to the border of the terminal\r
+ switch(dir) {\r
+ case 0:\r
+ x = bounds.getMinX();\r
+ break;\r
+ case 1:\r
+ y = bounds.getMinY();\r
+ break;\r
+ case 2:\r
+ x = bounds.getMaxX();\r
+ break;\r
+ case 3:\r
+ y = bounds.getMaxY();\r
+ break;\r
+ default:\r
+ return;\r
+ }\r
+ AffineTransform old = g.getTransform();\r
+ g.translate(x, y);\r
+ g.rotate(dir*Math.PI*0.5);\r
+ g.setColor(Color.BLACK);\r
+\r
+ switch (type) {\r
+ case Fill:\r
+ g.fill(path);\r
+ break;\r
+ case Stroke:\r
+ g.draw(path);\r
+ break;\r
+ }\r
+\r
+ g.setTransform(old);\r
+ }\r
+\r
+ @Override\r
+ public double getLineEndLength(int direction) {\r
+ switch(direction) {\r
+ case 0:\r
+ lineEndLength = bounds.getWidth() / 2.0;\r
+ break;\r
+ case 1:\r
+ lineEndLength = bounds.getHeight() / 2.0;\r
+ break;\r
+ case 2:\r
+ lineEndLength = bounds.getWidth() / 2.0;\r
+ break;\r
+ case 3:\r
+ lineEndLength = bounds.getHeight() / 2.0;\r
+ break;\r
+ }\r
+ return lineEndLength;\r
+ }\r
+\r
+ private static Path2D arrow(double length, double width, double space) {\r
+ Path2D.Double path = new Path2D.Double();\r
+ path.moveTo(-space, 0);\r
+ path.lineTo(-length-space, -width);\r
+ path.lineTo(-length-space, +width);\r
+ path.closePath();\r
+ return path;\r
+ }\r
+\r
+ private double parseSize(String size, double defaultValue) {\r
+ try {\r
+ return Double.parseDouble(size);\r
+ } catch (NumberFormatException e) {\r
+ return defaultValue;\r
+ }\r
+ }\r
+\r
+ private ArrowType parseType(String type) {\r
+ String lower = type.toLowerCase();\r
+ if ("none".equals(lower))\r
+ return ArrowType.None;\r
+ if ("stroke".equals(lower))\r
+ return ArrowType.Stroke;\r
+ if ("fill".equals(lower))\r
+ return ArrowType.Fill;\r
+ throw new IllegalArgumentException("unrecognized arrow type: " + type);\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return getClass().getSimpleName() + "[" + type + ", " + path + "]";\r
+ }\r
+\r
+}\r
* \r
* @author Tuukka Lehtonen\r
*/\r
-public class FlowConnectionFactory extends ElementFactoryAdapter {\r
+public class FlowConnectionFactoryOld extends ElementFactoryAdapter {\r
\r
public static final ElementClass CLASS = SysdynConnectionClass.CLASS;\r
\r
--- /dev/null
+package org.simantics.sysdyn.ui.elements2.connections;\r
+\r
+import java.awt.Color;\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
+\r
+public class FlowConnectionStyle implements ConnectionStyle, Serializable {\r
+\r
+ private static final long serialVersionUID = 2777194644079591357L;\r
+\r
+ Color lineColor;\r
+ Stroke lineStroke;\r
+\r
+ public FlowConnectionStyle(Color lineColor, Stroke lineStroke) {\r
+ this.lineColor = lineColor;\r
+ this.lineStroke = lineStroke;\r
+ }\r
+ \r
+ @Override\r
+ public void drawBranchPoint(Graphics2D g, double x, double y) {\r
+ }\r
+\r
+ @Override\r
+ public void drawLine(Graphics2D g, double x1, double y1, double x2, double y2, boolean isTransient) {\r
+ System.out.println("DrawLine");\r
+ }\r
+\r
+ @Override\r
+ public void drawPath(Graphics2D g, Path2D path, boolean isTransient) {\r
+ if (lineColor != null)\r
+ g.setColor(lineColor);\r
+ if (lineStroke != null)\r
+ g.setStroke(lineStroke);\r
+\r
+ Path2D p1 = createOffsetPath(g, path, 1);\r
+ Path2D p2 = createOffsetPath(g, path, -1);\r
+ p1.append(p2, false);\r
+ g.draw(p1);\r
+ }\r
+\r
+ @Override\r
+ public void drawDegeneratedLine(Graphics2D g, double x, double y, boolean isHorizontal, boolean isTransient) {\r
+ }\r
+\r
+ @Override\r
+ public double getDegeneratedLineLength() {\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
import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler;\r
import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;\r
import org.simantics.g2d.elementclass.connection.EdgeSceneGraph;\r
-import org.simantics.g2d.routing.ConnectionDirectionUtil;\r
import org.simantics.g2d.routing.Constants;\r
import org.simantics.g2d.routing.IRouter2;\r
import org.simantics.g2d.utils.PathUtils;\r
import org.simantics.sysdyn.ui.editor.routing.FlowRouter;\r
import org.simantics.sysdyn.ui.elements2.ValveFactory.ValveSceneGraph;\r
\r
-public class FlowEdgeClass {\r
+public class FlowEdgeClassOld {\r
\r
// TODO scale, rotate, move, transform\r
public static final ElementClass CLASS = ElementClass.compile(\r
@Override\r
public void init(IElement e, G2DParentNode parent) {\r
ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE,\r
- "edge_" + e.hashCode(), FlowEdgeNode.class);\r
+ "edge_" + e.hashCode(), FlowEdgeNodeOld.class);\r
final IDiagram diagram = ElementUtils.peekDiagram(e);\r
\r
boolean toValve = false;\r
* \r
* @author Tuukka Lehtonen\r
*/\r
-public class FlowEdgeFactory extends ElementFactoryAdapter {\r
+public class FlowEdgeFactoryOld extends ElementFactoryAdapter {\r
\r
- private static final ElementClass CLASS = FlowEdgeClass.CLASS;\r
+ private static final ElementClass CLASS = FlowEdgeClassOld.CLASS;\r
\r
@Override\r
public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType,\r
import org.simantics.scenegraph.g2d.nodes.EdgeNode;\r
import org.simantics.scenegraph.utils.NodeUtil;\r
\r
-public class FlowEdgeNode extends EdgeNode implements ISelectionPainterNode {\r
+public class FlowEdgeNodeOld extends EdgeNode implements ISelectionPainterNode {\r
\r
private static final long serialVersionUID = -6774653631527343539L;\r
\r
import org.simantics.scenegraph.g2d.G2DNode;\r
import org.simantics.scenegraph.utils.NodeUtil;\r
\r
-public class FlowNode extends G2DNode implements ISelectionPainterNode {\r
+public class FlowNodeOld extends G2DNode implements ISelectionPainterNode {\r
\r
private static final long serialVersionUID = 328942356917631237L;\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.elements2.connections;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.SyncElementFactory;\r
+import org.simantics.diagram.connection.ConnectionVisuals;\r
+import org.simantics.diagram.connection.RouteGraph;\r
+import org.simantics.diagram.connection.RouteGraphConnectionClass;\r
+import org.simantics.diagram.connection.RouteLine;\r
+import org.simantics.diagram.connection.RouteNode;\r
+import org.simantics.diagram.connection.RouteTerminal;\r
+import org.simantics.diagram.connection.rendering.ConnectionStyle;\r
+import org.simantics.diagram.connection.rendering.StyledRouteGraphRenderer;\r
+import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;\r
+import org.simantics.diagram.content.EdgeResource;\r
+import org.simantics.diagram.content.ResourceTerminal;\r
+import org.simantics.diagram.content.TerminalMap;\r
+import org.simantics.diagram.query.DiagramRequests;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
+import org.simantics.diagram.synchronization.graph.RouteGraphConnection;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.connection.ConnectionEntity;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.DataElementMap;\r
+import org.simantics.g2d.diagram.handler.Topology.Connection;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\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.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.handler.TerminalTopology;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.routing.algorithm2.Router4;\r
+import org.simantics.g2d.utils.TopologicalSelectionExpander;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.scenegraph.g2d.nodes.connection.IRouteGraphListener;\r
+import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphChangeEvent;\r
+import org.simantics.scenegraph.utils.GeometryUtils;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.structural2.modelingRules.CPTerminal;\r
+import org.simantics.structural2.modelingRules.IAttachmentRelationMap;\r
+import org.simantics.structural2.modelingRules.IModelingRules;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.sysdyn.ui.elements2.ValveFactory.ValveSceneGraph;\r
+/**\r
+ * An element class for Sysdyn Flow elements.\r
+ * Copied from RouteGraphConnectionClassFactory and adapted to Flow needs\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ * \r
+ * \r
+ * \r
+ts. oma ehdotukseni on tämä:\r
+- etsi miten pystyt syöttämään jokaiselle sysdynin "terminaalille" oman ILineEndStyle:n joka sisältää viitteen mokkulan mittoihin\r
+- lisää direction-parametri getLineEndLength:iin niin että voit palauttaa siellä mokkulan mittojen mukaisen etäisyyden\r
+ */\r
+public class RouteFlowConnectionFactory extends SyncElementFactory {\r
+\r
+ public static final ElementClass CLASS = RouteFlowEdgeClass.FLOW_CLASS;\r
+\r
+ Layer0 L0;\r
+ DiagramResource DIA;\r
+ StructuralResource2 STR;\r
+ ModelingResources MOD;\r
+\r
+ public RouteFlowConnectionFactory(ReadGraph graph) {\r
+ this.L0 = Layer0.getInstance(graph);\r
+ this.DIA = DiagramResource.getInstance(graph);\r
+ this.STR = StructuralResource2.getInstance(graph);\r
+ this.MOD = ModelingResources.getInstance(graph);\r
+ }\r
+\r
+ @Override\r
+ public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, final AsyncProcedure<ElementClass> procedure) {\r
+ SysdynResource sr = graph.getService(SysdynResource.class);\r
+ graph.forSingleType(elementType, sr.FlowConnection, new AsyncProcedure<Resource>() {\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+ procedure.exception(graph, throwable);\r
+ }\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, Resource connectionType) {\r
+ procedure.execute(graph, CLASS.newClassWith(false, new StaticObjectAdapter(connectionType)));\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public void load(ReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource connection,\r
+ IElement element) throws DatabaseException {\r
+ \r
+ // Do we need this?\r
+ element.setHint(DiagramHints.ROUTE_ALGORITHM, new Router4(false));\r
+ \r
+ IModelingRules modelingRules = diagram.getHint(DiagramModelHints.KEY_MODELING_RULES);\r
+\r
+ IElement mappedElement = ElementUtils.getByData(diagram, connection);\r
+ if (mappedElement == null)\r
+ // FIXME: With undo this seems to happen, don't know why yet!\r
+ return;\r
+\r
+ RouteGraph rg = new RouteGraph();\r
+\r
+ Set<Resource> nodes = new HashSet<Resource>();\r
+ Set<EdgeResource> links = new HashSet<EdgeResource>();\r
+ Map<Object, RouteNode> nodeByData = new HashMap<Object, RouteNode>();\r
+\r
+ // Needed to support ConnectionEntity#getTerminalConnections\r
+ Set<BackendConnection> backendonnections = new HashSet<BackendConnection>();\r
+\r
+ // Load all route graph interior RouteNodes: route lines and points\r
+ for (Resource interiorNode : graph.getObjects(connection, DIA.HasInteriorRouteNode)) {\r
+ if (graph.isInstanceOf(interiorNode, DIA.RouteLine)) {\r
+ Boolean isHorizontal = graph.getRelatedValue(interiorNode, DIA.IsHorizontal, Bindings.BOOLEAN);\r
+ Double position = graph.getRelatedValue(interiorNode, DIA.HasPosition, Bindings.DOUBLE);\r
+ RouteLine line = rg.addLine(isHorizontal, position);\r
+ line.setData( RouteGraphConnection.serialize(graph, interiorNode) );\r
+\r
+ nodes.add( interiorNode );\r
+ nodeByData.put( interiorNode, line );\r
+\r
+ for (Resource connectedTo : graph.getObjects(interiorNode, DIA.AreConnected)) {\r
+ links.add( new EdgeResource(interiorNode, connectedTo) );\r
+ }\r
+ } else if (graph.isInstanceOf(interiorNode, DIA.RoutePoint)) {\r
+ // Not supported yet. Ignore.\r
+ }\r
+ }\r
+\r
+ Rectangle2D bounds = new Rectangle2D.Double();\r
+\r
+ // Load all node terminal connections as RouteTerminals\r
+ for (Statement toConnector : graph.getStatements(connection, DIA.HasConnector)) {\r
+ Resource connector = toConnector.getObject();\r
+ Resource attachmentRelation = toConnector.getPredicate();\r
+\r
+ Statement terminalStm = findTerminalStatement(graph, STR, connection, connector);\r
+ if (terminalStm == null)\r
+ // Ignore broken connector: attached to the connection but not to any terminal.\r
+ continue;\r
+\r
+ Resource terminalElement = terminalStm.getObject();\r
+ Resource terminalElementType = graph.getPossibleType(terminalElement, DIA.Element);\r
+ if (terminalElementType == null)\r
+ // Ignore non-element terminal elements\r
+ continue;\r
+\r
+ Resource connectionRelation = graph.getInverse(terminalStm.getPredicate());\r
+\r
+ // Discover node and terminal this connector is connected to.\r
+ TerminalMap terminals = graph.syncRequest(DiagramRequests.elementTypeTerminals(terminalElementType),\r
+ TransientCacheListener.<TerminalMap> instance());\r
+ Resource terminal = terminals.getTerminal(connectionRelation);\r
+ if (terminal == null) {\r
+ System.err.println(getClass().getSimpleName()\r
+ + ": Could not find terminal for connection point "\r
+ + NameUtils.getSafeName(graph, connectionRelation, true)\r
+ + " in element "\r
+ + NameUtils.getSafeName(graph, terminalElement, true)); \r
+ continue;\r
+ }\r
+\r
+ double[] position = graph.getRelatedValue(connector, DIA.HasRelativeLocation, Bindings.DOUBLE_ARRAY);\r
+ if (position.length != 2)\r
+ position = new double[] { 0, 0 };\r
+\r
+ //System.out.println("terminalStm: " + NameUtils.toString(graph, terminalStm));\r
+ AffineTransform terminalElementTr = getWorldTransform(graph, terminalElement);\r
+\r
+ double x = terminalElementTr.getTranslateX();\r
+ double y = terminalElementTr.getTranslateY();\r
+ double minx = x-1, miny = y-1, maxx = x+1, maxy = y+1;\r
+ int direction = 0x0;\r
+\r
+ // Use modelingRules to ascertain the proper attachmentRelation\r
+ // for this terminal connection, if available.\r
+ if (modelingRules != null) {\r
+ // Get attachmentRelation from modelingRules if possible.\r
+ IAttachmentRelationMap map = modelingRules.getAttachmentRelations(graph, connection);\r
+ Resource att = map.get(graph, new CPTerminal(terminalElement, terminal));\r
+ if (att != null) {\r
+ //System.out.println("modeling rules attachment: " + NameUtils.getSafeLabel(graph, att));\r
+ attachmentRelation = att;\r
+ }\r
+ }\r
+ //System.out.println("attachment: " + NameUtils.getSafeLabel(graph, attachmentRelation));\r
+\r
+ // Get element bounds to decide allowed terminal direction(s)\r
+ IElement te = graph.syncRequest(DiagramRequests.getElement(canvas, diagram, terminalElement, null));\r
+ \r
+ \r
+ ElementUtils.getElementBounds(te, bounds);\r
+ {\r
+ Shape shp = org.simantics.g2d.utils.GeometryUtils.transformShape(bounds, terminalElementTr);\r
+ bounds.setFrame(shp.getBounds2D());\r
+ }\r
+ \r
+ // Valve behaves differently. The flow must start inside the valve bounds\r
+ if(te.getElementClass().containsClass(ValveSceneGraph.class)) {\r
+ bounds.setFrame(new Rectangle2D.Double(bounds.getCenterX() - 1, bounds.getCenterY() - 1, 2, 2));\r
+ }\r
+\r
+ x = bounds.getCenterX();\r
+ y = bounds.getCenterY();\r
+ \r
+ // Expand bounds by 4mm to make the connections enter the terminals\r
+ // at a straight angle and from a distance instead of coming in\r
+ // "horizontally".\r
+ GeometryUtils.expandRectangle(bounds, 4);\r
+\r
+ minx = bounds.getMinX();\r
+ miny = bounds.getMinY();\r
+ maxx = bounds.getMaxX();\r
+ maxy = bounds.getMaxY();\r
+ \r
+\r
+ Integer allowedDirections = graph.getPossibleRelatedValue(terminal, DIA.Terminal_AllowedDirections, Bindings.INTEGER);\r
+ \r
+ // Valve behaves differently. Allowed directions depend on the orientation of the valve\r
+ if(te.getElementClass().containsClass(ValveSceneGraph.class)) {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ if(graph.hasStatement(terminalElement, sr.HasValveOrientation, sr.Vertical)) {\r
+ allowedDirections = 10; // Directions up and down (1010)\r
+ } else {\r
+ allowedDirections = 5; // Directions left and right (0101)\r
+ }\r
+ }\r
+ if (allowedDirections != null) {\r
+ direction |= allowedDirections;\r
+ } else {\r
+ direction |= RouteGraphConnectionClass.shortestDirectionOutOfBounds(x, y, bounds);\r
+ }\r
+\r
+ backendonnections.add(\r
+ new BackendConnection(\r
+ toEdgeEnd(graph, attachmentRelation, EdgeEnd.Begin),\r
+ terminalElement,\r
+ terminal)\r
+ );\r
+\r
+ if (direction == 0)\r
+ // Accept any horizontal/vertical direction if nothing is defined\r
+ direction = 0xf;\r
+\r
+ //System.out.println("load line style: " + NameUtils.getSafeLabel(graph, attachmentRelation));\r
+ ILineEndStyle endStyle = loadLineEndStyle(graph, te, attachmentRelation, new Rectangle2D.Double(\r
+ bounds.getX(), \r
+ bounds.getY(), \r
+ bounds.getWidth(), \r
+ bounds.getHeight())\r
+ );\r
+\r
+ RouteTerminal routeTerminal = rg.addTerminal(x, y, minx, miny, maxx, maxy, direction, endStyle);\r
+ routeTerminal.setData( RouteGraphConnection.serialize(graph, connector) );\r
+\r
+ nodes.add( connector );\r
+ nodeByData.put( connector, routeTerminal );\r
+\r
+ for (Resource connectedTo : graph.getObjects(connector, DIA.AreConnected)) {\r
+ links.add( new EdgeResource(connectedTo, connector) );\r
+ }\r
+ }\r
+\r
+ // Finish route graph loading by Linking route nodes together\r
+ for (EdgeResource link : links) {\r
+ RouteNode n1 = nodeByData.get(link.first());\r
+ RouteNode n2 = nodeByData.get(link.second());\r
+ if (n1 == null || n2 == null) {\r
+ System.err.println("Stray connection link found: " + link.toString(graph));\r
+ continue;\r
+ }\r
+ rg.link(n1, n2);\r
+ }\r
+\r
+ // Load connection line style\r
+ ConnectionStyle style = readConnectionStyle(graph, modelingRules, connection, element);\r
+ StyledRouteGraphRenderer renderer = new StyledRouteGraphRenderer(style);\r
+\r
+ // Finish element load\r
+ element.setHint(RouteGraphConnectionClass.KEY_ROUTEGRAPH, rg);\r
+ element.setHint(RouteGraphConnectionClass.KEY_RENDERER, renderer);\r
+ element.setHint(RouteGraphConnectionClass.KEY_PICK_TOLERANCE, 0.5);\r
+\r
+ // Initialize ConnectionEntity in element\r
+ // NOTE: MUST use the mapped element with class CE, not the connection (element) were loading into.\r
+ // GDS will synchronize element into mappedElement in a controlled manner.\r
+ element.setHint(ElementHints.KEY_CONNECTION_ENTITY, new CE(connection, mappedElement, backendonnections));\r
+\r
+ // Setup graph writeback support for route graph modifications\r
+ final Session session = graph.getSession();\r
+ element.setHint(RouteGraphConnectionClass.KEY_RG_LISTENER, new IRouteGraphListener() {\r
+ @Override\r
+ public void routeGraphChanged(RouteGraphChangeEvent event) {\r
+ scheduleSynchronize(session, connection, event);\r
+ }\r
+ });\r
+ }\r
+\r
+ private EdgeEnd toEdgeEnd(ReadGraph graph, Resource attachmentRelation, EdgeEnd defaultValue)\r
+ throws DatabaseException {\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.IsTailConnectorOf))\r
+ return EdgeEnd.Begin;\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.IsHeadConnectorOf))\r
+ return EdgeEnd.End;\r
+ return defaultValue;\r
+ }\r
+\r
+ private ConnectionStyle readConnectionStyle(ReadGraph graph, IModelingRules modelingRules, Resource connection,\r
+ IElement element) throws DatabaseException {\r
+ Resource connectionType = null;\r
+ if (modelingRules != null)\r
+ connectionType = modelingRules.getConnectionType(graph, connection);\r
+ if (connectionType == null)\r
+ connectionType = graph.getPossibleObject(connection, STR.HasConnectionType);\r
+\r
+ ConnectionVisuals cv = null;\r
+ if (connectionType != null)\r
+ cv = graph.syncRequest(DiagramRequests.getConnectionVisuals(connectionType),\r
+ TransientCacheListener.<ConnectionVisuals> instance());\r
+\r
+ Color lineColor = cv != null ? cv.toColor() : null;\r
+ if (lineColor == null)\r
+ lineColor = Color.DARK_GRAY;\r
+ Stroke lineStroke = cv != null ? cv.stroke : null;\r
+ if (lineStroke == null)\r
+ lineStroke = new BasicStroke(0.1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, null, 0);\r
+\r
+ return new FlowConnectionStyle(\r
+ lineColor,\r
+ lineStroke);\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param STR\r
+ * @param connection\r
+ * @param connector\r
+ * @return connection relation statement from diagram connection connector\r
+ * to a node\r
+ * @throws DatabaseException\r
+ */\r
+ private static Statement findTerminalStatement(ReadGraph graph, StructuralResource2 STR, Resource connection,\r
+ Resource connector) throws DatabaseException {\r
+ for (Statement stm : graph.getStatements(connector, STR.Connects)) {\r
+ if (connection.equals(stm.getObject()))\r
+ continue;\r
+ return stm;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public ILineEndStyle loadLineEndStyle(ReadGraph graph, IElement te, Resource attachmentRelation, Rectangle2D bounds)\r
+ throws DatabaseException {\r
+ ILineEndStyle style;\r
+ // TODO: change bounds according to terminal type: Very small rectangle for Valves, Text box size for Stocks and Clouds\r
+ if(te.getElementClass().containsClass(ValveSceneGraph.class)) {\r
+ GeometryUtils.expandRectangle(bounds, -4);\r
+ style = new FlowArrowLineStyle("none 0 0 0", bounds);\r
+ } else {\r
+ if (graph.isSubrelationOf(attachmentRelation, DIA.HasHeadConnector)) {\r
+ GeometryUtils.expandRectangle(bounds, -2.5);\r
+ style = new FlowArrowLineStyle("fill 2 2 -1.5", bounds);\r
+ } else {\r
+ GeometryUtils.expandRectangle(bounds, -4);\r
+ style = new FlowArrowLineStyle("none 0 0 0", bounds);\r
+ }\r
+ }\r
+ return style;\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param element\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ private static AffineTransform getWorldTransform(ReadGraph graph, Resource element) throws DatabaseException {\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ AffineTransform result = DiagramGraphUtil.getAffineTransform(graph, element);\r
+ while (true) {\r
+ Resource parentComponent = graph.getPossibleObject(element, MOD.HasParentComponent);\r
+ if (parentComponent == null)\r
+ return result;\r
+ element = graph.getPossibleObject(parentComponent, MOD.ComponentToElement);\r
+ if (element == null)\r
+ return result;\r
+ AffineTransform tr = DiagramGraphUtil.getAffineTransform(graph, element);\r
+ tr.setToTranslation(tr.getTranslateX(), tr.getTranslateY());\r
+ result.preConcatenate(tr);\r
+ }\r
+ }\r
+\r
+// private int directionSetToToDirectionMask(DirectionSet directions) {\r
+// if (directions == DirectionSet.ANY)\r
+// return 0xf;\r
+// int mask = 0;\r
+// for (Double d : directions) {\r
+// mask |= compassAngleToToDirectionMask(d);\r
+// }\r
+// return mask;\r
+// }\r
+//\r
+// private int compassAngleToToDirectionMask(double compassAngle) {\r
+// Double d = DirectionSet.NESW.getClosestDirection(compassAngle);\r
+// int id = (int) Math.round(d);\r
+// // bits:\r
+// // 0 right (1,0)\r
+// // 1 down (0,1)\r
+// // 2 left (-1,0)\r
+// // 3 up (0,-1)\r
+// switch (id) {\r
+// case 0: return (1 << 3);\r
+// case 90: return (1 << 2);\r
+// case 180: return (1 << 1);\r
+// case 270: return (1 << 0);\r
+// }\r
+// return 0xf;\r
+// }\r
+\r
+ protected void scheduleSynchronize(Session session, Resource connection, RouteGraphChangeEvent event) {\r
+ session.asyncRequest(RouteGraphConnection.synchronizer(connection, event));\r
+ }\r
+\r
+ /**\r
+ * Must have this in order for {@link TopologicalSelectionExpander} to work.\r
+ * Otherwise this is pretty useless and should be deprecated altogether.\r
+ * \r
+ * @see ElementHints#KEY_CONNECTION_ENTITY\r
+ */\r
+ static class CE implements ConnectionEntity {\r
+\r
+ /**\r
+ * The connection instance resource in the graph backend.\r
+ */\r
+ final Resource connection;\r
+\r
+ /**\r
+ * The connection entity element which is a part of the diagram.\r
+ */\r
+ final IElement connectionElement;\r
+\r
+ /**\r
+ * @see #getTerminalConnections(Collection)\r
+ */\r
+ final Set<BackendConnection> backendConnections;\r
+\r
+ /**\r
+ * Cache.\r
+ */\r
+ Set<Connection> terminalConnections;\r
+\r
+ CE(Resource connection, IElement connectionElement, Set<BackendConnection> backendConnections) {\r
+ this.connection = connection;\r
+ this.connectionElement = connectionElement;\r
+ this.backendConnections = backendConnections;\r
+ }\r
+\r
+ @Override\r
+ public IElement getConnection() {\r
+ return connectionElement;\r
+ }\r
+\r
+ public Object getConnectionObject() {\r
+ return connection;\r
+ }\r
+\r
+ public IElement getConnectionElement() {\r
+ return connectionElement;\r
+ }\r
+\r
+ @Override\r
+ public Collection<IElement> getBranchPoints(Collection<IElement> result) {\r
+ return result != null ? result : Collections.<IElement> emptyList();\r
+ }\r
+\r
+ @Override\r
+ public Collection<IElement> getSegments(Collection<IElement> result) {\r
+ return result != null ? result : Collections.<IElement> emptyList();\r
+ }\r
+\r
+ @Override\r
+ public Collection<Connection> getTerminalConnections(Collection<Connection> result) {\r
+ if (terminalConnections == null)\r
+ terminalConnections = calculateTerminalConnections();\r
+ if (result == null)\r
+ result = new ArrayList<Connection>(terminalConnections);\r
+ else\r
+ result.addAll(terminalConnections);\r
+ return terminalConnections;\r
+ }\r
+\r
+ private Set<Connection> calculateTerminalConnections() {\r
+ IDiagram diagram = connectionElement.getDiagram();\r
+ DataElementMap dem = diagram.getDiagramClass().getSingleItem(DataElementMap.class);\r
+ Set<Connection> result = new HashSet<Connection>();\r
+ ArrayList<Terminal> ts = new ArrayList<Terminal>();\r
+ for (BackendConnection bc : backendConnections) {\r
+ IElement e = dem.getElement(diagram, bc.node);\r
+ if (e == null)\r
+ continue;\r
+ TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
+ tt.getTerminals(e, ts);\r
+ for (Terminal t : ts) {\r
+ if (t instanceof ResourceTerminal) {\r
+ ResourceTerminal rt = (ResourceTerminal) t;\r
+ if (bc.terminal.equals(rt.getResource())) {\r
+ result.add(new Connection(connectionElement, bc.end, e, t));\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public void setListener(ConnectionListener listener) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return getClass().getSimpleName() + "[resource=" + connection + ", connectionElement=" + connectionElement\r
+ + "]";\r
+ }\r
+\r
+ }\r
+\r
+ public static class BackendConnection {\r
+ public final Resource node;\r
+ public final Resource terminal;\r
+ public final EdgeEnd end;\r
+ public BackendConnection(EdgeEnd end, Resource node, Resource terminal) {\r
+ assert end != null;\r
+ assert node != null;\r
+ assert terminal != null;\r
+ this.end = end;\r
+ this.node = node;\r
+ this.terminal = terminal;\r
+ }\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (!(obj instanceof Connection))\r
+ return false;\r
+ Connection other = (Connection) obj;\r
+ return other.terminal == terminal\r
+ && other.node == node\r
+ && other.end == end;\r
+ }\r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + end.hashCode();\r
+ result = prime * result + ((node == null) ? 0 : node.hashCode());\r
+ result = prime * result + ((terminal == null) ? 0 : terminal.hashCode());\r
+ return result;\r
+ }\r
+ @Override\r
+ public String toString() {\r
+ return "BackendConnection[node=" + node + ", terminal=" + terminal + ", end=" + end + "]";\r
+ }\r
+ }\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.elements2.connections;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.diagram.connection.RouteGraph;\r
+import org.simantics.diagram.connection.RouteGraphConnectionClass;\r
+import org.simantics.diagram.connection.rendering.IRouteGraphRenderer;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.ElementHandler;\r
+import org.simantics.g2d.element.handler.SceneGraph;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.scenegraph.g2d.nodes.connection.IRouteGraphListener;\r
+import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;\r
+\r
+\r
+\r
+public class RouteFlowEdgeClass extends RouteGraphConnectionClass {\r
+ \r
+ public static final ElementClass FLOW_CLASS = getElementClass();\r
+\r
+ \r
+ public static final ElementClass getElementClass() {\r
+ List<ElementHandler> oldList = CLASS.getAll();\r
+ ArrayList<ElementHandler> list = new ArrayList<ElementHandler>();\r
+ list.add(FlowConnectionSceneGraph.INSTANCE);\r
+ for(ElementHandler eh : oldList) {\r
+ if(!(eh instanceof SceneGraph)) {\r
+ list.add(eh);\r
+ }\r
+ }\r
+ return ElementClass.compile(list);\r
+ }\r
+ \r
+ \r
+ static final class FlowConnectionSceneGraph implements SceneGraph {\r
+\r
+ public static final FlowConnectionSceneGraph INSTANCE = new FlowConnectionSceneGraph();\r
+\r
+ private static final long serialVersionUID = 1865920472882420644L;\r
+\r
+ @Override\r
+ public void init(IElement connection, G2DParentNode parent) {\r
+ RouteGraph rg = connection.getHint(KEY_ROUTEGRAPH);\r
+ IRouteGraphRenderer renderer = connection.getHint(KEY_RENDERER);\r
+ if (rg == null || renderer == null) {\r
+ cleanup(connection);\r
+ } else {\r
+ RouteGraphNode rgn = connection.getHint(KEY_RG_NODE);\r
+ if (rgn == null) {\r
+ rgn = parent.addNode(ElementUtils.generateNodeId(connection), RouteGraphNode.class);\r
+ connection.setHint(KEY_RG_NODE, rgn);\r
+ }\r
+ rgn.setRouteGraph(rg);\r
+ rgn.setRenderer(renderer);\r
+\r
+ IRouteGraphListener listener = connection.getHint(KEY_RG_LISTENER);\r
+ rgn.setRouteGraphListener(listener);\r
+\r
+ Double tolerance = connection.getHint(KEY_PICK_TOLERANCE);\r
+ if (tolerance != null)\r
+ rgn.setPickTolerance(tolerance);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void cleanup(IElement connection) {\r
+ ElementUtils.removePossibleNode(connection, KEY_RG_NODE);\r
+ connection.removeHint(KEY_RG_NODE);\r
+ }\r
+ }\r
+\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.elements2.connections;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.adapter.ElementFactoryAdapter;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+\r
+public class RouteFlowEdgeFactory extends ElementFactoryAdapter {\r
+\r
+ private static final ElementClass CLASS = RouteFlowEdgeClass.FLOW_CLASS;\r
+\r
+ @Override\r
+ public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType,\r
+ AsyncProcedure<ElementClass> procedure) {\r
+ procedure.execute(graph, CLASS);\r
+ }\r
+\r
+ @Override\r
+ public void getClass(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource,\r
+ AsyncProcedure<ElementClass> procedure) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+}\r
/*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 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
import org.simantics.db.management.ISessionContext;\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.factories.DoublePropertyFactory;\r
import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier;\r
\r
rangeStep.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasRangeStep));\r
rangeStep.setInputValidator(new DoubleValidator());\r
GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeStep.getWidget());\r
+ \r
+ \r
+ new ValveOrientationGroup(composite, context, support, SWT.NONE);\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.properties.widgets;\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.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.WidgetImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\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.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.utils.datastructures.Triple;\r
+\r
+public class ValveOrientationGroup extends WidgetImpl {\r
+\r
+ Group group;\r
+ Button vertical, horizontal;\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
+ GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(group);\r
+ \r
+ horizontal = new Button(group, support, SWT.RADIO);\r
+ horizontal.setText("Horizontal");\r
+ horizontal.setSelectionFactory(new OrientationSelectionFactory(SysdynResource.URIs.Horizontal, true));\r
+ horizontal.addSelectionListener(new OrientationSelectionListener(context, SysdynResource.URIs.Horizontal));\r
+ \r
+ vertical = new Button(group, support, SWT.RADIO);\r
+ vertical.setText("Vertical");\r
+ vertical.setSelectionFactory(new OrientationSelectionFactory(SysdynResource.URIs.Vertical));\r
+ vertical.addSelectionListener(new OrientationSelectionListener(context, SysdynResource.URIs.Vertical));\r
+ }\r
+\r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ \r
+ \r
+ }\r
+\r
+ @Override\r
+ public Control getControl() {\r
+ return this.group;\r
+ }\r
+ \r
+ private class OrientationSelectionFactory extends ReadFactoryImpl<Resource, Boolean> {\r
+ \r
+ boolean defaultSelected;\r
+ String uri;\r
+ \r
+ public OrientationSelectionFactory(String uri) {\r
+ this(uri, false);\r
+ }\r
+\r
+ public OrientationSelectionFactory(String uri, boolean defaultSelected) {\r
+ this.uri = uri;\r
+ this.defaultSelected = defaultSelected;\r
+ }\r
+ \r
+ public Object getIdentity(Object inputContents) {\r
+ return new Triple<Object, Object, Class<?>>(uri, defaultSelected, getClass());\r
+ }\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph graph, Resource valve) throws DatabaseException {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ if(!graph.isInstanceOf(valve, sr.Valve))\r
+ return Boolean.FALSE;\r
+ \r
+ Resource symbol = graph.getPossibleObject(valve, mr.ComponentToElement);\r
+ if(symbol == null)\r
+ return Boolean.FALSE;\r
+ \r
+ Resource orientation = graph.getPossibleObject(symbol, sr.HasValveOrientation);\r
+ \r
+ if(orientation == null)\r
+ return defaultSelected;\r
+ \r
+ return orientation.equals(graph.getResource(uri));\r
+ }\r
+ \r
+ }\r
+ \r
+ \r
+ private class OrientationSelectionListener extends SelectionListenerImpl<Resource> {\r
+ \r
+ String uri;\r
+ \r
+ public OrientationSelectionListener(ISessionContext context, String uri) {\r
+ super(context);\r
+ this.uri = uri;\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource valve) throws DatabaseException {\r
+ SysdynResource sr = SysdynResource.getInstance(graph);\r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ if(!graph.isInstanceOf(valve, sr.Valve))\r
+ return;\r
+ \r
+ Resource symbol = graph.getPossibleObject(valve, mr.ComponentToElement);\r
+ if(symbol == null)\r
+ return;\r
+ \r
+ if(graph.hasStatement(symbol, sr.HasValveOrientation))\r
+ graph.deny(symbol, sr.HasValveOrientation);\r
+ graph.claim(symbol, sr.HasValveOrientation, graph.getResource(uri));\r
+ }\r
+ \r
+ }\r
+\r
+}\r
public class SheetFormatUtils {\r
\r
public static String reformatSheetReferences(Variable v, String expression) {\r
- if(!expression.contains("("))\r
+ if(expression == null || !expression.contains("("))\r
return expression;\r
ExpressionParser parser = new ExpressionParser(new StringReader(expression));\r
try {\r