From 18018f8c7bb12c157e4f8a8a39a931db5ea8549c Mon Sep 17 00:00:00 2001 From: qinoy Date: Fri, 30 Jun 2023 16:53:34 +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=8C=83=E5=9B=B4=E6=A1=86=E5=86=85=E5=A4=96=E5=85=83?= =?UTF-8?q?=E7=B4=A0=20=E8=BF=9E=E7=BA=BF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oft.apps.coe.method.process.subprocess.jar | Bin 88227 -> 99907 bytes .../subprocess/constant/SubProcessConst.java | 19 + ...ExpandOrCloseShapeLinkerConvertHandle.java | 229 +++++++++ .../process/subprocess/graph/GraphLayout.java | 16 +- .../graph/GraphNodeCloseHandle.java | 184 +++---- .../graph/GraphNodeExpandHandle.java | 127 +++-- .../process/subprocess/graph/GraphRender.java | 48 +- .../component/AbstractDefinitionHandle.java | 58 +++ .../graph/util/DefinitionThreadSafe.java | 62 +++ .../graph/util/DefinitionThreadUnSafe.java | 44 ++ .../graph/util/GraphNodeCloseUtil.java | 9 - .../util/LinkerPointCalculationHandle.java | 452 ++++++++++++++++++ .../util}/ScopeShapeMonitor.java | 54 +-- .../graph/util/SubProcessNodeDefineUtil.java | 5 + .../observers/node/NodeObserver.java | 3 +- .../observers/node/NodeSubject.java | 2 +- .../method/process/subprocess/uitl/Node.java | 22 - .../subprocess/uitl/UtilTestGraph.java | 113 ----- .../process/subprocess/web/SubProcessWeb.java | 4 + 19 files changed, 1066 insertions(+), 385 deletions(-) create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ExpandOrCloseShapeLinkerConvertHandle.java delete mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/GraphNodeCloseUtil.java create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/LinkerPointCalculationHandle.java rename com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/{mode => graph/util}/ScopeShapeMonitor.java (80%) delete mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java delete mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.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 3b6cf9827d46aa1562fab8eb7954203dec471dca..74f9ac779bfcb89303ab75790ae57973d2fcb046 100644 GIT binary patch delta 73662 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�O~~ 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 diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java index b2d0510c..d3c81f2d 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java @@ -38,4 +38,23 @@ public interface SubProcessConst { // 范围选择框内边距 double SCOPE_SHAPE_PADDING = 300; + + // 子流程节点上扩展的属性名 用来存储当前子流程节点标识的模型文件信息 + String EXTEND_ATTR = "extendAttr"; + + // 节点展开时 范围框上扩镇的属性名 用来存储自身内部元素 + String INNER_ELEMENTS = "innerElements"; + + // 流程接口图形的唯一标识 + String SHAPE_NAME_PROCEDURE = "procedure"; + + // 范围框 内部前置或者后置流程接口元素 的特殊属性名 + String SHAPE_PROCEDURE_ATTR_MARK = "attrMark"; + + // 水平布局 + String DIRECTION_H = "horizontal"; + + // 垂直布局 + String DIRECTION_V = "vertically"; + } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ExpandOrCloseShapeLinkerConvertHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ExpandOrCloseShapeLinkerConvertHandle.java new file mode 100644 index 00000000..09df5bb8 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ExpandOrCloseShapeLinkerConvertHandle.java @@ -0,0 +1,229 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph; + +import com.actionsoft.apps.coe.method.process.subprocess.constant.ElementType; +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.graph.util.LinkerPointCalculationHandle; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author oYang + * @Description 端到端总图 连线后置处理 + * 针对展开或者闭合节点上的连线进行后置处理 + * 此时总图的状态是节点展开或者闭合已经处理 + * 展开的话连线此时是连在了范围框上 此处处理的是将范围框上的连线连到内部节点上(如果此节点存在的话) + * 闭合的话连线此时是连在了范围框的内部节点上(也有可能是在范围框上 范围框上不处理) 此处处理的是将内部节点的连线连到闭合后的子流程节点上 + * @createTime 2023年06月28日 13:47:00 + */ +public class ExpandOrCloseShapeLinkerConvertHandle { + + private AbstractDefinitionHandle definitionHandle; // 总图的存储模型define处理器 + private LinkerPointCalculationHandle linkerPointCalculationHandle; // 连线上起始点以及折点处理器 + private String direction; // 当前布局方式 + + public ExpandOrCloseShapeLinkerConvertHandle(AbstractDefinitionHandle definitionHandle) { + this.definitionHandle = definitionHandle; + + this.linkerPointCalculationHandle = new LinkerPointCalculationHandle(definitionHandle); + + JSONObject processProperties = definitionHandle.getProcessProperties(); + this.direction = processProperties.getString("direction"); + } + + + public void scopeShapeLinkerHandle(){ + + Set scopeShapeIds = definitionHandle.getElements().keySet().stream().filter(key -> definitionHandle.getElementTypeByKey(key).name().equals(ElementType.SCOPE_NODE.name())).collect(Collectors.toSet()); + if (scopeShapeIds.size() > 0){ + for (String shapeId : scopeShapeIds) { + // 1、准备当前展开的子流程节点的前置连线与后置连线 + JSONArray linkers = definitionHandle.getLinkers(); + // 2、准备当前展开的子流程节点的内部元素中的流程接口 其中代表前置/后置流程文件属性的流程接口上会有 attrMark 属性 + JSONObject scopeShape = definitionHandle.getShapeByKey(shapeId); + JSONArray innerEleKeyArr = scopeShape.getJSONArray(SubProcessConst.INNER_ELEMENTS); + // 获取当前范围框 内部前置或者后置流程接口元素集合 + JSONArray procedureArr = innerEleKeyArr + .stream() + .filter(innerEleKey -> definitionHandle.getElementTypeByKey(innerEleKey.toString()).name().equals(ElementType.INNER_NODE.name())) + .filter(innerEleKey -> SubProcessConst.SHAPE_NAME_PROCEDURE.equals(definitionHandle.getShapeByKey(innerEleKey.toString()).getString("name"))) + .filter(innerEleKey -> definitionHandle.getShapeByKey(innerEleKey.toString()).containsKey(SubProcessConst.SHAPE_PROCEDURE_ATTR_MARK)) + .map(innerEleKey -> definitionHandle.getShapeByKey(innerEleKey.toString())) + .collect(Collectors.toCollection(JSONArray::new)); + + // 3、找到当前节点的所有前置连线 + JSONArray leadNodeLinkers = linkers + .stream() + .filter(l -> shapeId.equals(((JSONObject) l).getJSONObject("to").getString("id"))) + .collect(Collectors.toCollection(JSONArray::new)); + // 3.1、判断当前展开的子流程节点的内部元素中的流程接口上的文件标识 是否存在 前置子流程节点所代表的子流程文件 如果有将当前前置连线转为 与内部流程接口相连 + for (Object o1 : leadNodeLinkers) { + JSONObject leadNodeLinker = (JSONObject) o1; + String leadNodeId = leadNodeLinker.getJSONObject("from").getString("id"); + ElementType leadNodeType = definitionHandle.getElementTypeByKey(leadNodeId); + JSONObject leadNode = definitionHandle.getShapeByKey(leadNodeId); + if (procedureArr.size() > 0){ // 范围框内部存在前置或者后置流程接口 + // 判断当前前置节点的类型 如果未展开 继续判断内部节点是否与其有关联 如果有重新渲染连线 没有不处理 + if (leadNodeType.name().equals(ElementType.OUTER_NODE.name()) || leadNodeType.name().equals(ElementType.SCOPE_NODE.name())){ + // 获取前置节点的扩展属性 + JSONObject extendAttr = leadNode.getJSONObject(SubProcessConst.EXTEND_ATTR); + // 当前前置节点 所代表的子流程文件ID + String leadNodeRelationId = extendAttr.getString("id"); + // 1、未展开 子流程节点 + // 2、此时前置节点为范围框 同时说明之前范围框内部没有节点与当前节点有关联关系 + // 判断当前节点内部是否有流程接口 与范围框有关联关系 因为范围框本身也是一个文件 + for (Object o2 : procedureArr) { + JSONObject procedure = (JSONObject) o2; + JSONObject attrMark = procedure.getJSONObject(SubProcessConst.SHAPE_PROCEDURE_ATTR_MARK); + String procedureNodeRelationId = attrMark.getString("id"); + if (leadNodeRelationId.equals(procedureNodeRelationId)){ // 前置节点与内部流程接口有关联关系 + // 删除当前 前置节点与范围框上的连线 + definitionHandle.removeShape(leadNodeLinker.getString("id")); + // 重新渲染当前 前置节点与范围框的连线 + String procedureId = procedure.getString("id"); + double[] fromBounding = new double[]{definitionHandle.getShapeX(leadNodeId), definitionHandle.getShapeY(leadNodeId), definitionHandle.getShapeW(leadNodeId), definitionHandle.getShapeH(leadNodeId)}; + double[] toBounding = new double[]{definitionHandle.getShapeX(procedureId), definitionHandle.getShapeY(procedureId), definitionHandle.getShapeW(procedureId), definitionHandle.getShapeH(procedureId)}; + JSONObject linker = linkerPointCalculationHandle.toAssembleLinker(direction, leadNodeId, procedureId, fromBounding, toBounding); + // 连线属于内外交叉连线 加个特殊标识属性 + linker.put("elementType", ElementType.CROSS_LINKER.name()); + definitionHandle.addEle(linker.getString("id"), linker); + break; + } + } + }else { // 已展开 内部节点 + // 此时前置节点为某一个范围框的内部节点 找到当前内部节点归属哪个范围框 判断当前范围框是否与当前展开的内部流程接口有关联 + String scopeShapeId = leadNode.getString("scopeShapeId"); + for (Object o2 : procedureArr) { + JSONObject procedure = (JSONObject) o2; + JSONObject attrMark = procedure.getJSONObject(SubProcessConst.SHAPE_PROCEDURE_ATTR_MARK); + String procedureNodeRelationId = attrMark.getString("id"); + if (procedureNodeRelationId.equals(scopeShapeId)){ // 前置内部节点所在的范围框 与 内部流程接口有关联关系 + String procedureId = procedure.getString("id"); + double[] fromBounding = new double[]{definitionHandle.getShapeX(scopeShapeId), definitionHandle.getShapeY(scopeShapeId), definitionHandle.getShapeW(scopeShapeId), definitionHandle.getShapeH(scopeShapeId)}; + double[] toBounding = new double[]{definitionHandle.getShapeX(procedureId), definitionHandle.getShapeY(procedureId), definitionHandle.getShapeW(procedureId), definitionHandle.getShapeH(procedureId)}; + JSONObject linker = linkerPointCalculationHandle.toAssembleLinker(direction, scopeShapeId, procedureId, fromBounding, toBounding); + // 连线属于内外交叉连线 加个特殊标识属性 + linker.put("elementType", ElementType.CROSS_LINKER.name()); + definitionHandle.addEle(linker.getString("id"), linker); + break; + } + } + } + } + } + // 4、根据后置连线找到后置子流程节点 + JSONArray rearNodeLinkers = linkers + .stream() + .filter(l -> shapeId.equals(((JSONObject) l).getJSONObject("from").getString("id"))) + .collect(Collectors.toCollection(JSONArray::new)); + // 4.1、同3.1 + for (Object o1 : rearNodeLinkers) { + JSONObject rearNodeLinker = (JSONObject) o1; + String rearNodeId = rearNodeLinker.getJSONObject("to").getString("id"); + ElementType rearNodeType = definitionHandle.getElementTypeByKey(rearNodeId); + JSONObject rearNode = definitionHandle.getShapeByKey(rearNodeId); + if (procedureArr.size() > 0){ // 范围框内部存在前置或者后置流程接口 + if (rearNodeType.name().equals(ElementType.OUTER_NODE.name()) || rearNodeType.name().equals(ElementType.SCOPE_NODE.name())){ + JSONObject extendAttr = rearNode.getJSONObject(SubProcessConst.EXTEND_ATTR); + // 当前后置节点 所代表的子流程文件ID + String rearNodeRelationId = extendAttr.getString("id"); + for (Object o2 : procedureArr) { + JSONObject procedure = (JSONObject) o2; + JSONObject attrMark = procedure.getJSONObject(SubProcessConst.SHAPE_PROCEDURE_ATTR_MARK); + String procedureNodeRelationId = attrMark.getString("id"); + if (rearNodeRelationId.equals(procedureNodeRelationId)){ // 后置节点与内部流程接口有关联关系 + definitionHandle.removeShape(rearNodeLinker.getString("id")); + // 重新渲染当前 前置节点与范围框的连线 + String procedureId = procedure.getString("id"); + double[] fromBounding = new double[]{definitionHandle.getShapeX(procedureId), definitionHandle.getShapeY(procedureId), definitionHandle.getShapeW(procedureId), definitionHandle.getShapeH(procedureId)}; + double[] toBounding = new double[]{definitionHandle.getShapeX(rearNodeId), definitionHandle.getShapeY(rearNodeId), definitionHandle.getShapeW(rearNodeId), definitionHandle.getShapeH(rearNodeId)}; + JSONObject linker = linkerPointCalculationHandle.toAssembleLinker(direction, procedureId, rearNodeId, fromBounding, toBounding); + // 连线属于内外交叉连线 加个特殊标识属性 + linker.put("elementType", ElementType.CROSS_LINKER.name()); + definitionHandle.addEle(linker.getString("id"), linker); + break; + } + } + }else { + // 此时后置节点为某一个范围框的内部节点 找到当前内部节点归属哪个范围框 判断当前范围框是否与当前展开的内部流程接口有关联 + String scopeShapeId = rearNode.getString("scopeShapeId"); + for (Object o2 : procedureArr) { + JSONObject procedure = (JSONObject) o2; + JSONObject attrMark = procedure.getJSONObject(SubProcessConst.SHAPE_PROCEDURE_ATTR_MARK); + String procedureNodeRelationId = attrMark.getString("id"); + if (procedureNodeRelationId.equals(scopeShapeId)){ // 前置内部节点所在的范围框 与 内部流程接口有关联关系 + String procedureId = procedure.getString("id"); + double[] fromBounding = new double[]{definitionHandle.getShapeX(procedureId), definitionHandle.getShapeY(procedureId), definitionHandle.getShapeW(procedureId), definitionHandle.getShapeH(procedureId)}; + double[] toBounding = new double[]{definitionHandle.getShapeX(scopeShapeId), definitionHandle.getShapeY(scopeShapeId), definitionHandle.getShapeW(scopeShapeId), definitionHandle.getShapeH(scopeShapeId)}; + JSONObject linker = linkerPointCalculationHandle.toAssembleLinker(direction, procedureId, scopeShapeId, fromBounding, toBounding); + // 连线属于内外交叉连线 加个特殊标识属性 + linker.put("elementType", ElementType.CROSS_LINKER.name()); + definitionHandle.addEle(linker.getString("id"), linker); + break; + } + } + } + } + } + } + } + } + + /** + * 针对闭合的节点相关连线 后置处理 + */ + public void closeShapeLinkerConvertHandle(){ +// JSONObject subProcessNode = definitionHandle.getShapeByKey(shapeId); +// JSONObject extendAttr = subProcessNode.getJSONObject(SubProcessConst.EXTEND_ATTR); +// JSONArray linkers = definitionHandle.getLinkers(); +// // 当前节点的前置节点 +// JSONArray leadNodeArr = extendAttr.getJSONArray("leadNodeArr"); +// if (leadNodeArr.size() > 0){ +// for (Object o : leadNodeArr) { +// String leadNodeId = (String) o; +// Set linkerIds = linkers.stream() +// .filter(l -> ((JSONObject) l).getJSONObject("from").getString("id").equals(leadNodeId) && ((JSONObject) l).getJSONObject("to").getString("id").equals(shapeId)) +// .map(l -> ((JSONObject) l).getString("id")) +// .collect(Collectors.toSet()); +// if (linkerIds.size() > 0){ +// for (String linkerId : linkerIds) { +// definitionHandle.removeShape(linkerId); +// } +// } +// // 生成连线 +// double[] fromBounding = new double[]{definitionHandle.getShapeX(leadNodeId), definitionHandle.getShapeY(leadNodeId), definitionHandle.getShapeW(leadNodeId), definitionHandle.getShapeH(leadNodeId)}; +// double[] toBounding = new double[]{definitionHandle.getShapeX(shapeId), definitionHandle.getShapeY(shapeId), definitionHandle.getShapeW(shapeId), definitionHandle.getShapeH(shapeId)}; +// JSONObject linker = linkerPointCalculationHandle.toAssembleLinker(direction, leadNodeId, shapeId, fromBounding, toBounding); +// +// linker.put("elementType", ElementType.OUTER_LINKER.name()); +// definitionHandle.addEle(linker.getString("id"), linker); +// } +// } +// // 当前节点的后置节点 +// JSONArray rearNodeArr = extendAttr.getJSONArray("rearNodeArr"); +// if (rearNodeArr.size() > 0){ +// for (Object o : rearNodeArr) { +// String rearNodeId = (String) o; +// Set linkerIds = linkers.stream() +// .filter(l -> ((JSONObject) l).getJSONObject("from").getString("id").equals(shapeId) && ((JSONObject) l).getJSONObject("to").getString("id").equals(rearNodeId)) +// .map(l -> ((JSONObject) l).getString("id")) +// .collect(Collectors.toSet()); +// if (linkerIds.size() > 0){ +// for (String linkerId : linkerIds) { +// definitionHandle.removeShape(linkerId); +// } +// } +// // 生成连线 +// double[] fromBounding = new double[]{definitionHandle.getShapeX(shapeId), definitionHandle.getShapeY(shapeId), definitionHandle.getShapeW(shapeId), definitionHandle.getShapeH(shapeId)}; +// double[] toBounding = new double[]{definitionHandle.getShapeX(rearNodeId), definitionHandle.getShapeY(rearNodeId), definitionHandle.getShapeW(rearNodeId), definitionHandle.getShapeH(rearNodeId)}; +// JSONObject linker = linkerPointCalculationHandle.toAssembleLinker(direction, shapeId, rearNodeId, fromBounding, toBounding); +// +// linker.put("elementType", ElementType.OUTER_LINKER.name()); +// definitionHandle.addEle(linker.getString("id"), linker); +// } +// } + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLayout.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLayout.java index 7dc87313..feb351a8 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLayout.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLayout.java @@ -130,10 +130,10 @@ public class GraphLayout { this.canvasHeight = h + 200.0; // 打印节点坐标与画布大小 - System.out.printf("画布(%.2f, %.2f)", canvasWidth, canvasHeight); - for (int i = 0; i < position.length; i++) { - System.out.printf("坐标(%.2f, %.2f)", position[i][0], position[i][1]); - } + // System.out.printf("画布(%.2f, %.2f)", canvasWidth, canvasHeight); + // for (int i = 0; i < position.length; i++) { + // System.out.printf("坐标(%.2f, %.2f)", position[i][0], position[i][1]); + // } return position; } @@ -205,10 +205,10 @@ public class GraphLayout { this.canvasHeight = h + 200.0; // 打印节点坐标与画布大小 - System.out.printf("画布(%.2f, %.2f)", canvasWidth, canvasHeight); - for (int i = 0; i < position.length; i++) { - System.out.printf("坐标(%.2f, %.2f)", position[i][0], position[i][1]); - } + // System.out.printf("画布(%.2f, %.2f)", canvasWidth, canvasHeight); + // for (int i = 0; i < position.length; i++) { + // System.out.printf("坐标(%.2f, %.2f)", position[i][0], position[i][1]); + // } return position; } 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 60c07541..ef3e9559 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,23 +7,19 @@ import com.actionsoft.apps.coe.method.process.subprocess.graph.component.Abstrac import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; 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.graph.util.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; -import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.cache.DesignerShapeRelationCache; -import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; import com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil; import com.actionsoft.bpms.util.ConsolePrinter; import com.actionsoft.bpms.util.UUIDGener; -import com.actionsoft.bpms.util.UtilString; import com.actionsoft.exception.AWSException; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.util.*; -import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; /** * 图节点关闭处理 @@ -40,6 +36,8 @@ public class GraphNodeCloseHandle { private ScopeShapeMonitor scopeShapeMonitor; // 范围选择框及其内部元素监视器 private NodeSubject nodeSubject; // 当前操作的节点主题类 + private ExpandOrCloseShapeLinkerConvertHandle linkerConvertHandle; // 范围框内元素与外部元素连线处理器 + public GraphNodeCloseHandle(String repositoryId, String shapeId, String endToEndProcessDefineStr) throws AWSException{ this.repositoryId = repositoryId; this.shapeId = shapeId; @@ -62,6 +60,8 @@ public class GraphNodeCloseHandle { nodeSubject = new NodeSubject(definitionHandle, scopeShapeMonitor, shapeId, "close"); nodeSubject.buildObservers(); + linkerConvertHandle = new ExpandOrCloseShapeLinkerConvertHandle(definitionHandle); + } catch (AWSException e) { throw new AWSException(e); } @@ -74,15 +74,19 @@ public class GraphNodeCloseHandle { */ public String handleNodeClose() throws AWSException { + // 删除现有连线 + removeEndToEndGraphOldLinker(); - // 1、处理范围选择框及其内部节点 + // 处理范围选择框及其内部节点 removeScopeShapeAndInRangeEle(); - // 2、处理总图中的节点与连线 + // 处理总图中的节点与连线 handleEndToEndGraphNodeAndLinker(); scopeShapeMonitor.updateScopeShapeInnerEle(); + linkerConvertHandle.scopeShapeLinkerHandle(); + return definitionHandle.getDefine().toJSONString(); } @@ -91,22 +95,27 @@ public class GraphNodeCloseHandle { JSONObject subProcessNode = buildSubProcessNode(shapeId, scopeLimitationShape); definitionHandle.addEle(shapeId, subProcessNode); + // 范围框闭合 将扩展属性复制到新的子流程节点上 + subProcessNode.put(SubProcessConst.EXTEND_ATTR, scopeLimitationShape.getJSONObject(SubProcessConst.EXTEND_ATTR)); + // 通知其它节点位置更新 nodeSubject.setScopeW(subProcessNode.getJSONObject("props").getDoubleValue("w")); nodeSubject.setScopeH(subProcessNode.getJSONObject("props").getDoubleValue("h")); // 2、根据现有连线关系创建邻接矩阵 - NodeCloseAdjMatrix closeAdjMatrix = buildEndToEndGraphAdjMatrix(); + JSONObject elements = definitionHandle.getElements(); + List nodeList = elements.keySet().stream() + .filter(key -> definitionHandle.getElementTypeByKey(key).name().equals(ElementType.OUTER_NODE.name()) || definitionHandle.getElementTypeByKey(key).name().equals(ElementType.SCOPE_NODE.name())) + .map(key -> definitionHandle.getShapeByKey(key)) + .collect(Collectors.toList()); + NodeCloseAdjMatrix closeAdjMatrix = new NodeCloseAdjMatrix(nodeList); closeAdjMatrix.buildAdjMatrix(); - JSONObject elements = definitionHandle.getElements(); // 更新因节点展开后 坐标发生变化的节点坐标 String direction = definitionHandle.getProcessProperties().getString("direction"); - // graphPartNodePoiRenderAgain(elements, direction, subProcessNode); // 3、收集现有元素坐标 double[][] vertexBounding = closeAdjMatrix.getVertexBounding(elements); - // 4、删除现有连线 - removeEndToEndGraphOldLinker(); + // 5、构建新的连线 NodeCloseLinkerRender linkerRender = new NodeCloseLinkerRender(vertexBounding, closeAdjMatrix, definitionHandle); JSONArray linkers = linkerRender.toAssembleLinker(direction); @@ -126,76 +135,6 @@ public class GraphNodeCloseHandle { page.put("height", h + 300); } - /** - * 节点闭合 部分节点坐标再次更新 - */ - private void graphPartNodePoiRenderAgain(JSONObject elements, String direction, JSONObject subProcessNode){ - // 闭合节点的位置 及大小 - JSONObject props = subProcessNode.getJSONObject("props"); - double x = props.getDoubleValue("x"); - double y = props.getDoubleValue("y"); - - // 当前关闭的节点范围标识框的位置与大小 - double[] scope = SubProcessNodeDefineUtil.calculateSubProcessNodeExpandScope(subProcessNodeDefineHandle); - - // double[] scopeShapeBounding = new double[]{x, y, scope[2], scope[3]}; - - // boolean yIsMove = checkShapeYIsMove(elements, scopeShapeBounding); - - for (String key : elements.keySet()) { - JSONObject ele = elements.getJSONObject(key); - if ("linker".equals(ele.getString("name"))) continue; - if (ele.getString("id").equals(subProcessNode.getString("id"))) continue; - if (scopeShapeMonitor.checkShapeIsScopeInRange(key)) continue; - JSONObject eleProps = ele.getJSONObject("props"); - if ("vertically".equals(direction)){ // 垂直布局 - if (x + scope[2] < eleProps.getDoubleValue("x")) { - double xMoveDistance = -scope[2] + SubProcessConst.SUB_PROCESS_SHAPE_W; - eleProps.put("x", eleProps.getDoubleValue("x") - scope[2] + SubProcessConst.SUB_PROCESS_SHAPE_W); - if (scopeShapeMonitor.checkShapeIsScopeShape(key)){ - scopeShapeMonitor.updateMonitorXInfo(key, true, xMoveDistance); - } - } - if (y +scope[3] < eleProps.getDoubleValue("y")){ - double yMoveDistance = -scope[3] + SubProcessConst.SUB_PROCESS_SHAPE_H; - eleProps.put("y", eleProps.getDoubleValue("y") - scope[3] + SubProcessConst.SUB_PROCESS_SHAPE_H); - if (scopeShapeMonitor.checkShapeIsScopeShape(key)){ - scopeShapeMonitor.updateMonitorYInfo(key, true, yMoveDistance); - } - }else if (y < eleProps.getDoubleValue("y") && eleProps.getDoubleValue("y") < y + scope[3]){ - eleProps.put("y", y); - double yMoveDistance = y - eleProps.getDoubleValue("y"); - if (scopeShapeMonitor.checkShapeIsScopeShape(key)){ - scopeShapeMonitor.updateMonitorYInfo(key, true, yMoveDistance); - } - } - }else { // 横向布局 - if (x + scope[2] < eleProps.getDoubleValue("x")){ // 节点在范围框右侧的节点 - double xMoveDistance = -scope[2] + SubProcessConst.SUB_PROCESS_SHAPE_W; - eleProps.put("x", eleProps.getDoubleValue("x") - scope[2] + SubProcessConst.SUB_PROCESS_SHAPE_W); - if (scopeShapeMonitor.checkShapeIsScopeShape(key)){ - scopeShapeMonitor.updateMonitorXInfo(key, true, xMoveDistance); - } - }else if (x < eleProps.getDoubleValue("x") - && eleProps.getDoubleValue("x") < x + scope[2] - && y + scope[3] < eleProps.getDoubleValue("y")){ - double xMoveDistance = x - eleProps.getDoubleValue("x"); - eleProps.put("x", x); - if (scopeShapeMonitor.checkShapeIsScopeShape(key)){ - scopeShapeMonitor.updateMonitorXInfo(key, true, xMoveDistance); - } - } - if (y + scope[3] < eleProps.getDoubleValue("y")){ // 节点在范围框下方的节点 - double yMoveDistance = -scope[3] + SubProcessConst.SUB_PROCESS_SHAPE_H; - eleProps.put("y", eleProps.getDoubleValue("y") - scope[3] + SubProcessConst.SUB_PROCESS_SHAPE_H); - if (scopeShapeMonitor.checkShapeIsScopeShape(key)){ - scopeShapeMonitor.updateMonitorYInfo(key, true, yMoveDistance); - } - } - } - } - } - /** * 在节点闭合的时候 检查当前闭合的节点的下方节点是否需要上下移动 * @param elements @@ -251,41 +190,15 @@ public class GraphNodeCloseHandle { */ private void removeEndToEndGraphOldLinker(){ JSONObject elements = definitionHandle.getElements(); - Set eleKeys = new HashSet<>(); - for (String key : elements.keySet()) { - JSONObject ele = elements.getJSONObject(key); - if ("linker".equals(ele.getString("name")) && !scopeShapeMonitor.checkShapeIsScopeInRange(key)){ - eleKeys.add(key); - } - } - for (String eleKey : eleKeys) { + Set linkerIds = elements.keySet() + .stream() + .filter(key -> definitionHandle.getElementTypeByKey(key).equals(ElementType.OUTER_LINKER) || definitionHandle.getElementTypeByKey(key).equals(ElementType.CROSS_LINKER)) + .collect(Collectors.toSet()); + for (String eleKey : linkerIds) { definitionHandle.removeShape(eleKey); } } - - /** - * 构建节点展开前 端到端总图的邻接矩阵 - * 方便后续节点展开或者闭合进行重新连线 - */ - private NodeCloseAdjMatrix buildEndToEndGraphAdjMatrix(){ - - List nodeIdList = new ArrayList<>(); - List linkerList = new ArrayList<>(); - JSONObject endToEndProcessElements = definitionHandle.getElements(); - for (String key : endToEndProcessElements.keySet()) { - if (scopeShapeMonitor.checkShapeIsScopeInRange(key)) continue; - JSONObject ele = endToEndProcessElements.getJSONObject(key); - if ("linker".equals(ele.getString("name"))) { - linkerList.add(ele); - }else { - nodeIdList.add(key); - } - } - NodeCloseAdjMatrix closeAdjMatrix = new NodeCloseAdjMatrix(nodeIdList, linkerList); - return closeAdjMatrix; - } - /** * 构建子流程节点 * @param shapeId @@ -312,7 +225,8 @@ public class GraphNodeCloseHandle { */ private void removeScopeShapeAndInRangeEle(){ - Set keys = SubProcessNodeDefineUtil.getInScopeLimitationRangeEles(shapeId, definitionHandle, subProcessNodeDefineHandle); + JSONArray innerEleKeySet = scopeLimitationShape.getJSONArray(SubProcessConst.INNER_ELEMENTS); + Set keys = innerEleKeySet.stream().map(o -> o.toString()).collect(Collectors.toSet()); for (String key : keys) { definitionHandle.removeShape(key); } @@ -329,32 +243,42 @@ public class GraphNodeCloseHandle { class NodeCloseAdjMatrix extends AbstractAdjMatrix { private List nodeIds; - private List linkerList; + private List nodeList; // 当前画布中所有子流程节点以及范围框节点 不包含内部节点与连线 - public NodeCloseAdjMatrix(List nodeIds, List linkerList) { - super(nodeIds.size()); - this.nodeIds = nodeIds; - this.linkerList = linkerList; + public NodeCloseAdjMatrix(List nodeList) { + super(nodeList.size()); + this.nodeList = nodeList; + + this.nodeIds = nodeList.stream().map(o -> o.getString("id")).collect(Collectors.toList()); } public List getNodeIds() { return nodeIds; } - public List getLinkerList() { - return linkerList; - } - /** * 构建邻接矩阵 */ public void buildAdjMatrix(){ - for (JSONObject linker : linkerList) { - JSONObject from = linker.getJSONObject("from"); - JSONObject to = linker.getJSONObject("to"); - int fromIndex = nodeIds.indexOf(from.getString("id")); - int toIndex = nodeIds.indexOf(to.getString("id")); - addEdge(fromIndex, toIndex); + for (JSONObject node : nodeList) { + String currentNodeId = node.getString("id"); + JSONObject extendAttr = node.getJSONObject(SubProcessConst.EXTEND_ATTR); + // 当前节点的前置节点 + JSONArray leadNodeArr = extendAttr.getJSONArray("leadNodeArr"); + if (leadNodeArr.size() > 0){ + for (Object o : leadNodeArr) { + String leadNodeId = (String) o; + addEdge(nodeIds.indexOf(leadNodeId), nodeIds.indexOf(currentNodeId)); + } + } + // 当前节点的后置节点 + JSONArray rearNodeArr = extendAttr.getJSONArray("rearNodeArr"); + if (rearNodeArr.size() > 0){ + for (Object o : rearNodeArr) { + String rearNodeId = (String) o; + addEdge(nodeIds.indexOf(currentNodeId), nodeIds.indexOf(rearNodeId)); + } + } } } 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 7f04417a..10ec4f51 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 @@ -7,25 +7,20 @@ import com.actionsoft.apps.coe.method.process.subprocess.graph.component.Abstrac import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; 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.Node; -import com.actionsoft.apps.coe.method.process.subprocess.mode.ScopeShapeMonitor; +import com.actionsoft.apps.coe.method.process.subprocess.graph.util.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; -import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.cache.DesignerShapeRelationCache; -import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; -import com.actionsoft.apps.coe.pal.pal.repository.designer.util.CoeDesignerUtil; import com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil; import com.actionsoft.bpms.util.ConsolePrinter; import com.actionsoft.bpms.util.UUIDGener; -import com.actionsoft.bpms.util.UtilString; import com.actionsoft.exception.AWSException; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.util.*; -import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; /** * 图节点展开处理 @@ -42,6 +37,8 @@ public class GraphNodeExpandHandle { private ScopeShapeMonitor scopeShapeMonitor; // 范围选择框及其内部元素监视器 private NodeSubject nodeSubject; // 当前操作的节点主题类 + private ExpandOrCloseShapeLinkerConvertHandle linkerConvertHandle; // 范围框内元素与外部元素连线处理器 + private double[] scopeLimitationShapeBeforePoi; // 范围选择框在子流程文件中的坐标 public GraphNodeExpandHandle(String repositoryId, String shapeId, String endToEndProcessDefineStr) throws AWSException{ @@ -58,12 +55,13 @@ 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(); + linkerConvertHandle = new ExpandOrCloseShapeLinkerConvertHandle(definitionHandle); + toAssembleScopeLimitationShape(); } catch (Exception e) { throw new AWSException(e); @@ -113,6 +111,9 @@ public class GraphNodeExpandHandle { minRange.put("y2", y + scope[3]); scopeLimitationShape.put("minRange", minRange); + // 扩展属性 extendAttr 存储的是关联的文件信息 + scopeLimitationShape.put(SubProcessConst.EXTEND_ATTR, currentExpandShape.getJSONObject(SubProcessConst.EXTEND_ATTR)); + this.scopeLimitationShape = scopeLimitationShape; // 通知其它节点位置更新 @@ -128,15 +129,17 @@ public class GraphNodeExpandHandle { */ public String handleNodeExpand() throws AWSException{ - // 2、总图节点以及连线处理 + // 总图节点以及连线处理 handleEndToEndGraphNodeAndLinker(); - // 3、当前展开的子流程节点内部元素 以及 范围框处理 + // 当前展开的子流程节点内部元素 以及 范围框处理 handleRelationModelNodePosition(); - // 4、范围框内的元素 坐标更新 + // 当前节点展开前已存在的其它范围框内的元素 坐标更新 scopeShapeMonitor.updateScopeShapeInnerEle(); + linkerConvertHandle.scopeShapeLinkerHandle(); + return definitionHandle.getDefine().toJSONString(); } @@ -157,17 +160,20 @@ public class GraphNodeExpandHandle { // 2、添加到总图中 definitionHandle.addEle(shapeId, scopeLimitationShape); - // 3、总图中符合范围选择框条件的节点 坐标更新 - // handleEndToEndGraphNodeExcluedExpandNode(); - - // 4、构建邻接矩阵 - NodeExpandAdjMatrix expandAdjMatrix = buildEndToEndGraphAdjMatrix(); - expandAdjMatrix.buildAdjMatrix(); - // expandAdjMatrix.printAdjMatrix(); // 5、删除节点展开前的连线 removeEndToEndGraphOldLinker(); - // 6、获取所有节点坐标 + + // 4、构建邻接矩阵 JSONObject elements = definitionHandle.getElements(); + List nodeList = elements.keySet().stream() + .filter(key -> definitionHandle.getElementTypeByKey(key).name().equals(ElementType.OUTER_NODE.name()) || definitionHandle.getElementTypeByKey(key).name().equals(ElementType.SCOPE_NODE.name())) + .map(key -> definitionHandle.getShapeByKey(key)) + .collect(Collectors.toList()); + NodeExpandAdjMatrix expandAdjMatrix = new NodeExpandAdjMatrix(nodeList); + + expandAdjMatrix.buildAdjMatrix(); + + // 6、获取所有节点坐标 double[][] vertexBounding = expandAdjMatrix.getVertexBounding(elements); // 7、构建新的连线 JSONObject processProperties = definitionHandle.getProcessProperties(); @@ -204,6 +210,7 @@ public class GraphNodeExpandHandle { // 根据范围标注框的坐标 调整子流程所有元素的坐标 JSONObject elements = subProcessNodeDefineHandle.getElements(); + JSONArray innerEleKeyArr = new JSONArray(); for (String key : elements.keySet()) { JSONObject ele = elements.getJSONObject(key); // 元素分为两类 一类为图形 一类为连线 @@ -231,8 +238,15 @@ public class GraphNodeExpandHandle { ele.put("elementType", ElementType.INNER_NODE.name()); } + // 指向范围框 + ele.put("scopeShapeId", scopeLimitationShape.getString("id")); + + // 存入内部元素 + innerEleKeyArr.add(key); + definitionHandle.addEle(key, ele); } + scopeLimitationShape.put(SubProcessConst.INNER_ELEMENTS, innerEleKeyArr); } /** @@ -324,41 +338,16 @@ public class GraphNodeExpandHandle { } - /** - * 构建节点展开前 端到端总图的邻接矩阵 - * 方便后续节点展开或者闭合进行重新连线 - */ - private NodeExpandAdjMatrix buildEndToEndGraphAdjMatrix(){ - - List nodeIdList = new ArrayList<>(); - List linkerList = new ArrayList<>(); - JSONObject endToEndProcessElements = definitionHandle.getElements(); - for (String key : endToEndProcessElements.keySet()) { - if (scopeShapeMonitor.checkShapeIsScopeInRange(key)) continue; // 范围框内的元素 暂不处理 - JSONObject ele = endToEndProcessElements.getJSONObject(key); - if ("linker".equals(ele.getString("name"))) { - linkerList.add(ele); - }else { - nodeIdList.add(key); - } - } - NodeExpandAdjMatrix expandAdjMatrix = new NodeExpandAdjMatrix(nodeIdList, linkerList); - return expandAdjMatrix; - } - /** * 删除总图中节点展开前的连线 */ private void removeEndToEndGraphOldLinker(){ JSONObject elements = definitionHandle.getElements(); - Set eleKeys = new HashSet<>(); - for (String key : elements.keySet()) { - JSONObject ele = elements.getJSONObject(key); - if ("linker".equals(ele.getString("name")) && !scopeShapeMonitor.checkShapeIsScopeInRange(key)){ - eleKeys.add(key); - } - } - for (String eleKey : eleKeys) { + Set linkerIds = elements.keySet() + .stream() + .filter(key -> definitionHandle.getElementTypeByKey(key).equals(ElementType.OUTER_LINKER) || definitionHandle.getElementTypeByKey(key).equals(ElementType.CROSS_LINKER)) + .collect(Collectors.toSet()); + for (String eleKey : linkerIds) { definitionHandle.removeShape(eleKey); } } @@ -380,32 +369,42 @@ public class GraphNodeExpandHandle { class NodeExpandAdjMatrix extends AbstractAdjMatrix { private List nodeIds; - private List linkerList; + private List nodeList; // 当前画布中所有子流程节点以及范围框节点 不包含内部节点与连线 - public NodeExpandAdjMatrix(List nodeIds, List linkerList) { - super(nodeIds.size()); - this.nodeIds = nodeIds; - this.linkerList = linkerList; + public NodeExpandAdjMatrix(List nodeList) { + super(nodeList.size()); + this.nodeList = nodeList; + + this.nodeIds = nodeList.stream().map(o -> o.getString("id")).collect(Collectors.toList()); } public List getNodeIds() { return nodeIds; } - public List getLinkerList() { - return linkerList; - } - /** * 构建邻接矩阵 */ public void buildAdjMatrix(){ - for (JSONObject linker : linkerList) { - JSONObject from = linker.getJSONObject("from"); - JSONObject to = linker.getJSONObject("to"); - int fromIndex = nodeIds.indexOf(from.getString("id")); - int toIndex = nodeIds.indexOf(to.getString("id")); - addEdge(fromIndex, toIndex); + for (JSONObject node : nodeList) { + String currentNodeId = node.getString("id"); + JSONObject extendAttr = node.getJSONObject(SubProcessConst.EXTEND_ATTR); + // 当前节点的前置节点 + JSONArray leadNodeArr = extendAttr.getJSONArray("leadNodeArr"); + if (leadNodeArr.size() > 0){ + for (Object o : leadNodeArr) { + String leadNodeId = (String) o; + addEdge(nodeIds.indexOf(leadNodeId), nodeIds.indexOf(currentNodeId)); + } + } + // 当前节点的后置节点 + JSONArray rearNodeArr = extendAttr.getJSONArray("rearNodeArr"); + if (rearNodeArr.size() > 0){ + for (Object o : rearNodeArr) { + String rearNodeId = (String) o; + addEdge(nodeIds.indexOf(currentNodeId), nodeIds.indexOf(rearNodeId)); + } + } } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java index 8ce372f3..4b1f7742 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java @@ -20,10 +20,8 @@ import com.actionsoft.exception.AWSException; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; public class GraphRender { @@ -79,6 +77,11 @@ public class GraphRender { subProcessNode.put("text", repositoryModel.getName()); // 增加元素类型属性 subProcessNode.put("elementType", ElementType.OUTER_NODE.name()); + // 增加关联文件的标识 + JSONObject extendAttr = new JSONObject(); + extendAttr.put("id", nodeList.get(i).getId()); + extendAttr.put("name", repositoryModel.getName()); + subProcessNode.put(SubProcessConst.EXTEND_ATTR, extendAttr); // 处理子流程模型节点形状属性 JSONArray dataAttributes = subProcessNode.getJSONArray("dataAttributes"); @@ -194,4 +197,41 @@ public class GraphRender { this.baseModel.setDefinition(defineJsonObj.toJSONString()); CoeDesignerAPIManager.getInstance().storeDefinition(this.baseModel); } + + /** + * 依据生成后的总图的连线关系 在子流程节点属性中加入 前置节点与后置节点信息 + */ + public void addLeadAndRearInfoToElements(){ + JSONObject defineJsonObj = JSONObject.parseObject(this.baseModel.getDefinition()); + JSONObject elements = defineJsonObj.getJSONObject("elements"); + + Set subProcessNodeKeySet = elements.keySet().stream().filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name"))).collect(Collectors.toSet()); + for (String subProcessNodeKey : subProcessNodeKeySet) { + JSONObject subProcessNode = elements.getJSONObject(subProcessNodeKey); + JSONObject extendAttr = subProcessNode.getJSONObject(SubProcessConst.EXTEND_ATTR); + + // 当前节点的前置节点 + JSONArray leadNodeKeyArr = elements.keySet().stream() + .filter(key -> "linker".equals(elements.getJSONObject(key).getString("name"))) + .map(key -> elements.getJSONObject(key)) + .filter(l -> ((JSONObject)l).getJSONObject("to").getString("id").equals(subProcessNodeKey)) + .map(l -> ((JSONObject)l).getJSONObject("from").getString("id")) + .collect(Collectors.toCollection(JSONArray::new)); + + extendAttr.put("leadNodeArr", leadNodeKeyArr); + + // 当前节点的后置节点 + JSONArray rearNodeKeyArr = elements.keySet().stream() + .filter(key -> "linker".equals(elements.getJSONObject(key).getString("name"))) + .map(key -> elements.getJSONObject(key)) + .filter(l -> ((JSONObject)l).getJSONObject("from").getString("id").equals(subProcessNodeKey)) + .map(l -> ((JSONObject)l).getJSONObject("to").getString("id")) + .collect(Collectors.toCollection(JSONArray::new)); + + extendAttr.put("rearNodeArr", rearNodeKeyArr); + } + + this.baseModel.setDefinition(defineJsonObj.toJSONString()); + CoeDesignerAPIManager.getInstance().storeDefinition(this.baseModel); + } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/component/AbstractDefinitionHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/component/AbstractDefinitionHandle.java index b0a47037..c51eb8b2 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/component/AbstractDefinitionHandle.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/component/AbstractDefinitionHandle.java @@ -1,7 +1,12 @@ package com.actionsoft.apps.coe.method.process.subprocess.graph.component; +import com.actionsoft.apps.coe.method.process.subprocess.constant.ElementType; +import com.actionsoft.exception.AWSException; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import java.util.List; + /** * @author oYang * @Description TODO @@ -99,9 +104,62 @@ public abstract class AbstractDefinitionHandle { */ public abstract void updateShapeH(String shapeKey, double h); + /** + * 获取图形的 x坐标 + * @param shapeKey + * @return + */ public abstract double getShapeX(String shapeKey); + + /** + * 获取图形的 y坐标 + * @param shapeKey + * @return + */ public abstract double getShapeY(String shapeKey); + + /** + * 获取图形的 w宽度 + * @param shapeKey + * @return + */ public abstract double getShapeW(String shapeKey); + + /** + * 获取图形的 h高度 + * @param shapeKey + * @return + */ public abstract double getShapeH(String shapeKey); + /** + * 获取所有连线 + * @return + * @throws AWSException + */ + public abstract JSONArray getLinkers() throws AWSException; + + /** + * 获取指定的连线 + * @param key + * @return + * @throws AWSException + */ + public abstract JSONObject getLinkerByKey(String key) throws AWSException; + + /** + * 获取指定元素的元素类型 + * @param key + * @return + * @throws AWSException + */ + public abstract ElementType getElementTypeByKey(String key) throws AWSException; + + /** + * 获取元素类型为 SCOPE_NODE 的元素ID集合 + * @return + * @throws AWSException + */ + public abstract List getScopeNodeIds() throws AWSException; + } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadSafe.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadSafe.java index 776a7cfc..7658d199 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadSafe.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadSafe.java @@ -1,9 +1,14 @@ package com.actionsoft.apps.coe.method.process.subprocess.graph.util; +import com.actionsoft.apps.coe.method.process.subprocess.constant.ElementType; import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; +import com.actionsoft.exception.AWSException; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import java.util.List; import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; /** * @author oYang @@ -178,4 +183,61 @@ public class DefinitionThreadSafe extends AbstractDefinitionHandle { lock.unlock(); } } + + @Override + public JSONArray getLinkers() throws AWSException { + lock.lock(); + try{ + JSONObject elements = getElements(); + JSONArray linkers = elements.keySet() + .stream() + .filter(key -> "linker".equals(elements.getJSONObject(key).getString("name"))) + .map(key -> elements.getJSONObject(key)) + .collect(Collectors.toCollection(JSONArray::new)); + return linkers; + }finally { + lock.unlock(); + } + } + + @Override + public JSONObject getLinkerByKey(String key) throws AWSException { + lock.lock(); + try{ + JSONObject elements = getElements(); + JSONObject ele = elements.getJSONObject(key); + if (!"linker".equals(ele.getString("name"))){ + throw new AWSException("不存在指定的连线"); + } + return ele; + }finally { + lock.unlock(); + } + } + + @Override + public ElementType getElementTypeByKey(String key) throws AWSException { + lock.lock(); + try { + JSONObject ele = getShapeByKey(key); + if (ele == null){ + throw new AWSException("不存在指定的元素"); + } + return ElementType.valueOf(ele.getString("elementType")); + } finally { + lock.unlock(); + } + } + + @Override + public List getScopeNodeIds() throws AWSException { + lock.lock(); + try { + JSONObject elements = getElements(); + List scopeShapeIds = elements.keySet().stream().filter(key -> elements.getJSONObject(key).getString("elementType").equals(ElementType.SCOPE_NODE.name())).collect(Collectors.toList()); + return scopeShapeIds; + } finally { + lock.unlock(); + } + } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadUnSafe.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadUnSafe.java index 2a1e5ad0..ebc580b4 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadUnSafe.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/DefinitionThreadUnSafe.java @@ -1,8 +1,15 @@ package com.actionsoft.apps.coe.method.process.subprocess.graph.util; +import com.actionsoft.apps.coe.method.process.subprocess.constant.ElementType; import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; +import com.actionsoft.exception.AWSException; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + /** * @author oYang * @Description 操作 definition 工具类 线程不安全 @@ -98,4 +105,41 @@ public class DefinitionThreadUnSafe extends AbstractDefinitionHandle { public double getShapeH(String shapeKey) { return getShapeByProps(shapeKey).getDoubleValue("h"); } + + @Override + public JSONArray getLinkers() throws AWSException { + JSONObject elements = getElements(); + JSONArray linkers = elements.keySet() + .stream() + .filter(key -> "linker".equals(elements.getJSONObject(key).getString("name"))) + .map(key -> elements.getJSONObject(key)) + .collect(Collectors.toCollection(JSONArray::new)); + return linkers; + } + + @Override + public JSONObject getLinkerByKey(String key) throws AWSException { + JSONObject elements = getElements(); + JSONObject ele = elements.getJSONObject(key); + if (!"linker".equals(ele.getString("name"))){ + throw new AWSException("不存在指定的连线"); + } + return ele; + } + + @Override + public ElementType getElementTypeByKey(String key) throws AWSException { + JSONObject ele = getShapeByKey(key); + if (ele == null){ + throw new AWSException("不存在指定的元素"); + } + return ElementType.valueOf(ele.getString("elementType")); + } + + @Override + public List getScopeNodeIds() throws AWSException { + JSONObject elements = getElements(); + List scopeShapeIds = elements.keySet().stream().filter(key -> elements.getJSONObject(key).getString("elementType").equals(ElementType.SCOPE_NODE.name())).collect(Collectors.toList()); + return scopeShapeIds; + } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/GraphNodeCloseUtil.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/GraphNodeCloseUtil.java deleted file mode 100644 index fd915eef..00000000 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/GraphNodeCloseUtil.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.actionsoft.apps.coe.method.process.subprocess.graph.util; - -/** - * @author oYang - * @Description TODO - * @createTime 2023年06月09日 16:26:00 - */ -public class GraphNodeCloseUtil { -} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/LinkerPointCalculationHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/LinkerPointCalculationHandle.java new file mode 100644 index 00000000..b8c2d3d5 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/LinkerPointCalculationHandle.java @@ -0,0 +1,452 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph.util; + +import com.actionsoft.apps.coe.method.process.subprocess.constant.LinkerDefConstant; +import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.method.process.subprocess.graph.component.AbstractDefinitionHandle; +import com.actionsoft.bpms.util.ConsolePrinter; +import com.actionsoft.bpms.util.UUIDGener; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.util.Comparator; +import java.util.List; + +/** + * @author oYang + * @Description 连线上所有关键节点(包括起始点以及折点)计算处理 + * 类比起始图形作为直角坐标系的原点 目标图形的位置大体在四个象限内 + * @createTime 2023年06月28日 17:56:00 + */ +public class LinkerPointCalculationHandle { + + private AbstractDefinitionHandle definitionHandle; + + public LinkerPointCalculationHandle(AbstractDefinitionHandle definitionHandle) { + this.definitionHandle = definitionHandle; + } + + /** + * 根据布局方向 组装连线 + * @param direction 布局方向 + * @param fromId 起点节点ID + * @param toId 终点节点ID + * @param fromBounding 起点节点边框信息 + * @param toBounding 终点节点边框信息 + * @return + */ + public JSONObject toAssembleLinker(String direction, String fromId, String toId, double[] fromBounding, double[] toBounding){ + double[][] turnPoi = direction.equals(SubProcessConst.DIRECTION_H) ? horizLayOut(fromBounding, toBounding) : vertLayOut(fromBounding, toBounding); + double[] angleArr = calculationLinkerAngle(turnPoi[0], turnPoi[turnPoi.length - 1], turnPoi[1], turnPoi[turnPoi.length - 2]); + // 构建连线 + JSONObject linkerObj = JSONObject.parseObject(LinkerDefConstant.linker); + linkerObj.put("id", UUIDGener.getObjectId()); + // 折点 + JSONArray points = new JSONArray(); + for (int j = 0; j < turnPoi.length; j++) { + if (j > 0 && j < turnPoi.length - 1){ + JSONObject pointObj = new JSONObject(); + pointObj.put("x", turnPoi[j][0]); + pointObj.put("y", turnPoi[j][1]); + points.add(pointObj); + } + } + linkerObj.put("points", points); + // 起点与终点 + JSONObject fromObj = new JSONObject(); + fromObj.put("x", turnPoi[0][0]); + fromObj.put("y", turnPoi[0][1]); + fromObj.put("angle", angleArr[0]); + fromObj.put("id", fromId); + linkerObj.put("from", fromObj); + JSONObject toObj = new JSONObject(); + toObj.put("x", turnPoi[turnPoi.length - 1][0]); + toObj.put("y", turnPoi[turnPoi.length - 1][1]); + toObj.put("angle", angleArr[1]); + toObj.put("id", toId); + linkerObj.put("to", toObj); + + return linkerObj; + } + + + /** + * 节点水平布局下计算连线 + * @param fromBounding + * @param toBounding + * @return + */ + public double[][] horizLayOut(double[] fromBounding, double[] toBounding){ + double fromX = fromBounding[0],fromY = fromBounding[1], fromW = fromBounding[2], fromH = fromBounding[3]; + double toX = toBounding[0], toY = toBounding[1], toW = toBounding[2], toH = toBounding[3]; + if (fromY == toY) { + return fromX < toX + ? new double[][] + { + {fromX + fromW, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {toX - rowNodeDistanceWrapper(getNearLeftNodeDistance(toBounding)) / 2, toY + toH / 2}, + {toX, toY + toH / 2} + } + : new double[][] + { + {fromX + fromW, fromY + fromH / 2}, + {fromX + fromW + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {fromX + fromW + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY - colNodeDistanceWrapper(getNearTopNodeDistance(fromBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY} + }; + }else if (fromX == toX) { // 垂直 + // 节点横向分布 连线按照大原则 垂直 不存在 fromY < toY 的情况 也就是不存在 连线从上到下直连的情况 + double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; + double[] endPoint = new double[]{toX + toW / 2, toY}; + return new double[][]{startPoint, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + endPoint}; + }else { + if (fromX < toX && fromY > toY){ // 目标节点在第一象限 + double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; + double turnPointX = fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2; + if (fromX + getCurrentColMaxW(fromX) + getNearRightNodeDistance(fromBounding) == toX){ // 相邻节点 存在两个折点 + double[] endPoint = new double[]{toX, toY + toH / 2}; + return new double[][]{startPoint,{turnPointX, fromY + fromH / 2},{turnPointX, toY + toH / 2}, endPoint}; + }else { // 不相邻节点 存在三个折点 + double[] endPoint = new double[]{toX + toW / 2, toY}; + return new double[][]{ + startPoint, + {turnPointX, fromY + fromH / 2}, + {turnPointX, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + endPoint + }; + } + }else if (fromX > toX && fromY > toY) { // 目标节点在第二象限 无论节点是否相邻 都按照三个折点走 + double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; + double[] endPoint = new double[]{toX + toW / 2, toY}; + return new double[][]{ + startPoint, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + endPoint + }; + }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 + double[] startPoint = new double[]{fromX + fromW, fromY + fromH / 2}; + if (fromX + getCurrentColMaxW(fromX) + getNearRightNodeDistance(fromBounding) == toX){ // 相邻节点 存在两个折点 + double turnPointX = fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2; + double[] endPoint = new double[]{toX, toY + toH / 2}; + return new double[][]{ + startPoint, + {turnPointX, fromY + fromH / 2}, + {turnPointX, toY + toH / 2}, + endPoint + }; + }else { // 不相邻节点 存在三个折点 + double[] endPoint = new double[]{toX + toW / 2, toY}; + return new double[][]{ + startPoint, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + endPoint + }; + } + }else if (fromX > toX && fromY < toY){ // 目标节点在第三象限 横向布局的情况下 应该不会出现目标节点在第三象限的情况 + ConsolePrinter.warn("[端到端功能][节点展开模块]处理连线时目标节点在[横向布局]的情况下出现在了第三象限"); + } + } + return new double[2][2]; + } + + /** + * 节点垂直布局下计算连线 + * @param fromBounding + * @param toBounding + * @return + */ + public double[][] vertLayOut(double[] fromBounding, double[] toBounding){ + double fromX = fromBounding[0],fromY = fromBounding[1], fromW = fromBounding[2], fromH = fromBounding[3]; + double toX = toBounding[0], toY = toBounding[1], toW = toBounding[2], toH = toBounding[3]; + if (fromY == toY){ // 水平 分析可知 水平方向上不会出现 从左到右直连的情况 只有 右边节点右侧锚点出 向上走 左折 连到左侧节点上方锚点 + double[] startPoi = new double[]{fromX + fromW, fromY + fromH / 2}; + double[] turnPoi1 = new double[]{fromX + fromW + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}; + double[] turnPoi2 = new double[]{fromX + fromW + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}; + double[] turnPoi3 = new double[]{toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}; + double[] endPoi = new double[]{toX + toW / 2, toY}; + return new double[][]{startPoi, turnPoi1, turnPoi2, turnPoi3, endPoi}; + }else if (fromX == toX){ // 垂直 分析可知 垂直方向上应该不会有 toY < fromY 的情况 鉴于数据不确定性 先写上 + double[] startPoi = fromY < toY + ? new double[]{fromX + fromW / 2, fromY + fromH} + : new double[]{fromX +fromW, fromY + fromH / 2}; + double[] endPoi = new double[]{toX + toW / 2, toY}; + return fromY < toY + ? new double[][]{ + startPoi, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + colNodeDistanceWrapper(getNearBootomNodeDistance(fromBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + endPoi} + : new double[][]{ + startPoi, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + endPoi}; + }else { // 分布在四个象限内 + if (fromX > toX && fromY > toY){ // 目标节点在第二象限 + return new double[][]{ + {fromX + fromW, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, fromY + fromH / 2}, + {fromX + getCurrentColMaxW(fromX) + rowNodeDistanceWrapper(getNearRightNodeDistance(fromBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY} + }; + }else if (fromX > toX && fromY < toY){ // 目标节点在第三象限 + return toY - getCurrentRowMaxH(fromY) == getNearBootomNodeDistance(fromBounding) // 相邻行节点 + ? new double[][] + { + {fromX + fromW / 2, fromY + fromH}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + colNodeDistanceWrapper(getNearBootomNodeDistance(fromBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY} + } + : new double[][] + { + {fromX + fromW / 2, fromY + fromH}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + colNodeDistanceWrapper(getNearBootomNodeDistance(fromBounding)) / 2}, + {toX + toW + rowNodeDistanceWrapper(getNearRightNodeDistance(toBounding)) / 2, fromY + getCurrentRowMaxH(fromY) + colNodeDistanceWrapper(getNearBootomNodeDistance(fromBounding)) / 2}, + {toX + toW + rowNodeDistanceWrapper(getNearRightNodeDistance(toBounding)) / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY - colNodeDistanceWrapper(getNearTopNodeDistance(toBounding)) / 2}, + {toX + toW / 2, toY} + }; + }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 + return new double[][]{ + {fromX + fromW / 2, fromY + fromH}, + {fromX + fromW / 2, fromY + getCurrentRowMaxH(fromY) + colNodeDistanceWrapper(getNearBootomNodeDistance(fromBounding)) / 2}, + {toX + toW / 2, fromY + getCurrentRowMaxH(fromY) + colNodeDistanceWrapper(getNearBootomNodeDistance(fromBounding)) / 2}, + {toX + toW / 2, toY} + }; + }else { + // fromX < toX && fromY > toY 目标节点在第一象限 分析可知 纵向排布的情况下 应该不会出现目标节点在第一象限的情况 + } + } + return new double[2][2]; + } + + /** + * 获取当前同一列图形的最大宽度 在水平布局中 + * @param fromShapeX 当前图形的 x 坐标 + * @return + */ + private double getCurrentColMaxW(double shapeX){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && shapeX == 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 shapeY){ + JSONObject elements = definitionHandle.getElements(); + JSONObject props = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name")) && shapeY == 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"); + } + + /** + * 获取当前图形 水平方向上 左侧相邻节点 可能为空 + * @param shapeBounding [x, y, w, h] + * @return JSONObject shape + */ + private JSONObject getNearLeftNode(double[] shapeBounding){ + double shapeX = shapeBounding[0], shapeY = shapeBounding[1]; + JSONObject elements = definitionHandle.getElements(); + JSONObject leftNode = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name"))) + .filter(key -> shapeY == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .filter(key -> shapeX > elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .map(key -> elements.getJSONObject(key)) + .max(Comparator.comparing(o -> o.getJSONObject("props").getDoubleValue("x"))).orElse(null); + return leftNode; + } + + /** + * 获取当前图形 水平方向上 与左侧相邻节点的间距 如果为空 则返回默认间距 + * @param shapeBounding [x, y, w, h] + * @return + */ + private double getNearLeftNodeDistance(double[] shapeBounding){ + JSONObject nearLeftNode = getNearLeftNode(shapeBounding); + if (nearLeftNode == null){ + return SubProcessConst.SHAPE_HORIZ_INTERVAL; + } + double shapeX = shapeBounding[0]; + JSONObject props = nearLeftNode.getJSONObject("props"); + return shapeX - props.getDoubleValue("x") + props.getDoubleValue("w"); + } + + /** + * 获取当前图形 水平方向上 右侧相邻节点 可能为空 + * @param shapeBounding [x, y, w, h] + * @return + */ + private JSONObject getNearRightNode(double[] shapeBounding){ + double shapeX = shapeBounding[0], shapeY = shapeBounding[1]; + JSONObject elements = definitionHandle.getElements(); + JSONObject rightNode = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name"))) + .filter(key -> shapeY == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .filter(key -> shapeX < elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .map(key -> elements.getJSONObject(key)) + .min(Comparator.comparing(o -> o.getJSONObject("props").getDoubleValue("x"))).orElse(null); + return rightNode; + } + + /** + * 获取当前图形 水平方向上 与右侧相邻节点的间距 如果为空 则返回默认间距 + * @param shapeBounding [x, y, w, h] + * @return + */ + private double getNearRightNodeDistance(double[] shapeBounding){ + JSONObject nearRightNode = getNearRightNode(shapeBounding); + if (nearRightNode == null){ + return SubProcessConst.SHAPE_HORIZ_INTERVAL; + } + double shapeX = shapeBounding[0], shapeW = shapeBounding[2]; + JSONObject props = nearRightNode.getJSONObject("props"); + return props.getDoubleValue("x") - shapeX + shapeW; + } + + /** + * 获取当前图形 垂直方向上 与上侧相邻节点 可能为空 + * @param shapeBounding [x, y, w, h] + * @return + */ + private JSONObject getNearTopNode(double[] shapeBounding){ + double shapeX = shapeBounding[0], shapeY = shapeBounding[1]; + JSONObject elements = definitionHandle.getElements(); + JSONObject topNode = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name"))) + .filter(key -> shapeX == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .filter(key -> shapeY > elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .map(key -> elements.getJSONObject(key)) + .max(Comparator.comparing(o -> o.getJSONObject("props").getDoubleValue("y"))).orElse(null); + return topNode; + } + + /** + * 获取当前图形 垂直方向上 与上侧相邻节点的间距 如果为空 则返回默认间距 + * @param shapeBounding [x, y, w, h] + * @return + */ + private double getNearTopNodeDistance(double[] shapeBounding){ + JSONObject nearTopNode = getNearTopNode(shapeBounding); + if (nearTopNode == null){ + return SubProcessConst.SHAPE_VERT_INTERVAL; + } + JSONObject props = nearTopNode.getJSONObject("props"); + double shapeY = shapeBounding[1]; + return shapeY - props.getDoubleValue("y") + props.getDoubleValue("h"); + } + + /** + * 获取当前图形 垂直方向上 与下侧相邻节点 可能为空 + * @param shapeBounding [x, y, w, h] + * @return + */ + private JSONObject getNearBootomNode(double[] shapeBounding){ + double shapeX = shapeBounding[0], shapeY = shapeBounding[1]; + JSONObject elements = definitionHandle.getElements(); + JSONObject bottomNode = elements.keySet().stream() + .filter(key -> !"linker".equals(elements.getJSONObject(key).getString("name"))) + .filter(key -> shapeX == elements.getJSONObject(key).getJSONObject("props").getDoubleValue("x")) + .filter(key -> shapeY < elements.getJSONObject(key).getJSONObject("props").getDoubleValue("y")) + .map(key -> elements.getJSONObject(key)) + .min(Comparator.comparing(o -> o.getJSONObject("props").getDoubleValue("y"))).orElse(null); + return bottomNode; + } + + /** + * 获取当前图形 垂直方向上 与下侧相邻节点的间距 如果为空 则返回默认间距 + * @param shapeBounding [x, y, w, h] + * @return + */ + private double getNearBootomNodeDistance(double[] shapeBounding){ + JSONObject nearBootomNode = getNearBootomNode(shapeBounding); + if (nearBootomNode == null){ + return SubProcessConst.SHAPE_VERT_INTERVAL; + } + JSONObject props = nearBootomNode.getJSONObject("props"); + double shapeY = shapeBounding[1], shapeH = shapeBounding[3]; + return props.getDoubleValue("y") - shapeY + shapeH; + } + + + /** + * 如果水平方向上节点间距大于默认间距 返回默认间距 否则返回实际间距 + * @param distance + * @return + */ + private double rowNodeDistanceWrapper(double distance){ + if (distance > SubProcessConst.SHAPE_HORIZ_INTERVAL){ + return SubProcessConst.SHAPE_HORIZ_INTERVAL; + } + return distance; + } + + /** + * 如果垂直方向上节点间距大于默认间距 返回默认间距 否则返回实际间距 + * @param distance + * @return + */ + private double colNodeDistanceWrapper(double distance){ + if (distance > SubProcessConst.SHAPE_VERT_INTERVAL){ + return SubProcessConst.SHAPE_VERT_INTERVAL; + } + return distance; + } + + /** + * 计算angle值 + * @param fromPoi 起始节点坐标 + * @param toPoi 结束节点坐标 + * @param firstTurnPoi 连线第一个折点坐标 + * @param lastTurnPoi 连线最后一个折点坐标 + * @return [0]: from的angle [1]: to的angle + */ + private double[] calculationLinkerAngle(double[] fromPoi, double[] toPoi, double[] firstTurnPoi, double[] lastTurnPoi){ + double fromX = fromPoi[0], fromY = fromPoi[1]; + double toX = toPoi[0], toY = toPoi[1]; + double firstTurnX = firstTurnPoi[0], firstTurnY = firstTurnPoi[1]; + double lastTurnX = lastTurnPoi[0], lastTurnY = lastTurnPoi[1]; + + if (fromY == toY){ // 水平 + return fromX < toX ? new double[]{LinkerDefConstant.ANGLE_LEFT, LinkerDefConstant.ANGLE_RIGHT} : new double[]{LinkerDefConstant.ANGLE_RIGHT, LinkerDefConstant.ANGLE_LEFT}; + }else if (fromX == toX){ // 垂直 + return fromY < toY ? new double[]{LinkerDefConstant.ANGLE_UP, LinkerDefConstant.ANGLE_DOWN} : new double[]{LinkerDefConstant.ANGLE_DOWN, LinkerDefConstant.ANGLE_UP}; + }else { + double fromAngle = 0.0; + if (fromY == firstTurnY){ // 水平 + fromAngle = fromX < firstTurnX ? LinkerDefConstant.ANGLE_LEFT : LinkerDefConstant.ANGLE_RIGHT; + }else if (fromX == firstTurnX){ // 垂直 + fromAngle = fromY < firstTurnY ? LinkerDefConstant.ANGLE_UP : LinkerDefConstant.ANGLE_DOWN; + } + double toAngle = 0.0; + if (toY == lastTurnY){ // 水平 + toAngle = toX < lastTurnX ? LinkerDefConstant.ANGLE_LEFT : LinkerDefConstant.ANGLE_RIGHT; + }else if (toX == lastTurnX){ // 垂直 + toAngle = toY < lastTurnY ? LinkerDefConstant.ANGLE_UP : LinkerDefConstant.ANGLE_DOWN; + } + return new double[]{fromAngle, toAngle}; + } + } + +} 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/graph/util/ScopeShapeMonitor.java similarity index 80% rename from com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/ScopeShapeMonitor.java rename to com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/ScopeShapeMonitor.java index c13ed59f..34fe066b 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/graph/util/ScopeShapeMonitor.java @@ -1,20 +1,20 @@ -package com.actionsoft.apps.coe.method.process.subprocess.mode; +package com.actionsoft.apps.coe.method.process.subprocess.graph.util; +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.graph.util.SubProcessNodeDefineUtil; import com.actionsoft.exception.AWSException; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** * @author oYang - * @Description 构建虚线范围框监视器模型且关联其内部元素 方便最后调整范围框内的元素 + * @Description 构建总图中已存在的范围框监视器模型且关联其内部元素 + * 方便最后调整范围框内的元素位置 + * 内部元素只包含元素类型为 ElementType.INNER_NODE ElementType.INNER_LINKER * @createTime 2023年06月13日 14:46:00 */ public class ScopeShapeMonitor { @@ -34,43 +34,34 @@ public class ScopeShapeMonitor { */ public void buildScopeShapeMonitors(){ JSONObject elements = definitionHandle.getElements(); - Set scopeShapeKeySet = elements.keySet().stream().filter(key -> "scopeLimitation".equals(elements.getJSONObject(key).getString("name"))).collect(Collectors.toSet()); + // 获取总图中已存在的范围框图形ID集合 + List scopeShapeKeySet = definitionHandle.getScopeNodeIds(); if (scopeShapeKeySet.size() == 0) return; Map scopeShapeMonitorMap = new HashMap<>(); for (String scopeShapeKey : scopeShapeKeySet) { - JSONObject props = definitionHandle.getShapeByProps(scopeShapeKey); - double scopeX = props.getDoubleValue("x"), scopeY = props.getDoubleValue("y"), scopeW = props.getDoubleValue("w"), scopeH = props.getDoubleValue("h"); - // 判断当前元素是否在范围选择框的范围内 - Set inRangeEleKeySet = new HashSet<>(); - for (String key : elements.keySet()) { - if (scopeShapeKey.equals(key)) continue; // 范围框本身不算作其内部元素 - JSONObject shape = definitionHandle.getShapeByKey(key); - if ("linker".equals(shape.getString("name"))){ // 连线 - JSONObject from = shape.getJSONObject("from"); - JSONObject to = shape.getJSONObject("to"); - double fromX = from.getDoubleValue("x"), fromY = from.getDoubleValue("y"), toX = to.getDoubleValue("x"), toY = to.getDoubleValue("y"); - if ((scopeX < fromX && fromX < scopeX + scopeW && scopeY < fromY && fromY < scopeY + scopeH) || (scopeX < toX && toX < scopeX + scopeW && scopeY < toY && toY < scopeY + scopeH)){ - inRangeEleKeySet.add(key); - } - }else { - double x = definitionHandle.getShapeByProps(key).getDoubleValue("x"); - double y = definitionHandle.getShapeByProps(key).getDoubleValue("y"); - if (scopeX <= x && x < scopeX + scopeW && scopeY <= y && y < scopeY + scopeH){ - inRangeEleKeySet.add(key); - } - } - } + JSONObject scopeShape = definitionHandle.getShapeByKey(scopeShapeKey); + // 获取范围框内部元素 + JSONArray innerEleIds = scopeShape.getJSONArray(SubProcessConst.INNER_ELEMENTS); + Set inRangeEleKeySet = innerEleIds.stream().map(o -> o.toString()).collect(Collectors.toSet()); MonitorInfo monitorInfo = new MonitorInfo(scopeShapeKey, false, 0.0, false, 0.0, inRangeEleKeySet); scopeShapeMonitorMap.put(scopeShapeKey, monitorInfo); } this.scopeShapeMonitorMap = scopeShapeMonitorMap; } + /** + * 返回所有的范围框监视器数据模型 + * @return + */ public Map getScopeShapeMonitorMap() { return scopeShapeMonitorMap; } + /** + * 移除指定的范围框监视器数据模型 + * @param scopeShapeId + */ public void removeScopeShapeByKey(String scopeShapeId){ if (scopeShapeMonitorMap.containsKey(scopeShapeId)){ scopeShapeMonitorMap.remove(scopeShapeId); @@ -78,7 +69,7 @@ public class ScopeShapeMonitor { } /** - * 更新范围框的监视属性信息 + * 更新指定范围框内部元素在x方向上的位置信息 * @param scopeShapeId 当前范围框图形ID * @param isRightMove 是否右移 * @param rightMoveDistance 右移动距离 @@ -94,7 +85,7 @@ public class ScopeShapeMonitor { } /** - * 更新范围框的监视属性信息 + * 更新指定范围框内部元素在y方向上的位置信息 * @param scopeShapeId 当前范围框图形ID * @param isBottomMove 是否下移 * @param bottomMoveDistance 下移距离 @@ -194,7 +185,6 @@ public class ScopeShapeMonitor { } } - public class MonitorInfo { private String scopeShapeId; // 当前虚线范围框的图形ID diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/SubProcessNodeDefineUtil.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/SubProcessNodeDefineUtil.java index 06ed1bd0..449abe4a 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/SubProcessNodeDefineUtil.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/util/SubProcessNodeDefineUtil.java @@ -36,6 +36,11 @@ public class SubProcessNodeDefineUtil { if (childProcessBaseModel == null) throw new AWSException("当前子流程节点内部可能没有图形元素,可以去添加后展开"); subProcessNodeDefineStr = childProcessBaseModel.getDefinition(); + JSONObject defineObj = JSONObject.parseObject(subProcessNodeDefineStr); + JSONObject elements = defineObj.getJSONObject("elements"); + if (elements.size() == 0){ + throw new AWSException("当前子流程节点内部可能没有图形元素,可以去添加后展开"); + } } return subProcessNodeDefineStr; } 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 index 8fc5721a..c0986894 100644 --- 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 @@ -1,9 +1,8 @@ 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.graph.util.ScopeShapeMonitor; import com.actionsoft.apps.coe.method.process.subprocess.observers.Observer; -import com.alibaba.fastjson.JSONObject; /** * @author oYang 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 index 44df489d..c470ebb2 100644 --- 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 @@ -2,7 +2,7 @@ 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.graph.util.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; diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java deleted file mode 100644 index 2a210048..00000000 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.actionsoft.apps.coe.method.process.subprocess.uitl; - -/** - * @author oYang - * @create 2023-05-11 13:57 - */ -public class Node { - - public int id; // 节点id - public double x; // 节点x坐标 - public double y; // 节点y坐标 - public double displaceX; // x方向移动位移 - public double displaceY; // y方向移动位移 - - public Node(int id) { - this.id = id; - this.x = 0; - this.y = 0; - this.displaceX = 0; - this.displaceY = 0; - } -} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.java deleted file mode 100644 index f2799d77..00000000 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.actionsoft.apps.coe.method.process.subprocess.uitl; - -import java.util.ArrayList; -import java.util.Random; - -/** - * @author oYang - * @create 2023-05-11 13:53 - */ -public class UtilTestGraph { - - private final int width; // 布局区域宽度 - private final int height; // 布局区域高度 - private final double k; // 弹性系数 - private final double k2; // 斥力系数 - private final double damping; // 阻尼系数 - private final double maxDisplace; // 最大移动距离 - private final int maxIterations; // 最大迭代次数 - - // 存储每个节点的位置信息 - private ArrayList nodes; - - // 存储每个节点之间的连线信息(邻接矩阵) - private int[][] adjacencyMatrix; - - public UtilTestGraph(int width, int height, double k, double k2, double damping, double maxDisplace, int maxIterations, int nodeCount) { - this.width = width; - this.height = height; - this.k = k; - this.k2 = k2; - this.damping = damping; - this.maxDisplace = maxDisplace; - this.maxIterations = maxIterations; - - // 初始化节点数组 - this.nodes = new ArrayList<>(nodeCount); - for (int i = 0; i < nodeCount; i++) { - Node node = new Node(i); - node.x = Math.random() * this.width; - node.y = Math.random() * this.height; - nodes.add(node); - } - - // 初始化邻接矩阵 - this.adjacencyMatrix = new int[nodeCount][nodeCount]; - Random random = new Random(); - for (int i = 0; i < nodeCount; i++) { - for (int j = i + 1; j < nodeCount; j++) { - // 随机生成一个有连线的概率 - double p = random.nextDouble(); - if (p < 0.3) { - adjacencyMatrix[i][j] = 1; - adjacencyMatrix[j][i] = 1; - } - } - } - } - - // 执行布局操作 - public void executeLayout() { - for (int i = 0; i < maxIterations; i++) { - for (int j = 0; j < nodes.size(); j++) { - Node node = nodes.get(j); - node.displaceX = 0; - node.displaceY = 0; - for (int k = 0; k < nodes.size(); k++) { - if (j == k) continue; - Node other = nodes.get(k); - double dx = other.x - node.x; - double dy = other.y - node.y; - double distanceSquared = dx * dx + dy * dy; - if (distanceSquared == 0) { - dx = randomDisplacement(); - dy = randomDisplacement(); - distanceSquared = dx * dx + dy * dy; - } - double distance = Math.sqrt(distanceSquared); - double force = (k * k / distance) - (k2 * distance); - node.displaceX += (dx / distance) * force; - node.displaceY += (dy / distance) * force; - } - } - - // 移动节点的位置 - for (Node node : nodes) { - double xDisplace = node.displaceX * damping; - double yDisplace = node.displaceY * damping; - double displace = Math.sqrt(xDisplace * xDisplace + yDisplace * yDisplace); - if (displace > maxDisplace) { - xDisplace *= maxDisplace / displace; - yDisplace *= maxDisplace / displace; - } - node.x += xDisplace; - node.y += yDisplace; - } - } - } - - // 随机生成一个小的位移量 - private double randomDisplacement() { - return (Math.random() - 0.5) * 0.1; - } - - public static void main(String[] args) { - UtilTestGraph layout = new UtilTestGraph(800, 600, 5.0, 0.1, 0.9, 5.0, 100, 20); - layout.executeLayout(); - - // 输出节点的最终位置 - for (Node node : layout.nodes) { - System.out.println("Node " + node.id + ": (" + node.x + ", " + node.y + ")"); - } - } -} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java index c318ede8..7ea2ce4f 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java @@ -306,6 +306,8 @@ public class SubProcessWeb extends ActionWeb { // 流程属性中加入布局方向 graphRender.addDirectionToProcessProperties(direction); + graphRender.addLeadAndRearInfoToElements(); + } @@ -324,6 +326,7 @@ public class SubProcessWeb extends ActionWeb { ro.setData(define); return ro.toString(); } catch (AWSException e) { + e.printStackTrace(); return ResponseObject.newErrResponse(e.getMessage()).toString(); } } @@ -343,6 +346,7 @@ public class SubProcessWeb extends ActionWeb { ro.setData(define); return ro.toString(); } catch (AWSException e) { + e.printStackTrace(); return ResponseObject.newErrResponse(e.getMessage()).toString(); } }