@plait/mind 0.2.0-next.3 → 0.2.0-next.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/draw/indented-link.d.ts +2 -2
- package/draw/link/logic-link.d.ts +2 -2
- package/draw/link.d.ts +2 -2
- package/esm2020/draw/indented-link.mjs +7 -6
- package/esm2020/draw/link/logic-link.mjs +7 -6
- package/esm2020/draw/link.mjs +8 -7
- package/esm2020/draw/shape.mjs +3 -3
- package/esm2020/drawer/quick-insert.drawer.mjs +9 -8
- package/esm2020/interfaces/element.mjs +13 -2
- package/esm2020/node.component.mjs +6 -6
- package/esm2020/plugins/emoji/emoji-base.component.mjs +4 -2
- package/esm2020/plugins/emoji/emoji.drawer.mjs +2 -1
- package/esm2020/plugins/with-abstract.mjs +2 -2
- package/esm2020/plugins/with-dnd.mjs +2 -2
- package/esm2020/plugins/with-mind.mjs +3 -2
- package/esm2020/transforms/layout.mjs +8 -2
- package/esm2020/utils/abstract/common.mjs +49 -15
- package/esm2020/utils/abstract/resize.mjs +2 -2
- package/esm2020/utils/clipboard.mjs +10 -3
- package/esm2020/utils/draw-placeholder.mjs +20 -20
- package/esm2020/utils/index.mjs +2 -2
- package/esm2020/utils/mind.mjs +30 -21
- package/esm2020/utils/node-style/branch.mjs +28 -0
- package/esm2020/utils/node-style/index.mjs +3 -0
- package/esm2020/utils/node-style/node.mjs +22 -0
- package/esm2020/utils/path.mjs +3 -3
- package/fesm2015/plait-mind.mjs +1449 -1377
- package/fesm2015/plait-mind.mjs.map +1 -1
- package/fesm2020/plait-mind.mjs +1451 -1379
- package/fesm2020/plait-mind.mjs.map +1 -1
- package/interfaces/element.d.ts +3 -2
- package/package.json +1 -1
- package/plugins/emoji/emoji-base.component.d.ts +3 -1
- package/utils/abstract/common.d.ts +6 -1
- package/utils/abstract/resize.d.ts +1 -1
- package/utils/draw-placeholder.d.ts +8 -8
- package/utils/index.d.ts +1 -1
- package/utils/mind.d.ts +2 -1
- package/utils/node-style/branch.d.ts +7 -0
- package/utils/node-style/index.d.ts +2 -0
- package/utils/node-style/node.d.ts +3 -0
- package/esm2020/utils/colors.mjs +0 -41
- package/utils/colors.d.ts +0 -4
package/fesm2015/plait-mind.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Component, ChangeDetectionStrategy, NgModule, Directive, Input } from '@angular/core';
|
|
3
3
|
import * as i2 from '@plait/core';
|
|
4
|
-
import { distanceBetweenPointAndRectangle, PlaitElement,
|
|
5
|
-
import { isIndentedLayout, MindLayoutType, isStandardLayout, isTopLayout, isLeftLayout, isHorizontalLogicLayout, isVerticalLogicLayout, isBottomLayout, isRightLayout, isHorizontalLayout,
|
|
4
|
+
import { distanceBetweenPointAndRectangle, PlaitElement, PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, ELEMENT_TO_COMPONENT, Transforms, idCreator, isNullOrUndefined, clearSelectedElement, addSelectedElement, drawRoundRectangle, getRectangleByElements, RectangleClient, getSelectedElements, createG, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, depthFirstRecursion, PlaitModule, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
|
|
5
|
+
import { AbstractNode, isChildOfAbstract, isIndentedLayout, getAbstractLayout, MindLayoutType, isStandardLayout, isTopLayout, isLeftLayout, isHorizontalLogicLayout, isVerticalLogicLayout, isBottomLayout, isRightLayout, isHorizontalLayout, getCorrectStartEnd, ConnectingPosition, GlobalLayout } from '@plait/layouts';
|
|
6
6
|
import { getSizeByText, ROOT_DEFAULT_HEIGHT, TEXT_DEFAULT_HEIGHT, drawRichtext, updateForeignObject, createForeignObject, updateRichText, setFullSelectionAndFocus, getRichtextContentSize, hasEditableTarget, RichtextModule } from '@plait/richtext';
|
|
7
7
|
import { fromEvent, Subject, timer } from 'rxjs';
|
|
8
8
|
import { take, takeUntil, filter, debounceTime } from 'rxjs/operators';
|
|
9
|
-
import { Node,
|
|
9
|
+
import { Node, Path as Path$1, Editor, Operation } from 'slate';
|
|
10
10
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
11
11
|
import { isKeyHotkey } from 'is-hotkey';
|
|
12
12
|
import * as i1 from '@angular/common';
|
|
@@ -68,6 +68,250 @@ function hitMindElement(board, point, element) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* get correctly layout:
|
|
73
|
+
* 1. root is standard -> left or right
|
|
74
|
+
* 2. correct layout by incorrect layout direction
|
|
75
|
+
* @param element
|
|
76
|
+
*/
|
|
77
|
+
const getCorrectLayoutByElement = (element) => {
|
|
78
|
+
var _a;
|
|
79
|
+
const { root } = findUpElement(element);
|
|
80
|
+
const rootLayout = root.layout || getDefaultLayout();
|
|
81
|
+
let correctRootLayout = rootLayout;
|
|
82
|
+
if (element.isRoot) {
|
|
83
|
+
return correctRootLayout;
|
|
84
|
+
}
|
|
85
|
+
const component = PlaitElement.getComponent(element);
|
|
86
|
+
let layout = element.layout;
|
|
87
|
+
let parentComponent = null;
|
|
88
|
+
let parent = component.parent.origin;
|
|
89
|
+
while (!layout && parent) {
|
|
90
|
+
parentComponent = PlaitElement.getComponent(parent);
|
|
91
|
+
layout = parentComponent.node.origin.layout;
|
|
92
|
+
parent = (_a = parentComponent.parent) === null || _a === void 0 ? void 0 : _a.origin;
|
|
93
|
+
}
|
|
94
|
+
if ((AbstractNode.isAbstract(element) || isChildOfAbstract(MindElement.getNode(element))) &&
|
|
95
|
+
isIndentedLayout(layout)) {
|
|
96
|
+
return getAbstractLayout(layout);
|
|
97
|
+
}
|
|
98
|
+
// handle root standard
|
|
99
|
+
if (rootLayout === MindLayoutType.standard) {
|
|
100
|
+
correctRootLayout = (component === null || component === void 0 ? void 0 : component.node.left) ? MindLayoutType.left : MindLayoutType.right;
|
|
101
|
+
}
|
|
102
|
+
if (parentComponent && parentComponent.node.origin.isRoot) {
|
|
103
|
+
return correctRootLayout;
|
|
104
|
+
}
|
|
105
|
+
if (layout) {
|
|
106
|
+
const incorrectDirection = getInCorrectLayoutDirection(correctRootLayout, layout);
|
|
107
|
+
if (incorrectDirection) {
|
|
108
|
+
return correctLayoutByDirection(layout, incorrectDirection);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return layout;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return correctRootLayout;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const getBranchLayouts = (element) => {
|
|
120
|
+
const layouts = [];
|
|
121
|
+
if (element.layout) {
|
|
122
|
+
//getCorrectLayoutByElement含有递归操作,getBranchMindmapLayouts本身也有递归操作,有待优化
|
|
123
|
+
layouts.unshift(getCorrectLayoutByElement(element));
|
|
124
|
+
}
|
|
125
|
+
let parent = findParentElement(element);
|
|
126
|
+
while (parent) {
|
|
127
|
+
if (parent.layout) {
|
|
128
|
+
layouts.unshift(parent.layout);
|
|
129
|
+
}
|
|
130
|
+
parent = findParentElement(parent);
|
|
131
|
+
}
|
|
132
|
+
return layouts;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* get available sub layouts by element
|
|
137
|
+
* @param element
|
|
138
|
+
* @returns MindLayoutType[]
|
|
139
|
+
*/
|
|
140
|
+
const getAvailableSubLayoutsByElement = (element) => {
|
|
141
|
+
const parentElement = findParentElement(element);
|
|
142
|
+
if (parentElement) {
|
|
143
|
+
const branchLayouts = getBranchLayouts(parentElement);
|
|
144
|
+
if (branchLayouts[0] === MindLayoutType.standard) {
|
|
145
|
+
const node = MindElement.getNode(element);
|
|
146
|
+
branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
|
|
147
|
+
}
|
|
148
|
+
const currentLayoutDirections = getBranchDirectionsByLayouts(branchLayouts);
|
|
149
|
+
let availableSubLayouts = getAvailableSubLayoutsByLayoutDirections(currentLayoutDirections);
|
|
150
|
+
const parentLayout = [branchLayouts[branchLayouts.length - 1]];
|
|
151
|
+
const parentDirections = getBranchDirectionsByLayouts(parentLayout);
|
|
152
|
+
const parentAvailableSubLayouts = getAvailableSubLayoutsByLayoutDirections(parentDirections);
|
|
153
|
+
availableSubLayouts = availableSubLayouts.filter(layout => parentAvailableSubLayouts.some(parentAvailableSubLayout => parentAvailableSubLayout === layout));
|
|
154
|
+
return availableSubLayouts;
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 获取父节点布局类型
|
|
161
|
+
* @param element
|
|
162
|
+
* @returns MindLayoutType
|
|
163
|
+
*/
|
|
164
|
+
const getLayoutParentByElement = (element) => {
|
|
165
|
+
let parent = findParentElement(element);
|
|
166
|
+
while (parent) {
|
|
167
|
+
if (parent.layout) {
|
|
168
|
+
return parent.layout;
|
|
169
|
+
}
|
|
170
|
+
parent = findParentElement(parent);
|
|
171
|
+
}
|
|
172
|
+
return getDefaultLayout();
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const getLayoutByElement = (element) => {
|
|
176
|
+
const layout = element.layout;
|
|
177
|
+
if (layout) {
|
|
178
|
+
return layout;
|
|
179
|
+
}
|
|
180
|
+
if (AbstractNode.isAbstract(element) ||
|
|
181
|
+
(isChildOfAbstract(MindElement.getNode(element)) && isIndentedLayout(layout))) {
|
|
182
|
+
const parentLayout = getLayoutParentByElement(element);
|
|
183
|
+
return getAbstractLayout(parentLayout);
|
|
184
|
+
}
|
|
185
|
+
return getLayoutParentByElement(element);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const MindQueries = {
|
|
189
|
+
getAvailableSubLayoutsByElement,
|
|
190
|
+
getLayoutParentByElement,
|
|
191
|
+
getBranchLayouts,
|
|
192
|
+
getLayoutByElement,
|
|
193
|
+
getCorrectLayoutByElement
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const PlaitMind = {
|
|
197
|
+
isMind: (value) => {
|
|
198
|
+
return value.type === 'mindmap';
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
const MindElement = {
|
|
202
|
+
hasLayout(value, layout) {
|
|
203
|
+
const _layout = MindQueries.getLayoutByElement(value);
|
|
204
|
+
return _layout === layout;
|
|
205
|
+
},
|
|
206
|
+
isIndentedLayout(value) {
|
|
207
|
+
const _layout = MindQueries.getLayoutByElement(value);
|
|
208
|
+
return isIndentedLayout(_layout);
|
|
209
|
+
},
|
|
210
|
+
isMindElement(board, element) {
|
|
211
|
+
const path = PlaitBoard.findPath(board, element);
|
|
212
|
+
const rootElement = PlaitNode.get(board, path.slice(0, 1));
|
|
213
|
+
if (PlaitMind.isMind(rootElement)) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
getParent(node) {
|
|
221
|
+
if (PlaitMind.isMind(node)) {
|
|
222
|
+
throw new Error('mind root node can not get parent');
|
|
223
|
+
}
|
|
224
|
+
const parent = NODE_TO_PARENT.get(node);
|
|
225
|
+
return parent;
|
|
226
|
+
},
|
|
227
|
+
getRoot(board, element) {
|
|
228
|
+
const path = PlaitBoard.findPath(board, element);
|
|
229
|
+
return PlaitNode.get(board, path.slice(0, 1));
|
|
230
|
+
},
|
|
231
|
+
getAncestors(board, element) {
|
|
232
|
+
const path = PlaitBoard.findPath(board, element);
|
|
233
|
+
const parents = [];
|
|
234
|
+
for (const p of Path.ancestors(path, { reverse: true })) {
|
|
235
|
+
const n = PlaitNode.get(board, p);
|
|
236
|
+
if (n && !PlaitBoard.isBoard(n)) {
|
|
237
|
+
parents.push(n);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return parents;
|
|
241
|
+
},
|
|
242
|
+
getNode(element) {
|
|
243
|
+
const node = ELEMENT_TO_NODE.get(element);
|
|
244
|
+
if (!node) {
|
|
245
|
+
throw new Error(`can not get node from ${JSON.stringify(element)}`);
|
|
246
|
+
}
|
|
247
|
+
return node;
|
|
248
|
+
},
|
|
249
|
+
hasEmojis(element) {
|
|
250
|
+
if (element.data.emojis) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
getEmojis(element) {
|
|
258
|
+
return element.data.emojis;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const MindNode = {
|
|
263
|
+
get(root, path) {
|
|
264
|
+
let node = root;
|
|
265
|
+
for (let i = 0; i < path.length; i++) {
|
|
266
|
+
const p = path[i];
|
|
267
|
+
if (!node || !node.children || !node.children[p]) {
|
|
268
|
+
throw new Error(`Cannot find a descendant at path [${path}]`);
|
|
269
|
+
}
|
|
270
|
+
node = node.children[p];
|
|
271
|
+
}
|
|
272
|
+
return node;
|
|
273
|
+
},
|
|
274
|
+
isEquals(node, otherNode) {
|
|
275
|
+
const hasSameSize = node.x === otherNode.x && node.y === otherNode.y && node.width === otherNode.width && node.height === otherNode.height;
|
|
276
|
+
const hasSameOrigin = node.origin === otherNode.origin;
|
|
277
|
+
let hasSameParentOriginChildren = false;
|
|
278
|
+
if (node.parent && otherNode.parent) {
|
|
279
|
+
hasSameParentOriginChildren = node.parent.origin.children == otherNode.parent.origin.children;
|
|
280
|
+
}
|
|
281
|
+
return hasSameSize && hasSameOrigin && hasSameParentOriginChildren;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
var LayoutDirection;
|
|
286
|
+
(function (LayoutDirection) {
|
|
287
|
+
LayoutDirection["top"] = "top";
|
|
288
|
+
LayoutDirection["right"] = "right";
|
|
289
|
+
LayoutDirection["bottom"] = "bottom";
|
|
290
|
+
LayoutDirection["left"] = "left";
|
|
291
|
+
})(LayoutDirection || (LayoutDirection = {}));
|
|
292
|
+
const LayoutDirectionsMap = {
|
|
293
|
+
[MindLayoutType.right]: [LayoutDirection.right],
|
|
294
|
+
[MindLayoutType.left]: [LayoutDirection.left],
|
|
295
|
+
[MindLayoutType.upward]: [LayoutDirection.top],
|
|
296
|
+
[MindLayoutType.downward]: [LayoutDirection.bottom],
|
|
297
|
+
[MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
|
|
298
|
+
[MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
|
|
299
|
+
[MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
|
|
300
|
+
[MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
var AbstractHandlePosition;
|
|
304
|
+
(function (AbstractHandlePosition) {
|
|
305
|
+
AbstractHandlePosition["start"] = "start";
|
|
306
|
+
AbstractHandlePosition["end"] = "end";
|
|
307
|
+
})(AbstractHandlePosition || (AbstractHandlePosition = {}));
|
|
308
|
+
var AbstractResizeState;
|
|
309
|
+
(function (AbstractResizeState) {
|
|
310
|
+
AbstractResizeState["start"] = "start";
|
|
311
|
+
AbstractResizeState["resizing"] = "resizing";
|
|
312
|
+
AbstractResizeState["end"] = "end";
|
|
313
|
+
})(AbstractResizeState || (AbstractResizeState = {}));
|
|
314
|
+
|
|
71
315
|
const getBranchDirectionsByLayouts = (branchLayouts) => {
|
|
72
316
|
const branchDirections = [];
|
|
73
317
|
branchLayouts.forEach(l => {
|
|
@@ -171,1468 +415,1283 @@ const getRootLayout = (root) => {
|
|
|
171
415
|
return root.layout || getDefaultLayout();
|
|
172
416
|
};
|
|
173
417
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
let parent = findParentElement(element);
|
|
180
|
-
while (parent) {
|
|
181
|
-
if (parent.shape) {
|
|
182
|
-
return parent.shape;
|
|
183
|
-
}
|
|
184
|
-
parent = findParentElement(parent);
|
|
185
|
-
}
|
|
186
|
-
return MindNodeShape.roundRectangle;
|
|
187
|
-
};
|
|
418
|
+
function enterNodeEditing(element) {
|
|
419
|
+
const component = ELEMENT_TO_COMPONENT.get(element);
|
|
420
|
+
component.startEditText(false, false);
|
|
421
|
+
}
|
|
188
422
|
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function drawLink(roughSVG, node, child, defaultStroke = null, isHorizontal = true, needDrawUnderline = true) {
|
|
202
|
-
var _a;
|
|
203
|
-
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
204
|
-
const layout = MindQueries.getCorrectLayoutByElement(node.origin);
|
|
205
|
-
if (isHorizontal) {
|
|
206
|
-
if (!isChildRight(node, child)) {
|
|
207
|
-
beginNode = child;
|
|
208
|
-
endNode = node;
|
|
423
|
+
const separateChildren = (parentElement) => {
|
|
424
|
+
const rightNodeCount = parentElement.rightNodeCount;
|
|
425
|
+
const children = parentElement.children;
|
|
426
|
+
let rightChildren = [], leftChildren = [];
|
|
427
|
+
for (let i = 0; i < children.length; i++) {
|
|
428
|
+
const child = children[i];
|
|
429
|
+
if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
|
|
430
|
+
rightChildren.push(child);
|
|
431
|
+
continue;
|
|
209
432
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
endY = node.y + node.height - node.vGap;
|
|
222
|
-
}
|
|
433
|
+
if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
|
|
434
|
+
leftChildren.push(child);
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (i < rightNodeCount) {
|
|
438
|
+
rightChildren.push(child);
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
leftChildren.push(child);
|
|
223
442
|
}
|
|
224
443
|
}
|
|
444
|
+
return { leftChildren, rightChildren };
|
|
445
|
+
};
|
|
446
|
+
const isSetAbstract = (element) => {
|
|
447
|
+
return !!getCorrespondingAbstract(element);
|
|
448
|
+
};
|
|
449
|
+
const canSetAbstract = (element) => {
|
|
450
|
+
return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
|
|
451
|
+
};
|
|
452
|
+
const setAbstract = (board, elements) => {
|
|
453
|
+
let elementGroup = filterChildElement(elements);
|
|
454
|
+
const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
|
|
455
|
+
abstractIncludedGroups.forEach((group, index) => {
|
|
456
|
+
const groupParent = parentElements[index];
|
|
457
|
+
setAbstractByElements(board, groupParent, group);
|
|
458
|
+
});
|
|
459
|
+
};
|
|
460
|
+
const setAbstractByElements = (board, groupParent, group) => {
|
|
461
|
+
const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
|
|
462
|
+
const rightNodeCount = groupParent === null || groupParent === void 0 ? void 0 : groupParent.rightNodeCount;
|
|
463
|
+
const start = indexArray[0], end = indexArray[indexArray.length - 1];
|
|
464
|
+
if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
|
|
465
|
+
rightNodeCount &&
|
|
466
|
+
start < rightNodeCount &&
|
|
467
|
+
end >= rightNodeCount) {
|
|
468
|
+
const childrenLength = groupParent.children.length;
|
|
469
|
+
const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
|
|
470
|
+
const leftChildren = indexArray.filter(index => index >= rightNodeCount);
|
|
471
|
+
const rightChildren = indexArray.filter(index => index < rightNodeCount);
|
|
472
|
+
insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
|
|
473
|
+
insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
|
|
474
|
+
}
|
|
225
475
|
else {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
endNode = node;
|
|
229
|
-
}
|
|
230
|
-
beginX = beginNode.x + beginNode.width / 2;
|
|
231
|
-
beginY = beginNode.y + beginNode.height - beginNode.vGap;
|
|
232
|
-
endX = endNode.x + endNode.width / 2;
|
|
233
|
-
endY = endNode.y + endNode.vGap;
|
|
476
|
+
const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
|
|
477
|
+
insertAbstractNode(board, path, start, end);
|
|
234
478
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
479
|
+
};
|
|
480
|
+
const insertAbstractNode = (board, path, start, end) => {
|
|
481
|
+
const mindElement = createMindElement('概要', 28, 20, {
|
|
482
|
+
strokeColor: GRAY_COLOR,
|
|
483
|
+
branchColor: GRAY_COLOR
|
|
484
|
+
});
|
|
485
|
+
mindElement.start = start;
|
|
486
|
+
mindElement.end = end;
|
|
487
|
+
Transforms.insertNode(board, mindElement, path);
|
|
488
|
+
};
|
|
489
|
+
const handleAbstractIncluded = (board, element) => {
|
|
490
|
+
const rightNodeCount = element.rightNodeCount;
|
|
491
|
+
const abstract = element.children.find(child => {
|
|
492
|
+
return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
|
|
493
|
+
});
|
|
494
|
+
if (abstract) {
|
|
495
|
+
const path = PlaitBoard.findPath(board, abstract);
|
|
496
|
+
Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
|
|
244
497
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
498
|
+
};
|
|
499
|
+
const getCorrespondingAbstract = (element) => {
|
|
500
|
+
const parent = MindElement.getParent(element);
|
|
501
|
+
if (!parent)
|
|
502
|
+
return undefined;
|
|
503
|
+
const elementIndex = parent.children.indexOf(element);
|
|
504
|
+
return parent.children.find(child => {
|
|
505
|
+
return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
|
|
506
|
+
});
|
|
507
|
+
};
|
|
508
|
+
const getBehindAbstracts = (element) => {
|
|
509
|
+
const parent = MindElement.getParent(element);
|
|
510
|
+
const index = parent.children.indexOf(element);
|
|
511
|
+
return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
|
|
512
|
+
};
|
|
513
|
+
const insertSiblingElementHandleAbstract = (board, selectedElement) => {
|
|
514
|
+
const abstract = getCorrespondingAbstract(selectedElement);
|
|
515
|
+
if (abstract) {
|
|
516
|
+
PlaitBoard.findPath(board, abstract);
|
|
517
|
+
Transforms.setNode(board, { end: abstract.end + 1 }, PlaitBoard.findPath(board, abstract));
|
|
252
518
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
257
|
-
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
258
|
-
[endX, endY]
|
|
259
|
-
];
|
|
260
|
-
const shape = getNodeShapeByElement(child.origin);
|
|
261
|
-
if (!node.origin.isRoot) {
|
|
262
|
-
if (node.x > child.x) {
|
|
263
|
-
curve = [
|
|
264
|
-
[beginX, beginY],
|
|
265
|
-
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
266
|
-
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
267
|
-
[endX - 12, endY]
|
|
268
|
-
];
|
|
269
|
-
const line = [
|
|
270
|
-
[endX - 12, endY],
|
|
271
|
-
[endX - 12, endY],
|
|
272
|
-
[endX, endY]
|
|
273
|
-
];
|
|
274
|
-
curve = [...curve, ...line];
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
curve = [
|
|
278
|
-
[beginX + 12, beginY],
|
|
279
|
-
[beginX + (beginNode.hGap + endNode.hGap) / 2, beginY],
|
|
280
|
-
[endX - (beginNode.hGap + endNode.hGap) / 3, endY],
|
|
281
|
-
[endX, endY]
|
|
282
|
-
];
|
|
283
|
-
const line = [
|
|
284
|
-
[beginX, beginY],
|
|
285
|
-
[beginX + 12, beginY],
|
|
286
|
-
[beginX + 12, beginY]
|
|
287
|
-
];
|
|
288
|
-
curve = [...line, ...curve];
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
if (needDrawUnderline && shape === MindNodeShape.underline) {
|
|
292
|
-
if (child.left) {
|
|
293
|
-
const underline = [
|
|
294
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
295
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
296
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY]
|
|
297
|
-
];
|
|
298
|
-
curve = [...underline, ...curve];
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
const underline = [
|
|
302
|
-
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
303
|
-
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
304
|
-
[endX + (endNode.width - endNode.hGap * 2), endY]
|
|
305
|
-
];
|
|
306
|
-
curve = [...curve, ...underline];
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
const points = pointsOnBezierCurves(curve);
|
|
310
|
-
return roughSVG.curve(points, { stroke, strokeWidth });
|
|
519
|
+
const abstracts = getBehindAbstracts(selectedElement);
|
|
520
|
+
if (abstracts.length) {
|
|
521
|
+
moveAbstractPosition(board, abstracts, 1);
|
|
311
522
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
324
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
325
|
-
[endX, endY - 12]
|
|
326
|
-
];
|
|
327
|
-
const line = [
|
|
328
|
-
[endX, endY - 12],
|
|
329
|
-
[endX, endY - 12],
|
|
330
|
-
[endX, endY]
|
|
331
|
-
];
|
|
332
|
-
curve = [...curve, ...line];
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
curve = [
|
|
336
|
-
[beginX, beginY + 12],
|
|
337
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
338
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
339
|
-
[endX, endY]
|
|
340
|
-
];
|
|
341
|
-
const line = [
|
|
342
|
-
[beginX, beginY],
|
|
343
|
-
[beginX, beginY + 12],
|
|
344
|
-
[beginX, beginY + 12]
|
|
345
|
-
];
|
|
346
|
-
curve = [...line, ...curve];
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
const points = pointsOnBezierCurves(curve);
|
|
350
|
-
return roughSVG.curve(points, { stroke, strokeWidth });
|
|
523
|
+
};
|
|
524
|
+
const moveAbstractPosition = (board, abstracts, step) => {
|
|
525
|
+
abstracts.forEach(abstract => {
|
|
526
|
+
Transforms.setNode(board, { start: abstract.start + step, end: abstract.end + step }, PlaitBoard.findPath(board, abstract));
|
|
527
|
+
});
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
function findParentElement(element) {
|
|
531
|
+
const component = PlaitElement.getComponent(element);
|
|
532
|
+
if (component && component.parent) {
|
|
533
|
+
return component.parent.origin;
|
|
351
534
|
}
|
|
535
|
+
return undefined;
|
|
352
536
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
537
|
+
function findUpElement(element) {
|
|
538
|
+
let branch;
|
|
539
|
+
let root = element;
|
|
540
|
+
let parent = findParentElement(element);
|
|
541
|
+
while (parent) {
|
|
542
|
+
branch = root;
|
|
543
|
+
root = parent;
|
|
544
|
+
parent = findParentElement(parent);
|
|
359
545
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
546
|
+
return { root, branch };
|
|
547
|
+
}
|
|
548
|
+
const getChildrenCount = (element) => {
|
|
549
|
+
const count = element.children.reduce((p, c) => {
|
|
550
|
+
return p + getChildrenCount(c);
|
|
551
|
+
}, 0);
|
|
552
|
+
return count + element.children.length;
|
|
553
|
+
};
|
|
554
|
+
const isChildElement = (origin, child) => {
|
|
555
|
+
let parent = findParentElement(child);
|
|
556
|
+
while (parent) {
|
|
557
|
+
if (parent === origin) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
parent = findParentElement(parent);
|
|
364
561
|
}
|
|
562
|
+
return false;
|
|
365
563
|
};
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
375
|
-
}
|
|
376
|
-
if (isHorizontalLogicLayout(parentNodeLayout)) {
|
|
377
|
-
fakeY = getHorizontalFakeY(detectResult, targetIndex, parentComponent.node, targetRect, layout, fakeY);
|
|
378
|
-
if (isStandardLayout(parentNodeLayout)) {
|
|
379
|
-
const rightNodeCount = parentComponent.node.origin.rightNodeCount || 0;
|
|
380
|
-
const idx = parentComponent.node.children.findIndex(x => x === targetComponent.node);
|
|
381
|
-
const isLeft = idx >= rightNodeCount;
|
|
382
|
-
// 标准布局的左,需要调整 x
|
|
383
|
-
if (isLeft) {
|
|
384
|
-
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
385
|
-
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
386
|
-
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
387
|
-
}
|
|
388
|
-
const isLeftFirst = idx === rightNodeCount;
|
|
389
|
-
const isRightLast = idx === rightNodeCount - 1;
|
|
390
|
-
// 拖拽至左第一个节点的情况
|
|
391
|
-
if (detectResult === 'top' && isLeftFirst) {
|
|
392
|
-
fakeY = targetRect.y - targetRect.height;
|
|
393
|
-
}
|
|
394
|
-
if (detectResult === 'bottom' && isRightLast) {
|
|
395
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
fakeRectangleStartY = fakeY;
|
|
399
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
400
|
-
}
|
|
401
|
-
if (isVerticalLogicLayout(layout)) {
|
|
402
|
-
parentComponent = targetComponent;
|
|
403
|
-
targetComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
404
|
-
fakeX = parentComponent.node.x;
|
|
405
|
-
width = parentComponent.node.width;
|
|
406
|
-
const vGap = BASE * 6 + strokeWidth;
|
|
407
|
-
if (isTopLayout(layout) && detectResult === 'top') {
|
|
408
|
-
fakeY = targetRect.y - vGap;
|
|
409
|
-
fakeRectangleStartY = fakeY - vGap + strokeWidth;
|
|
410
|
-
}
|
|
411
|
-
if (isBottomLayout(layout) && detectResult === 'bottom') {
|
|
412
|
-
fakeY = targetRect.y + targetRect.height + vGap;
|
|
413
|
-
fakeRectangleStartY = fakeY + vGap - strokeWidth;
|
|
414
|
-
}
|
|
415
|
-
fakeRectangleStartX = fakeX + Math.ceil(parentComponent.node.width / 2) - parentComponent.node.hGap - Math.ceil(strokeWidth / 2);
|
|
416
|
-
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
417
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
418
|
-
}
|
|
419
|
-
if (isIndentedLayout(layout)) {
|
|
420
|
-
// 偏移一个 Gap
|
|
421
|
-
if (isLeftLayout(layout)) {
|
|
422
|
-
fakeX -= BASE * 4;
|
|
423
|
-
}
|
|
424
|
-
if (isRightLayout(layout)) {
|
|
425
|
-
fakeX += BASE * 4;
|
|
426
|
-
}
|
|
427
|
-
if (isTopLayout(layout)) {
|
|
428
|
-
if (detectResult === 'top') {
|
|
429
|
-
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
430
|
-
if (isLastNode) {
|
|
431
|
-
fakeY = targetRect.y - targetRect.height - BASE;
|
|
432
|
-
}
|
|
433
|
-
else {
|
|
434
|
-
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
435
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
436
|
-
fakeY = targetRect.y - Math.abs((nextRect.y + nextRect.height - targetRect.y) / 2);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
if (detectResult === 'bottom') {
|
|
440
|
-
const isFirstNode = targetIndex === 0;
|
|
441
|
-
if (isFirstNode) {
|
|
442
|
-
const parentRect = getRectangleByNode(parentComponent.node);
|
|
443
|
-
fakeY = parentRect.y - parentRect.height / 2 - BASE;
|
|
444
|
-
}
|
|
445
|
-
else {
|
|
446
|
-
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
447
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
448
|
-
fakeY = previousRect.y - Math.abs((targetRect.y + targetRect.height - previousRect.y) / 2);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
fakeRectangleStartX = fakeX;
|
|
453
|
-
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
454
|
-
fakeRectangleStartY = fakeY;
|
|
455
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
456
|
-
}
|
|
457
|
-
// 构造一条曲线
|
|
458
|
-
const fakeNode = Object.assign(Object.assign({}, targetComponent.node), { x: fakeX, y: fakeY, width, height: 12 });
|
|
459
|
-
const linkSVGG = isIndentedLayout(layout)
|
|
460
|
-
? drawIndentedLink(roughSVG, parentComponent.node, fakeNode, PRIMARY_COLOR, false)
|
|
461
|
-
: drawLink(roughSVG, parentComponent.node, fakeNode, PRIMARY_COLOR, isHorizontalLayout(layout), false);
|
|
462
|
-
// 构造一个矩形框坐标
|
|
463
|
-
const fakeRectangleG = drawRoundRectangle(roughSVG, fakeRectangleStartX, fakeRectangleStartY, fakeRectangleEndX, fakeRectangleEndY, {
|
|
464
|
-
stroke: PRIMARY_COLOR,
|
|
465
|
-
strokeWidth: 2,
|
|
466
|
-
fill: PRIMARY_COLOR,
|
|
467
|
-
fillStyle: 'solid'
|
|
468
|
-
});
|
|
469
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
470
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
|
|
471
|
-
};
|
|
472
|
-
const drawStraightDropNodeG = (targetRect, detectResult, targetComponent, roughSVG, fakeDropNodeG) => {
|
|
473
|
-
const { x, y, width, height } = targetRect;
|
|
474
|
-
const lineLength = 40;
|
|
475
|
-
let startLinePoint = x + width;
|
|
476
|
-
let endLinePoint = x + width + lineLength;
|
|
477
|
-
let startRectanglePointX = x + width + lineLength;
|
|
478
|
-
let endRectanglePointX = x + lineLength + width + 30;
|
|
479
|
-
let startRectanglePointY = y + height / 2 - 6;
|
|
480
|
-
let endRectanglePointY = y + height / 2 - 6 + 12;
|
|
481
|
-
if (detectResult === 'left') {
|
|
482
|
-
startLinePoint = x - lineLength;
|
|
483
|
-
endLinePoint = x;
|
|
484
|
-
startRectanglePointX = x - lineLength - 30;
|
|
485
|
-
endRectanglePointX = x - lineLength;
|
|
486
|
-
}
|
|
487
|
-
let fakeY = targetComponent.node.y;
|
|
488
|
-
let fakeX = targetRect.x;
|
|
489
|
-
const strokeWidth = targetComponent.node.origin.linkLineWidth ? targetComponent.node.origin.linkLineWidth : STROKE_WIDTH;
|
|
490
|
-
const pointOptions = {
|
|
491
|
-
fakeX,
|
|
492
|
-
fakeY,
|
|
493
|
-
x,
|
|
494
|
-
y,
|
|
495
|
-
width,
|
|
496
|
-
height,
|
|
497
|
-
strokeWidth
|
|
498
|
-
};
|
|
499
|
-
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
500
|
-
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
501
|
-
if (!isMixedLayout(parentLayout, layout)) {
|
|
502
|
-
// 构造一条直线
|
|
503
|
-
let linePoints = [
|
|
504
|
-
[startLinePoint, y + height / 2],
|
|
505
|
-
[endLinePoint, y + height / 2]
|
|
506
|
-
];
|
|
507
|
-
if (isIndentedLayout(parentLayout)) {
|
|
508
|
-
const fakePoint = getIndentedFakePoint(parentLayout, pointOptions);
|
|
509
|
-
drawIndentNodeG(fakeDropNodeG, roughSVG, fakePoint, targetComponent.node);
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
else if (isVerticalLogicLayout(parentLayout)) {
|
|
513
|
-
if (!targetComponent.node.origin.isRoot) {
|
|
514
|
-
/**
|
|
515
|
-
* 计算逻辑:
|
|
516
|
-
* 1. 移动到左侧:当前节点 startX - 偏移值,偏移值计算如下:
|
|
517
|
-
* a. 第一个节点: 固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
|
|
518
|
-
* b. 第二个节点到最后一个节点之间:上一个节点到当前节点间距的一半((当前节点 startX - 上一个节点的 endX) / 2),endX = 当前节点的 startX + width;
|
|
519
|
-
* 2. 移动到右侧:当前节点 x + width + 偏移值,偏移值计算如下:
|
|
520
|
-
* a. 第二个节点到最后一个节点之间的右侧:当前节点到下一个节点间距的一半((下一个节点 startX - 当前节点的 endX) / 2),endX = 当前节点的 startX + width;
|
|
521
|
-
* b. 最后一个节点的右侧:固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
|
|
522
|
-
*/
|
|
523
|
-
fakeY = targetComponent.node.y;
|
|
524
|
-
const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
525
|
-
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
526
|
-
if (detectResult === 'left') {
|
|
527
|
-
let offsetX = 0;
|
|
528
|
-
const isFirstNode = targetIndex === 0;
|
|
529
|
-
if (isFirstNode) {
|
|
530
|
-
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex - 1]);
|
|
534
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
535
|
-
const space = targetRect.x - (previousRect.x + previousRect.width);
|
|
536
|
-
offsetX = space / 2;
|
|
537
|
-
}
|
|
538
|
-
fakeX = targetRect.x - offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
539
|
-
}
|
|
540
|
-
if (detectResult === 'right') {
|
|
541
|
-
let offsetX = 0;
|
|
542
|
-
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
543
|
-
if (isLastNode) {
|
|
544
|
-
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
545
|
-
}
|
|
546
|
-
else {
|
|
547
|
-
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
548
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
549
|
-
const space = nextRect.x - (targetRect.x + targetRect.width);
|
|
550
|
-
offsetX = space / 2;
|
|
551
|
-
}
|
|
552
|
-
fakeX = targetRect.x + width + offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
553
|
-
}
|
|
554
|
-
startRectanglePointX = fakeX;
|
|
555
|
-
if (isTopLayout(parentLayout)) {
|
|
556
|
-
// 因为矩形是从左上角为起点向下画的,所以需要向上偏移一个矩形的高度(-12)
|
|
557
|
-
startRectanglePointY = fakeY + height + targetComponent.node.vGap - 12;
|
|
558
|
-
}
|
|
559
|
-
if (isBottomLayout(parentLayout)) {
|
|
560
|
-
startRectanglePointY = fakeY + targetComponent.node.vGap;
|
|
561
|
-
}
|
|
562
|
-
endRectanglePointX = startRectanglePointX + 30;
|
|
563
|
-
endRectanglePointY = startRectanglePointY + 12;
|
|
564
|
-
const fakeNode = Object.assign(Object.assign({}, targetComponent.node), { x: fakeX, y: fakeY, width: 30 });
|
|
565
|
-
const linkSVGG = drawLink(roughSVG, parentComponent.node, fakeNode, PRIMARY_COLOR, false, false);
|
|
566
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
else {
|
|
570
|
-
let linkSVGG = roughSVG.linearPath(linePoints, { stroke: PRIMARY_COLOR, strokeWidth });
|
|
571
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
572
|
-
}
|
|
573
|
-
// 构造一个矩形框坐标
|
|
574
|
-
let fakeRectangleG = drawRoundRectangle(roughSVG, startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
575
|
-
stroke: PRIMARY_COLOR,
|
|
576
|
-
strokeWidth: 2,
|
|
577
|
-
fill: PRIMARY_COLOR,
|
|
578
|
-
fillStyle: 'solid'
|
|
579
|
-
});
|
|
580
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
|
|
581
|
-
}
|
|
582
|
-
else {
|
|
583
|
-
// 混合布局画线逻辑
|
|
584
|
-
if (isHorizontalLogicLayout(parentLayout)) {
|
|
585
|
-
if (isIndentedLayout(layout)) {
|
|
586
|
-
const fakePoint = getIndentedFakePoint(layout, pointOptions);
|
|
587
|
-
drawIndentNodeG(fakeDropNodeG, roughSVG, fakePoint, targetComponent.node);
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
const getHorizontalFakeY = (detectResult, targetIndex, parentNode, targetRect, layout, fakeY) => {
|
|
594
|
-
if (detectResult === 'top') {
|
|
595
|
-
if (targetIndex === 0 && isTopLayout(layout)) {
|
|
596
|
-
fakeY = targetRect.y + targetRect.height;
|
|
597
|
-
}
|
|
598
|
-
if (targetIndex > 0) {
|
|
599
|
-
const previousComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex - 1]);
|
|
600
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
601
|
-
const topY = previousRect.y + previousRect.height;
|
|
602
|
-
fakeY = topY + (targetRect.y - topY) / 5;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
if (detectResult === 'bottom') {
|
|
606
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
607
|
-
if (targetIndex < parentNode.origin.children.length - 1) {
|
|
608
|
-
const nextComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex + 1]);
|
|
609
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
610
|
-
const topY = targetRect.y + targetRect.height;
|
|
611
|
-
fakeY = topY + (nextRect.y - topY) / 5;
|
|
612
|
-
}
|
|
613
|
-
if (targetIndex === parentNode.origin.children.length - 1) {
|
|
614
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return fakeY;
|
|
618
|
-
};
|
|
619
|
-
const getIndentedFakePoint = (layout, pointOptions) => {
|
|
620
|
-
let { fakeX, fakeY, x, y, width, height, strokeWidth } = pointOptions;
|
|
621
|
-
const hGap = BASE * 4;
|
|
622
|
-
const vGap = BASE * 6;
|
|
623
|
-
const offsetX = hGap + width / 2 + strokeWidth;
|
|
624
|
-
const offsetY = vGap + height / 2 + strokeWidth;
|
|
625
|
-
if (isLeftLayout(layout)) {
|
|
626
|
-
fakeX = x - offsetX;
|
|
627
|
-
}
|
|
628
|
-
if (isRightLayout(layout)) {
|
|
629
|
-
fakeX = x + offsetX;
|
|
630
|
-
}
|
|
631
|
-
if (isTopLayout(layout)) {
|
|
632
|
-
fakeY = y - offsetY;
|
|
633
|
-
}
|
|
634
|
-
if (isBottomLayout(layout)) {
|
|
635
|
-
fakeY = y + height + offsetY;
|
|
636
|
-
}
|
|
637
|
-
return { fakeX, fakeY };
|
|
638
|
-
};
|
|
639
|
-
const drawIndentNodeG = (fakeDropNodeG, roughSVG, fakePoint, node) => {
|
|
640
|
-
const { fakeX, fakeY } = fakePoint;
|
|
641
|
-
const fakeNode = Object.assign(Object.assign({}, node), { x: fakeX, y: fakeY, width: 30, height: 12 });
|
|
642
|
-
const linkSVGG = drawIndentedLink(roughSVG, node, fakeNode, PRIMARY_COLOR, false);
|
|
643
|
-
const startRectanglePointX = fakeX, startRectanglePointY = fakeY, endRectanglePointX = fakeX + 30, endRectanglePointY = fakeY + 12;
|
|
644
|
-
const fakeRectangleG = drawRoundRectangle(roughSVG, startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
645
|
-
stroke: PRIMARY_COLOR,
|
|
646
|
-
strokeWidth: 2,
|
|
647
|
-
fill: PRIMARY_COLOR,
|
|
648
|
-
fillStyle: 'solid'
|
|
649
|
-
});
|
|
650
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
651
|
-
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
|
|
652
|
-
};
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
*
|
|
656
|
-
* @param targetNode
|
|
657
|
-
* @param centerPoint
|
|
658
|
-
* @returns DetectResult[] | null
|
|
659
|
-
*/
|
|
660
|
-
const directionDetector = (targetNode, centerPoint) => {
|
|
661
|
-
const { x, y, width, height } = getRectangleByNode(targetNode);
|
|
662
|
-
const yCenter = y + height / 2;
|
|
663
|
-
const xCenter = x + width / 2;
|
|
664
|
-
const top = targetNode.y;
|
|
665
|
-
const bottom = targetNode.y + targetNode.height;
|
|
666
|
-
const left = targetNode.x;
|
|
667
|
-
const right = targetNode.x + targetNode.width;
|
|
668
|
-
const direction = [];
|
|
669
|
-
// x 轴
|
|
670
|
-
if (centerPoint[1] > y && centerPoint[1] < y + height) {
|
|
671
|
-
if (centerPoint[0] > left && centerPoint[0] < xCenter) {
|
|
672
|
-
direction.push('left');
|
|
673
|
-
}
|
|
674
|
-
if (centerPoint[0] > xCenter && centerPoint[0] < right) {
|
|
675
|
-
direction.push('right');
|
|
676
|
-
}
|
|
677
|
-
// 重合区域,返回两个方向
|
|
678
|
-
if ((centerPoint[0] > x && centerPoint[0] < xCenter) || (centerPoint[0] > xCenter && centerPoint[0] < x + width)) {
|
|
679
|
-
if (centerPoint[1] < yCenter) {
|
|
680
|
-
direction.push('top');
|
|
681
|
-
}
|
|
682
|
-
else {
|
|
683
|
-
direction.push('bottom');
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
return direction.length ? direction : null;
|
|
687
|
-
}
|
|
688
|
-
// y 轴
|
|
689
|
-
if (centerPoint[0] > x && centerPoint[0] < x + width) {
|
|
690
|
-
if (centerPoint[1] > top && centerPoint[1] < yCenter) {
|
|
691
|
-
direction.push('top');
|
|
692
|
-
}
|
|
693
|
-
if (centerPoint[1] > yCenter && centerPoint[1] < bottom) {
|
|
694
|
-
direction.push('bottom');
|
|
695
|
-
}
|
|
696
|
-
if ((centerPoint[1] > y && centerPoint[1] < y + height) || (centerPoint[1] > yCenter && centerPoint[1] < y + height)) {
|
|
697
|
-
if (centerPoint[0] < xCenter) {
|
|
698
|
-
direction.push('left');
|
|
699
|
-
}
|
|
700
|
-
else {
|
|
701
|
-
direction.push('right');
|
|
702
|
-
}
|
|
564
|
+
const filterChildElement = (elements) => {
|
|
565
|
+
let result = [];
|
|
566
|
+
elements.forEach(element => {
|
|
567
|
+
const isChild = elements.some(node => {
|
|
568
|
+
return isChildElement(node, element);
|
|
569
|
+
});
|
|
570
|
+
if (!isChild) {
|
|
571
|
+
result.push(element);
|
|
703
572
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
return null;
|
|
573
|
+
});
|
|
574
|
+
return result;
|
|
707
575
|
};
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
if (isRightLayout(parentlayout)) {
|
|
721
|
-
return getAllowedDirection(detectResults, ['left']);
|
|
722
|
-
}
|
|
723
|
-
if (parentlayout === MindLayoutType.upward) {
|
|
724
|
-
return getAllowedDirection(detectResults, ['bottom']);
|
|
725
|
-
}
|
|
726
|
-
if (parentlayout === MindLayoutType.downward) {
|
|
727
|
-
return getAllowedDirection(detectResults, ['top']);
|
|
728
|
-
}
|
|
576
|
+
const isChildRight = (node, child) => {
|
|
577
|
+
return node.x < child.x;
|
|
578
|
+
};
|
|
579
|
+
const isChildUp = (node, child) => {
|
|
580
|
+
return node.y > child.y;
|
|
581
|
+
};
|
|
582
|
+
const copyNewNode = (node) => {
|
|
583
|
+
const newNode = Object.assign({}, node);
|
|
584
|
+
newNode.id = idCreator();
|
|
585
|
+
newNode.children = [];
|
|
586
|
+
for (const childNode of node.children) {
|
|
587
|
+
newNode.children.push(copyNewNode(childNode));
|
|
729
588
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
}
|
|
744
|
-
if (layout === MindLayoutType.right) {
|
|
745
|
-
return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
|
|
746
|
-
}
|
|
589
|
+
return newNode;
|
|
590
|
+
};
|
|
591
|
+
const transformRootToNode = (board, node) => {
|
|
592
|
+
const newNode = Object.assign({}, node);
|
|
593
|
+
delete newNode.isRoot;
|
|
594
|
+
delete newNode.rightNodeCount;
|
|
595
|
+
delete newNode.type;
|
|
596
|
+
const text = Node.string(node.data.topic.children[0]) || ' ';
|
|
597
|
+
const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT);
|
|
598
|
+
newNode.width = Math.max(width, NODE_MIN_WIDTH);
|
|
599
|
+
newNode.height = height;
|
|
600
|
+
if (newNode.layout === MindLayoutType.standard) {
|
|
601
|
+
delete newNode.layout;
|
|
747
602
|
}
|
|
748
|
-
return
|
|
603
|
+
return newNode;
|
|
749
604
|
};
|
|
750
|
-
const
|
|
751
|
-
const
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
directions.splice(bottomDirectionIndex, 1);
|
|
756
|
-
}
|
|
757
|
-
});
|
|
758
|
-
return directions.length ? directions : null;
|
|
605
|
+
const transformAbstractToNode = (node) => {
|
|
606
|
+
const newNode = Object.assign({}, node);
|
|
607
|
+
delete newNode.start;
|
|
608
|
+
delete newNode.end;
|
|
609
|
+
return newNode;
|
|
759
610
|
};
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
768
|
-
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
769
|
-
if (['right', 'left'].includes(dropTarget.detectResult)) {
|
|
770
|
-
if (!isMixedLayout(parentLayout, layout)) {
|
|
771
|
-
if (targetComponent.node.origin.isRoot) {
|
|
772
|
-
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
773
|
-
// 标准布局,根节点
|
|
774
|
-
if (isStandardLayout(layout)) {
|
|
775
|
-
const rightNodeCount = targetComponent.node.origin.rightNodeCount;
|
|
776
|
-
if (detectResult === 'left') {
|
|
777
|
-
// 作为左的第一个节点
|
|
778
|
-
if (targetComponent.node.children.length === rightNodeCount) {
|
|
779
|
-
return newDropTarget;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
else {
|
|
783
|
-
// 作为右的第一个节点或最后一个节点
|
|
784
|
-
if (rightNodeCount === 0) {
|
|
785
|
-
newDropTarget.target = target;
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
newDropTarget.target = targetComponent.node.children[rightNodeCount - 1].origin;
|
|
789
|
-
newDropTarget.detectResult = 'bottom';
|
|
790
|
-
}
|
|
791
|
-
return newDropTarget;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
// 缩进布局探测到第一个子节点
|
|
796
|
-
if (isIndentedLayout(parentLayout)) {
|
|
797
|
-
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
798
|
-
newDropTarget.detectResult = isTopLayout(parentLayout) ? 'bottom' : 'top';
|
|
799
|
-
return newDropTarget;
|
|
800
|
-
}
|
|
801
|
-
// 上下布局的根节点只可以探测到上或者下,子节点的左右探测不处理,跳过。
|
|
802
|
-
if (isVerticalLogicLayout(parentLayout)) {
|
|
803
|
-
return newDropTarget;
|
|
804
|
-
}
|
|
805
|
-
// 剩下是水平布局的默认情况:插入最后一个子节点的下方
|
|
806
|
-
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
807
|
-
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
808
|
-
newDropTarget.detectResult = 'bottom';
|
|
809
|
-
}
|
|
810
|
-
else {
|
|
811
|
-
// 处理左右布局下的混合布局
|
|
812
|
-
if ([MindLayoutType.left, MindLayoutType.right].includes(parentLayout)) {
|
|
813
|
-
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
814
|
-
if (isIndentedLayout(layout)) {
|
|
815
|
-
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
816
|
-
newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
|
|
817
|
-
return newDropTarget;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
if (['top', 'bottom'].includes(dropTarget.detectResult)) {
|
|
823
|
-
// 缩进布局移动至第一个节点
|
|
824
|
-
if (targetComponent.node.origin.isRoot && isIndentedLayout(layout)) {
|
|
825
|
-
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
826
|
-
newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
|
|
827
|
-
return newDropTarget;
|
|
828
|
-
}
|
|
829
|
-
// 上下布局,插到右边
|
|
830
|
-
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
831
|
-
if (isVerticalLogicLayout(parentLayout)) {
|
|
832
|
-
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
833
|
-
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
834
|
-
newDropTarget.detectResult = 'right';
|
|
835
|
-
return newDropTarget;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
return newDropTarget;
|
|
611
|
+
const transformNodeToRoot = (board, node) => {
|
|
612
|
+
var _a;
|
|
613
|
+
const newElement = Object.assign({}, node);
|
|
614
|
+
let text = Node.string(newElement.data.topic);
|
|
615
|
+
if (!text) {
|
|
616
|
+
text = '思维导图';
|
|
617
|
+
newElement.data.topic = { children: [{ text }] };
|
|
839
618
|
}
|
|
840
|
-
|
|
619
|
+
newElement === null || newElement === void 0 ? true : delete newElement.strokeColor;
|
|
620
|
+
newElement === null || newElement === void 0 ? true : delete newElement.fill;
|
|
621
|
+
newElement === null || newElement === void 0 ? true : delete newElement.shape;
|
|
622
|
+
newElement === null || newElement === void 0 ? true : delete newElement.strokeWidth;
|
|
623
|
+
const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT, ROOT_TOPIC_FONT_SIZE);
|
|
624
|
+
newElement.width = Math.max(width, NODE_MIN_WIDTH);
|
|
625
|
+
newElement.height = height;
|
|
626
|
+
return Object.assign(Object.assign({}, newElement), { layout: (_a = newElement.layout) !== null && _a !== void 0 ? _a : MindLayoutType.right, isCollapsed: false, isRoot: true, type: 'mindmap' });
|
|
841
627
|
};
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
const child = children[i];
|
|
849
|
-
if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
|
|
850
|
-
rightChildren.push(child);
|
|
851
|
-
continue;
|
|
852
|
-
}
|
|
853
|
-
if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
|
|
854
|
-
leftChildren.push(child);
|
|
855
|
-
continue;
|
|
856
|
-
}
|
|
857
|
-
if (i < rightNodeCount) {
|
|
858
|
-
rightChildren.push(child);
|
|
859
|
-
}
|
|
860
|
-
else {
|
|
861
|
-
leftChildren.push(child);
|
|
628
|
+
const extractNodesText = (node) => {
|
|
629
|
+
let str = '';
|
|
630
|
+
if (node) {
|
|
631
|
+
str += Node.string(node.data.topic.children[0]) + ' ';
|
|
632
|
+
for (const childNode of node.children) {
|
|
633
|
+
str += extractNodesText(childNode);
|
|
862
634
|
}
|
|
863
635
|
}
|
|
864
|
-
return
|
|
636
|
+
return str;
|
|
865
637
|
};
|
|
866
|
-
const
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
});
|
|
638
|
+
const changeRightNodeCount = (board, parentPath, changeNumber) => {
|
|
639
|
+
const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
|
|
640
|
+
Transforms.setNode(board, {
|
|
641
|
+
rightNodeCount: changeNumber >= 0
|
|
642
|
+
? _rightNodeCount + changeNumber
|
|
643
|
+
: _rightNodeCount + changeNumber < 0
|
|
644
|
+
? 0
|
|
645
|
+
: _rightNodeCount + changeNumber
|
|
646
|
+
}, parentPath);
|
|
875
647
|
};
|
|
876
|
-
const
|
|
877
|
-
|
|
648
|
+
const shouldChangeRightNodeCount = (selectedElement) => {
|
|
649
|
+
const parentElement = findParentElement(selectedElement);
|
|
650
|
+
if (parentElement) {
|
|
651
|
+
const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
|
|
652
|
+
if (parentElement.isRoot &&
|
|
653
|
+
getRootLayout(parentElement) === MindLayoutType.standard &&
|
|
654
|
+
parentElement.rightNodeCount &&
|
|
655
|
+
nodeIndex <= parentElement.rightNodeCount - 1) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return false;
|
|
878
660
|
};
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
661
|
+
const createDefaultMindMapElement = (point, rightNodeCount, layout) => {
|
|
662
|
+
const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle, layout });
|
|
663
|
+
root.rightNodeCount = rightNodeCount;
|
|
664
|
+
root.isRoot = true;
|
|
665
|
+
root.type = 'mindmap';
|
|
666
|
+
root.points = [point];
|
|
667
|
+
const children = [1, 1, 1].map(() => {
|
|
668
|
+
return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle });
|
|
885
669
|
});
|
|
670
|
+
root.children = children;
|
|
671
|
+
return root;
|
|
886
672
|
};
|
|
887
|
-
const
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
673
|
+
const createMindElement = (text, width, height, options) => {
|
|
674
|
+
const newElement = {
|
|
675
|
+
id: idCreator(),
|
|
676
|
+
data: {
|
|
677
|
+
topic: { children: [{ text }] }
|
|
678
|
+
},
|
|
679
|
+
children: [],
|
|
680
|
+
width,
|
|
681
|
+
height,
|
|
682
|
+
fill: options.fill,
|
|
683
|
+
strokeColor: options.strokeColor,
|
|
684
|
+
strokeWidth: options.strokeWidth,
|
|
685
|
+
shape: options.shape
|
|
686
|
+
};
|
|
687
|
+
if (options.fill) {
|
|
688
|
+
newElement.fill = options.fill;
|
|
901
689
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
690
|
+
if (options.strokeColor) {
|
|
691
|
+
newElement.strokeColor = options.strokeColor;
|
|
692
|
+
}
|
|
693
|
+
if (!isNullOrUndefined(options.strokeWidth)) {
|
|
694
|
+
newElement.strokeWidth = options.strokeWidth;
|
|
905
695
|
}
|
|
696
|
+
if (options.shape) {
|
|
697
|
+
newElement.shape = options.shape;
|
|
698
|
+
}
|
|
699
|
+
if (options.layout) {
|
|
700
|
+
newElement.layout = options.layout;
|
|
701
|
+
}
|
|
702
|
+
if (options.branchColor) {
|
|
703
|
+
newElement.branchColor = options.branchColor;
|
|
704
|
+
}
|
|
705
|
+
return newElement;
|
|
906
706
|
};
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
707
|
+
// layoutLevel 用来表示插入兄弟节点还是子节点
|
|
708
|
+
const insertMindElement = (board, inheritNode, path) => {
|
|
709
|
+
let fill, strokeColor, strokeWidth, shape = MindNodeShape.roundRectangle;
|
|
710
|
+
if (!inheritNode.isRoot) {
|
|
711
|
+
fill = inheritNode.fill;
|
|
712
|
+
strokeColor = inheritNode.strokeColor;
|
|
713
|
+
strokeWidth = inheritNode.strokeWidth;
|
|
714
|
+
}
|
|
715
|
+
shape = inheritNode.shape;
|
|
716
|
+
const newElement = createMindElement('', NODE_MIN_WIDTH, TEXT_DEFAULT_HEIGHT, { fill, strokeColor, strokeWidth, shape });
|
|
717
|
+
Transforms.insertNode(board, newElement, path);
|
|
718
|
+
clearSelectedElement(board);
|
|
719
|
+
addSelectedElement(board, newElement);
|
|
720
|
+
setTimeout(() => {
|
|
721
|
+
enterNodeEditing(newElement);
|
|
911
722
|
});
|
|
912
|
-
mindElement.start = start;
|
|
913
|
-
mindElement.end = end;
|
|
914
|
-
Transforms.insertNode(board, mindElement, path);
|
|
915
723
|
};
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
return Object.assign(Object.assign({}, abstractRectangle), { y: location, height: abstractRectangle.height + abstractRectangle.y - location });
|
|
921
|
-
}
|
|
922
|
-
else {
|
|
923
|
-
return Object.assign(Object.assign({}, abstractRectangle), { height: location - abstractRectangle.y });
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
else {
|
|
927
|
-
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
928
|
-
return Object.assign(Object.assign({}, abstractRectangle), { x: location, width: abstractRectangle.width + abstractRectangle.x - location });
|
|
929
|
-
}
|
|
930
|
-
else {
|
|
931
|
-
return Object.assign(Object.assign({}, abstractRectangle), { width: location - abstractRectangle.x });
|
|
932
|
-
}
|
|
724
|
+
const findLastChild = (child) => {
|
|
725
|
+
let result = child;
|
|
726
|
+
while (result.children.length !== 0) {
|
|
727
|
+
result = result.children[result.children.length - 1];
|
|
933
728
|
}
|
|
729
|
+
return result;
|
|
934
730
|
};
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
const
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
731
|
+
const deleteSelectedELements = (board, selectedElements) => {
|
|
732
|
+
//翻转,从下到上修改,防止找不到 path
|
|
733
|
+
const deletableElements = filterChildElement(selectedElements).reverse();
|
|
734
|
+
const relativeAbstracts = [];
|
|
735
|
+
const accumulativeProperties = new WeakMap();
|
|
736
|
+
deletableElements.forEach(node => {
|
|
737
|
+
if (!PlaitMind.isMind(node)) {
|
|
738
|
+
const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
|
|
739
|
+
if (behindAbstracts.length) {
|
|
740
|
+
behindAbstracts.forEach(abstract => {
|
|
741
|
+
let newProperties = accumulativeProperties.get(abstract);
|
|
742
|
+
if (!newProperties) {
|
|
743
|
+
newProperties = { start: abstract.start, end: abstract.end };
|
|
744
|
+
accumulativeProperties.set(abstract, newProperties);
|
|
745
|
+
relativeAbstracts.push(abstract);
|
|
746
|
+
}
|
|
747
|
+
newProperties.start = newProperties.start - 1;
|
|
748
|
+
newProperties.end = newProperties.end - 1;
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
const correspondingAbstract = getCorrespondingAbstract(node);
|
|
752
|
+
if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
|
|
753
|
+
let newProperties = accumulativeProperties.get(correspondingAbstract);
|
|
754
|
+
if (!newProperties) {
|
|
755
|
+
newProperties = { start: correspondingAbstract.start, end: correspondingAbstract.end };
|
|
756
|
+
accumulativeProperties.set(correspondingAbstract, newProperties);
|
|
757
|
+
relativeAbstracts.push(correspondingAbstract);
|
|
758
|
+
}
|
|
759
|
+
newProperties.end = newProperties.end - 1;
|
|
760
|
+
}
|
|
962
761
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
762
|
+
});
|
|
763
|
+
const abstractHandles = relativeAbstracts.map(value => {
|
|
764
|
+
const newProperties = accumulativeProperties.get(value);
|
|
765
|
+
if (newProperties) {
|
|
766
|
+
const path = PlaitBoard.findPath(board, value);
|
|
767
|
+
return () => {
|
|
768
|
+
if (newProperties.start > newProperties.end) {
|
|
769
|
+
Transforms.removeNode(board, path);
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
Transforms.setNode(board, newProperties, path);
|
|
773
|
+
}
|
|
967
774
|
};
|
|
968
775
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
.
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
};
|
|
776
|
+
return () => { };
|
|
777
|
+
});
|
|
778
|
+
const deletableHandles = deletableElements.map(node => {
|
|
779
|
+
const path = PlaitBoard.findPath(board, node);
|
|
780
|
+
return () => {
|
|
781
|
+
if (shouldChangeRightNodeCount(node)) {
|
|
782
|
+
changeRightNodeCount(board, path.slice(0, path.length - 1), -1);
|
|
783
|
+
}
|
|
784
|
+
Transforms.removeNode(board, path);
|
|
785
|
+
};
|
|
786
|
+
});
|
|
787
|
+
abstractHandles.forEach(action => action());
|
|
788
|
+
deletableHandles.forEach(action => action());
|
|
789
|
+
};
|
|
790
|
+
const divideElementByParent = (elements) => {
|
|
791
|
+
const abstractIncludedGroups = [];
|
|
792
|
+
const parentElements = [];
|
|
793
|
+
for (let i = 0; i < elements.length; i++) {
|
|
794
|
+
const parent = MindElement.getParent(elements[i]);
|
|
795
|
+
const parentIndex = parentElements.indexOf(parent);
|
|
796
|
+
if (parentIndex === -1) {
|
|
797
|
+
parentElements.push(parent);
|
|
798
|
+
abstractIncludedGroups.push([elements[i]]);
|
|
993
799
|
}
|
|
994
800
|
else {
|
|
995
|
-
|
|
996
|
-
max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
997
|
-
min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
998
|
-
};
|
|
801
|
+
abstractIncludedGroups[parentIndex].push(elements[i]);
|
|
999
802
|
}
|
|
1000
803
|
}
|
|
804
|
+
return { parentElements, abstractIncludedGroups };
|
|
1001
805
|
};
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
return null;
|
|
806
|
+
|
|
807
|
+
const getNodeShapeByElement = (element) => {
|
|
808
|
+
let nodeShape = element.shape;
|
|
809
|
+
if (nodeShape) {
|
|
810
|
+
return nodeShape;
|
|
811
|
+
}
|
|
812
|
+
let parent = findParentElement(element);
|
|
813
|
+
while (parent) {
|
|
814
|
+
if (parent.shape) {
|
|
815
|
+
return parent.shape;
|
|
816
|
+
}
|
|
817
|
+
parent = findParentElement(parent);
|
|
818
|
+
}
|
|
819
|
+
return MindNodeShape.roundRectangle;
|
|
1017
820
|
};
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
821
|
+
|
|
822
|
+
const getBranchColorByMindElement = (board, element) => {
|
|
823
|
+
const ancestors = MindElement.getAncestors(board, element);
|
|
824
|
+
ancestors.unshift(element);
|
|
825
|
+
const ancestor = ancestors.find(value => value.branchColor);
|
|
826
|
+
if (ancestor && ancestor.branchColor) {
|
|
827
|
+
return ancestor.branchColor;
|
|
828
|
+
}
|
|
829
|
+
const root = ancestors[ancestors.length - 1];
|
|
830
|
+
const branch = ancestors[ancestors.length - 2];
|
|
831
|
+
if (branch) {
|
|
832
|
+
const index = root.children.indexOf(branch);
|
|
833
|
+
const length = COLORS.length;
|
|
834
|
+
const remainder = index % length;
|
|
835
|
+
return COLORS[remainder];
|
|
1024
836
|
}
|
|
1025
837
|
else {
|
|
1026
|
-
|
|
1027
|
-
result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
|
|
1028
|
-
result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
838
|
+
throw new Error('root element should not have branch color');
|
|
1029
839
|
}
|
|
1030
|
-
return result;
|
|
1031
840
|
};
|
|
1032
|
-
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
const
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
}
|
|
1046
|
-
const
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
recArray.push(fakeRightRec);
|
|
1054
|
-
recArray.unshift(fakeLeftRec);
|
|
1055
|
-
for (let i = 0; i < recArray.length - 1; i++) {
|
|
1056
|
-
const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
|
|
1057
|
-
const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
|
|
1058
|
-
if (location >= recXOrY + recWidthOrHeight / 2 &&
|
|
1059
|
-
location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
|
|
1060
|
-
return i - 1;
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
return 0;
|
|
1064
|
-
}
|
|
1065
|
-
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1066
|
-
let touchedHandle;
|
|
1067
|
-
const abstract = getSelectedElements(board)
|
|
1068
|
-
.filter(element => AbstractNode.isAbstract(element))
|
|
1069
|
-
.find(element => {
|
|
1070
|
-
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1071
|
-
return touchedHandle;
|
|
1072
|
-
});
|
|
1073
|
-
if (touchedAbstract === abstract) {
|
|
1074
|
-
return touchedAbstract;
|
|
1075
|
-
}
|
|
1076
|
-
if (touchedAbstract) {
|
|
1077
|
-
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1078
|
-
component.updateAbstractIncludedOutline();
|
|
1079
|
-
touchedAbstract = undefined;
|
|
841
|
+
const getNextBranchColor = (root) => {
|
|
842
|
+
const index = root.children.length;
|
|
843
|
+
const length = COLORS.length;
|
|
844
|
+
const remainder = index % length;
|
|
845
|
+
return COLORS[remainder];
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
const getStrokeByMindElement = (board, element) => {
|
|
849
|
+
const ancestors = MindElement.getAncestors(board, element);
|
|
850
|
+
ancestors.unshift(element);
|
|
851
|
+
const ancestor = ancestors.find(value => value.strokeColor);
|
|
852
|
+
if (ancestor && ancestor.strokeColor) {
|
|
853
|
+
return ancestor.strokeColor;
|
|
854
|
+
}
|
|
855
|
+
const root = ancestors[ancestors.length - 1];
|
|
856
|
+
const branch = ancestors[ancestors.length - 2];
|
|
857
|
+
if (branch) {
|
|
858
|
+
const index = root.children.indexOf(branch);
|
|
859
|
+
const length = COLORS.length;
|
|
860
|
+
const remainder = index % length;
|
|
861
|
+
return COLORS[remainder];
|
|
1080
862
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1084
|
-
component.updateAbstractIncludedOutline(touchedHandle);
|
|
863
|
+
else {
|
|
864
|
+
return ROOT_NODE_STROKE;
|
|
1085
865
|
}
|
|
1086
|
-
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
function isVirtualKey(e) {
|
|
869
|
+
const isMod = e.ctrlKey || e.metaKey;
|
|
870
|
+
const isAlt = isKeyHotkey('alt', e);
|
|
871
|
+
const isShift = isKeyHotkey('shift', e);
|
|
872
|
+
const isCapsLock = e.key.includes('CapsLock');
|
|
873
|
+
const isTab = e.key.includes('Tab');
|
|
874
|
+
const isEsc = e.key.includes('Escape');
|
|
875
|
+
const isF = e.key.startsWith('F');
|
|
876
|
+
const isArrow = e.key.includes('Arrow') ? true : false;
|
|
877
|
+
return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
|
|
1087
878
|
}
|
|
1088
879
|
|
|
1089
|
-
|
|
1090
|
-
* get correctly layout:
|
|
1091
|
-
* 1. root is standard -> left or right
|
|
1092
|
-
* 2. correct layout by incorrect layout direction
|
|
1093
|
-
* @param element
|
|
1094
|
-
*/
|
|
1095
|
-
const getCorrectLayoutByElement = (element) => {
|
|
880
|
+
function drawLink(board, node, child, defaultStroke = null, isHorizontal = true, needDrawUnderline = true) {
|
|
1096
881
|
var _a;
|
|
1097
|
-
|
|
1098
|
-
const
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
882
|
+
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
883
|
+
const layout = MindQueries.getCorrectLayoutByElement(node.origin);
|
|
884
|
+
if (isHorizontal) {
|
|
885
|
+
if (!isChildRight(node, child)) {
|
|
886
|
+
beginNode = child;
|
|
887
|
+
endNode = node;
|
|
888
|
+
}
|
|
889
|
+
beginX = beginNode.x + beginNode.width - beginNode.hGap;
|
|
890
|
+
beginY = beginNode.y + beginNode.height / 2;
|
|
891
|
+
endX = endNode.x + endNode.hGap;
|
|
892
|
+
endY = endNode.y + endNode.height / 2;
|
|
893
|
+
if (node.parent &&
|
|
894
|
+
isIndentedLayout(MindQueries.getLayoutByElement((_a = node.parent) === null || _a === void 0 ? void 0 : _a.origin)) &&
|
|
895
|
+
getNodeShapeByElement(node.origin) === MindNodeShape.underline) {
|
|
896
|
+
if (isChildRight(node, child)) {
|
|
897
|
+
beginY = node.y + node.height - node.vGap;
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
endY = node.y + node.height - node.vGap;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
1111
903
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
904
|
+
else {
|
|
905
|
+
if (node.y > child.y) {
|
|
906
|
+
beginNode = child;
|
|
907
|
+
endNode = node;
|
|
908
|
+
}
|
|
909
|
+
beginX = beginNode.x + beginNode.width / 2;
|
|
910
|
+
beginY = beginNode.y + beginNode.height - beginNode.vGap;
|
|
911
|
+
endX = endNode.x + endNode.width / 2;
|
|
912
|
+
endY = endNode.y + endNode.vGap;
|
|
1115
913
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
914
|
+
const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
|
|
915
|
+
const strokeWidth = child.origin.branchWidth ? child.origin.branchWidth : STROKE_WIDTH;
|
|
916
|
+
if (endNode.origin.isRoot) {
|
|
917
|
+
if (layout === MindLayoutType.left || isStandardLayout(layout)) {
|
|
918
|
+
endX -= strokeWidth;
|
|
919
|
+
}
|
|
920
|
+
if (layout === MindLayoutType.upward) {
|
|
921
|
+
endY -= strokeWidth;
|
|
922
|
+
}
|
|
1119
923
|
}
|
|
1120
|
-
if (
|
|
1121
|
-
|
|
924
|
+
if (beginNode.origin.isRoot) {
|
|
925
|
+
if (layout === MindLayoutType.right || isStandardLayout(layout)) {
|
|
926
|
+
beginX += strokeWidth;
|
|
927
|
+
}
|
|
928
|
+
if (layout === MindLayoutType.downward) {
|
|
929
|
+
beginY += strokeWidth;
|
|
930
|
+
}
|
|
1122
931
|
}
|
|
1123
|
-
if (
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
932
|
+
if (isHorizontal) {
|
|
933
|
+
let curve = [
|
|
934
|
+
[beginX, beginY],
|
|
935
|
+
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
936
|
+
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
937
|
+
[endX, endY]
|
|
938
|
+
];
|
|
939
|
+
const shape = getNodeShapeByElement(child.origin);
|
|
940
|
+
if (!node.origin.isRoot) {
|
|
941
|
+
if (node.x > child.x) {
|
|
942
|
+
curve = [
|
|
943
|
+
[beginX, beginY],
|
|
944
|
+
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
945
|
+
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
946
|
+
[endX - 12, endY]
|
|
947
|
+
];
|
|
948
|
+
const line = [
|
|
949
|
+
[endX - 12, endY],
|
|
950
|
+
[endX - 12, endY],
|
|
951
|
+
[endX, endY]
|
|
952
|
+
];
|
|
953
|
+
curve = [...curve, ...line];
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
curve = [
|
|
957
|
+
[beginX + 12, beginY],
|
|
958
|
+
[beginX + (beginNode.hGap + endNode.hGap) / 2, beginY],
|
|
959
|
+
[endX - (beginNode.hGap + endNode.hGap) / 3, endY],
|
|
960
|
+
[endX, endY]
|
|
961
|
+
];
|
|
962
|
+
const line = [
|
|
963
|
+
[beginX, beginY],
|
|
964
|
+
[beginX + 12, beginY],
|
|
965
|
+
[beginX + 12, beginY]
|
|
966
|
+
];
|
|
967
|
+
curve = [...line, ...curve];
|
|
968
|
+
}
|
|
1127
969
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
970
|
+
if (needDrawUnderline && shape === MindNodeShape.underline) {
|
|
971
|
+
if (child.left) {
|
|
972
|
+
const underline = [
|
|
973
|
+
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
974
|
+
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
975
|
+
[beginX - (beginNode.width - beginNode.hGap * 2), beginY]
|
|
976
|
+
];
|
|
977
|
+
curve = [...underline, ...curve];
|
|
978
|
+
}
|
|
979
|
+
else {
|
|
980
|
+
const underline = [
|
|
981
|
+
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
982
|
+
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
983
|
+
[endX + (endNode.width - endNode.hGap * 2), endY]
|
|
984
|
+
];
|
|
985
|
+
curve = [...curve, ...underline];
|
|
986
|
+
}
|
|
1130
987
|
}
|
|
988
|
+
const points = pointsOnBezierCurves(curve);
|
|
989
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
1131
990
|
}
|
|
1132
991
|
else {
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
992
|
+
let curve = [
|
|
993
|
+
[beginX, beginY],
|
|
994
|
+
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
995
|
+
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
996
|
+
[endX, endY]
|
|
997
|
+
];
|
|
998
|
+
if (!node.origin.isRoot) {
|
|
999
|
+
if (isTopLayout(layout)) {
|
|
1000
|
+
curve = [
|
|
1001
|
+
[beginX, beginY],
|
|
1002
|
+
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
1003
|
+
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
1004
|
+
[endX, endY - 12]
|
|
1005
|
+
];
|
|
1006
|
+
const line = [
|
|
1007
|
+
[endX, endY - 12],
|
|
1008
|
+
[endX, endY - 12],
|
|
1009
|
+
[endX, endY]
|
|
1010
|
+
];
|
|
1011
|
+
curve = [...curve, ...line];
|
|
1012
|
+
}
|
|
1013
|
+
else {
|
|
1014
|
+
curve = [
|
|
1015
|
+
[beginX, beginY + 12],
|
|
1016
|
+
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
1017
|
+
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
1018
|
+
[endX, endY]
|
|
1019
|
+
];
|
|
1020
|
+
const line = [
|
|
1021
|
+
[beginX, beginY],
|
|
1022
|
+
[beginX, beginY + 12],
|
|
1023
|
+
[beginX, beginY + 12]
|
|
1024
|
+
];
|
|
1025
|
+
curve = [...line, ...curve];
|
|
1026
|
+
}
|
|
1147
1027
|
}
|
|
1148
|
-
|
|
1028
|
+
const points = pointsOnBezierCurves(curve);
|
|
1029
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
1149
1030
|
}
|
|
1150
|
-
|
|
1151
|
-
};
|
|
1031
|
+
}
|
|
1152
1032
|
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
const getAvailableSubLayoutsByElement = (element) => {
|
|
1159
|
-
const parentElement = findParentElement(element);
|
|
1160
|
-
if (parentElement) {
|
|
1161
|
-
const branchLayouts = getBranchLayouts(parentElement);
|
|
1162
|
-
if (branchLayouts[0] === MindLayoutType.standard) {
|
|
1163
|
-
const node = MindElement.getNode(element);
|
|
1164
|
-
branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
|
|
1165
|
-
}
|
|
1166
|
-
const currentLayoutDirections = getBranchDirectionsByLayouts(branchLayouts);
|
|
1167
|
-
let availableSubLayouts = getAvailableSubLayoutsByLayoutDirections(currentLayoutDirections);
|
|
1168
|
-
const parentLayout = [branchLayouts[branchLayouts.length - 1]];
|
|
1169
|
-
const parentDirections = getBranchDirectionsByLayouts(parentLayout);
|
|
1170
|
-
const parentAvailableSubLayouts = getAvailableSubLayoutsByLayoutDirections(parentDirections);
|
|
1171
|
-
availableSubLayouts = availableSubLayouts.filter(layout => parentAvailableSubLayouts.some(parentAvailableSubLayout => parentAvailableSubLayout === layout));
|
|
1172
|
-
return availableSubLayouts;
|
|
1033
|
+
const drawPlaceholderDropNodeG = (board, dropTarget, fakeDropNodeG) => {
|
|
1034
|
+
const targetComponent = PlaitElement.getComponent(dropTarget.target);
|
|
1035
|
+
const targetRect = getRectangleByNode(targetComponent.node);
|
|
1036
|
+
if (dropTarget.detectResult && ['right', 'left'].includes(dropTarget.detectResult)) {
|
|
1037
|
+
drawStraightDropNodeG(board, targetRect, dropTarget.detectResult, targetComponent, fakeDropNodeG);
|
|
1173
1038
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
* 获取父节点布局类型
|
|
1179
|
-
* @param element
|
|
1180
|
-
* @returns MindLayoutType
|
|
1181
|
-
*/
|
|
1182
|
-
const getLayoutParentByElement = (element) => {
|
|
1183
|
-
let parent = findParentElement(element);
|
|
1184
|
-
while (parent) {
|
|
1185
|
-
if (parent.layout) {
|
|
1186
|
-
return parent.layout;
|
|
1187
|
-
}
|
|
1188
|
-
parent = findParentElement(parent);
|
|
1039
|
+
if (targetComponent.parent && dropTarget.detectResult && ['top', 'bottom'].includes(dropTarget.detectResult)) {
|
|
1040
|
+
const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
1041
|
+
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
1042
|
+
drawCurvePlaceholderDropNodeG(board, targetRect, dropTarget.detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG);
|
|
1189
1043
|
}
|
|
1190
|
-
return getDefaultLayout();
|
|
1191
1044
|
};
|
|
1192
|
-
|
|
1193
|
-
const
|
|
1194
|
-
const layout =
|
|
1195
|
-
|
|
1196
|
-
|
|
1045
|
+
const drawCurvePlaceholderDropNodeG = (board, targetRect, detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG) => {
|
|
1046
|
+
const parentNodeLayout = MindQueries.getCorrectLayoutByElement(parentComponent.node.origin);
|
|
1047
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.parent.origin);
|
|
1048
|
+
const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
|
|
1049
|
+
let fakeX = targetComponent.node.x, fakeY = targetRect.y - 30, fakeRectangleStartX = targetRect.x, fakeRectangleEndX = targetRect.x + 30, fakeRectangleStartY = fakeY, fakeRectangleEndY = fakeRectangleStartY + 12, width = 30;
|
|
1050
|
+
if (isLeftLayout(layout)) {
|
|
1051
|
+
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
1052
|
+
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
1053
|
+
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
1197
1054
|
}
|
|
1198
|
-
if (
|
|
1199
|
-
(
|
|
1200
|
-
|
|
1201
|
-
|
|
1055
|
+
if (isHorizontalLogicLayout(parentNodeLayout)) {
|
|
1056
|
+
fakeY = getHorizontalFakeY(detectResult, targetIndex, parentComponent.node, targetRect, layout, fakeY);
|
|
1057
|
+
if (isStandardLayout(parentNodeLayout)) {
|
|
1058
|
+
const rightNodeCount = parentComponent.node.origin.rightNodeCount || 0;
|
|
1059
|
+
const idx = parentComponent.node.children.findIndex(x => x === targetComponent.node);
|
|
1060
|
+
const isLeft = idx >= rightNodeCount;
|
|
1061
|
+
// 标准布局的左,需要调整 x
|
|
1062
|
+
if (isLeft) {
|
|
1063
|
+
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
1064
|
+
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
1065
|
+
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
1066
|
+
}
|
|
1067
|
+
const isLeftFirst = idx === rightNodeCount;
|
|
1068
|
+
const isRightLast = idx === rightNodeCount - 1;
|
|
1069
|
+
// 拖拽至左第一个节点的情况
|
|
1070
|
+
if (detectResult === 'top' && isLeftFirst) {
|
|
1071
|
+
fakeY = targetRect.y - targetRect.height;
|
|
1072
|
+
}
|
|
1073
|
+
if (detectResult === 'bottom' && isRightLast) {
|
|
1074
|
+
fakeY = targetRect.y + targetRect.height + 30;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
fakeRectangleStartY = fakeY;
|
|
1078
|
+
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1202
1079
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1080
|
+
if (isVerticalLogicLayout(layout)) {
|
|
1081
|
+
parentComponent = targetComponent;
|
|
1082
|
+
targetComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
1083
|
+
fakeX = parentComponent.node.x;
|
|
1084
|
+
width = parentComponent.node.width;
|
|
1085
|
+
const vGap = BASE * 6 + strokeWidth;
|
|
1086
|
+
if (isTopLayout(layout) && detectResult === 'top') {
|
|
1087
|
+
fakeY = targetRect.y - vGap;
|
|
1088
|
+
fakeRectangleStartY = fakeY - vGap + strokeWidth;
|
|
1089
|
+
}
|
|
1090
|
+
if (isBottomLayout(layout) && detectResult === 'bottom') {
|
|
1091
|
+
fakeY = targetRect.y + targetRect.height + vGap;
|
|
1092
|
+
fakeRectangleStartY = fakeY + vGap - strokeWidth;
|
|
1093
|
+
}
|
|
1094
|
+
fakeRectangleStartX = fakeX + Math.ceil(parentComponent.node.width / 2) - parentComponent.node.hGap - Math.ceil(strokeWidth / 2);
|
|
1095
|
+
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
1096
|
+
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1217
1097
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
return _layout === layout;
|
|
1223
|
-
},
|
|
1224
|
-
isIndentedLayout(value) {
|
|
1225
|
-
const _layout = MindQueries.getLayoutByElement(value);
|
|
1226
|
-
return isIndentedLayout(_layout);
|
|
1227
|
-
},
|
|
1228
|
-
isMindElement(board, element) {
|
|
1229
|
-
const path = PlaitBoard.findPath(board, element);
|
|
1230
|
-
const rootElement = PlaitNode.get(board, path.slice(0, 1));
|
|
1231
|
-
if (PlaitMind.isMind(rootElement)) {
|
|
1232
|
-
return true;
|
|
1098
|
+
if (isIndentedLayout(layout)) {
|
|
1099
|
+
// 偏移一个 Gap
|
|
1100
|
+
if (isLeftLayout(layout)) {
|
|
1101
|
+
fakeX -= BASE * 4;
|
|
1233
1102
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1103
|
+
if (isRightLayout(layout)) {
|
|
1104
|
+
fakeX += BASE * 4;
|
|
1236
1105
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1106
|
+
if (isTopLayout(layout)) {
|
|
1107
|
+
if (detectResult === 'top') {
|
|
1108
|
+
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
1109
|
+
if (isLastNode) {
|
|
1110
|
+
fakeY = targetRect.y - targetRect.height - BASE;
|
|
1111
|
+
}
|
|
1112
|
+
else {
|
|
1113
|
+
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1114
|
+
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1115
|
+
fakeY = targetRect.y - Math.abs((nextRect.y + nextRect.height - targetRect.y) / 2);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
if (detectResult === 'bottom') {
|
|
1119
|
+
const isFirstNode = targetIndex === 0;
|
|
1120
|
+
if (isFirstNode) {
|
|
1121
|
+
const parentRect = getRectangleByNode(parentComponent.node);
|
|
1122
|
+
fakeY = parentRect.y - parentRect.height / 2 - BASE;
|
|
1123
|
+
}
|
|
1124
|
+
else {
|
|
1125
|
+
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1126
|
+
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1127
|
+
fakeY = previousRect.y - Math.abs((targetRect.y + targetRect.height - previousRect.y) / 2);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1241
1130
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
},
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1131
|
+
fakeRectangleStartX = fakeX;
|
|
1132
|
+
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
1133
|
+
fakeRectangleStartY = fakeY;
|
|
1134
|
+
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1135
|
+
}
|
|
1136
|
+
// 构造一条曲线
|
|
1137
|
+
const fakeNode = Object.assign(Object.assign({}, targetComponent.node), { x: fakeX, y: fakeY, width, height: 12 });
|
|
1138
|
+
const linkSVGG = isIndentedLayout(layout)
|
|
1139
|
+
? drawIndentedLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false)
|
|
1140
|
+
: drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, isHorizontalLayout(layout), false);
|
|
1141
|
+
// 构造一个矩形框坐标
|
|
1142
|
+
const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), fakeRectangleStartX, fakeRectangleStartY, fakeRectangleEndX, fakeRectangleEndY, {
|
|
1143
|
+
stroke: PRIMARY_COLOR,
|
|
1144
|
+
strokeWidth: 2,
|
|
1145
|
+
fill: PRIMARY_COLOR,
|
|
1146
|
+
fillStyle: 'solid'
|
|
1147
|
+
});
|
|
1148
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
1149
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
|
|
1150
|
+
};
|
|
1151
|
+
const drawStraightDropNodeG = (board, targetRect, detectResult, targetComponent, fakeDropNodeG) => {
|
|
1152
|
+
const { x, y, width, height } = targetRect;
|
|
1153
|
+
const lineLength = 40;
|
|
1154
|
+
let startLinePoint = x + width;
|
|
1155
|
+
let endLinePoint = x + width + lineLength;
|
|
1156
|
+
let startRectanglePointX = x + width + lineLength;
|
|
1157
|
+
let endRectanglePointX = x + lineLength + width + 30;
|
|
1158
|
+
let startRectanglePointY = y + height / 2 - 6;
|
|
1159
|
+
let endRectanglePointY = y + height / 2 - 6 + 12;
|
|
1160
|
+
if (detectResult === 'left') {
|
|
1161
|
+
startLinePoint = x - lineLength;
|
|
1162
|
+
endLinePoint = x;
|
|
1163
|
+
startRectanglePointX = x - lineLength - 30;
|
|
1164
|
+
endRectanglePointX = x - lineLength;
|
|
1165
|
+
}
|
|
1166
|
+
let fakeY = targetComponent.node.y;
|
|
1167
|
+
let fakeX = targetRect.x;
|
|
1168
|
+
const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
|
|
1169
|
+
const pointOptions = {
|
|
1170
|
+
fakeX,
|
|
1171
|
+
fakeY,
|
|
1172
|
+
x,
|
|
1173
|
+
y,
|
|
1174
|
+
width,
|
|
1175
|
+
height,
|
|
1176
|
+
strokeWidth
|
|
1177
|
+
};
|
|
1178
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1179
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1180
|
+
if (!isMixedLayout(parentLayout, layout)) {
|
|
1181
|
+
// 构造一条直线
|
|
1182
|
+
let linePoints = [
|
|
1183
|
+
[startLinePoint, y + height / 2],
|
|
1184
|
+
[endLinePoint, y + height / 2]
|
|
1185
|
+
];
|
|
1186
|
+
if (isIndentedLayout(parentLayout)) {
|
|
1187
|
+
const fakePoint = getIndentedFakePoint(parentLayout, pointOptions);
|
|
1188
|
+
drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
|
|
1189
|
+
return;
|
|
1253
1190
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1191
|
+
else if (isVerticalLogicLayout(parentLayout)) {
|
|
1192
|
+
if (!targetComponent.node.origin.isRoot) {
|
|
1193
|
+
/**
|
|
1194
|
+
* 计算逻辑:
|
|
1195
|
+
* 1. 移动到左侧:当前节点 startX - 偏移值,偏移值计算如下:
|
|
1196
|
+
* a. 第一个节点: 固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
|
|
1197
|
+
* b. 第二个节点到最后一个节点之间:上一个节点到当前节点间距的一半((当前节点 startX - 上一个节点的 endX) / 2),endX = 当前节点的 startX + width;
|
|
1198
|
+
* 2. 移动到右侧:当前节点 x + width + 偏移值,偏移值计算如下:
|
|
1199
|
+
* a. 第二个节点到最后一个节点之间的右侧:当前节点到下一个节点间距的一半((下一个节点 startX - 当前节点的 endX) / 2),endX = 当前节点的 startX + width;
|
|
1200
|
+
* b. 最后一个节点的右侧:固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
|
|
1201
|
+
*/
|
|
1202
|
+
fakeY = targetComponent.node.y;
|
|
1203
|
+
const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
1204
|
+
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
1205
|
+
if (detectResult === 'left') {
|
|
1206
|
+
let offsetX = 0;
|
|
1207
|
+
const isFirstNode = targetIndex === 0;
|
|
1208
|
+
if (isFirstNode) {
|
|
1209
|
+
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
1210
|
+
}
|
|
1211
|
+
else {
|
|
1212
|
+
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex - 1]);
|
|
1213
|
+
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1214
|
+
const space = targetRect.x - (previousRect.x + previousRect.width);
|
|
1215
|
+
offsetX = space / 2;
|
|
1216
|
+
}
|
|
1217
|
+
fakeX = targetRect.x - offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
1218
|
+
}
|
|
1219
|
+
if (detectResult === 'right') {
|
|
1220
|
+
let offsetX = 0;
|
|
1221
|
+
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
1222
|
+
if (isLastNode) {
|
|
1223
|
+
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
1224
|
+
}
|
|
1225
|
+
else {
|
|
1226
|
+
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1227
|
+
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1228
|
+
const space = nextRect.x - (targetRect.x + targetRect.width);
|
|
1229
|
+
offsetX = space / 2;
|
|
1230
|
+
}
|
|
1231
|
+
fakeX = targetRect.x + width + offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
1232
|
+
}
|
|
1233
|
+
startRectanglePointX = fakeX;
|
|
1234
|
+
if (isTopLayout(parentLayout)) {
|
|
1235
|
+
// 因为矩形是从左上角为起点向下画的,所以需要向上偏移一个矩形的高度(-12)
|
|
1236
|
+
startRectanglePointY = fakeY + height + targetComponent.node.vGap - 12;
|
|
1237
|
+
}
|
|
1238
|
+
if (isBottomLayout(parentLayout)) {
|
|
1239
|
+
startRectanglePointY = fakeY + targetComponent.node.vGap;
|
|
1240
|
+
}
|
|
1241
|
+
endRectanglePointX = startRectanglePointX + 30;
|
|
1242
|
+
endRectanglePointY = startRectanglePointY + 12;
|
|
1243
|
+
const fakeNode = Object.assign(Object.assign({}, targetComponent.node), { x: fakeX, y: fakeY, width: 30 });
|
|
1244
|
+
const linkSVGG = drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false, false);
|
|
1245
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
1246
|
+
}
|
|
1259
1247
|
}
|
|
1260
1248
|
else {
|
|
1261
|
-
|
|
1249
|
+
let linkSVGG = PlaitBoard.getRoughSVG(board).linearPath(linePoints, { stroke: PRIMARY_COLOR, strokeWidth });
|
|
1250
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
1262
1251
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1252
|
+
// 构造一个矩形框坐标
|
|
1253
|
+
let fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
1254
|
+
stroke: PRIMARY_COLOR,
|
|
1255
|
+
strokeWidth: 2,
|
|
1256
|
+
fill: PRIMARY_COLOR,
|
|
1257
|
+
fillStyle: 'solid'
|
|
1258
|
+
});
|
|
1259
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
|
|
1266
1260
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
if (!node || !node.children || !node.children[p]) {
|
|
1275
|
-
throw new Error(`Cannot find a descendant at path [${path}]`);
|
|
1261
|
+
else {
|
|
1262
|
+
// 混合布局画线逻辑
|
|
1263
|
+
if (isHorizontalLogicLayout(parentLayout)) {
|
|
1264
|
+
if (isIndentedLayout(layout)) {
|
|
1265
|
+
const fakePoint = getIndentedFakePoint(layout, pointOptions);
|
|
1266
|
+
drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
|
|
1267
|
+
return;
|
|
1276
1268
|
}
|
|
1277
|
-
node = node.children[p];
|
|
1278
|
-
}
|
|
1279
|
-
return node;
|
|
1280
|
-
},
|
|
1281
|
-
isEquals(node, otherNode) {
|
|
1282
|
-
const hasSameSize = node.x === otherNode.x && node.y === otherNode.y && node.width === otherNode.width && node.height === otherNode.height;
|
|
1283
|
-
const hasSameOrigin = node.origin === otherNode.origin;
|
|
1284
|
-
let hasSameParentOriginChildren = false;
|
|
1285
|
-
if (node.parent && otherNode.parent) {
|
|
1286
|
-
hasSameParentOriginChildren = node.parent.origin.children == otherNode.parent.origin.children;
|
|
1287
1269
|
}
|
|
1288
|
-
return hasSameSize && hasSameOrigin && hasSameParentOriginChildren;
|
|
1289
|
-
}
|
|
1290
|
-
};
|
|
1291
|
-
|
|
1292
|
-
var LayoutDirection;
|
|
1293
|
-
(function (LayoutDirection) {
|
|
1294
|
-
LayoutDirection["top"] = "top";
|
|
1295
|
-
LayoutDirection["right"] = "right";
|
|
1296
|
-
LayoutDirection["bottom"] = "bottom";
|
|
1297
|
-
LayoutDirection["left"] = "left";
|
|
1298
|
-
})(LayoutDirection || (LayoutDirection = {}));
|
|
1299
|
-
const LayoutDirectionsMap = {
|
|
1300
|
-
[MindLayoutType.right]: [LayoutDirection.right],
|
|
1301
|
-
[MindLayoutType.left]: [LayoutDirection.left],
|
|
1302
|
-
[MindLayoutType.upward]: [LayoutDirection.top],
|
|
1303
|
-
[MindLayoutType.downward]: [LayoutDirection.bottom],
|
|
1304
|
-
[MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
|
|
1305
|
-
[MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
|
|
1306
|
-
[MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
|
|
1307
|
-
[MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
|
|
1308
|
-
};
|
|
1309
|
-
|
|
1310
|
-
var AbstractHandlePosition;
|
|
1311
|
-
(function (AbstractHandlePosition) {
|
|
1312
|
-
AbstractHandlePosition["start"] = "start";
|
|
1313
|
-
AbstractHandlePosition["end"] = "end";
|
|
1314
|
-
})(AbstractHandlePosition || (AbstractHandlePosition = {}));
|
|
1315
|
-
var AbstractResizeState;
|
|
1316
|
-
(function (AbstractResizeState) {
|
|
1317
|
-
AbstractResizeState["start"] = "start";
|
|
1318
|
-
AbstractResizeState["resizing"] = "resizing";
|
|
1319
|
-
AbstractResizeState["end"] = "end";
|
|
1320
|
-
})(AbstractResizeState || (AbstractResizeState = {}));
|
|
1321
|
-
|
|
1322
|
-
function enterNodeEditing(element) {
|
|
1323
|
-
const component = ELEMENT_TO_COMPONENT.get(element);
|
|
1324
|
-
component.startEditText(false, false);
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
function findParentElement(element) {
|
|
1328
|
-
const component = PlaitElement.getComponent(element);
|
|
1329
|
-
if (component && component.parent) {
|
|
1330
|
-
return component.parent.origin;
|
|
1331
|
-
}
|
|
1332
|
-
return undefined;
|
|
1333
|
-
}
|
|
1334
|
-
function findUpElement(element) {
|
|
1335
|
-
let branch;
|
|
1336
|
-
let root = element;
|
|
1337
|
-
let parent = findParentElement(element);
|
|
1338
|
-
while (parent) {
|
|
1339
|
-
branch = root;
|
|
1340
|
-
root = parent;
|
|
1341
|
-
parent = findParentElement(parent);
|
|
1342
1270
|
}
|
|
1343
|
-
return { root, branch };
|
|
1344
|
-
}
|
|
1345
|
-
const getChildrenCount = (element) => {
|
|
1346
|
-
const count = element.children.reduce((p, c) => {
|
|
1347
|
-
return p + getChildrenCount(c);
|
|
1348
|
-
}, 0);
|
|
1349
|
-
return count + element.children.length;
|
|
1350
1271
|
};
|
|
1351
|
-
const
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
return true;
|
|
1272
|
+
const getHorizontalFakeY = (detectResult, targetIndex, parentNode, targetRect, layout, fakeY) => {
|
|
1273
|
+
if (detectResult === 'top') {
|
|
1274
|
+
if (targetIndex === 0 && isTopLayout(layout)) {
|
|
1275
|
+
fakeY = targetRect.y + targetRect.height;
|
|
1356
1276
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
let result = [];
|
|
1363
|
-
elements.forEach(element => {
|
|
1364
|
-
const isChild = elements.some(node => {
|
|
1365
|
-
return isChildElement(node, element);
|
|
1366
|
-
});
|
|
1367
|
-
if (!isChild) {
|
|
1368
|
-
result.push(element);
|
|
1277
|
+
if (targetIndex > 0) {
|
|
1278
|
+
const previousComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex - 1]);
|
|
1279
|
+
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1280
|
+
const topY = previousRect.y + previousRect.height;
|
|
1281
|
+
fakeY = topY + (targetRect.y - topY) / 5;
|
|
1369
1282
|
}
|
|
1370
|
-
});
|
|
1371
|
-
return result;
|
|
1372
|
-
};
|
|
1373
|
-
const isChildRight = (node, child) => {
|
|
1374
|
-
return node.x < child.x;
|
|
1375
|
-
};
|
|
1376
|
-
const isChildUp = (node, child) => {
|
|
1377
|
-
return node.y > child.y;
|
|
1378
|
-
};
|
|
1379
|
-
const copyNewNode = (node) => {
|
|
1380
|
-
const newNode = Object.assign({}, node);
|
|
1381
|
-
newNode.id = idCreator();
|
|
1382
|
-
newNode.children = [];
|
|
1383
|
-
for (const childNode of node.children) {
|
|
1384
|
-
newNode.children.push(copyNewNode(childNode));
|
|
1385
|
-
}
|
|
1386
|
-
return newNode;
|
|
1387
|
-
};
|
|
1388
|
-
const transformRootToNode = (board, node) => {
|
|
1389
|
-
const newNode = Object.assign({}, node);
|
|
1390
|
-
delete newNode.isRoot;
|
|
1391
|
-
delete newNode.rightNodeCount;
|
|
1392
|
-
delete newNode.type;
|
|
1393
|
-
const text = Node.string(node.data.topic.children[0]) || ' ';
|
|
1394
|
-
const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT);
|
|
1395
|
-
newNode.width = Math.max(width, NODE_MIN_WIDTH);
|
|
1396
|
-
newNode.height = height;
|
|
1397
|
-
if (newNode.layout === MindLayoutType.standard) {
|
|
1398
|
-
delete newNode.layout;
|
|
1399
|
-
}
|
|
1400
|
-
return newNode;
|
|
1401
|
-
};
|
|
1402
|
-
const transformNodeToRoot = (board, node) => {
|
|
1403
|
-
var _a;
|
|
1404
|
-
const newElement = Object.assign({}, node);
|
|
1405
|
-
let text = Node.string(newElement.data.topic);
|
|
1406
|
-
if (!text) {
|
|
1407
|
-
text = '思维导图';
|
|
1408
|
-
newElement.data.topic = { children: [{ text }] };
|
|
1409
1283
|
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
return Object.assign(Object.assign({}, newElement), { layout: (_a = newElement.layout) !== null && _a !== void 0 ? _a : MindLayoutType.right, isCollapsed: false, isRoot: true, type: 'mindmap' });
|
|
1418
|
-
};
|
|
1419
|
-
const extractNodesText = (node) => {
|
|
1420
|
-
let str = '';
|
|
1421
|
-
if (node) {
|
|
1422
|
-
str += Node.string(node.data.topic.children[0]) + ' ';
|
|
1423
|
-
for (const childNode of node.children) {
|
|
1424
|
-
str += extractNodesText(childNode);
|
|
1284
|
+
if (detectResult === 'bottom') {
|
|
1285
|
+
fakeY = targetRect.y + targetRect.height + 30;
|
|
1286
|
+
if (targetIndex < parentNode.origin.children.length - 1) {
|
|
1287
|
+
const nextComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex + 1]);
|
|
1288
|
+
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1289
|
+
const topY = targetRect.y + targetRect.height;
|
|
1290
|
+
fakeY = topY + (nextRect.y - topY) / 5;
|
|
1425
1291
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
};
|
|
1429
|
-
const changeRightNodeCount = (board, parentPath, changeNumber) => {
|
|
1430
|
-
const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
|
|
1431
|
-
Transforms.setNode(board, {
|
|
1432
|
-
rightNodeCount: changeNumber >= 0
|
|
1433
|
-
? _rightNodeCount + changeNumber
|
|
1434
|
-
: _rightNodeCount + changeNumber < 0
|
|
1435
|
-
? 0
|
|
1436
|
-
: _rightNodeCount + changeNumber
|
|
1437
|
-
}, parentPath);
|
|
1438
|
-
};
|
|
1439
|
-
const shouldChangeRightNodeCount = (selectedElement) => {
|
|
1440
|
-
const parentElement = findParentElement(selectedElement);
|
|
1441
|
-
if (parentElement) {
|
|
1442
|
-
const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
|
|
1443
|
-
if (parentElement.isRoot &&
|
|
1444
|
-
getRootLayout(parentElement) === MindLayoutType.standard &&
|
|
1445
|
-
parentElement.rightNodeCount &&
|
|
1446
|
-
nodeIndex <= parentElement.rightNodeCount - 1) {
|
|
1447
|
-
return true;
|
|
1292
|
+
if (targetIndex === parentNode.origin.children.length - 1) {
|
|
1293
|
+
fakeY = targetRect.y + targetRect.height + 30;
|
|
1448
1294
|
}
|
|
1449
1295
|
}
|
|
1450
|
-
return
|
|
1451
|
-
};
|
|
1452
|
-
const createDefaultMindMapElement = (point, rightNodeCount, layout) => {
|
|
1453
|
-
const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle, layout });
|
|
1454
|
-
root.rightNodeCount = rightNodeCount;
|
|
1455
|
-
root.isRoot = true;
|
|
1456
|
-
root.type = 'mindmap';
|
|
1457
|
-
root.points = [point];
|
|
1458
|
-
const children = [1, 1, 1].map(() => {
|
|
1459
|
-
return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle });
|
|
1460
|
-
});
|
|
1461
|
-
root.children = children;
|
|
1462
|
-
return root;
|
|
1296
|
+
return fakeY;
|
|
1463
1297
|
};
|
|
1464
|
-
const
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
height,
|
|
1473
|
-
fill: options.fill,
|
|
1474
|
-
strokeColor: options.strokeColor,
|
|
1475
|
-
strokeWidth: options.strokeWidth,
|
|
1476
|
-
shape: options.shape
|
|
1477
|
-
};
|
|
1478
|
-
if (options.fill) {
|
|
1479
|
-
newElement.fill = options.fill;
|
|
1298
|
+
const getIndentedFakePoint = (layout, pointOptions) => {
|
|
1299
|
+
let { fakeX, fakeY, x, y, width, height, strokeWidth } = pointOptions;
|
|
1300
|
+
const hGap = BASE * 4;
|
|
1301
|
+
const vGap = BASE * 6;
|
|
1302
|
+
const offsetX = hGap + width / 2 + strokeWidth;
|
|
1303
|
+
const offsetY = vGap + height / 2 + strokeWidth;
|
|
1304
|
+
if (isLeftLayout(layout)) {
|
|
1305
|
+
fakeX = x - offsetX;
|
|
1480
1306
|
}
|
|
1481
|
-
if (
|
|
1482
|
-
|
|
1307
|
+
if (isRightLayout(layout)) {
|
|
1308
|
+
fakeX = x + offsetX;
|
|
1483
1309
|
}
|
|
1484
|
-
if (
|
|
1485
|
-
|
|
1310
|
+
if (isTopLayout(layout)) {
|
|
1311
|
+
fakeY = y - offsetY;
|
|
1486
1312
|
}
|
|
1487
|
-
if (
|
|
1488
|
-
|
|
1313
|
+
if (isBottomLayout(layout)) {
|
|
1314
|
+
fakeY = y + height + offsetY;
|
|
1489
1315
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1316
|
+
return { fakeX, fakeY };
|
|
1317
|
+
};
|
|
1318
|
+
const drawIndentNodeG = (board, fakeDropNodeG, fakePoint, node) => {
|
|
1319
|
+
const { fakeX, fakeY } = fakePoint;
|
|
1320
|
+
const fakeNode = Object.assign(Object.assign({}, node), { x: fakeX, y: fakeY, width: 30, height: 12 });
|
|
1321
|
+
const linkSVGG = drawIndentedLink(board, node, fakeNode, PRIMARY_COLOR, false);
|
|
1322
|
+
const startRectanglePointX = fakeX, startRectanglePointY = fakeY, endRectanglePointX = fakeX + 30, endRectanglePointY = fakeY + 12;
|
|
1323
|
+
const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
1324
|
+
stroke: PRIMARY_COLOR,
|
|
1325
|
+
strokeWidth: 2,
|
|
1326
|
+
fill: PRIMARY_COLOR,
|
|
1327
|
+
fillStyle: 'solid'
|
|
1328
|
+
});
|
|
1329
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
|
|
1330
|
+
fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
|
|
1331
|
+
};
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
*
|
|
1335
|
+
* @param targetNode
|
|
1336
|
+
* @param centerPoint
|
|
1337
|
+
* @returns DetectResult[] | null
|
|
1338
|
+
*/
|
|
1339
|
+
const directionDetector = (targetNode, centerPoint) => {
|
|
1340
|
+
const { x, y, width, height } = getRectangleByNode(targetNode);
|
|
1341
|
+
const yCenter = y + height / 2;
|
|
1342
|
+
const xCenter = x + width / 2;
|
|
1343
|
+
const top = targetNode.y;
|
|
1344
|
+
const bottom = targetNode.y + targetNode.height;
|
|
1345
|
+
const left = targetNode.x;
|
|
1346
|
+
const right = targetNode.x + targetNode.width;
|
|
1347
|
+
const direction = [];
|
|
1348
|
+
// x 轴
|
|
1349
|
+
if (centerPoint[1] > y && centerPoint[1] < y + height) {
|
|
1350
|
+
if (centerPoint[0] > left && centerPoint[0] < xCenter) {
|
|
1351
|
+
direction.push('left');
|
|
1352
|
+
}
|
|
1353
|
+
if (centerPoint[0] > xCenter && centerPoint[0] < right) {
|
|
1354
|
+
direction.push('right');
|
|
1355
|
+
}
|
|
1356
|
+
// 重合区域,返回两个方向
|
|
1357
|
+
if ((centerPoint[0] > x && centerPoint[0] < xCenter) || (centerPoint[0] > xCenter && centerPoint[0] < x + width)) {
|
|
1358
|
+
if (centerPoint[1] < yCenter) {
|
|
1359
|
+
direction.push('top');
|
|
1360
|
+
}
|
|
1361
|
+
else {
|
|
1362
|
+
direction.push('bottom');
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
return direction.length ? direction : null;
|
|
1492
1366
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1367
|
+
// y 轴
|
|
1368
|
+
if (centerPoint[0] > x && centerPoint[0] < x + width) {
|
|
1369
|
+
if (centerPoint[1] > top && centerPoint[1] < yCenter) {
|
|
1370
|
+
direction.push('top');
|
|
1371
|
+
}
|
|
1372
|
+
if (centerPoint[1] > yCenter && centerPoint[1] < bottom) {
|
|
1373
|
+
direction.push('bottom');
|
|
1374
|
+
}
|
|
1375
|
+
if ((centerPoint[1] > y && centerPoint[1] < y + height) || (centerPoint[1] > yCenter && centerPoint[1] < y + height)) {
|
|
1376
|
+
if (centerPoint[0] < xCenter) {
|
|
1377
|
+
direction.push('left');
|
|
1378
|
+
}
|
|
1379
|
+
else {
|
|
1380
|
+
direction.push('right');
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return direction.length ? direction : null;
|
|
1495
1384
|
}
|
|
1496
|
-
return
|
|
1385
|
+
return null;
|
|
1497
1386
|
};
|
|
1498
|
-
|
|
1499
|
-
const
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1387
|
+
|
|
1388
|
+
const directionCorrector = (node, detectResults) => {
|
|
1389
|
+
if (!node.origin.isRoot) {
|
|
1390
|
+
const parentlayout = MindQueries.getCorrectLayoutByElement(node === null || node === void 0 ? void 0 : node.parent.origin);
|
|
1391
|
+
if (isStandardLayout(parentlayout)) {
|
|
1392
|
+
const idx = node.parent.children.findIndex(x => x === node);
|
|
1393
|
+
const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
|
|
1394
|
+
return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
|
|
1395
|
+
}
|
|
1396
|
+
if (isLeftLayout(parentlayout)) {
|
|
1397
|
+
return getAllowedDirection(detectResults, ['right']);
|
|
1398
|
+
}
|
|
1399
|
+
if (isRightLayout(parentlayout)) {
|
|
1400
|
+
return getAllowedDirection(detectResults, ['left']);
|
|
1401
|
+
}
|
|
1402
|
+
if (parentlayout === MindLayoutType.upward) {
|
|
1403
|
+
return getAllowedDirection(detectResults, ['bottom']);
|
|
1404
|
+
}
|
|
1405
|
+
if (parentlayout === MindLayoutType.downward) {
|
|
1406
|
+
return getAllowedDirection(detectResults, ['top']);
|
|
1407
|
+
}
|
|
1505
1408
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1409
|
+
else {
|
|
1410
|
+
const layout = MindQueries.getCorrectLayoutByElement(node === null || node === void 0 ? void 0 : node.origin);
|
|
1411
|
+
if (isStandardLayout(layout)) {
|
|
1412
|
+
return getAllowedDirection(detectResults, ['top', 'bottom']);
|
|
1413
|
+
}
|
|
1414
|
+
if (isTopLayout(layout)) {
|
|
1415
|
+
return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
|
|
1416
|
+
}
|
|
1417
|
+
if (isBottomLayout(layout)) {
|
|
1418
|
+
return getAllowedDirection(detectResults, ['left', 'right', 'top']);
|
|
1419
|
+
}
|
|
1420
|
+
if (layout === MindLayoutType.left) {
|
|
1421
|
+
return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
|
|
1422
|
+
}
|
|
1423
|
+
if (layout === MindLayoutType.right) {
|
|
1424
|
+
return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
return null;
|
|
1428
|
+
};
|
|
1429
|
+
const getAllowedDirection = (detectResults, illegalDirections) => {
|
|
1430
|
+
const directions = detectResults;
|
|
1431
|
+
illegalDirections.forEach(item => {
|
|
1432
|
+
const bottomDirectionIndex = directions.findIndex(direction => direction === item);
|
|
1433
|
+
if (bottomDirectionIndex !== -1) {
|
|
1434
|
+
directions.splice(bottomDirectionIndex, 1);
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
return directions.length ? directions : null;
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
/* 根据布局调整 target 以及 direction */
|
|
1441
|
+
const readjustmentDropTarget = (dropTarget) => {
|
|
1442
|
+
const { target, detectResult } = dropTarget;
|
|
1443
|
+
const newDropTarget = { target, detectResult };
|
|
1444
|
+
const targetComponent = PlaitElement.getComponent(target);
|
|
1445
|
+
if (targetComponent.node.children.length > 0 && dropTarget.detectResult) {
|
|
1446
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1447
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1448
|
+
if (['right', 'left'].includes(dropTarget.detectResult)) {
|
|
1449
|
+
if (!isMixedLayout(parentLayout, layout)) {
|
|
1450
|
+
if (targetComponent.node.origin.isRoot) {
|
|
1451
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1452
|
+
// 标准布局,根节点
|
|
1453
|
+
if (isStandardLayout(layout)) {
|
|
1454
|
+
const rightNodeCount = targetComponent.node.origin.rightNodeCount;
|
|
1455
|
+
if (detectResult === 'left') {
|
|
1456
|
+
// 作为左的第一个节点
|
|
1457
|
+
if (targetComponent.node.children.length === rightNodeCount) {
|
|
1458
|
+
return newDropTarget;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
else {
|
|
1462
|
+
// 作为右的第一个节点或最后一个节点
|
|
1463
|
+
if (rightNodeCount === 0) {
|
|
1464
|
+
newDropTarget.target = target;
|
|
1465
|
+
}
|
|
1466
|
+
else {
|
|
1467
|
+
newDropTarget.target = targetComponent.node.children[rightNodeCount - 1].origin;
|
|
1468
|
+
newDropTarget.detectResult = 'bottom';
|
|
1469
|
+
}
|
|
1470
|
+
return newDropTarget;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
// 缩进布局探测到第一个子节点
|
|
1475
|
+
if (isIndentedLayout(parentLayout)) {
|
|
1476
|
+
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
1477
|
+
newDropTarget.detectResult = isTopLayout(parentLayout) ? 'bottom' : 'top';
|
|
1478
|
+
return newDropTarget;
|
|
1479
|
+
}
|
|
1480
|
+
// 上下布局的根节点只可以探测到上或者下,子节点的左右探测不处理,跳过。
|
|
1481
|
+
if (isVerticalLogicLayout(parentLayout)) {
|
|
1482
|
+
return newDropTarget;
|
|
1483
|
+
}
|
|
1484
|
+
// 剩下是水平布局的默认情况:插入最后一个子节点的下方
|
|
1485
|
+
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
1486
|
+
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
1487
|
+
newDropTarget.detectResult = 'bottom';
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
// 处理左右布局下的混合布局
|
|
1491
|
+
if ([MindLayoutType.left, MindLayoutType.right].includes(parentLayout)) {
|
|
1492
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1493
|
+
if (isIndentedLayout(layout)) {
|
|
1494
|
+
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
1495
|
+
newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
|
|
1496
|
+
return newDropTarget;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
if (['top', 'bottom'].includes(dropTarget.detectResult)) {
|
|
1502
|
+
// 缩进布局移动至第一个节点
|
|
1503
|
+
if (targetComponent.node.origin.isRoot && isIndentedLayout(layout)) {
|
|
1504
|
+
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
1505
|
+
newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
|
|
1506
|
+
return newDropTarget;
|
|
1507
|
+
}
|
|
1508
|
+
// 上下布局,插到右边
|
|
1509
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1510
|
+
if (isVerticalLogicLayout(parentLayout)) {
|
|
1511
|
+
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
1512
|
+
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
1513
|
+
newDropTarget.detectResult = 'right';
|
|
1514
|
+
return newDropTarget;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
return newDropTarget;
|
|
1513
1518
|
}
|
|
1514
|
-
|
|
1515
|
-
clearSelectedElement(board);
|
|
1516
|
-
addSelectedElement(board, newElement);
|
|
1517
|
-
setTimeout(() => {
|
|
1518
|
-
enterNodeEditing(newElement);
|
|
1519
|
-
});
|
|
1519
|
+
return dropTarget;
|
|
1520
1520
|
};
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1521
|
+
|
|
1522
|
+
const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
|
|
1523
|
+
if (isHorizontal) {
|
|
1524
|
+
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
1525
|
+
return Object.assign(Object.assign({}, abstractRectangle), { y: location, height: abstractRectangle.height + abstractRectangle.y - location });
|
|
1526
|
+
}
|
|
1527
|
+
else {
|
|
1528
|
+
return Object.assign(Object.assign({}, abstractRectangle), { height: location - abstractRectangle.y });
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
else {
|
|
1532
|
+
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
1533
|
+
return Object.assign(Object.assign({}, abstractRectangle), { x: location, width: abstractRectangle.width + abstractRectangle.x - location });
|
|
1534
|
+
}
|
|
1535
|
+
else {
|
|
1536
|
+
return Object.assign(Object.assign({}, abstractRectangle), { width: location - abstractRectangle.x });
|
|
1537
|
+
}
|
|
1525
1538
|
}
|
|
1526
|
-
return result;
|
|
1527
1539
|
};
|
|
1528
|
-
const
|
|
1529
|
-
|
|
1530
|
-
const
|
|
1531
|
-
const
|
|
1532
|
-
const
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
const
|
|
1538
|
-
|
|
1539
|
-
const
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
accumulativeProperties.set(abstractNode, newProperties);
|
|
1545
|
-
relativeAbstracts.push(abstractNode);
|
|
1546
|
-
}
|
|
1547
|
-
newProperties.end = newProperties.end - 1;
|
|
1548
|
-
}
|
|
1549
|
-
});
|
|
1540
|
+
const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
|
|
1541
|
+
const node = MindElement.getNode(element);
|
|
1542
|
+
const { start, end } = getCorrectStartEnd(node.origin, parent);
|
|
1543
|
+
const startNode = parentChildren[start];
|
|
1544
|
+
const endNode = parentChildren[end];
|
|
1545
|
+
if (handlePosition === AbstractHandlePosition.start) {
|
|
1546
|
+
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
|
|
1547
|
+
let minNode;
|
|
1548
|
+
if (abstractNode.length) {
|
|
1549
|
+
const index = abstractNode
|
|
1550
|
+
.map(node => {
|
|
1551
|
+
const { end } = getCorrectStartEnd(node, parent);
|
|
1552
|
+
return end;
|
|
1553
|
+
})
|
|
1554
|
+
.sort((a, b) => b - a)[0];
|
|
1555
|
+
minNode = parentChildren[index + 1];
|
|
1550
1556
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
else {
|
|
1561
|
-
Transforms.setNode(board, newProperties, path);
|
|
1562
|
-
}
|
|
1557
|
+
else {
|
|
1558
|
+
minNode = parentChildren[0];
|
|
1559
|
+
}
|
|
1560
|
+
const minNodeRectangle = getRectangleByElements(board, [minNode], true);
|
|
1561
|
+
const endNodeRectangle = getRectangleByElements(board, [endNode], false);
|
|
1562
|
+
if (isHorizontal) {
|
|
1563
|
+
return {
|
|
1564
|
+
max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1565
|
+
min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1563
1566
|
};
|
|
1564
1567
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
};
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
const parent = MindElement.getParent(elements[i]);
|
|
1584
|
-
const parentIndex = parentElements.indexOf(parent);
|
|
1585
|
-
if (parentIndex === -1) {
|
|
1586
|
-
parentElements.push(parent);
|
|
1587
|
-
abstractIncludedGroups.push([elements[i]]);
|
|
1568
|
+
else {
|
|
1569
|
+
return {
|
|
1570
|
+
max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1571
|
+
min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
else {
|
|
1576
|
+
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
|
|
1577
|
+
let maxNode;
|
|
1578
|
+
if (abstractNode.length) {
|
|
1579
|
+
const index = abstractNode
|
|
1580
|
+
.map(node => {
|
|
1581
|
+
const { start } = getCorrectStartEnd(node, parent);
|
|
1582
|
+
return start;
|
|
1583
|
+
})
|
|
1584
|
+
.sort((a, b) => a - b)[0];
|
|
1585
|
+
maxNode = parentChildren[index - 1];
|
|
1588
1586
|
}
|
|
1589
1587
|
else {
|
|
1590
|
-
|
|
1588
|
+
const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
|
|
1589
|
+
maxNode = parentChildren[children.length - 1];
|
|
1590
|
+
}
|
|
1591
|
+
const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
|
|
1592
|
+
const startNodeRectangle = getRectangleByElements(board, [startNode], false);
|
|
1593
|
+
if (isHorizontal) {
|
|
1594
|
+
return {
|
|
1595
|
+
max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1596
|
+
min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
else {
|
|
1600
|
+
return {
|
|
1601
|
+
max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1602
|
+
min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1603
|
+
};
|
|
1591
1604
|
}
|
|
1592
1605
|
}
|
|
1593
|
-
return { parentElements, abstractIncludedGroups };
|
|
1594
1606
|
};
|
|
1595
|
-
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
return
|
|
1607
|
+
const getHitAbstractHandle = (board, element, point) => {
|
|
1608
|
+
const nodeLayout = MindQueries.getCorrectLayoutByElement(element);
|
|
1609
|
+
const isHorizontal = isHorizontalLayout(nodeLayout);
|
|
1610
|
+
const parentElement = MindElement.getParent(element);
|
|
1611
|
+
const includedElements = parentElement.children.slice(element.start, element.end + 1);
|
|
1612
|
+
let abstractRectangle = getRectangleByElements(board, includedElements, true);
|
|
1613
|
+
abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
|
|
1614
|
+
const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
|
|
1615
|
+
const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
|
|
1616
|
+
const pointRec = RectangleClient.toRectangleClient([point, point]);
|
|
1617
|
+
if (RectangleClient.isHit(pointRec, startHandleRec))
|
|
1618
|
+
return AbstractHandlePosition.start;
|
|
1619
|
+
if (RectangleClient.isHit(pointRec, endHandleRec))
|
|
1620
|
+
return AbstractHandlePosition.end;
|
|
1621
|
+
return undefined;
|
|
1622
|
+
};
|
|
1623
|
+
const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
|
|
1624
|
+
let result;
|
|
1625
|
+
if (position === AbstractHandlePosition.start) {
|
|
1626
|
+
const location = isHorizontal ? rectangle.y : rectangle.x;
|
|
1627
|
+
result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
|
|
1628
|
+
result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1607
1629
|
}
|
|
1608
1630
|
else {
|
|
1609
|
-
|
|
1631
|
+
const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
|
|
1632
|
+
result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
|
|
1633
|
+
result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1610
1634
|
}
|
|
1635
|
+
return result;
|
|
1611
1636
|
};
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1637
|
+
function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
|
|
1638
|
+
const children = parentChildren.filter(child => {
|
|
1639
|
+
return !AbstractNode.isAbstract(child);
|
|
1640
|
+
});
|
|
1641
|
+
const recArray = children.map(child => {
|
|
1642
|
+
return getRectangleByElements(board, [child], false);
|
|
1643
|
+
});
|
|
1644
|
+
const firstRec = getRectangleByElements(board, [children[0]], true);
|
|
1645
|
+
const fakeLeftRec = {
|
|
1646
|
+
x: firstRec.x - firstRec.width,
|
|
1647
|
+
y: firstRec.y - firstRec.height,
|
|
1648
|
+
width: firstRec.width,
|
|
1649
|
+
height: firstRec.height
|
|
1650
|
+
};
|
|
1651
|
+
const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
|
|
1652
|
+
const fakeRightRec = {
|
|
1653
|
+
x: lastRec.x + lastRec.width,
|
|
1654
|
+
y: lastRec.y + lastRec.height,
|
|
1655
|
+
width: lastRec.width,
|
|
1656
|
+
height: lastRec.height
|
|
1657
|
+
};
|
|
1658
|
+
recArray.push(fakeRightRec);
|
|
1659
|
+
recArray.unshift(fakeLeftRec);
|
|
1660
|
+
for (let i = 0; i < recArray.length - 1; i++) {
|
|
1661
|
+
const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
|
|
1662
|
+
const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
|
|
1663
|
+
if (location >= recXOrY + recWidthOrHeight / 2 &&
|
|
1664
|
+
location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
|
|
1665
|
+
return i - 1;
|
|
1666
|
+
}
|
|
1616
1667
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1668
|
+
return 0;
|
|
1669
|
+
}
|
|
1670
|
+
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1671
|
+
let touchedHandle;
|
|
1672
|
+
const abstract = getSelectedElements(board)
|
|
1673
|
+
.filter(element => AbstractNode.isAbstract(element))
|
|
1674
|
+
.find(element => {
|
|
1675
|
+
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1676
|
+
return touchedHandle;
|
|
1677
|
+
});
|
|
1678
|
+
if (touchedAbstract === abstract) {
|
|
1679
|
+
return touchedAbstract;
|
|
1623
1680
|
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1681
|
+
if (touchedAbstract) {
|
|
1682
|
+
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1683
|
+
component.updateAbstractIncludedOutline();
|
|
1684
|
+
touchedAbstract = undefined;
|
|
1626
1685
|
}
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
return
|
|
1633
|
-
}
|
|
1686
|
+
if (abstract) {
|
|
1687
|
+
touchedAbstract = abstract;
|
|
1688
|
+
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1689
|
+
component.updateAbstractIncludedOutline(touchedHandle);
|
|
1690
|
+
}
|
|
1691
|
+
return touchedAbstract;
|
|
1692
|
+
}
|
|
1634
1693
|
|
|
1635
|
-
function drawIndentedLink(
|
|
1694
|
+
function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true) {
|
|
1636
1695
|
const isUnderlineShap = getNodeShapeByElement(child.origin) === MindNodeShape.underline;
|
|
1637
1696
|
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
1638
1697
|
const beginRectangle = getRectangleByNode(beginNode);
|
|
@@ -1644,7 +1703,7 @@ function drawIndentedLink(roughSVG, node, child, defaultStroke = null, needDrawU
|
|
|
1644
1703
|
//根据位置,设置正负参数
|
|
1645
1704
|
let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
|
|
1646
1705
|
const layout = MindQueries.getCorrectLayoutByElement(node.origin);
|
|
1647
|
-
const strokeWidth = child.origin.
|
|
1706
|
+
const strokeWidth = child.origin.branchWidth ? child.origin.branchWidth : STROKE_WIDTH;
|
|
1648
1707
|
if (beginNode.origin.isRoot) {
|
|
1649
1708
|
if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
|
|
1650
1709
|
beginY += strokeWidth;
|
|
@@ -1665,9 +1724,9 @@ function drawIndentedLink(roughSVG, node, child, defaultStroke = null, needDrawU
|
|
|
1665
1724
|
isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
|
|
1666
1725
|
isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
|
|
1667
1726
|
];
|
|
1668
|
-
const stroke = defaultStroke ||
|
|
1727
|
+
const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
|
|
1669
1728
|
const points = pointsOnBezierCurves(curve);
|
|
1670
|
-
return
|
|
1729
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
1671
1730
|
}
|
|
1672
1731
|
|
|
1673
1732
|
var HorizontalPlacement;
|
|
@@ -1780,9 +1839,9 @@ const transformPlacement = (placement, direction) => {
|
|
|
1780
1839
|
}
|
|
1781
1840
|
};
|
|
1782
1841
|
|
|
1783
|
-
function drawLogicLink(
|
|
1784
|
-
const
|
|
1785
|
-
const strokeWidth = node.origin.
|
|
1842
|
+
function drawLogicLink(board, node, parent, isHorizontal) {
|
|
1843
|
+
const branchColor = getBranchColorByMindElement(board, node.origin);
|
|
1844
|
+
const strokeWidth = node.origin.branchWidth ? node.origin.branchWidth : STROKE_WIDTH;
|
|
1786
1845
|
const hasStraightLine = !parent.origin.isRoot;
|
|
1787
1846
|
const hasUnderlineShape = node.origin.shape === MindNodeShape.underline;
|
|
1788
1847
|
const hasUnderlineShapeOfParent = parent.origin.shape === MindNodeShape.underline;
|
|
@@ -1822,7 +1881,7 @@ function drawLogicLink(roughSVG, node, parent, isHorizontal) {
|
|
|
1822
1881
|
const underlineEnd = movePoint(endPoint, nodeClient.width, linkDirection);
|
|
1823
1882
|
const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
|
|
1824
1883
|
const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
|
|
1825
|
-
return
|
|
1884
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth });
|
|
1826
1885
|
}
|
|
1827
1886
|
|
|
1828
1887
|
function getEmojisRectangle(element) {
|
|
@@ -1945,7 +2004,7 @@ function getRichtextRectangleByNode(node) {
|
|
|
1945
2004
|
function drawRectangleNode(board, node) {
|
|
1946
2005
|
const { x, y, width, height } = getRectangleByNode(node);
|
|
1947
2006
|
const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? ROOT_NODE_FILL : NODE_FILL;
|
|
1948
|
-
const stroke = getStrokeByMindElement(node.origin);
|
|
2007
|
+
const stroke = getStrokeByMindElement(board, node.origin);
|
|
1949
2008
|
const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : STROKE_WIDTH;
|
|
1950
2009
|
const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), x, y, x + width, y + height, {
|
|
1951
2010
|
stroke,
|
|
@@ -2004,6 +2063,7 @@ class EmojiDrawer {
|
|
|
2004
2063
|
const componentType = this.board.drawEmoji(emoji, element);
|
|
2005
2064
|
this.componentRef = this.viewContainerRef.createComponent(componentType);
|
|
2006
2065
|
this.componentRef.instance.emojiItem = emoji;
|
|
2066
|
+
this.componentRef.instance.board = this.board;
|
|
2007
2067
|
const fontSize = PlaitMind.isMind(element) ? 18 : 14;
|
|
2008
2068
|
this.componentRef.instance.fontSize = fontSize;
|
|
2009
2069
|
}
|
|
@@ -2068,6 +2128,10 @@ class EmojisDrawer {
|
|
|
2068
2128
|
|
|
2069
2129
|
const setLayout = (board, layout, path) => {
|
|
2070
2130
|
correctLogicLayoutNode(board, layout, path);
|
|
2131
|
+
const element = PlaitNode.get(board, path);
|
|
2132
|
+
if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
|
|
2133
|
+
handleAbstractIncluded(board, element);
|
|
2134
|
+
}
|
|
2071
2135
|
Transforms.setNode(board, { layout }, path);
|
|
2072
2136
|
};
|
|
2073
2137
|
const correctLogicLayoutNode = (board, layout, path) => {
|
|
@@ -2236,6 +2300,14 @@ function hasAfterDraw(value) {
|
|
|
2236
2300
|
return false;
|
|
2237
2301
|
}
|
|
2238
2302
|
|
|
2303
|
+
function findNewChildNodePath(board, element) {
|
|
2304
|
+
return PlaitBoard.findPath(board, element).concat((element.children || []).filter(child => !AbstractNode.isAbstract(child)).length);
|
|
2305
|
+
}
|
|
2306
|
+
function findNewSiblingNodePath(board, element) {
|
|
2307
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2308
|
+
return Path$1.next(path);
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2239
2311
|
class QuickInsertDrawer extends BaseDrawer {
|
|
2240
2312
|
canDraw(element) {
|
|
2241
2313
|
if (PlaitBoard.isReadonly(this.board) || (element === null || element === void 0 ? void 0 : element.isCollapsed)) {
|
|
@@ -2259,7 +2331,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2259
2331
|
*/
|
|
2260
2332
|
const shape = getNodeShapeByElement(element);
|
|
2261
2333
|
// 形状是矩形要偏移边框的线宽
|
|
2262
|
-
const strokeWidth = element.
|
|
2334
|
+
const strokeWidth = element.branchWidth ? element.branchWidth : STROKE_WIDTH;
|
|
2263
2335
|
let offsetBorderLineWidth = 0;
|
|
2264
2336
|
if (shape === MindNodeShape.roundRectangle && offset === 0) {
|
|
2265
2337
|
offsetBorderLineWidth = strokeWidth;
|
|
@@ -2367,7 +2439,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2367
2439
|
underlineCoordinates[MindLayoutType.right].startY -= height * 0.5;
|
|
2368
2440
|
underlineCoordinates[MindLayoutType.right].endY -= height * 0.5;
|
|
2369
2441
|
}
|
|
2370
|
-
const
|
|
2442
|
+
const branchColor = PlaitMind.isMind(element) ? getNextBranchColor(element) : getBranchColorByMindElement(this.board, element);
|
|
2371
2443
|
let nodeLayout = MindQueries.getCorrectLayoutByElement(element);
|
|
2372
2444
|
if (element.isRoot && isStandardLayout(nodeLayout)) {
|
|
2373
2445
|
const root = element;
|
|
@@ -2375,7 +2447,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2375
2447
|
}
|
|
2376
2448
|
const underlineCoordinate = underlineCoordinates[nodeLayout];
|
|
2377
2449
|
if (underlineCoordinate) {
|
|
2378
|
-
const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke, strokeWidth });
|
|
2450
|
+
const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke: branchColor, strokeWidth });
|
|
2379
2451
|
const circleCoordinates = {
|
|
2380
2452
|
startX: underlineCoordinate.endX,
|
|
2381
2453
|
startY: underlineCoordinate.endY
|
|
@@ -2426,7 +2498,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2426
2498
|
fromEvent(this.g, 'mouseup')
|
|
2427
2499
|
.pipe(take(1))
|
|
2428
2500
|
.subscribe(() => {
|
|
2429
|
-
const path =
|
|
2501
|
+
const path = findNewChildNodePath(this.board, element);
|
|
2430
2502
|
insertMindElement(this.board, element, path);
|
|
2431
2503
|
});
|
|
2432
2504
|
}
|
|
@@ -2543,10 +2615,10 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2543
2615
|
this.linkG = drawAbstractLink(this.board, this.node, isHorizontalLayout(layout));
|
|
2544
2616
|
}
|
|
2545
2617
|
else if (MindElement.isIndentedLayout(this.parent.origin)) {
|
|
2546
|
-
this.linkG = drawIndentedLink(this.
|
|
2618
|
+
this.linkG = drawIndentedLink(this.board, this.parent, this.node);
|
|
2547
2619
|
}
|
|
2548
2620
|
else {
|
|
2549
|
-
this.linkG = drawLogicLink(this.
|
|
2621
|
+
this.linkG = drawLogicLink(this.board, this.node, this.parent, isHorizontalLayout(layout));
|
|
2550
2622
|
}
|
|
2551
2623
|
this.g.append(this.linkG);
|
|
2552
2624
|
}
|
|
@@ -2704,8 +2776,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2704
2776
|
Transforms.setNode(this.board, newElement, path);
|
|
2705
2777
|
});
|
|
2706
2778
|
const { x, y, width, height } = getRectangleByNode(this.node);
|
|
2707
|
-
const stroke =
|
|
2708
|
-
const strokeWidth = this.node.origin.
|
|
2779
|
+
const stroke = getBranchColorByMindElement(this.board, this.element);
|
|
2780
|
+
const strokeWidth = this.node.origin.branchWidth ? this.node.origin.branchWidth : STROKE_WIDTH;
|
|
2709
2781
|
const extendY = y + height / 2;
|
|
2710
2782
|
const nodeLayout = MindQueries.getCorrectLayoutByElement(this.element);
|
|
2711
2783
|
let extendLineXY = [
|
|
@@ -3205,7 +3277,7 @@ const withDnd = (board) => {
|
|
|
3205
3277
|
});
|
|
3206
3278
|
if (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) {
|
|
3207
3279
|
dropTarget = readjustmentDropTarget(dropTarget);
|
|
3208
|
-
drawPlaceholderDropNodeG(
|
|
3280
|
+
drawPlaceholderDropNodeG(board, dropTarget, fakeDropNodeG);
|
|
3209
3281
|
}
|
|
3210
3282
|
}
|
|
3211
3283
|
mousemove(event);
|
|
@@ -3365,7 +3437,7 @@ const setIsDragging = (board, state) => {
|
|
|
3365
3437
|
|
|
3366
3438
|
const buildClipboardData = (board, selectedElements) => {
|
|
3367
3439
|
let result = [];
|
|
3368
|
-
const selectedMindNodes = selectedElements.map(
|
|
3440
|
+
const selectedMindNodes = selectedElements.map(value => MindElement.getNode(value));
|
|
3369
3441
|
const nodesRectangle = getRectangleByElements(board, selectedElements, true);
|
|
3370
3442
|
selectedElements.forEach((node, index) => {
|
|
3371
3443
|
const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
|
|
@@ -3401,12 +3473,18 @@ const insertClipboardData = (board, elements, targetPoint) => {
|
|
|
3401
3473
|
if (item.isRoot) {
|
|
3402
3474
|
newElement = transformRootToNode(board, newElement);
|
|
3403
3475
|
}
|
|
3476
|
+
if (AbstractNode.isAbstract(item)) {
|
|
3477
|
+
newElement = transformAbstractToNode(newElement);
|
|
3478
|
+
}
|
|
3404
3479
|
const selectedElementPath = PlaitBoard.findPath(board, selectedElements[0]);
|
|
3405
3480
|
path = selectedElementPath.concat((selectedElements[0].children || []).length + index);
|
|
3406
3481
|
}
|
|
3407
3482
|
else {
|
|
3408
3483
|
const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
|
|
3409
3484
|
newElement.points = [point];
|
|
3485
|
+
if (AbstractNode.isAbstract(item)) {
|
|
3486
|
+
newElement = transformAbstractToNode(newElement);
|
|
3487
|
+
}
|
|
3410
3488
|
if (!item.isRoot) {
|
|
3411
3489
|
newElement = transformNodeToRoot(board, newElement);
|
|
3412
3490
|
}
|
|
@@ -3425,15 +3503,6 @@ const insertClipboardText = (board, parentElement, text, width, height) => {
|
|
|
3425
3503
|
return;
|
|
3426
3504
|
};
|
|
3427
3505
|
|
|
3428
|
-
function findNewChildNodePath(board, element) {
|
|
3429
|
-
const path = PlaitBoard.findPath(board, element);
|
|
3430
|
-
return path.concat((element.children || []).length);
|
|
3431
|
-
}
|
|
3432
|
-
function findNewSiblingNodePath(board, element) {
|
|
3433
|
-
const path = PlaitBoard.findPath(board, element);
|
|
3434
|
-
return Path$1.next(path);
|
|
3435
|
-
}
|
|
3436
|
-
|
|
3437
3506
|
const withEmoji = (board) => {
|
|
3438
3507
|
const newBoard = board;
|
|
3439
3508
|
newBoard.drawEmoji = (emoji, element) => {
|
|
@@ -3521,7 +3590,7 @@ const withAbstract = (board) => {
|
|
|
3521
3590
|
};
|
|
3522
3591
|
board.mouseup = (event) => {
|
|
3523
3592
|
startPoint = undefined;
|
|
3524
|
-
abstractHandlePosition =
|
|
3593
|
+
abstractHandlePosition = undefined;
|
|
3525
3594
|
if (activeAbstractElement) {
|
|
3526
3595
|
if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.abstractResize) {
|
|
3527
3596
|
newBoard.abstractResize(AbstractResizeState.end);
|
|
@@ -3605,6 +3674,7 @@ const withMind = (board) => {
|
|
|
3605
3674
|
if (shouldChangeRightNodeCount(selectedElement)) {
|
|
3606
3675
|
changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
|
|
3607
3676
|
}
|
|
3677
|
+
insertSiblingElementHandleAbstract(board, selectedElement);
|
|
3608
3678
|
insertMindElement(board, selectedElement, findNewSiblingNodePath(board, selectedElement));
|
|
3609
3679
|
}
|
|
3610
3680
|
return;
|
|
@@ -3721,13 +3791,15 @@ class MindEmojiBaseComponent {
|
|
|
3721
3791
|
}
|
|
3722
3792
|
}
|
|
3723
3793
|
MindEmojiBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
3724
|
-
MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem" }, ngImport: i0 });
|
|
3794
|
+
MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem", board: "board" }, ngImport: i0 });
|
|
3725
3795
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, decorators: [{
|
|
3726
3796
|
type: Directive
|
|
3727
3797
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { fontSize: [{
|
|
3728
3798
|
type: Input
|
|
3729
3799
|
}], emojiItem: [{
|
|
3730
3800
|
type: Input
|
|
3801
|
+
}], board: [{
|
|
3802
|
+
type: Input
|
|
3731
3803
|
}] } });
|
|
3732
3804
|
|
|
3733
3805
|
/*
|
|
@@ -3738,5 +3810,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3738
3810
|
* Generated bundle index. Do not edit.
|
|
3739
3811
|
*/
|
|
3740
3812
|
|
|
3741
|
-
export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, COLORS, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, LayoutDirection, LayoutDirectionsMap, MAX_RADIUS, MINDMAP_KEY, MindElement, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindNodeShape, MindQueries, MindTransforms, NODE_FILL, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_NODE_FILL, ROOT_NODE_STROKE, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMindMapElement, createMindElement, deleteSelectedELements, directionCorrector, directionDetector, divideElementByParent, drawCurvePlaceholderDropNodeG, drawIndentNodeG, drawPlaceholderDropNodeG, drawStraightDropNodeG, extractNodesText, filterChildElement, findLastChild, findLocationLeftIndex, findParentElement, findUpElement, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBranchDirectionsByLayouts, getChildrenCount, getDefaultLayout, getEmojiFontSize, getEmojisRectangle, getHitAbstractHandle, getHorizontalFakeY, getInCorrectLayoutDirection, getIndentedFakePoint, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection,
|
|
3813
|
+
export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, COLORS, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, LayoutDirection, LayoutDirectionsMap, MAX_RADIUS, MINDMAP_KEY, MindElement, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindNodeShape, MindQueries, MindTransforms, NODE_FILL, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_NODE_FILL, ROOT_NODE_STROKE, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMindMapElement, createMindElement, deleteSelectedELements, directionCorrector, directionDetector, divideElementByParent, drawCurvePlaceholderDropNodeG, drawIndentNodeG, drawPlaceholderDropNodeG, drawStraightDropNodeG, extractNodesText, filterChildElement, findLastChild, findLocationLeftIndex, findParentElement, findUpElement, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getChildrenCount, getCorrespondingAbstract, getDefaultLayout, getEmojiFontSize, getEmojisRectangle, getHitAbstractHandle, getHorizontalFakeY, getInCorrectLayoutDirection, getIndentedFakePoint, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getNodeShapeByElement, getRectangleByNode, getRectangleByResizingLocation, getRootLayout, getStrokeByMindElement, handleAbstractIncluded, handleTouchedAbstract, hitMindElement, insertAbstractNode, insertMindElement, insertSiblingElementHandleAbstract, isChildElement, isChildRight, isChildUp, isCorrectLayout, isMixedLayout, isSetAbstract, isVirtualKey, moveAbstractPosition, readjustmentDropTarget, separateChildren, setAbstract, setAbstractByElements, shouldChangeRightNodeCount, transformAbstractToNode, transformNodeToRoot, transformRootToNode, withEmoji, withMind };
|
|
3742
3814
|
//# sourceMappingURL=plait-mind.mjs.map
|