端到端流程 节点展开与闭合代码优化 节点闭合 之前因展开移动的节点随着节点闭合而归位

This commit is contained in:
qinoy 2023-06-12 10:08:25 +08:00
parent a91dd7482b
commit 57124ad5dd
7 changed files with 167 additions and 14 deletions

View File

@ -3,6 +3,9 @@ package com.actionsoft.apps.coe.method.process.subprocess.graph;
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.AbstractAdjMatrix;
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.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;
@ -31,6 +34,8 @@ public class GraphNodeCloseHandle {
private JSONObject childProcessDefine; // 要关闭的子流程模型信息
private JSONObject endToEndProcessDefine; // 总图的模型信息
private JSONObject scopeLimitationShape; // 范围标注框
private AbstractDefinitionHandle definitionHandle;
private AbstractDefinitionHandle subProcessNodeDefineHandle;
private final ReentrantLock lock = new ReentrantLock();
@ -40,7 +45,14 @@ public class GraphNodeCloseHandle {
apiManager = CoeDesignerAPIManager.getInstance();
definitionHandle = new DefinitionThreadUnSafe(endToEndProcessDefineStr);
try {
relationFileId = SubProcessNodeDefineUtil.getSubProcessNodeRelationFileId(repositoryId, shapeId);
subProcessNodeDefineHandle = new DefinitionThreadUnSafe(SubProcessNodeDefineUtil.readSubProcessNodeDefine(repositoryId, shapeId));
readChildProcessDefine();
readCurrentProcessDefine(endToEndProcessDefineStr);
} catch (AWSException e) {
@ -105,14 +117,17 @@ public class GraphNodeCloseHandle {
// 2根据现有连线关系创建邻接矩阵
NodeCloseAdjMatrix closeAdjMatrix = buildEndToEndGraphAdjMatrix();
closeAdjMatrix.buildAdjMatrix();
// 3收集现有元素坐标
JSONObject elements = readEndToEndGraphElements();
// 更新因节点展开后 坐标发生变化的节点坐标
String direction = definitionHandle.getProcessProperties().getString("direction");
graphPartNodePoiRenderAgain(elements, direction, subProcessNode);
// 3收集现有元素坐标
double[][] vertexPosition = closeAdjMatrix.getVertexPosition(elements);
// 4删除现有连线
removeEndToEndGraphOldLinker();
// 5构建新的连线
JSONObject processProperties = endToEndProcessDefine.getJSONObject("processProperties");
String direction = processProperties.getString("direction");
NodeCloseLinkerRender linkerRender = new NodeCloseLinkerRender(vertexPosition, closeAdjMatrix, scopeLimitationShape);
JSONArray linkers = linkerRender.toAssembleLinker(direction, shapeId);
for (Object o : linkers) {
@ -136,6 +151,48 @@ public class GraphNodeCloseHandle {
}
/**
* 节点闭合 部分节点坐标再次更新
*/
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);
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;
JSONObject eleProps = ele.getJSONObject("props");
if ("vertically".equals(direction)){ // 垂直布局
if (x + scope[0] < eleProps.getDoubleValue("x")) {
eleProps.put("x", eleProps.getDoubleValue("x") - scope[0] + SubProcessConst.SUB_PROCESS_SHAPE_W);
}
if (y +scope[1] < eleProps.getDoubleValue("y")){
eleProps.put("y", eleProps.getDoubleValue("y") - scope[1] + SubProcessConst.SUB_PROCESS_SHAPE_H);
}else if (y < eleProps.getDoubleValue("y") && eleProps.getDoubleValue("y") < y + scope[1]){
eleProps.put("y", y);
}
}else { // 横向布局
if (x + scope[0] < eleProps.getDoubleValue("x")){ // 节点在范围框右侧的节点
eleProps.put("x", eleProps.getDoubleValue("x") - scope[0] + SubProcessConst.SUB_PROCESS_SHAPE_W);
}else if (x < eleProps.getDoubleValue("x")
&& eleProps.getDoubleValue("x") < x + scope[0]
&& y + scope[1] < eleProps.getDoubleValue("y")){
eleProps.put("x", x);
}
if (y + scope[1] < eleProps.getDoubleValue("y")){ // 节点在范围框下方的节点
eleProps.put("y", eleProps.getDoubleValue("y") - scope[1] + SubProcessConst.SUB_PROCESS_SHAPE_H);
}
}
}
}
/**
* 删除总图中节点展开前的连线
*/

View File

@ -90,7 +90,6 @@ public class GraphNodeExpandHandle {
*/
private void toAssembleScopeLimitationShape() throws AWSException{
JSONObject scopeLimitationShape = ShapeUtil.getProcessShapeDefinition(SubProcessConst.SUB_PROCESS_METHOD_ID, "展开范围标注");
JSONObject childProcessPage = childProcessDefine.getJSONObject("page");
JSONObject childProcessElements = childProcessDefine.getJSONObject("elements");
JSONObject childProcessEleMaxX = childProcessElements.keySet()
.stream()
@ -113,8 +112,6 @@ public class GraphNodeExpandHandle {
.map(key -> childProcessElements.getJSONObject(key).getJSONObject("props"))
.min((o1, o2) -> Double.compare(o1.getDoubleValue("y"), o2.getDoubleValue("y"))).get();
// 当前节点所标识的子流程文件的 画布宽度与高度 减去边距
// double childProcessPageWidth = childProcessPage.getDoubleValue("width") - childProcessPage.getDoubleValue("padding") * 2;
// double childProcessPageHeight = childProcessPage.getDoubleValue("height") - childProcessPage.getDoubleValue("padding") * 2;
double scopeShapeW = childProcessEleMaxX.getDoubleValue("x") + childProcessEleMaxX.getDoubleValue("w") - childProcessEleMixX.getDoubleValue("x") + SubProcessConst.SCOPE_SHAPE_PADDING;
double scopeShapeH = childProcessEleMaxY.getDoubleValue("y") + childProcessEleMaxY.getDoubleValue("h") - childProcessEleMinY.getDoubleValue("y") + SubProcessConst.SCOPE_SHAPE_PADDING;

View File

@ -24,24 +24,24 @@ public abstract class AbstractDefinitionHandle {
* 获取 elements 属性
* @return
*/
protected abstract JSONObject getElements();
public abstract JSONObject getElements();
/**
* 获取 processProperties 属性
* @return
*/
protected abstract JSONObject getProcessProperties();
public abstract JSONObject getProcessProperties();
/**
* 删除 elements 属性中元素
* @param key
*/
protected abstract void removeShape(String key);
public abstract void removeShape(String key);
/**
* 添加元素到 elements
* @param key
* @param ele
*/
protected abstract void addEle(String key, JSONObject ele);
public abstract void addEle(String key, JSONObject ele);
}

View File

@ -15,22 +15,22 @@ public class DefinitionThreadUnSafe extends AbstractDefinitionHandle {
}
@Override
protected JSONObject getElements() {
public JSONObject getElements() {
return getDefine().getJSONObject("elements");
}
@Override
protected JSONObject getProcessProperties() {
public JSONObject getProcessProperties() {
return getDefine().getJSONObject("processProperties");
}
@Override
protected void removeShape(String key) {
public void removeShape(String key) {
getElements().remove(key);
}
@Override
protected void addEle(String key, JSONObject ele) {
public void addEle(String key, JSONObject ele) {
getElements().put(key, ele);
}
}

View File

@ -0,0 +1,9 @@
package com.actionsoft.apps.coe.method.process.subprocess.graph.util;
/**
* @author oYang
* @Description TODO
* @createTime 2023年06月09日 16:26:00
*/
public class GraphNodeCloseUtil {
}

View File

@ -0,0 +1,90 @@
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.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.bpms.util.UtilString;
import com.actionsoft.exception.AWSException;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
/**
* @author oYang
* @Description 子流程节点所关联的 define 工具类
* @createTime 2023年06月09日 16:54:00
*/
public class SubProcessNodeDefineUtil {
/**
* 读取子流程节点 所关联的文件的 define
* @param repositoryId
* @param shapeId
* @return
*/
public static String readSubProcessNodeDefine(String repositoryId, String shapeId) throws AWSException{
String relationFileId = getSubProcessNodeRelationFileId(repositoryId, shapeId);
// 先去与总图存储的同级目录下读取 如果为空说明是初次读取
String subProcessNodeDefineStr = CoeDesignerAPIManager.getInstance().getChildProcessDefine(repositoryId, 0, relationFileId);
if (UtilString.isEmpty(subProcessNodeDefineStr)){ // 初次读取 去源文件目录读取
BaseModel childProcessBaseModel = CoeDesignerAPIManager.getInstance().getDefinition(relationFileId, 0);
if (childProcessBaseModel == null)
throw new AWSException("当前子流程节点内部可能没有图形元素,可以去添加后展开");
subProcessNodeDefineStr = childProcessBaseModel.getDefinition();
}
return subProcessNodeDefineStr;
}
/**
* 获取子流程节点 所关联的文件ID
* @param repositoryId
* @param shapeId
* @return
* @throws AWSException
*/
public static String getSubProcessNodeRelationFileId(String repositoryId, String shapeId) throws AWSException{
List<DesignerShapeRelationModel> relationModelList = DesignerShapeRelationCache.getListByAttrId(repositoryId, shapeId, SubProcessConst.CHILD_PROCESS);
DesignerShapeRelationModel relationModel = relationModelList.stream().findFirst().orElse(null);
if (relationModel == null)
throw new AWSException("未找到当前节点所标识的子流程文件信息");
return relationModel.getRelationFileId();
}
/**
* 计算子流程节点 展开后的宽度与高度
* @param definitionHandle
* @return double[]{w, h}
*/
public static double[] calculateSubProcessNodeExpandScope(AbstractDefinitionHandle definitionHandle){
JSONObject childProcessElements = definitionHandle.getElements();
JSONObject childProcessEleMaxX = childProcessElements.keySet()
.stream()
.filter(key -> !"linker".equals(childProcessElements.getJSONObject(key).getString("name")))
.map(key -> childProcessElements.getJSONObject(key).getJSONObject("props"))
.max((o1, o2) -> Double.compare(o1.getDoubleValue("x"), o2.getDoubleValue("x"))).get();
JSONObject childProcessEleMixX = childProcessElements.keySet()
.stream()
.filter(key -> !"linker".equals(childProcessElements.getJSONObject(key).getString("name")))
.map(key -> childProcessElements.getJSONObject(key).getJSONObject("props"))
.min((o1, o2) -> Double.compare(o1.getDoubleValue("x"), o2.getDoubleValue("x"))).get();
JSONObject childProcessEleMaxY = childProcessElements.keySet()
.stream()
.filter(key -> !"linker".equals(childProcessElements.getJSONObject(key).getString("name")))
.map(key -> childProcessElements.getJSONObject(key).getJSONObject("props"))
.max((o1, o2) -> Double.compare(o1.getDoubleValue("y"), o2.getDoubleValue("y"))).get();
JSONObject childProcessEleMinY = childProcessElements.keySet()
.stream()
.filter(key -> !"linker".equals(childProcessElements.getJSONObject(key).getString("name")))
.map(key -> childProcessElements.getJSONObject(key).getJSONObject("props"))
.min((o1, o2) -> Double.compare(o1.getDoubleValue("y"), o2.getDoubleValue("y"))).get();
// 当前节点所标识的子流程文件的 画布宽度与高度 减去边距
double scopeShapeW = childProcessEleMaxX.getDoubleValue("x") + childProcessEleMaxX.getDoubleValue("w") - childProcessEleMixX.getDoubleValue("x") + SubProcessConst.SCOPE_SHAPE_PADDING;
double scopeShapeH = childProcessEleMaxY.getDoubleValue("y") + childProcessEleMaxY.getDoubleValue("h") - childProcessEleMinY.getDoubleValue("y") + SubProcessConst.SCOPE_SHAPE_PADDING;
return new double[]{scopeShapeW, scopeShapeH};
}
}