GroupNode.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. "use strict";
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = function (d, b) {
  4. extendStatics = Object.setPrototypeOf ||
  5. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  6. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  7. return extendStatics(d, b);
  8. };
  9. return function (d, b) {
  10. extendStatics(d, b);
  11. function __() { this.constructor = d; }
  12. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  13. };
  14. })();
  15. var __assign = (this && this.__assign) || function () {
  16. __assign = Object.assign || function(t) {
  17. for (var s, i = 1, n = arguments.length; i < n; i++) {
  18. s = arguments[i];
  19. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  20. t[p] = s[p];
  21. }
  22. return t;
  23. };
  24. return __assign.apply(this, arguments);
  25. };
  26. var __read = (this && this.__read) || function (o, n) {
  27. var m = typeof Symbol === "function" && o[Symbol.iterator];
  28. if (!m) return o;
  29. var i = m.call(o), r, ar = [], e;
  30. try {
  31. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  32. }
  33. catch (error) { e = { error: error }; }
  34. finally {
  35. try {
  36. if (r && !r.done && (m = i["return"])) m.call(i);
  37. }
  38. finally { if (e) throw e.error; }
  39. }
  40. return ar;
  41. };
  42. var __spread = (this && this.__spread) || function () {
  43. for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
  44. return ar;
  45. };
  46. Object.defineProperty(exports, "__esModule", { value: true });
  47. var core_1 = require("@logicflow/core");
  48. var NodeResize_1 = require("../../NodeResize");
  49. var defaultWidth = 500;
  50. var defaultHeight = 300;
  51. var DEFAULT_BOTTOM_Z_INDEX = -10000;
  52. var GroupNodeModel = /** @class */ (function (_super) {
  53. __extends(GroupNodeModel, _super);
  54. function GroupNodeModel() {
  55. var _this = _super !== null && _super.apply(this, arguments) || this;
  56. _this.isGroup = true;
  57. _this.unfoldedWidth = defaultWidth;
  58. _this.unfoldedHight = defaultHeight;
  59. return _this;
  60. }
  61. GroupNodeModel.prototype.initNodeData = function (data) {
  62. var _this = this;
  63. _super.prototype.initNodeData.call(this, data);
  64. var children = [];
  65. if (Array.isArray(data.children)) {
  66. children = data.children;
  67. }
  68. // 初始化组的子节点
  69. this.children = new Set(children);
  70. this.width = defaultWidth;
  71. this.height = defaultHeight;
  72. this.foldedWidth = 80;
  73. this.foldedHeight = 60;
  74. this.zIndex = DEFAULT_BOTTOM_Z_INDEX;
  75. this.radius = 0;
  76. this.text.editable = false;
  77. this.text.draggable = false;
  78. this.isRestrict = false;
  79. this.resizable = false;
  80. this.autoToFront = false;
  81. this.foldable = false;
  82. if (this.properties.isFolded === undefined) {
  83. this.properties.isFolded = false;
  84. }
  85. this.isFolded = this.properties.isFolded;
  86. // fixme: 虽然默认保存的分组不会收起,但是如果重写保存数据分组了,
  87. // 此处代码会导致多一个history记录
  88. setTimeout(function () {
  89. _this.isFolded && _this.foldGroup(_this.isFolded);
  90. });
  91. // this.foldGroup(this.isFolded);
  92. };
  93. GroupNodeModel.prototype.getResizeOutlineStyle = function () {
  94. var style = _super.prototype.getResizeOutlineStyle.call(this);
  95. style.stroke = 'none';
  96. return style;
  97. };
  98. /**
  99. * 折叠分组
  100. * 1. 折叠分组的宽高
  101. * 2. 处理分组子节点
  102. * 3. 处理连线
  103. */
  104. GroupNodeModel.prototype.foldGroup = function (isFolded) {
  105. var _this = this;
  106. this.setProperty('isFolded', isFolded);
  107. this.isFolded = isFolded;
  108. // step 1
  109. if (isFolded) {
  110. this.x = this.x - this.width / 2 + this.foldedWidth / 2;
  111. this.y = this.y - this.height / 2 + this.foldedHeight / 2;
  112. this.unfoldedWidth = this.width;
  113. this.unfoldedHight = this.height;
  114. this.width = this.foldedWidth;
  115. this.height = this.foldedHeight;
  116. }
  117. else {
  118. this.width = this.unfoldedWidth;
  119. this.height = this.unfoldedHight;
  120. this.x = this.x + this.width / 2 - this.foldedWidth / 2;
  121. this.y = this.y + this.height / 2 - this.foldedHeight / 2;
  122. }
  123. // step 2
  124. var allEdges = this.incoming.edges.concat(this.outgoing.edges);
  125. this.children.forEach(function (elementId) {
  126. var nodeModel = _this.graphModel.getElement(elementId);
  127. // FIX: https://github.com/didi/LogicFlow/issues/1007
  128. if (nodeModel.isGroup && !nodeModel.isFolded) {
  129. nodeModel.foldGroup(isFolded);
  130. }
  131. nodeModel.visible = !isFolded;
  132. allEdges = allEdges.concat(nodeModel.incoming.edges.concat(nodeModel.outgoing.edges));
  133. });
  134. // step 3
  135. this.foldEdge(isFolded, allEdges);
  136. };
  137. GroupNodeModel.prototype.getAnchorStyle = function (anchorInfo) {
  138. var style = _super.prototype.getAnchorStyle.call(this, anchorInfo);
  139. style.stroke = 'transparent';
  140. style.fill = 'transparent';
  141. style.hover.fill = 'transparent';
  142. style.hover.stroke = 'transparent';
  143. return style;
  144. };
  145. /**
  146. * 折叠分组的时候,处理分组自身的连线和分组内部子节点上的连线
  147. * 边的分类:
  148. * - 虚拟边:分组被收起时,表示分组本身与外部节点关系的边。
  149. * - 真实边:分组本身或者分组内部节点与外部节点节点(非收起分组)关系的边。
  150. * 如果一个分组,本身与外部节点有M条连线,且内部N个子节点与外部节点有连线,那么这个分组收起时会生成M+N条连线。
  151. * 折叠分组时:
  152. * - 原有的虚拟边删除;
  153. * - 创建一个虚拟边;
  154. * - 真实边则隐藏;
  155. * 展开分组是:
  156. * - 原有的虚拟边删除;
  157. * - 如果目外部点是收起的分组,则创建虚拟边;
  158. * - 如果外部节点是普通节点,则显示真实边;
  159. */
  160. GroupNodeModel.prototype.foldEdge = function (isFolded, allEdges) {
  161. var _this = this;
  162. allEdges.forEach(function (edgeModel, index) {
  163. var id = edgeModel.id, sourceNodeId = edgeModel.sourceNodeId, targetNodeId = edgeModel.targetNodeId, startPoint = edgeModel.startPoint, endPoint = edgeModel.endPoint, type = edgeModel.type, properties = edgeModel.properties, text = edgeModel.text;
  164. var data = {
  165. id: id + "__" + index,
  166. sourceNodeId: sourceNodeId,
  167. targetNodeId: targetNodeId,
  168. startPoint: startPoint,
  169. endPoint: endPoint,
  170. type: type,
  171. properties: properties,
  172. text: text === null || text === void 0 ? void 0 : text.value,
  173. };
  174. if (edgeModel.virtual) {
  175. _this.graphModel.deleteEdgeById(edgeModel.id);
  176. }
  177. var targetNodeIdGroup = _this.graphModel.group.getNodeGroup(targetNodeId);
  178. // 考虑目标节点本来就是分组的情况
  179. if (!targetNodeIdGroup) {
  180. targetNodeIdGroup = _this.graphModel.getNodeModelById(targetNodeId);
  181. }
  182. var sourceNodeIdGroup = _this.graphModel.group.getNodeGroup(sourceNodeId);
  183. if (!sourceNodeIdGroup) {
  184. sourceNodeIdGroup = _this.graphModel.getNodeModelById(sourceNodeId);
  185. }
  186. // 折叠时,处理未被隐藏的边的逻辑
  187. if (isFolded && edgeModel.visible !== false) {
  188. // 需要确认此分组节点是新连线的起点还是终点
  189. // 创建一个虚拟边,虚拟边相对真实边,起点或者终点从一起分组内部的节点成为了分组,
  190. // 如果需要被隐藏的边的起点在需要折叠的分组中,那么设置虚拟边的开始节点为此分组
  191. if (_this.children.has(sourceNodeId) || _this.id === sourceNodeId) {
  192. data.startPoint = undefined;
  193. data.sourceNodeId = _this.id;
  194. }
  195. else {
  196. data.endPoint = undefined;
  197. data.targetNodeId = _this.id;
  198. }
  199. // 如果边的起点和终点都在分组内部,则不创建新的虚拟边
  200. if (targetNodeIdGroup.id !== _this.id || sourceNodeIdGroup.id !== _this.id) {
  201. _this.createVirtualEdge(data);
  202. }
  203. edgeModel.visible = false;
  204. }
  205. // 展开时,处理被隐藏的边的逻辑
  206. if (!isFolded && edgeModel.visible === false) {
  207. // 展开分组时:判断真实边的起点和终点是否有任一节点在已折叠分组中,如果不是,则显示真实边。如果是,这修改这个边的对应目标节点id来创建虚拟边。
  208. if (targetNodeIdGroup && targetNodeIdGroup.isGroup && targetNodeIdGroup.isFolded) {
  209. data.targetNodeId = targetNodeIdGroup.id;
  210. data.endPoint = undefined;
  211. _this.createVirtualEdge(data);
  212. }
  213. else if (sourceNodeIdGroup && sourceNodeIdGroup.isGroup && sourceNodeIdGroup.isFolded) {
  214. data.sourceNodeId = sourceNodeIdGroup.id;
  215. data.startPoint = undefined;
  216. _this.createVirtualEdge(data);
  217. }
  218. else {
  219. edgeModel.visible = true;
  220. }
  221. }
  222. });
  223. };
  224. GroupNodeModel.prototype.createVirtualEdge = function (edgeData) {
  225. edgeData.pointsList = undefined;
  226. var model = this.graphModel.addEdge(edgeData);
  227. model.virtual = true;
  228. // 强制不保存group连线数据
  229. // model.getData = () => null;
  230. model.text.editable = false;
  231. model.isFoldedEdge = true;
  232. };
  233. GroupNodeModel.prototype.isInRange = function (_a) {
  234. var x1 = _a.x1, y1 = _a.y1, x2 = _a.x2, y2 = _a.y2;
  235. return x1 >= (this.x - this.width / 2)
  236. && x2 <= (this.x + this.width / 2)
  237. && y1 >= (this.y - this.height / 2)
  238. && y2 <= (this.y + this.height / 2);
  239. };
  240. GroupNodeModel.prototype.isAllowMoveTo = function (_a) {
  241. var x1 = _a.x1, y1 = _a.y1, x2 = _a.x2, y2 = _a.y2;
  242. return {
  243. x: x1 >= (this.x - this.width / 2) && x2 <= (this.x + this.width / 2),
  244. y: y1 >= (this.y - this.height / 2) && y2 <= (this.y + this.height / 2),
  245. };
  246. };
  247. GroupNodeModel.prototype.setAllowAppendChild = function (isAllow) {
  248. this.setProperty('groupAddable', isAllow);
  249. };
  250. /**
  251. * 添加分组子节点
  252. * @param id 节点id
  253. */
  254. GroupNodeModel.prototype.addChild = function (id) {
  255. this.children.add(id);
  256. };
  257. /**
  258. * 删除分组子节点
  259. * @param id 节点id
  260. */
  261. GroupNodeModel.prototype.removeChild = function (id) {
  262. this.children.delete(id);
  263. };
  264. GroupNodeModel.prototype.getAddableOutlineStyle = function () {
  265. return {
  266. stroke: '#FEB663',
  267. strokeWidth: 2,
  268. strokeDasharray: '4 4',
  269. fill: 'transparent',
  270. };
  271. };
  272. GroupNodeModel.prototype.getData = function () {
  273. var data = _super.prototype.getData.call(this);
  274. data.children = __spread(this.children);
  275. var properties = data.properties;
  276. delete properties.groupAddable;
  277. delete properties.isFolded;
  278. return data;
  279. };
  280. GroupNodeModel.prototype.getHistoryData = function () {
  281. var data = _super.prototype.getData.call(this);
  282. data.children = __spread(this.children);
  283. data.isGroup = true;
  284. var properties = data.properties;
  285. delete properties.groupAddable;
  286. if (properties.isFolded) { // 如果分组被折叠
  287. data.x = data.x + this.unfoldedWidth / 2 - this.foldedWidth / 2;
  288. data.y = data.y + this.unfoldedHight / 2 - this.foldedHeight / 2;
  289. }
  290. return data;
  291. };
  292. /**
  293. * 是否允许此节点添加到此分组中
  294. */
  295. GroupNodeModel.prototype.isAllowAppendIn = function (nodeData) {
  296. return true;
  297. };
  298. /**
  299. * 当groupA被添加到groupB中时,将groupB及groupB所属的group的zIndex减1
  300. */
  301. GroupNodeModel.prototype.toBack = function () {
  302. this.zIndex--;
  303. };
  304. return GroupNodeModel;
  305. }(NodeResize_1.RectResize.model));
  306. var GroupNode = /** @class */ (function (_super) {
  307. __extends(GroupNode, _super);
  308. function GroupNode() {
  309. return _super !== null && _super.apply(this, arguments) || this;
  310. }
  311. GroupNode.prototype.getControlGroup = function () {
  312. var _a = this.props.model, resizable = _a.resizable, properties = _a.properties;
  313. return resizable && !properties.isFolded ? _super.prototype.getControlGroup.call(this) : null;
  314. };
  315. GroupNode.prototype.getAddableShape = function () {
  316. var _a = this.props.model, width = _a.width, height = _a.height, x = _a.x, y = _a.y, radius = _a.radius, properties = _a.properties;
  317. if (!properties.groupAddable)
  318. return null;
  319. var strokeWidth = this.props.model.getNodeStyle().strokeWidth;
  320. var style = this.props.model.getAddableOutlineStyle();
  321. var newWidth = width + strokeWidth + 8;
  322. var newHeight = height + strokeWidth + 8;
  323. return core_1.h('rect', __assign(__assign({}, style), { width: newWidth, height: newHeight, x: x - newWidth / 2, y: y - newHeight / 2, rx: radius, ry: radius }));
  324. };
  325. GroupNode.prototype.getFoldIcon = function () {
  326. var model = this.props.model;
  327. var foldX = model.x - model.width / 2 + 5;
  328. var foldY = model.y - model.height / 2 + 5;
  329. if (!model.foldable)
  330. return null;
  331. var iconIcon = core_1.h('path', {
  332. fill: 'none',
  333. stroke: '#818281',
  334. strokeWidth: 2,
  335. 'pointer-events': 'none',
  336. d: model.properties.isFolded
  337. ? "M " + (foldX + 3) + "," + (foldY + 6) + " " + (foldX + 11) + "," + (foldY + 6) + " M" + (foldX + 7) + "," + (foldY + 2) + " " + (foldX + 7) + "," + (foldY + 10)
  338. : "M " + (foldX + 3) + "," + (foldY + 6) + " " + (foldX + 11) + "," + (foldY + 6) + " ",
  339. });
  340. return core_1.h('g', {}, [
  341. core_1.h('rect', {
  342. height: 12,
  343. width: 14,
  344. rx: 2,
  345. ry: 2,
  346. strokeWidth: 1,
  347. fill: '#F4F5F6',
  348. stroke: '#CECECE',
  349. cursor: 'pointer',
  350. x: model.x - model.width / 2 + 5,
  351. y: model.y - model.height / 2 + 5,
  352. onClick: function () {
  353. model.foldGroup(!model.properties.isFolded);
  354. },
  355. }),
  356. iconIcon,
  357. ]);
  358. };
  359. GroupNode.prototype.getResizeShape = function () {
  360. return core_1.h('g', {}, [
  361. this.getAddableShape(),
  362. _super.prototype.getResizeShape.call(this),
  363. this.getFoldIcon(),
  364. ]);
  365. };
  366. return GroupNode;
  367. }(NodeResize_1.RectResize.view));
  368. exports.default = {
  369. type: 'group',
  370. view: GroupNode,
  371. model: GroupNodeModel,
  372. };