From b59b8ed3f964d15a9aa432c543013e3b8bac7e31 Mon Sep 17 00:00:00 2001 From: qinoy Date: Sat, 17 Jun 2023 15:55:59 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AB=AF=E5=88=B0=E7=AB=AF=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=20=E8=8A=82=E7=82=B9=E5=B1=95=E5=BC=80=E4=B8=8E=E9=97=AD?= =?UTF-8?q?=E5=90=88=20=E5=BC=95=E5=85=A5=E8=A7=82=E5=AF=9F=E8=80=85?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E5=8F=98=E6=9B=B4=20=E4=BB=A5=E5=8F=8A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=BF=9E=E7=BA=BF=E6=B8=B2=E6=9F=93=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oft.apps.coe.method.process.subprocess.jar | Bin 79721 -> 85346 bytes .../graph/GraphNodeCloseHandle.java | 94 ++++++--- .../graph/GraphNodeExpandHandle.java | 92 ++++++--- .../subprocess/mode/ScopeShapeMonitor.java | 6 + .../subprocess/observers/Observer.java | 11 ++ .../process/subprocess/observers/Subject.java | 22 +++ .../observers/node/NodeObserver.java | 40 ++++ .../observers/node/NodeSubject.java | 182 ++++++++++++++++++ 8 files changed, 394 insertions(+), 53 deletions(-) create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Observer.java create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Subject.java create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeObserver.java create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeSubject.java diff --git a/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar b/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar index 61a12eb6c5a3ae26dc72236555e19b66119fa5a0..34bf91848984e1a59b514dabacb393a65497bf31 100644 GIT binary patch delta 34010 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 diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java index a4398c04..3230a2c3 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java @@ -7,6 +7,7 @@ import com.actionsoft.apps.coe.method.process.subprocess.graph.component.Abstrac import com.actionsoft.apps.coe.method.process.subprocess.graph.util.DefinitionThreadUnSafe; import com.actionsoft.apps.coe.method.process.subprocess.graph.util.SubProcessNodeDefineUtil; import com.actionsoft.apps.coe.method.process.subprocess.mode.ScopeShapeMonitor; +import com.actionsoft.apps.coe.method.process.subprocess.observers.node.NodeSubject; import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; import com.actionsoft.apps.coe.pal.pal.repository.designer.model.BaseModel; @@ -36,6 +37,7 @@ public class GraphNodeCloseHandle { private AbstractDefinitionHandle definitionHandle; // 当前总图 define 处理器 private AbstractDefinitionHandle subProcessNodeDefineHandle; // 子流程节点 define 处理器 private ScopeShapeMonitor scopeShapeMonitor; // 范围选择框及其内部元素监视器 + private NodeSubject nodeSubject; // 当前操作的节点主题类 public GraphNodeCloseHandle(String repositoryId, String shapeId, String endToEndProcessDefineStr) throws AWSException{ this.repositoryId = repositoryId; @@ -54,6 +56,10 @@ public class GraphNodeCloseHandle { scopeLimitationShape = definitionHandle.getShapeByKey(shapeId); scopeShapeMonitor = new ScopeShapeMonitor(definitionHandle); + scopeShapeMonitor.buildScopeShapeMonitors(); + + nodeSubject = new NodeSubject(definitionHandle, scopeShapeMonitor, shapeId, "close"); + nodeSubject.buildObservers(); } catch (AWSException e) { throw new AWSException(e); @@ -71,8 +77,6 @@ public class GraphNodeCloseHandle { // 1、处理范围选择框及其内部节点 removeScopeShapeAndInRangeEle(); - scopeShapeMonitor.buildScopeShapeMonitors(); - // 2、处理总图中的节点与连线 handleEndToEndGraphNodeAndLinker(); @@ -85,6 +89,11 @@ public class GraphNodeCloseHandle { // 1、创建对应子流程节点 JSONObject subProcessNode = buildSubProcessNode(shapeId, scopeLimitationShape); definitionHandle.addEle(shapeId, subProcessNode); + + // 通知其它节点位置更新 + nodeSubject.setScopeW(subProcessNode.getJSONObject("props").getDoubleValue("w")); + nodeSubject.setScopeH(subProcessNode.getJSONObject("props").getDoubleValue("h")); + // 2、根据现有连线关系创建邻接矩阵 NodeCloseAdjMatrix closeAdjMatrix = buildEndToEndGraphAdjMatrix(); closeAdjMatrix.buildAdjMatrix(); @@ -92,13 +101,13 @@ public class GraphNodeCloseHandle { JSONObject elements = definitionHandle.getElements(); // 更新因节点展开后 坐标发生变化的节点坐标 String direction = definitionHandle.getProcessProperties().getString("direction"); - graphPartNodePoiRenderAgain(elements, direction, subProcessNode); + // graphPartNodePoiRenderAgain(elements, direction, subProcessNode); // 3、收集现有元素坐标 double[][] vertexBounding = closeAdjMatrix.getVertexBounding(elements); // 4、删除现有连线 removeEndToEndGraphOldLinker(); // 5、构建新的连线 - NodeCloseLinkerRender linkerRender = new NodeCloseLinkerRender(vertexBounding, closeAdjMatrix); + NodeCloseLinkerRender linkerRender = new NodeCloseLinkerRender(vertexBounding, closeAdjMatrix, definitionHandle); JSONArray linkers = linkerRender.toAssembleLinker(direction); for (Object o : linkers) { JSONObject linker = (JSONObject) o; @@ -305,6 +314,8 @@ public class GraphNodeCloseHandle { } definitionHandle.removeShape(shapeId); + + scopeShapeMonitor.removeScopeShapeByKey(shapeId); } } @@ -374,11 +385,13 @@ class NodeCloseLinkerRender{ private List nodeIds; // 图形节点ID集合 private double[][] vertexPosition; // 所有节点的坐标 private NodeCloseAdjMatrix closeAdjMatrix; // 节点矩阵 + private AbstractDefinitionHandle definitionHandle; - public NodeCloseLinkerRender(double[][] vertexPosition, NodeCloseAdjMatrix closeAdjMatrix) { + public NodeCloseLinkerRender(double[][] vertexPosition, NodeCloseAdjMatrix closeAdjMatrix, AbstractDefinitionHandle definitionHandle) { this.nodeIds = closeAdjMatrix.getNodeIds(); this.vertexPosition = vertexPosition; this.closeAdjMatrix = closeAdjMatrix; + this.definitionHandle = definitionHandle; } /** @@ -451,38 +464,38 @@ class NodeCloseLinkerRender{ return fromY < toY ? new double[][]{ startPoi, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoi} : new double[][]{ startPoi, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoi}; }else { // 分布在四个象限内 if (fromX > toX && fromY > toY){ // 目标节点在第二象限 return new double[][]{ {fromX + fromW, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} }; }else if (fromX > toX && fromY < toY){ // 目标节点在第三象限 - return toY - fromY == SubProcessConst.SHAPE_VERT_INTERVAL + return toY - getCurrentRowMaxH(fromY) == SubProcessConst.SHAPE_VERT_INTERVAL // 相邻行节点 ? new double[][] { {fromX + fromW / 2, fromY + fromH}, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} } : new double[][] { {fromX + fromW / 2, fromY + fromH}, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, - {toX + toW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + toW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} @@ -490,7 +503,7 @@ class NodeCloseLinkerRender{ }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 return new double[][]{ {fromX + fromW / 2, fromY + fromH}, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} }; @@ -508,7 +521,7 @@ class NodeCloseLinkerRender{ ? new double[][] { {fromX + fromW, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, {toX - SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY + toH / 2}, {toX, toY + toH / 2} } @@ -525,15 +538,15 @@ class NodeCloseLinkerRender{ double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; double[] endPoint = new double[]{toX + toW / 2, toY}; return new double[][]{startPoint, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoint}; }else { if (fromX < toX && fromY > toY){ // 目标节点在第一象限 double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; - double turnPointX = fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; - if (fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 + double turnPointX = fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; + if (fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 double[] endPoint = new double[]{toX, toY + toH / 2}; return new double[][]{startPoint,{turnPointX, fromY + fromH / 2},{turnPointX, toY + toH / 2}, endPoint}; }else { // 不相邻节点 存在三个折点 @@ -551,15 +564,15 @@ class NodeCloseLinkerRender{ double[] endPoint = new double[]{toX + toW / 2, toY}; return new double[][]{ startPoint, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoint }; }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; - if (fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 - double turnPointX = fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; + if (fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 + double turnPointX = fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; double[] endPoint = new double[]{toX, toY + toH / 2}; return new double[][]{ startPoint, @@ -571,8 +584,8 @@ class NodeCloseLinkerRender{ double[] endPoint = new double[]{toX + toW / 2, toY}; return new double[][]{ startPoint, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoint }; @@ -584,6 +597,35 @@ class NodeCloseLinkerRender{ return new double[2][2]; } + /** + * 获取当前同一列图形的最大宽度 在水平布局中 + * @param fromShapeX 当前图形的 x 坐标 + * @return + */ + private double getCurrentColMaxW(double fromShapeX){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && fromShapeX == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("w"))).get(); + return props.getDoubleValue("w"); + } + + /** + * 获取当前同一行图形的最大高度 在垂直布局中 + * @param fromShapeY + * @return + */ + private double getCurrentRowMaxH(double fromShapeY){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && fromShapeY == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("h"))).get(); + return props.getDoubleValue("h"); + } + + /** * 计算angle值 * @param fromPoi 起始节点坐标 diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeExpandHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeExpandHandle.java index 4fcc3adb..4929b070 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeExpandHandle.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeExpandHandle.java @@ -8,6 +8,7 @@ import com.actionsoft.apps.coe.method.process.subprocess.graph.util.DefinitionTh import com.actionsoft.apps.coe.method.process.subprocess.graph.util.SubProcessNodeDefineUtil; import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; import com.actionsoft.apps.coe.method.process.subprocess.mode.ScopeShapeMonitor; +import com.actionsoft.apps.coe.method.process.subprocess.observers.node.NodeSubject; import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; import com.actionsoft.apps.coe.pal.pal.repository.designer.model.BaseModel; import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.cache.DesignerShapeRelationCache; @@ -37,6 +38,7 @@ public class GraphNodeExpandHandle { private AbstractDefinitionHandle definitionHandle; // 当前总图 define 处理器 private AbstractDefinitionHandle subProcessNodeDefineHandle; // 子流程节点 define 处理器 private ScopeShapeMonitor scopeShapeMonitor; // 范围选择框及其内部元素监视器 + private NodeSubject nodeSubject; // 当前操作的节点主题类 private double[] scopeLimitationShapeBeforePoi; // 范围选择框在子流程文件中的坐标 @@ -54,6 +56,11 @@ public class GraphNodeExpandHandle { subProcessNodeDefineHandle = new DefinitionThreadUnSafe(SubProcessNodeDefineUtil.readSubProcessNodeDefine(repositoryId, shapeId)); scopeShapeMonitor = new ScopeShapeMonitor(definitionHandle); + // 1、构建范围框监视器模型 并关联内部元素 + scopeShapeMonitor.buildScopeShapeMonitors(); + + nodeSubject = new NodeSubject(definitionHandle, scopeShapeMonitor, shapeId, "expand"); + nodeSubject.buildObservers(); toAssembleScopeLimitationShape(); } catch (Exception e) { @@ -93,6 +100,10 @@ public class GraphNodeExpandHandle { scopeLimitationShape.put("dataAttributes", currentExpandShape.getJSONArray("dataAttributes")); this.scopeLimitationShape = scopeLimitationShape; + + // 通知其它节点位置更新 + nodeSubject.setScopeW(scope[2]); + nodeSubject.setScopeH(scope[3]); } /** @@ -103,9 +114,6 @@ public class GraphNodeExpandHandle { */ public String handleNodeExpand() throws AWSException{ - // 1、构建范围框监视器模型 并关联内部元素 - scopeShapeMonitor.buildScopeShapeMonitors(); - // 2、总图节点以及连线处理 handleEndToEndGraphNodeAndLinker(); @@ -136,7 +144,7 @@ public class GraphNodeExpandHandle { definitionHandle.addEle(shapeId, scopeLimitationShape); // 3、总图中符合范围选择框条件的节点 坐标更新 - handleEndToEndGraphNodeExcluedExpandNode(); + // handleEndToEndGraphNodeExcluedExpandNode(); // 4、构建邻接矩阵 NodeExpandAdjMatrix expandAdjMatrix = buildEndToEndGraphAdjMatrix(); @@ -150,7 +158,7 @@ public class GraphNodeExpandHandle { // 7、构建新的连线 JSONObject processProperties = definitionHandle.getProcessProperties(); String direction = processProperties.getString("direction"); - NodeExpandLinkerRender linkerRender = new NodeExpandLinkerRender(vertexBounding, expandAdjMatrix); + NodeExpandLinkerRender linkerRender = new NodeExpandLinkerRender(vertexBounding, expandAdjMatrix, definitionHandle); JSONArray linkers = linkerRender.toAssembleLinker(direction); for (Object o : linkers) { JSONObject linker = (JSONObject) o; @@ -410,14 +418,16 @@ class NodeExpandAdjMatrix extends AbstractAdjMatrix { */ class NodeExpandLinkerRender{ + private AbstractDefinitionHandle definitionHandle; // 总图 define 处理器 private List nodeIds; // 图形节点ID集合 private double[][] vertexPosition; // 所有节点的坐标以及宽高 double[][]{{x, y, w, h},{}} private NodeExpandAdjMatrix expandAdjMatrix; // 节点矩阵 - public NodeExpandLinkerRender(double[][] vertexPosition, NodeExpandAdjMatrix expandAdjMatrix) { + public NodeExpandLinkerRender(double[][] vertexPosition, NodeExpandAdjMatrix expandAdjMatrix, AbstractDefinitionHandle definitionHandle) { this.nodeIds = expandAdjMatrix.getNodeIds(); this.vertexPosition = vertexPosition; this.expandAdjMatrix = expandAdjMatrix; + this.definitionHandle = definitionHandle; } /** @@ -491,38 +501,38 @@ class NodeExpandLinkerRender{ return fromY < toY ? new double[][]{ startPoi, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoi} : new double[][]{ startPoi, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoi}; }else { // 分布在四个象限内 if (fromX > toX && fromY > toY){ // 目标节点在第二象限 return new double[][]{ {fromX + fromW, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} }; }else if (fromX > toX && fromY < toY){ // 目标节点在第三象限 - return toY - fromY == SubProcessConst.SHAPE_VERT_INTERVAL + return toY - getCurrentRowMaxH(fromY) == SubProcessConst.SHAPE_VERT_INTERVAL // 相邻行节点 ? new double[][] { {fromX + fromW / 2, fromY + fromH}, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} } : new double[][] { {fromX + fromW / 2, fromY + fromH}, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, - {toX + toW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + toW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} @@ -530,7 +540,7 @@ class NodeExpandLinkerRender{ }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 return new double[][]{ {fromX + fromW / 2, fromY + fromH}, - {fromX + fromW / 2, fromY + fromH + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY} }; @@ -549,7 +559,7 @@ class NodeExpandLinkerRender{ ? new double[][] { {fromX + fromW, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, {toX - SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY + toH / 2}, {toX, toY + toH / 2} } @@ -566,15 +576,15 @@ class NodeExpandLinkerRender{ double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; double[] endPoint = new double[]{toX + toW / 2, toY}; return new double[][]{startPoint, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoint}; }else { if (fromX < toX && fromY > toY){ // 目标节点在第一象限 double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; - double turnPointX = fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; - if (fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 + double turnPointX = fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; + if (fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 double[] endPoint = new double[]{toX, toY + toH / 2}; return new double[][]{startPoint,{turnPointX, fromY + fromH / 2},{turnPointX, toY + toH / 2}, endPoint}; }else { // 不相邻节点 存在三个折点 @@ -592,15 +602,15 @@ class NodeExpandLinkerRender{ double[] endPoint = new double[]{toX + toW / 2, toY}; return new double[][]{ startPoint, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoint }; }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; - if (fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 - double turnPointX = fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; + if (fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 + double turnPointX = fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; double[] endPoint = new double[]{toX, toY + toH / 2}; return new double[][]{ startPoint, @@ -612,8 +622,8 @@ class NodeExpandLinkerRender{ double[] endPoint = new double[]{toX + toW / 2, toY}; return new double[][]{ startPoint, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, - {fromX + fromW + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, {toX + toW / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, endPoint }; @@ -625,6 +635,34 @@ class NodeExpandLinkerRender{ return new double[2][2]; } + /** + * 获取当前同一列图形的最大宽度 在水平布局中 + * @param fromShapeX 当前图形的 x 坐标 + * @return + */ + private double getCurrentColMaxW(double fromShapeX){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && fromShapeX == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("w"))).get(); + return props.getDoubleValue("w"); + } + + /** + * 获取当前同一行图形的最大高度 在垂直布局中 + * @param fromShapeY + * @return + */ + private double getCurrentRowMaxH(double fromShapeY){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && fromShapeY == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("h"))).get(); + return props.getDoubleValue("h"); + } + /** * 计算angle值 * @param fromPoi 起始节点坐标 diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/ScopeShapeMonitor.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/ScopeShapeMonitor.java index e06daead..c13ed59f 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/ScopeShapeMonitor.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/ScopeShapeMonitor.java @@ -71,6 +71,12 @@ public class ScopeShapeMonitor { return scopeShapeMonitorMap; } + public void removeScopeShapeByKey(String scopeShapeId){ + if (scopeShapeMonitorMap.containsKey(scopeShapeId)){ + scopeShapeMonitorMap.remove(scopeShapeId); + } + } + /** * 更新范围框的监视属性信息 * @param scopeShapeId 当前范围框图形ID diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Observer.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Observer.java new file mode 100644 index 00000000..9f155474 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Observer.java @@ -0,0 +1,11 @@ +package com.actionsoft.apps.coe.method.process.subprocess.observers; + +/** + * @author oYang + * @Description 观察者接口 + * @createTime 2023年06月16日 09:37:00 + */ +public interface Observer { + + void update(double deltaX, double deltaY); +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Subject.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Subject.java new file mode 100644 index 00000000..123bce26 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/Subject.java @@ -0,0 +1,22 @@ +package com.actionsoft.apps.coe.method.process.subprocess.observers; + +/** + * @author oYang + * @Description 主题接口 + * @createTime 2023年06月16日 09:45:00 + */ +public interface Subject { + + void addRightNodeObserver(Observer o); + + void addBottomNodeObserver(Observer o); + + void removeRightObserver(Observer o); + + void removeBottomObserver(Observer o); + + void notifyRightObservers(double deltaX, double deltaY); + + void notifyBottomObservers(double deltaX, double deltaY); + +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeObserver.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeObserver.java new file mode 100644 index 00000000..8fc5721a --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeObserver.java @@ -0,0 +1,40 @@ +package com.actionsoft.apps.coe.method.process.subprocess.observers.node; + +import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; +import com.actionsoft.apps.coe.method.process.subprocess.mode.ScopeShapeMonitor; +import com.actionsoft.apps.coe.method.process.subprocess.observers.Observer; +import com.alibaba.fastjson.JSONObject; + +/** + * @author oYang + * @Description 画布中除当前操作节点外 其它的节点观察者类 当前的操作节点的宽度与高度发生变化时 其它的观察者节点位置根据增量调整 + * @createTime 2023年06月16日 10:23:00 + */ +public class NodeObserver implements Observer { + + private AbstractDefinitionHandle definitionHandle; + private ScopeShapeMonitor scopeShapeMonitor; // 总图目前已存在的范围框监视模型 + private String nodeKey; // 画布中的节点元素的Id + + public NodeObserver(AbstractDefinitionHandle definitionHandle, ScopeShapeMonitor scopeShapeMonitor, String nodeKey) { + this.definitionHandle = definitionHandle; + this.scopeShapeMonitor = scopeShapeMonitor; + this.nodeKey = nodeKey; + } + + @Override + public void update(double deltaX, double deltaY) { + if (deltaX != 0) { + definitionHandle.updateShapeX(nodeKey, definitionHandle.getShapeX(nodeKey) + deltaX); + if (scopeShapeMonitor.checkShapeIsScopeShape(nodeKey)){ + scopeShapeMonitor.updateMonitorXInfo(nodeKey, true, deltaX); + } + } + if (deltaY != 0) { + definitionHandle.updateShapeY(nodeKey, definitionHandle.getShapeY(nodeKey) + deltaY); + if (scopeShapeMonitor.checkShapeIsScopeShape(nodeKey)){ + scopeShapeMonitor.updateMonitorYInfo(nodeKey, true, deltaY); + } + } + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeSubject.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeSubject.java new file mode 100644 index 00000000..44df489d --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/observers/node/NodeSubject.java @@ -0,0 +1,182 @@ +package com.actionsoft.apps.coe.method.process.subprocess.observers.node; + +import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; +import com.actionsoft.apps.coe.method.process.subprocess.mode.ScopeShapeMonitor; +import com.actionsoft.apps.coe.method.process.subprocess.observers.Observer; +import com.actionsoft.apps.coe.method.process.subprocess.observers.Subject; +import com.alibaba.fastjson.JSONObject; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * @author oYang + * @Description 当前展开或者闭合的操作节点的主题类 + * @createTime 2023年06月16日 10:19:00 + */ +public class NodeSubject implements Subject { + + private AbstractDefinitionHandle definitionHandle; // 总图 define 处理器 + private ScopeShapeMonitor scopeShapeMonitor; // 总图目前已存在的范围框监视模型 + private String scopeShapeId; // 当前展开或者闭合的节点ID + private double scopeX; // 当前展开或者闭合的节点 x + private double scopeY; // 当前展开或者闭合的节点 y + private double scopeW; // 当前展开或者闭合的节点 w + private double scopeH; // 当前展开或者闭合的节点 h + private String action; // expand / close + private List rightObservers = new ArrayList<>(); + private List bottomObservers = new ArrayList<>(); + + public NodeSubject(AbstractDefinitionHandle definitionHandle, ScopeShapeMonitor scopeShapeMonitor, String scopeShapeId, String action) { + this.definitionHandle = definitionHandle; + this.scopeShapeMonitor = scopeShapeMonitor; + this.scopeShapeId = scopeShapeId; + + JSONObject props = this.definitionHandle.getShapeByProps(scopeShapeId); + this.scopeX = props.getDoubleValue("x"); + this.scopeY = props.getDoubleValue("y"); + this.scopeW = props.getDoubleValue("w"); + this.scopeH = props.getDoubleValue("h"); + + this.action = action; + } + + // 构建当前节点的观察者列表 + public void buildObservers(){ + JSONObject elements = definitionHandle.getElements(); + for (String key : elements.keySet()) { + JSONObject ele = elements.getJSONObject(key); + if ("linker".equals(ele.getString("name"))) continue; // 连线不在这处理 + if (key.equals(scopeShapeId)) continue; // 当前被操作的节点 不处理 + if (scopeShapeMonitor.checkShapeIsScopeInRange(key)) continue; // 在已存在的范围框内部的元素不在这处理 + JSONObject props = ele.getJSONObject("props"); + double x = props.getDoubleValue("x"); + double y = props.getDoubleValue("y"); + NodeObserver nodeObserver = new NodeObserver(definitionHandle, scopeShapeMonitor, key); + if (scopeX < x) { + addRightNodeObserver(nodeObserver); + } + if (scopeY < y) { + addBottomNodeObserver(nodeObserver); + } + } + } + + public void setScopeW(double scopeW) { + // 计算 x 方向上的增量 + if ("expand".equals(action)){ // 展开操作 + double colMaxScopeW = getTheSameColMaxScopeW(); + if (scopeW > colMaxScopeW){ + double deltaX = scopeW - colMaxScopeW; + notifyRightObservers(deltaX, 0); + } + }else { // 闭合操作 + double colMaxScopeW = getTheSameColMaxScopeWUnSelf(); + if (this.scopeW > colMaxScopeW) { + double deltaX = colMaxScopeW - this.scopeW; + notifyRightObservers(deltaX, 0); + } + } + } + + public void setScopeH(double scopeH) { + // 计算 y 方向上的增量 + if ("expand".equals(action)){ // 展开操作 + double rowMaxScopeH = getTheSameRowMaxScopeH(); + if (scopeH > rowMaxScopeH){ + double deltaY = scopeH - rowMaxScopeH; + notifyBottomObservers(0, deltaY); + } + }else { // 闭合操作 + double rowMaxScopeH = getTheSameRowMaxScopeHUnSelf(); + if (this.scopeH > rowMaxScopeH) { + double delatY = rowMaxScopeH - this.scopeH; + notifyBottomObservers(0, delatY); + } + } + } + + // 获取当前操作节点同一列节点的最大宽度 + private double getTheSameColMaxScopeW(){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && scopeX == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("w"))) + .orElse(null); + return props.getDoubleValue("w"); + } + + // 获取当前操作节点同一列节点的最大宽度 不包含当前操作节点 + private double getTheSameColMaxScopeWUnSelf(){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !key.equals(scopeShapeId) && !"linker".equals(elements.getJSONObject(key).getString("name")) && scopeX == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("w"))) + .orElse(null); + if (props == null) // 如果为空 说明同一列就一个节点就是当前操作的节点 + return SubProcessConst.SUB_PROCESS_SHAPE_W; + return props.getDoubleValue("w"); + } + + // 获取当前操作节点同一行节点的最大高度 + private double getTheSameRowMaxScopeH(){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && scopeY == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("h"))) + .orElse(null); + return props.getDoubleValue("h"); + } + + // 获取当前操作节点同一行节点的最大高度 不包含当前操作节点 + private double getTheSameRowMaxScopeHUnSelf(){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !key.equals(scopeShapeId) && !"linker".equals(elements.getJSONObject(key).getString("name")) && scopeY == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .map(key -> elements.getJSONObject(key).getJSONObject("props")) + .max(Comparator.comparing(o -> o.getDoubleValue("h"))) + .orElse(null); + if (props == null) + return SubProcessConst.SUB_PROCESS_SHAPE_H; + return props.getDoubleValue("h"); + } + + @Override + public void addRightNodeObserver(Observer o) { + rightObservers.add(o); + } + + @Override + public void addBottomNodeObserver(Observer o) { + bottomObservers.add(o); + } + + @Override + public void removeRightObserver(Observer o) { + rightObservers.remove(o); + } + + @Override + public void removeBottomObserver(Observer o) { + bottomObservers.remove(o); + } + + @Override + public void notifyRightObservers(double deltaX, double deltaY) { + for (Observer observer : rightObservers) { + observer.update(deltaX, deltaY); + } + } + + @Override + public void notifyBottomObservers(double deltaX, double deltaY) { + for (Observer observer : bottomObservers) { + observer.update(deltaX, deltaY); + } + } +}