diff --git a/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-connector-hp.svg index fa273dc8ec..a0a56e37e5 100644 --- a/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/bottom-right-elbow-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Bottom right elbow connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `-${dashWidth + (dashGap || dashWidth)}` : `${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 200,100 L 125,100 Q 100,100 100,125 L 100, 200';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -53,8 +53,8 @@ }, { "id": "animationDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", @@ -130,36 +130,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -169,7 +146,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -177,11 +154,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -190,8 +167,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -199,13 +176,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -214,13 +192,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -228,7 +207,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -250,5 +229,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/bottom-tee-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/bottom-tee-connector-hp.svg index 2feb95e9ff..90cfe6ed2b 100644 --- a/application/src/main/data/json/system/scada_symbols/bottom-tee-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/bottom-tee-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Bottom tee connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst rightLine = \"M100 100H200\";\nconst bottomLine = \"M 100,200 V 103\";\n\nprepareFlowAnimation('left', leftLine);\nprepareFlowAnimation('right', rightLine);\nprepareFlowAnimation('bottom', bottomLine);\n\nfunction prepareFlowAnimation(prefix, line) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const offset = Date.now() % 1000;\n const duration = 1 / flowAnimationSpeed;\n \n const prevFlowAnimation = animation.remember('flowAnimation');\n const prevFlowDirection = animation.remember('flowDirection');\n const prevFlowDuration = animation.remember('flowDuration');\n \n if (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n } else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n }\n}\n\nfunction animateFlow(group, offset, flowDirection, duration, line) {\n group.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n group.add(``);\n}", + "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst leftLineReversed = \"M 100,100 H 0\";\nconst rightLine = \"M100 100H200\";\nconst rightLineReversed = \"M 200,100 H 100\";\nconst bottomLine = \"M 100,200 V 103\";\nconst bottomLineReversed = \"M 100,103 V 200\";\n\nprepareFlowAnimation('left', leftLine, leftLineReversed);\nprepareFlowAnimation('right', rightLine, rightLineReversed);\nprepareFlowAnimation('bottom', bottomLine, bottomLineReversed);\n\nfunction prepareFlowAnimation(prefix, line, reversedLine) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const duration = 1 / flowAnimationSpeed;\n \n let animateFlow = ctx.api.connectorAnimation(animation);\n \n if (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, reversedLine).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n } else {\n if (animateFlow) {\n animateFlow.finish();\n }\n }\n}\n", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null }, { @@ -58,8 +58,8 @@ }, { "id": "leftFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.left-connector}", "type": "value", "valueType": "BOOLEAN", @@ -174,8 +174,8 @@ }, { "id": "rightFlowDirection", - "name": "{i18n:scada.symbol.flow-direction}", - "hint": "{i18n:scada.symbol.flow-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.right-connector}", "type": "value", "valueType": "BOOLEAN", @@ -290,8 +290,8 @@ }, { "id": "bottomFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.bottom-connector}", "type": "value", "valueType": "BOOLEAN", @@ -367,36 +367,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -406,7 +383,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -414,11 +391,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -427,8 +404,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -436,13 +413,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -451,13 +429,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -465,7 +444,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ diff --git a/application/src/main/data/json/system/scada_symbols/cross-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/cross-connector-hp.svg index ab6798b48b..5ac0af8248 100644 --- a/application/src/main/data/json/system/scada_symbols/cross-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/cross-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Cross connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst topLine = \"M100 97L100 0\";\nconst rightLine = \"M100 100H200\";\nconst bottomLine = \"M 100,200 V 103\";\n\nprepareFlowAnimation('left', leftLine);\nprepareFlowAnimation('top', topLine);\nprepareFlowAnimation('right', rightLine);\nprepareFlowAnimation('bottom', bottomLine);\n\nfunction prepareFlowAnimation(prefix, line) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const offset = Date.now() % 1000;\n const duration = 1 / flowAnimationSpeed;\n \n const prevFlowAnimation = animation.remember('flowAnimation');\n const prevFlowDirection = animation.remember('flowDirection');\n const prevFlowDuration = animation.remember('flowDuration');\n \n if (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n } else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n }\n}\n\nfunction animateFlow(group, offset, flowDirection, duration, line) {\n group.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n group.add(``);\n}", + "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst leftLineReversed = \"M 100,100 H 0\";\nconst topLine = \"M100 97L100 0\";\nconst topLineReversed = \"M 100,0 V 97\";\nconst rightLine = \"M100 100H200\";\nconst rightLineReversed = \"M 200,100 H 100\";\nconst bottomLine = \"M 100,200 V 103\";\nconst bottomLineReversed = \"M 100,103 V 200\";\n\nprepareFlowAnimation('left', leftLine, leftLineReversed);\nprepareFlowAnimation('top', topLine, topLineReversed);\nprepareFlowAnimation('right', rightLine, rightLineReversed);\nprepareFlowAnimation('bottom', bottomLine, bottomLineReversed);\n\nfunction prepareFlowAnimation(prefix, line, reversedLine) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const duration = 1 / flowAnimationSpeed;\n \n let animateFlow = ctx.api.connectorAnimation(animation);\n \n if (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, reversedLine).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n } else {\n if (animateFlow) {\n animateFlow.finish();\n }\n }\n}", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null }, { @@ -58,8 +58,8 @@ }, { "id": "leftFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.left-connector}", "type": "value", "valueType": "BOOLEAN", @@ -174,8 +174,8 @@ }, { "id": "topFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.top-connector}", "type": "value", "valueType": "BOOLEAN", @@ -290,8 +290,8 @@ }, { "id": "rightFlowDirection", - "name": "{i18n:scada.symbol.flow-direction}", - "hint": "{i18n:scada.symbol.flow-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.right-connector}", "type": "value", "valueType": "BOOLEAN", @@ -406,8 +406,8 @@ }, { "id": "bottomFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.bottom-connector}", "type": "value", "valueType": "BOOLEAN", @@ -483,14 +483,6 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", @@ -500,29 +492,15 @@ "subLabel": "Main", "divider": true, "fieldSuffix": "px", + "condition": "return model.mainLine;", "min": 0, "max": 99, "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true + "disabled": false }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -530,11 +508,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -543,8 +521,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -552,13 +530,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -567,13 +546,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -581,7 +561,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ diff --git a/application/src/main/data/json/system/scada_symbols/horizontal-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/horizontal-connector-hp.svg index 74d048e884..f2fc9fb2e0 100644 --- a/application/src/main/data/json/system/scada_symbols/horizontal-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/horizontal-connector-hp.svg @@ -3,7 +3,7 @@ "description": "Horizontal connector with an optional directional arrow to visually indicate flow.", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 200,100 H 0';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n\n", "tags": [ { "tag": "arrow", @@ -12,7 +12,7 @@ }, { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -53,18 +53,18 @@ "defaultWidgetActionSettings": null }, { - "id": "arrowDirection", - "name": "{i18n:scada.symbol.arrow-direction}", - "hint": "{i18n:scada.symbol.arrow-direction-hint}", + "id": "flowAnimation", + "name": "{i18n:scada.symbol.flow-animation}", + "hint": "{i18n:scada.symbol.flow-animation-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.forward}", - "falseLabel": "{i18n:scada.symbol.reverse}", - "stateLabel": "{i18n:scada.symbol.forward}", + "trueLabel": "{i18n:scada.symbol.present}", + "falseLabel": "{i18n:scada.symbol.absent}", + "stateLabel": "{i18n:scada.symbol.flow-present}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": true, + "defaultValue": false, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -72,34 +72,38 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "scope": null, - "key": "state" + "key": "state", + "scope": null }, "getTimeSeries": { "key": "state" }, + "getAlarmStatus": { + "severityList": null, + "typeList": null + }, "dataToValue": { "type": "NONE", - "dataToValueFunction": "/* Should return boolean value */\nreturn data;", - "compareToValue": true + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" } }, "defaultSetValueSettings": null, "defaultWidgetActionSettings": null }, { - "id": "flowAnimation", - "name": "{i18n:scada.symbol.flow-animation}", - "hint": "{i18n:scada.symbol.flow-animation-hint}", + "id": "arrowDirection", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.present}", - "falseLabel": "{i18n:scada.symbol.absent}", - "stateLabel": "{i18n:scada.symbol.flow-present}", + "trueLabel": "{i18n:scada.symbol.forward}", + "falseLabel": "{i18n:scada.symbol.reverse}", + "stateLabel": "{i18n:scada.symbol.forward}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": false, + "defaultValue": true, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -107,20 +111,16 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "key": "state", - "scope": null + "scope": null, + "key": "state" }, "getTimeSeries": { "key": "state" }, - "getAlarmStatus": { - "severityList": null, - "typeList": null - }, "dataToValue": { "type": "NONE", - "compareToValue": true, - "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true } }, "defaultSetValueSettings": null, @@ -166,36 +166,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -205,7 +182,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -213,11 +190,10 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", "fieldSuffix": "px", "min": 1, "step": 1, @@ -226,20 +202,23 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", - "default": "#C8DFF7" + "default": "#C8DFF7", + "disabled": false, + "visible": true }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -248,13 +227,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -262,7 +242,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ diff --git a/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-connector-hp.svg index fd14834d12..8fd4ee09df 100644 --- a/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/left-bottom-elbow-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Left bottom elbow connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 100,200 L 100,125 Q 100,100 75,100 L 0, 100';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -32,8 +32,8 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "key": "state", - "scope": null + "scope": "SHARED_SCOPE", + "key": "flow" }, "getTimeSeries": { "key": "state" @@ -44,8 +44,8 @@ }, "dataToValue": { "type": "NONE", - "compareToValue": true, - "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true } }, "defaultSetValueSettings": null, @@ -53,8 +53,8 @@ }, { "id": "animationDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", @@ -130,36 +130,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -169,7 +146,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -177,11 +154,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -190,20 +167,23 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", - "default": "#C8DFF7" + "default": "#C8DFF7", + "disabled": false, + "visible": true }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -212,13 +192,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -226,7 +207,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -248,5 +229,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/left-tee-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/left-tee-connector-hp.svg index af83a4abb3..c3b4e67d56 100644 --- a/application/src/main/data/json/system/scada_symbols/left-tee-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/left-tee-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Left tee connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H97\";\nconst topLine = \"M100 100L100 0\";\nconst bottomLine = \"M 100,200 V 100\";\n\nprepareFlowAnimation('left', leftLine);\nprepareFlowAnimation('top', topLine);\nprepareFlowAnimation('bottom', bottomLine);\n\nfunction prepareFlowAnimation(prefix, line) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const offset = Date.now() % 1000;\n const duration = 1 / flowAnimationSpeed;\n \n const prevFlowAnimation = animation.remember('flowAnimation');\n const prevFlowDirection = animation.remember('flowDirection');\n const prevFlowDuration = animation.remember('flowDuration');\n \n if (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n } else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n }\n}\n\nfunction animateFlow(group, offset, flowDirection, duration, line) {\n group.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n group.add(``);\n}", + "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H97\";\nconst leftLineReversed = \"M 97,100 H 0\";\nconst topLine = \"M100 100L100 0\";\nconst topLineReversed = \"M 100,0 V 100\";\nconst bottomLine = \"M 100,200 V 100\";\nconst bottomLineReversed = \"M 100,100 V 200\";\n\nprepareFlowAnimation('left', leftLine, leftLineReversed);\nprepareFlowAnimation('top', topLine, topLineReversed);\nprepareFlowAnimation('bottom', bottomLine, bottomLineReversed);\n\nfunction prepareFlowAnimation(prefix, line, reversedLine) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const duration = 1 / flowAnimationSpeed;\n \n let animateFlow = ctx.api.connectorAnimation(animation);\n \n if (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, reversedLine).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n } else {\n if (animateFlow) {\n animateFlow.finish();\n }\n }\n}", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null }, { @@ -58,8 +58,8 @@ }, { "id": "leftFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.left-connector}", "type": "value", "valueType": "BOOLEAN", @@ -174,8 +174,8 @@ }, { "id": "topFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.top-connector}", "type": "value", "valueType": "BOOLEAN", @@ -290,8 +290,8 @@ }, { "id": "bottomFlowDirection", - "name": "{i18n:scada.symbol.flow-direction}", - "hint": "{i18n:scada.symbol.flow-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.bottom-connector}", "type": "value", "valueType": "BOOLEAN", @@ -367,36 +367,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -406,7 +383,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -414,11 +391,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -427,8 +404,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -436,13 +413,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -451,13 +429,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -465,7 +444,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -487,5 +466,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/left-top-elbow-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/left-top-elbow-connector-hp.svg index 5b6d30ab65..961c760f63 100644 --- a/application/src/main/data/json/system/scada_symbols/left-top-elbow-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/left-top-elbow-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Left top elbow connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 100,0 L 100,75 Q 100,100 75,100 L 0, 100';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -53,8 +53,8 @@ }, { "id": "animationDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", @@ -130,36 +130,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -169,7 +146,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -177,11 +154,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -190,8 +167,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -199,13 +176,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -214,13 +192,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -228,7 +207,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -250,5 +229,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/long-horizontal-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/long-horizontal-connector-hp.svg index 3e65bd6b04..f5f68c4934 100644 --- a/application/src/main/data/json/system/scada_symbols/long-horizontal-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/long-horizontal-connector-hp.svg @@ -1,10 +1,9 @@ - - `);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 400,100 H 0';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n", "tags": [ { "tag": "arrow", @@ -13,7 +12,7 @@ }, { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -54,18 +53,18 @@ "defaultWidgetActionSettings": null }, { - "id": "arrowDirection", - "name": "{i18n:scada.symbol.arrow-direction}", - "hint": "{i18n:scada.symbol.arrow-direction-hint}", + "id": "flowAnimation", + "name": "{i18n:scada.symbol.flow-animation}", + "hint": "{i18n:scada.symbol.flow-animation-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.forward}", - "falseLabel": "{i18n:scada.symbol.reverse}", - "stateLabel": "{i18n:scada.symbol.forward}", + "trueLabel": "{i18n:scada.symbol.present}", + "falseLabel": "{i18n:scada.symbol.absent}", + "stateLabel": "{i18n:scada.symbol.flow-present}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": true, + "defaultValue": false, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -73,34 +72,38 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "scope": null, - "key": "state" + "key": "state", + "scope": null }, "getTimeSeries": { "key": "state" }, + "getAlarmStatus": { + "severityList": null, + "typeList": null + }, "dataToValue": { "type": "NONE", - "dataToValueFunction": "/* Should return boolean value */\nreturn data;", - "compareToValue": true + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" } }, "defaultSetValueSettings": null, "defaultWidgetActionSettings": null }, { - "id": "flowAnimation", - "name": "{i18n:scada.symbol.flow-animation}", - "hint": "{i18n:scada.symbol.flow-animation-hint}", + "id": "arrowDirection", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.present}", - "falseLabel": "{i18n:scada.symbol.absent}", - "stateLabel": "{i18n:scada.symbol.flow-present}", + "trueLabel": "{i18n:scada.symbol.forward}", + "falseLabel": "{i18n:scada.symbol.reverse}", + "stateLabel": "{i18n:scada.symbol.forward}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": false, + "defaultValue": true, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -108,20 +111,16 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "key": "state", - "scope": null + "scope": null, + "key": "state" }, "getTimeSeries": { "key": "state" }, - "getAlarmStatus": { - "severityList": null, - "typeList": null - }, "dataToValue": { "type": "NONE", - "compareToValue": true, - "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true } }, "defaultSetValueSettings": null, @@ -167,36 +166,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -206,7 +182,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -214,11 +190,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -227,20 +203,23 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", - "default": "#C8DFF7" + "default": "#C8DFF7", + "disabled": false, + "visible": true }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -249,13 +228,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -263,7 +243,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -285,5 +265,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/long-vertical-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/long-vertical-connector-hp.svg index b5c9730842..f344823082 100644 --- a/application/src/main/data/json/system/scada_symbols/long-vertical-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/long-vertical-connector-hp.svg @@ -3,7 +3,7 @@ "description": "Long vertical connector with an optional directional arrow to visually indicate flow.", "widgetSizeX": 1, "widgetSizeY": 2, - "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 100,0 V 400';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n\n", "tags": [ { "tag": "arrow", @@ -12,7 +12,7 @@ }, { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -53,18 +53,18 @@ "defaultWidgetActionSettings": null }, { - "id": "arrowDirection", - "name": "{i18n:scada.symbol.arrow-direction}", - "hint": "{i18n:scada.symbol.arrow-direction-hint}", + "id": "flowAnimation", + "name": "{i18n:scada.symbol.flow-animation}", + "hint": "{i18n:scada.symbol.flow-animation-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.forward}", - "falseLabel": "{i18n:scada.symbol.reverse}", - "stateLabel": "{i18n:scada.symbol.forward}", + "trueLabel": "{i18n:scada.symbol.present}", + "falseLabel": "{i18n:scada.symbol.absent}", + "stateLabel": "{i18n:scada.symbol.flow-present}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": true, + "defaultValue": false, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -72,34 +72,38 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "scope": null, - "key": "state" + "key": "state", + "scope": null }, "getTimeSeries": { "key": "state" }, + "getAlarmStatus": { + "severityList": null, + "typeList": null + }, "dataToValue": { "type": "NONE", - "dataToValueFunction": "/* Should return boolean value */\nreturn data;", - "compareToValue": true + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" } }, "defaultSetValueSettings": null, "defaultWidgetActionSettings": null }, { - "id": "flowAnimation", - "name": "{i18n:scada.symbol.flow-animation}", - "hint": "{i18n:scada.symbol.flow-animation-hint}", + "id": "arrowDirection", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.present}", - "falseLabel": "{i18n:scada.symbol.absent}", - "stateLabel": "{i18n:scada.symbol.flow-present}", + "trueLabel": "{i18n:scada.symbol.forward}", + "falseLabel": "{i18n:scada.symbol.reverse}", + "stateLabel": "{i18n:scada.symbol.forward}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": false, + "defaultValue": true, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -107,20 +111,16 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "key": "state", - "scope": null + "scope": null, + "key": "state" }, "getTimeSeries": { "key": "state" }, - "getAlarmStatus": { - "severityList": null, - "typeList": null - }, "dataToValue": { "type": "NONE", - "compareToValue": true, - "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true } }, "defaultSetValueSettings": null, @@ -166,36 +166,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -205,7 +182,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -213,11 +190,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -226,20 +203,23 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", - "default": "#C8DFF7" + "default": "#C8DFF7", + "disabled": false, + "visible": true }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -248,21 +228,20 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, - "step": 1, - "disabled": false, - "visible": true + "min": 0, + "step": 1 }, { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -284,5 +263,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/right-tee-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/right-tee-connector-hp.svg index 62aecb065d..346d134f30 100644 --- a/application/src/main/data/json/system/scada_symbols/right-tee-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/right-tee-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Right tee connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst topLine = \"M100 100L100 0\";\nconst rightLine = \"M103 100H200\";\nconst bottomLine = \"M 100,200 V 100\";\n\nprepareFlowAnimation('top', topLine);\nprepareFlowAnimation('right', rightLine);\nprepareFlowAnimation('bottom', bottomLine);\n\nfunction prepareFlowAnimation(prefix, line) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const offset = Date.now() % 1000;\n const duration = 1 / flowAnimationSpeed;\n \n const prevFlowAnimation = animation.remember('flowAnimation');\n const prevFlowDirection = animation.remember('flowDirection');\n const prevFlowDuration = animation.remember('flowDuration');\n \n if (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n } else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n }\n}\n\nfunction animateFlow(group, offset, flowDirection, duration, line) {\n group.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n group.add(``);\n}", + "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst topLine = \"M100 100L100 0\";\nconst topLineReversed = \"M 100,0 V 100\";\nconst rightLine = \"M103 100H200\";\nconst rightLineReversed = \"M 200,100 H 103\";\nconst bottomLine = \"M 100,200 V 100\";\nconst bottomLineReversed = \"M 100,100 V 200\";\n\nprepareFlowAnimation('top', topLine, topLineReversed);\nprepareFlowAnimation('right', rightLine, rightLineReversed);\nprepareFlowAnimation('bottom', bottomLine, bottomLineReversed);\n\nfunction prepareFlowAnimation(prefix, line, reversedLine) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const duration = 1 / flowAnimationSpeed;\n \n let animateFlow = ctx.api.connectorAnimation(animation);\n \n if (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, reversedLine).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n } else {\n if (animateFlow) {\n animateFlow.finish();\n }\n }\n}", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null }, { @@ -58,8 +58,8 @@ }, { "id": "topFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.top-connector}", "type": "value", "valueType": "BOOLEAN", @@ -174,8 +174,8 @@ }, { "id": "rightFlowDirection", - "name": "{i18n:scada.symbol.flow-direction}", - "hint": "{i18n:scada.symbol.flow-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.right-connector}", "type": "value", "valueType": "BOOLEAN", @@ -290,8 +290,8 @@ }, { "id": "bottomFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.bottom-connector}", "type": "value", "valueType": "BOOLEAN", @@ -367,36 +367,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -406,7 +383,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -414,11 +391,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -427,8 +404,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -436,13 +413,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -451,13 +429,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -465,7 +444,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ diff --git a/application/src/main/data/json/system/scada_symbols/top-right-elbow-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/top-right-elbow-connector-hp.svg index 8ec4e3cc65..ca255abf14 100644 --- a/application/src/main/data/json/system/scada_symbols/top-right-elbow-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/top-right-elbow-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Top right elbow connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `-${dashWidth + (dashGap || dashWidth)}` : `${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n animationDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 200,100 L 125,100 Q 100,100 100,75 L 100, 0';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -53,8 +53,8 @@ }, { "id": "animationDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", @@ -130,36 +130,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -169,7 +146,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -177,11 +154,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -190,8 +167,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -199,13 +176,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -214,13 +192,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -228,7 +207,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -250,5 +229,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/application/src/main/data/json/system/scada_symbols/top-tee-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/top-tee-connector-hp.svg index e4561a8347..e63d465d8e 100644 --- a/application/src/main/data/json/system/scada_symbols/top-tee-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/top-tee-connector-hp.svg @@ -3,11 +3,11 @@ "description": "Top tee connector", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst topLine = \"M100 97L100 0\";\nconst rightLine = \"M100 100H200\";\n\nprepareFlowAnimation('left', leftLine);\nprepareFlowAnimation('top', topLine);\nprepareFlowAnimation('right', rightLine);\n\nfunction prepareFlowAnimation(prefix, line) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const offset = Date.now() % 1000;\n const duration = 1 / flowAnimationSpeed;\n \n const prevFlowAnimation = animation.remember('flowAnimation');\n const prevFlowDirection = animation.remember('flowDirection');\n const prevFlowDuration = animation.remember('flowDuration');\n \n if (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(animation, offset, flowDirection, duration, line);\n } else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n } else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n }\n}\n\nfunction animateFlow(group, offset, flowDirection, duration, line) {\n group.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n group.add(``);\n}", + "stateRenderFunction": "const {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\n\nconst leftLine = \"M0 100H100\";\nconst leftLineReversed = \"M 100,100 H 0\";\nconst topLine = \"M100 97L100 0\";\nconst topLineReversed = \"M 100,0 V 97\";\nconst rightLine = \"M100 100H200\";\nconst rightLineReversed = \"M 200,100 H 100\";\n\nprepareFlowAnimation('left', leftLine, leftLineReversed);\nprepareFlowAnimation('top', topLine, topLineReversed);\nprepareFlowAnimation('right', rightLine, rightLineReversed);\n\nfunction prepareFlowAnimation(prefix, line, reversedLine) {\n const flowAnimation = ctx.values[prefix + 'Flow'];\n const flowDirection = ctx.values[prefix + 'FlowDirection'];\n const flowAnimationSpeed = ctx.values[prefix + 'FlowAnimationSpeed'];\n\n const animation = ctx.tags[prefix + 'Line'][0];\n const duration = 1 / flowAnimationSpeed;\n \n let animateFlow = ctx.api.connectorAnimation(animation);\n \n if (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, reversedLine).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n } else {\n if (animateFlow) {\n animateFlow.finish();\n }\n }\n}", "tags": [ { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null }, { @@ -58,8 +58,8 @@ }, { "id": "leftFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.left-connector}", "type": "value", "valueType": "BOOLEAN", @@ -174,8 +174,8 @@ }, { "id": "topFlowDirection", - "name": "{i18n:scada.symbol.animation-direction}", - "hint": "{i18n:scada.symbol.animation-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.top-connector}", "type": "value", "valueType": "BOOLEAN", @@ -290,8 +290,8 @@ }, { "id": "rightFlowDirection", - "name": "{i18n:scada.symbol.flow-direction}", - "hint": "{i18n:scada.symbol.flow-direction-hint}", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": "{i18n:scada.symbol.right-connector}", "type": "value", "valueType": "BOOLEAN", @@ -367,36 +367,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -406,7 +383,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -414,11 +391,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -427,8 +404,8 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", "default": "#C8DFF7", "disabled": false, @@ -436,13 +413,14 @@ }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -451,13 +429,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -465,7 +444,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ diff --git a/application/src/main/data/json/system/scada_symbols/vertical-connector-hp.svg b/application/src/main/data/json/system/scada_symbols/vertical-connector-hp.svg index cfaf6793ea..87c3ef23ee 100644 --- a/application/src/main/data/json/system/scada_symbols/vertical-connector-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/vertical-connector-hp.svg @@ -3,7 +3,7 @@ "description": "Vertical connector with an optional directional arrow to visually indicate flow.", "widgetSizeX": 1, "widgetSizeY": 1, - "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst animation = ctx.tags.animationGroup[0];\nconst offset = Date.now() % 1000;\nconst duration = 1 / flowAnimationSpeed;\n\nconst prevFlowAnimation = animation.remember('flowAnimation');\nconst prevFlowDirection = animation.remember('flowDirection');\nconst prevFlowDuration = animation.remember('flowDuration');\n\nif (flowAnimation && flowAnimation !== prevFlowAnimation) {\n animation.remember('flowAnimation', flowAnimation);\n animation.remember('flowDuration', duration);\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && flowDirection !== prevFlowDirection) {\n animation.remember('flowDirection', flowDirection);\n animateFlow(offset, flowDirection);\n} else if (flowAnimation && duration !== prevFlowDuration) {\n animation.remember('flowDuration', duration);\n animation.findOne('animate').attr('dur', `${duration}s`) ;\n} else if (!flowAnimation && prevFlowAnimation) {\n animation.remember('flowAnimation', null);\n animation.clear();\n}\n\nfunction animateFlow(offset, flowDirection) {\n animation.clear();\n const dashArray = `${dashWidth}${dashGap ? ` ${dashGap}` : ''}`;\n const value = flowDirection ? `${dashWidth + (dashGap || dashWidth)}` : `-${dashWidth + (dashGap || dashWidth)}`;\n\n animation.add(``);\n}\n", + "stateRenderFunction": "const {\n flowAnimation,\n arrowDirection: flowDirection,\n flowAnimationSpeed\n} = ctx.values;\nconst {\n flowAnimationWidth: lineWidth,\n flowAnimationColor: lineColor,\n flowStyleDash: dashWidth,\n flowStyleGap: dashGap,\n flowDashCap: dashCap\n} = ctx.properties;\nconst line = ctx.tags.line[0].attr('d');\nconst lineReversed = 'M 100,0 V 200';\nconst animation = ctx.tags.animationGroup[0];\nconst duration = 1 / flowAnimationSpeed;\n\nlet animateFlow = ctx.api.connectorAnimation(animation);\n\nif (flowAnimation) {\n if (!animateFlow) {\n animateFlow = ctx.api.connectorAnimate(animation, line, lineReversed).flowAppearance(lineWidth, lineColor, dashCap, dashWidth, dashGap).duration(duration).direction(flowDirection).play();\n } else {\n animateFlow.duration(duration).direction(flowDirection).play();\n }\n} else {\n if (animateFlow) {\n animateFlow.finish();\n }\n}\n", "tags": [ { "tag": "arrow", @@ -12,7 +12,7 @@ }, { "tag": "line", - "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nif (ctx.properties.mainLine) {\n element.attr({'stroke-width': ctx.properties.mainLineSize});\n} else {\n element.attr({'stroke-width': ctx.properties.secondaryLineSize});\n}", + "stateRenderFunction": "element.stroke(ctx.properties.lineColor);\nelement.attr({'stroke-width': ctx.properties.mainLineSize});", "actions": null } ], @@ -53,18 +53,18 @@ "defaultWidgetActionSettings": null }, { - "id": "arrowDirection", - "name": "{i18n:scada.symbol.arrow-direction}", - "hint": "{i18n:scada.symbol.arrow-direction-hint}", + "id": "flowAnimation", + "name": "{i18n:scada.symbol.flow-animation}", + "hint": "{i18n:scada.symbol.flow-animation-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.forward}", - "falseLabel": "{i18n:scada.symbol.reverse}", - "stateLabel": "{i18n:scada.symbol.forward}", + "trueLabel": "{i18n:scada.symbol.present}", + "falseLabel": "{i18n:scada.symbol.absent}", + "stateLabel": "{i18n:scada.symbol.flow-present}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": true, + "defaultValue": false, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -72,34 +72,38 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "scope": null, - "key": "state" + "key": "state", + "scope": null }, "getTimeSeries": { "key": "state" }, + "getAlarmStatus": { + "severityList": null, + "typeList": null + }, "dataToValue": { "type": "NONE", - "dataToValueFunction": "/* Should return boolean value */\nreturn data;", - "compareToValue": true + "compareToValue": true, + "dataToValueFunction": "/* Should return boolean value */\nreturn data;" } }, "defaultSetValueSettings": null, "defaultWidgetActionSettings": null }, { - "id": "flowAnimation", - "name": "{i18n:scada.symbol.flow-animation}", - "hint": "{i18n:scada.symbol.flow-animation-hint}", + "id": "arrowDirection", + "name": "{i18n:scada.symbol.arrow-direction}", + "hint": "{i18n:scada.symbol.arrow-direction-hint}", "group": null, "type": "value", "valueType": "BOOLEAN", - "trueLabel": "{i18n:scada.symbol.present}", - "falseLabel": "{i18n:scada.symbol.absent}", - "stateLabel": "{i18n:scada.symbol.flow-present}", + "trueLabel": "{i18n:scada.symbol.forward}", + "falseLabel": "{i18n:scada.symbol.reverse}", + "stateLabel": "{i18n:scada.symbol.forward}", "defaultGetValueSettings": { "action": "DO_NOTHING", - "defaultValue": false, + "defaultValue": true, "executeRpc": { "method": "getState", "requestTimeout": 5000, @@ -107,20 +111,16 @@ "persistentPollingInterval": 1000 }, "getAttribute": { - "key": "state", - "scope": null + "scope": null, + "key": "state" }, "getTimeSeries": { "key": "state" }, - "getAlarmStatus": { - "severityList": null, - "typeList": null - }, "dataToValue": { "type": "NONE", - "compareToValue": true, - "dataToValueFunction": "/* Should return boolean value */\nreturn data;" + "dataToValueFunction": "/* Should return boolean value */\nreturn data;", + "compareToValue": true } }, "defaultSetValueSettings": null, @@ -166,36 +166,13 @@ } ], "properties": [ - { - "id": "mainLine", - "name": "{i18n:scada.symbol.main-line}", - "type": "switch", - "default": true, - "disabled": false, - "visible": true - }, { "id": "mainLineSize", "name": "{i18n:scada.symbol.line}", "type": "number", "default": 6, "required": true, - "subLabel": "Main", - "divider": true, - "fieldSuffix": "px", - "min": 0, - "max": 99, - "step": 1, - "disabled": false, - "visible": true - }, - { - "id": "secondaryLineSize", - "name": "{i18n:scada.symbol.line}", - "type": "number", - "default": 2, - "required": true, - "subLabel": "Secondary", + "divider": false, "fieldSuffix": "px", "min": 0, "max": 99, @@ -205,7 +182,7 @@ }, { "id": "lineColor", - "name": "{i18n:scada.symbol.line-color}", + "name": "{i18n:scada.symbol.line}", "type": "color", "default": "#1A1A1A", "disabled": false, @@ -213,11 +190,11 @@ }, { "id": "flowAnimationWidth", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 4, - "subLabel": "Width", + "divider": false, "fieldSuffix": "px", "min": 1, "step": 1, @@ -226,20 +203,23 @@ }, { "id": "flowAnimationColor", - "name": "{i18n:scada.symbol.flow}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line}", + "group": "{i18n:scada.symbol.flow}", "type": "color", - "default": "#C8DFF7" + "default": "#C8DFF7", + "disabled": false, + "visible": true }, { "id": "flowStyleDash", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "required": true, "subLabel": "{i18n:scada.symbol.dash}", - "divider": true, + "divider": false, "fieldSuffix": "px", "min": 0, "step": 1, @@ -248,13 +228,14 @@ }, { "id": "flowStyleGap", - "name": "{i18n:scada.symbol.flow-style}", - "group": "{i18n:scada.symbol.animation}", + "name": "{i18n:scada.symbol.flow-line-style}", + "hint": "{i18n:scada.symbol.flow-style-hint}", + "group": "{i18n:scada.symbol.flow}", "type": "number", "default": 10, "subLabel": "{i18n:scada.symbol.gap}", "fieldSuffix": "px", - "min": 1, + "min": 0, "step": 1, "disabled": false, "visible": true @@ -262,7 +243,7 @@ { "id": "flowDashCap", "name": "{i18n:scada.symbol.flow-dash-cap}", - "group": "{i18n:scada.symbol.animation}", + "group": "{i18n:scada.symbol.flow}", "type": "select", "default": "butt", "items": [ @@ -284,5 +265,5 @@ } ] }]]> - + \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index abe570fa3c..7bd835de88 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -83,6 +83,10 @@ export interface ScadaSymbolApi { cssAnimation: (element: Element) => ScadaSymbolAnimation | undefined; resetCssAnimation: (element: Element) => void; finishCssAnimation: (element: Element) => void; + connectorAnimation:(element: Element) => ConnectorScadaSymbolAnimation | undefined; + connectorAnimate:(element: Element, path: string, reversedPath: string) => ConnectorScadaSymbolAnimation; + resetConnectorAnimation: (element: Element) => void; + finishConnectorAnimation: (element: Element) => void; disable: (element: Element | Element[]) => void; enable: (element: Element | Element[]) => void; callAction: (event: Event, behaviorId: string, value?: any, observer?: Partial>) => void; @@ -186,6 +190,8 @@ const tbNamespaceRegex = //gm const tbTagRegex = /tb:tag="([^"]*)"/gms; +const syncTime = Date.now(); + const generateElementId = () => { const id = guid(); const firstChar = id.charAt(0); @@ -485,6 +491,7 @@ export class ScadaSymbolObject { private settings: ScadaSymbolObjectSettings; private context: ScadaSymbolContext; private cssAnimations: CssScadaSymbolAnimations; + private connectorAnimations: ScadaSymbolFlowConnectorAnimations; private svgShape: Svg; private box: Box; @@ -604,6 +611,7 @@ export class ScadaSymbolObject { private init() { this.cssAnimations = new CssScadaSymbolAnimations(this.svgShape, this.raf); + this.connectorAnimations = new ScadaSymbolFlowConnectorAnimations(); this.context = { api: { generateElementId: () => generateElementId(), @@ -615,6 +623,10 @@ export class ScadaSymbolObject { cssAnimation: this.cssAnimation.bind(this), resetCssAnimation: this.resetCssAnimation.bind(this), finishCssAnimation: this.finishCssAnimation.bind(this), + connectorAnimation: this.connectorAnimation.bind(this), + connectorAnimate: this.connectorAnimate.bind(this), + resetConnectorAnimation: this.resetConnectorAnimation.bind(this), + finishConnectorAnimation: this.finishConnectorAnimation.bind(this), disable: this.disableElement.bind(this), enable: this.enableElement.bind(this), callAction: this.callAction.bind(this), @@ -959,6 +971,22 @@ export class ScadaSymbolObject { this.cssAnimations.finishAnimation(element); } + private connectorAnimate(element: Element, path: string, reversedPath: string): ConnectorScadaSymbolAnimation { + return this.connectorAnimations.animate(element, path, reversedPath); + } + + private connectorAnimation(element: Element): ConnectorScadaSymbolAnimation | undefined { + return this.connectorAnimations.animation(element); + } + + private resetConnectorAnimation(element: Element) { + this.connectorAnimations.resetAnimation(element); + } + + private finishConnectorAnimation(element: Element) { + this.connectorAnimations.finishAnimation(element); + } + private disableElement(e: Element | Element[]) { this.elements(e).forEach(element => { element.attr({'pointer-events': 'none'}); @@ -1108,6 +1136,20 @@ interface ScadaSymbolAnimation { } +const scadaSymbolConnectorFlowAnimationId = 'scadaSymbolConnectorFlowAnimation'; + +type StrokeLineCap = 'butt' | 'round '| 'square'; + +interface ConnectorScadaSymbolAnimation { + play(): void; + stop(): void; + finish(): void; + + flowAppearance(width: number, color: string, lineCap: StrokeLineCap, dashWidth: number, dashGap: number): ConnectorScadaSymbolAnimation; + duration(speed: number): ConnectorScadaSymbolAnimation; + direction(direction: boolean): ConnectorScadaSymbolAnimation; +} + class CssScadaSymbolAnimations { constructor(private svgShape: Svg, private raf: RafService) {} @@ -1159,6 +1201,132 @@ class CssScadaSymbolAnimations { } } +class ScadaSymbolFlowConnectorAnimations { + constructor() {} + + public animate(element: Element, path = '', reversedPath = ''): ConnectorScadaSymbolAnimation { + this.checkOldAnimation(element); + return this.setupAnimation(element, this.createAnimation(element, path, reversedPath)); + } + + public animation(element: Element): ConnectorScadaSymbolAnimation | undefined { + return element.remember(scadaSymbolConnectorFlowAnimationId); + } + + public resetAnimation(element: Element) { + const animation: ConnectorScadaSymbolAnimation = element.remember(scadaSymbolConnectorFlowAnimationId); + if (animation) { + animation.stop(); + element.remember(scadaSymbolConnectorFlowAnimationId, null); + } + } + + public finishAnimation(element: Element) { + const animation: ConnectorScadaSymbolAnimation = element.remember(scadaSymbolConnectorFlowAnimationId); + if (animation) { + animation.finish(); + element.remember(scadaSymbolConnectorFlowAnimationId, null); + } + } + + private setupAnimation(element: Element, animation: ConnectorScadaSymbolAnimation): ConnectorScadaSymbolAnimation { + element.remember(scadaSymbolConnectorFlowAnimationId, animation); + return animation; + } + + private checkOldAnimation(element: Element) { + const previousAnimation: ConnectorScadaSymbolAnimation = element.remember(scadaSymbolConnectorFlowAnimationId); + if (previousAnimation) { + previousAnimation.finish(); + } + } + + private createAnimation(element: Element, path: string, reversedPath: string): ConnectorScadaSymbolAnimation { + return new FlowConnectorAnimation(element, path, reversedPath); + } +} + +class FlowConnectorAnimation implements ConnectorScadaSymbolAnimation { + + private readonly _path: string; + private readonly _reversedPath: string; + private readonly _animation: Element; + + private _duration: number = 1; + private _lineColor: string = '#C8DFF7'; + private _lineWidth: number = 4; + private _strokeLineCap: StrokeLineCap = 'butt'; + private _dashWidth: number = 10; + private _dashGap: number = 10; + private _direction: boolean = true; + + constructor(private element: Element, + path: string, + pathReversed: string) { + this._path = path; + this._reversedPath = pathReversed; + + const dashArray = `${this._dashWidth} ${this._dashGap}`; + const values = `${this._dashWidth + this._dashGap};0`; + + this._animation = SVG( + `` + + `` + ); + } + + public play() { + if (!this.element.node.childElementCount) { + this.element.add(this._animation); + } + const animateElement = this.element.node.getElementsByTagName('animate')[0]; + const offset = ((Date.now() - syncTime) % 1000) * -1; + (animateElement as SVGAnimationElement).beginElementAt(offset); + } + + public stop() { + const animateElement = this.element.node.getElementsByTagName('animate')[0]; + (animateElement as SVGAnimationElement)?.endElement(); + } + + public finish() { + this.element.findOne('path')?.remove(); + } + + public flowAppearance(width: number, color: string, linecap: StrokeLineCap, dashWidth: number, dashGap: number): this { + const totalLength = (this._animation.node as SVGPathElement).getTotalLength(); + let offset = 0; + if ((totalLength % 100) !== 0) { + const clientWidth = totalLength < 100 ? 100 : this.element.node.ownerSVGElement.clientWidth; + const clientWidthDash = clientWidth / (dashWidth + dashGap); + const totalLengthDash = totalLength / clientWidthDash; + offset = ((dashWidth + dashGap) - totalLengthDash) / 2; + } + this._lineColor = color; + this._lineWidth = width; + this._strokeLineCap = linecap; + this._dashWidth = dashWidth - offset; + this._dashGap = dashGap - offset; + const dashArray = `${this._dashWidth} ${this._dashGap}`; + const values = `${this._dashWidth + (this._dashGap || this._dashWidth)};0`; + this._animation.stroke({width, color, linecap, dasharray: dashArray}); + this._animation.findOne('animate').attr('values', values); + return this; + } + + public duration(speed: number): this { + this._duration = speed; + this._animation.findOne('animate').attr('dur', `${speed}s`); + return this; + } + + public direction(direction: boolean): this { + this._direction = direction; + this._animation.attr('d', direction ? this._path : this._reversedPath); + return this; + } +} + interface ScadaSymbolAnimationKeyframe { stop: string; style: any; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.html index b32c7b5ab1..af59457abe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.html @@ -30,6 +30,12 @@ + + scada.behavior.hint + + + + dynamic-form.property.group-title diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts index 2df62e1259..00a614636d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts @@ -104,6 +104,7 @@ export class DynamicFormPropertyPanelComponent implements OnInit { { id: [this.property.id, [Validators.required]], name: [this.property.name, [Validators.required]], + hint: [this.property.hint, []], group: [this.property.group, []], type: [this.property.type, [Validators.required]], arrayItemType: [this.property.arrayItemType, [Validators.required]], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.html index a64c178eb6..449af2b240 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.html @@ -91,9 +91,15 @@ - {{ propertyRow.label | customTranslate }} + + {{ propertyRow.label | customTranslate }} + - {{ propertyRow.label | customTranslate }} + + + {{ propertyRow.label | customTranslate }} + + diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts index 13b55d4f67..56d2801670 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts @@ -1129,6 +1129,8 @@ export const scadaSymbolContextCompletion = (metadata: ScadaSymbolMetadata, tags const scadaSymbolAnimationLink = HelpLinks.linksMap.scadaSymbolDevAnimation; const scadaSymbolAnimation = `ScadaSymbolAnimation`; + const connectorScadaSymbolAnimationLink = HelpLinks.linksMap.scadaSymbolDevConnectorAnimation; + const connectorScadaSymbolAnimation = `ConnectorScadaSymbolAnimation`; const properties: TbEditorCompletion = { meta: 'object', @@ -1229,6 +1231,68 @@ export const scadaSymbolContextCompletion = (metadata: ScadaSymbolMetadata, tags }, ] }, + connectorAnimate: { + meta: 'function', + description: 'Finishes any previous connector animation and starts a new connector animation for the SVG element along the specified path.', + args: [ + { + name: 'element', + description: 'SVG element', + type: 'Element' + }, + { + name: 'path', + description: 'Path defining the animation trajectory', + type: 'string' + }, + { + name: 'reversedPath', + description: 'Path for the reversed animation trajectory', + type: 'string' + } + ], + return: { + description: `Instance of ${connectorScadaSymbolAnimation} class with API to setup and control the connector animation.`, + type: connectorScadaSymbolAnimation + } + }, + connectorAnimation: { + meta: 'function', + description: 'Gets the current connector animation applied to the SVG element.', + args: [ + { + name: 'element', + description: 'SVG element', + type: 'Element' + } + ], + return: { + description: `Instance of ${connectorScadaSymbolAnimation} class with API to setup and control the connector animation, or undefined if no animation is applied.`, + type: 'ConnectorScadaSymbolAnimation | undefined' + } + }, + resetConnectorAnimation: { + meta: 'function', + description: 'Stops the connector animation if any and restores the SVG element to its initial state, removes the connector animation instance.', + args: [ + { + name: 'element', + description: 'SVG element', + type: 'Element' + } + ] + }, + finishConnectorAnimation: { + meta: 'function', + description: 'Finishes the connector animation if any, updates the SVG element state according to the end animation values, removes the connector animation instance.', + args: [ + { + name: 'element', + description: 'SVG element', + type: 'Element' + } + ] + }, generateElementId: { meta: 'function', description: 'Generates new unique element id.', diff --git a/ui-ngx/src/app/shared/models/constants.ts b/ui-ngx/src/app/shared/models/constants.ts index af576882b8..716f07e0aa 100644 --- a/ui-ngx/src/app/shared/models/constants.ts +++ b/ui-ngx/src/app/shared/models/constants.ts @@ -194,6 +194,7 @@ export const HelpLinks = { scada: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/scada`, scadaSymbolDev: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/scada/scada-symbols-dev-guide/`, scadaSymbolDevAnimation: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/scada/scada-symbols-dev-guide/#scadasymbolanimation`, + scadaSymbolDevConnectorAnimation: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/scada/scada-symbols-dev-guide/#connectorscadasymbolanimation`, domains: `${helpBaseUrl}/docs${docPlatformPrefix}/domains`, mobileApplication: `${helpBaseUrl}/docs${docPlatformPrefix}/mobile-center/applications/`, mobileBundle: `${helpBaseUrl}/docs${docPlatformPrefix}/mobile-center/mobile-center/`, diff --git a/ui-ngx/src/app/shared/models/dynamic-form.models.ts b/ui-ngx/src/app/shared/models/dynamic-form.models.ts index 4132eeff94..b1cc83dbd7 100644 --- a/ui-ngx/src/app/shared/models/dynamic-form.models.ts +++ b/ui-ngx/src/app/shared/models/dynamic-form.models.ts @@ -87,6 +87,7 @@ export type PropertyConditionFunction = (property: FormProperty, model: any) => export interface FormPropertyBase { id: string; name: string; + hint?: string; group?: string; type: FormPropertyType; default: any; @@ -237,6 +238,7 @@ export interface FormPropertyContainerBase { } export interface FormPropertyRow extends FormPropertyContainerBase { + hint?: string; properties?: FormProperty[]; switch?: FormProperty; rowClass?: string; @@ -362,6 +364,7 @@ const toPropertyContainers = (properties: FormProperty[], if (!propertyRow) { propertyRow = { label: property.name, + hint: property.hint, type: FormPropertyContainerType.row, properties: [], rowClass: property.rowClass, diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 72afcfc0b9..b9eaf3cb82 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3438,15 +3438,15 @@ "arrow-presence": "Arrow presence", "arrow-presence-hint": "Indicates whether arrow is present in connector.", "arrow-present": "Arrow present", - "arrow-direction": "Arrow/Animation direction", + "arrow-direction": "Flow direction", "arrow-direction-hint": "Indicates flow direction.", - "animation-direction": "Flow animation direction", - "animation-direction-hint": "Indicates animation flow direction.", - "flow-animation": "Flow animation", - "flow-animation-hint": "Indicates whether animation is present in connector.", + "flow-animation": "Flow presence", + "flow-animation-hint": "Indicates whether fluid is flowing in connector.", "flow": "Flow", - "flow-style": "Flow style", - "flow-dash-cap": "Flow dash cap", + "flow-line": "Line", + "flow-line-style": "Line style", + "flow-style-hint": "Set the Dash and Gap values so that their sum is divisible by 100 without a remainder for perfect animation synchronization.", + "flow-dash-cap": "Dash cap", "dash-cap-butt": "Butt", "dash-cap-round": "Round", "dash-cap-square": "Square",