@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/fesm2020/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,249 @@ 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
|
+
const { root } = findUpElement(element);
|
|
79
|
+
const rootLayout = root.layout || getDefaultLayout();
|
|
80
|
+
let correctRootLayout = rootLayout;
|
|
81
|
+
if (element.isRoot) {
|
|
82
|
+
return correctRootLayout;
|
|
83
|
+
}
|
|
84
|
+
const component = PlaitElement.getComponent(element);
|
|
85
|
+
let layout = element.layout;
|
|
86
|
+
let parentComponent = null;
|
|
87
|
+
let parent = component.parent.origin;
|
|
88
|
+
while (!layout && parent) {
|
|
89
|
+
parentComponent = PlaitElement.getComponent(parent);
|
|
90
|
+
layout = parentComponent.node.origin.layout;
|
|
91
|
+
parent = parentComponent.parent?.origin;
|
|
92
|
+
}
|
|
93
|
+
if ((AbstractNode.isAbstract(element) || isChildOfAbstract(MindElement.getNode(element))) &&
|
|
94
|
+
isIndentedLayout(layout)) {
|
|
95
|
+
return getAbstractLayout(layout);
|
|
96
|
+
}
|
|
97
|
+
// handle root standard
|
|
98
|
+
if (rootLayout === MindLayoutType.standard) {
|
|
99
|
+
correctRootLayout = component?.node.left ? MindLayoutType.left : MindLayoutType.right;
|
|
100
|
+
}
|
|
101
|
+
if (parentComponent && parentComponent.node.origin.isRoot) {
|
|
102
|
+
return correctRootLayout;
|
|
103
|
+
}
|
|
104
|
+
if (layout) {
|
|
105
|
+
const incorrectDirection = getInCorrectLayoutDirection(correctRootLayout, layout);
|
|
106
|
+
if (incorrectDirection) {
|
|
107
|
+
return correctLayoutByDirection(layout, incorrectDirection);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
return layout;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
return correctRootLayout;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const getBranchLayouts = (element) => {
|
|
119
|
+
const layouts = [];
|
|
120
|
+
if (element.layout) {
|
|
121
|
+
//getCorrectLayoutByElement含有递归操作,getBranchMindmapLayouts本身也有递归操作,有待优化
|
|
122
|
+
layouts.unshift(getCorrectLayoutByElement(element));
|
|
123
|
+
}
|
|
124
|
+
let parent = findParentElement(element);
|
|
125
|
+
while (parent) {
|
|
126
|
+
if (parent.layout) {
|
|
127
|
+
layouts.unshift(parent.layout);
|
|
128
|
+
}
|
|
129
|
+
parent = findParentElement(parent);
|
|
130
|
+
}
|
|
131
|
+
return layouts;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* get available sub layouts by element
|
|
136
|
+
* @param element
|
|
137
|
+
* @returns MindLayoutType[]
|
|
138
|
+
*/
|
|
139
|
+
const getAvailableSubLayoutsByElement = (element) => {
|
|
140
|
+
const parentElement = findParentElement(element);
|
|
141
|
+
if (parentElement) {
|
|
142
|
+
const branchLayouts = getBranchLayouts(parentElement);
|
|
143
|
+
if (branchLayouts[0] === MindLayoutType.standard) {
|
|
144
|
+
const node = MindElement.getNode(element);
|
|
145
|
+
branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
|
|
146
|
+
}
|
|
147
|
+
const currentLayoutDirections = getBranchDirectionsByLayouts(branchLayouts);
|
|
148
|
+
let availableSubLayouts = getAvailableSubLayoutsByLayoutDirections(currentLayoutDirections);
|
|
149
|
+
const parentLayout = [branchLayouts[branchLayouts.length - 1]];
|
|
150
|
+
const parentDirections = getBranchDirectionsByLayouts(parentLayout);
|
|
151
|
+
const parentAvailableSubLayouts = getAvailableSubLayoutsByLayoutDirections(parentDirections);
|
|
152
|
+
availableSubLayouts = availableSubLayouts.filter(layout => parentAvailableSubLayouts.some(parentAvailableSubLayout => parentAvailableSubLayout === layout));
|
|
153
|
+
return availableSubLayouts;
|
|
154
|
+
}
|
|
155
|
+
return undefined;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 获取父节点布局类型
|
|
160
|
+
* @param element
|
|
161
|
+
* @returns MindLayoutType
|
|
162
|
+
*/
|
|
163
|
+
const getLayoutParentByElement = (element) => {
|
|
164
|
+
let parent = findParentElement(element);
|
|
165
|
+
while (parent) {
|
|
166
|
+
if (parent.layout) {
|
|
167
|
+
return parent.layout;
|
|
168
|
+
}
|
|
169
|
+
parent = findParentElement(parent);
|
|
170
|
+
}
|
|
171
|
+
return getDefaultLayout();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const getLayoutByElement = (element) => {
|
|
175
|
+
const layout = element.layout;
|
|
176
|
+
if (layout) {
|
|
177
|
+
return layout;
|
|
178
|
+
}
|
|
179
|
+
if (AbstractNode.isAbstract(element) ||
|
|
180
|
+
(isChildOfAbstract(MindElement.getNode(element)) && isIndentedLayout(layout))) {
|
|
181
|
+
const parentLayout = getLayoutParentByElement(element);
|
|
182
|
+
return getAbstractLayout(parentLayout);
|
|
183
|
+
}
|
|
184
|
+
return getLayoutParentByElement(element);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const MindQueries = {
|
|
188
|
+
getAvailableSubLayoutsByElement,
|
|
189
|
+
getLayoutParentByElement,
|
|
190
|
+
getBranchLayouts,
|
|
191
|
+
getLayoutByElement,
|
|
192
|
+
getCorrectLayoutByElement
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const PlaitMind = {
|
|
196
|
+
isMind: (value) => {
|
|
197
|
+
return value.type === 'mindmap';
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const MindElement = {
|
|
201
|
+
hasLayout(value, layout) {
|
|
202
|
+
const _layout = MindQueries.getLayoutByElement(value);
|
|
203
|
+
return _layout === layout;
|
|
204
|
+
},
|
|
205
|
+
isIndentedLayout(value) {
|
|
206
|
+
const _layout = MindQueries.getLayoutByElement(value);
|
|
207
|
+
return isIndentedLayout(_layout);
|
|
208
|
+
},
|
|
209
|
+
isMindElement(board, element) {
|
|
210
|
+
const path = PlaitBoard.findPath(board, element);
|
|
211
|
+
const rootElement = PlaitNode.get(board, path.slice(0, 1));
|
|
212
|
+
if (PlaitMind.isMind(rootElement)) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
getParent(node) {
|
|
220
|
+
if (PlaitMind.isMind(node)) {
|
|
221
|
+
throw new Error('mind root node can not get parent');
|
|
222
|
+
}
|
|
223
|
+
const parent = NODE_TO_PARENT.get(node);
|
|
224
|
+
return parent;
|
|
225
|
+
},
|
|
226
|
+
getRoot(board, element) {
|
|
227
|
+
const path = PlaitBoard.findPath(board, element);
|
|
228
|
+
return PlaitNode.get(board, path.slice(0, 1));
|
|
229
|
+
},
|
|
230
|
+
getAncestors(board, element) {
|
|
231
|
+
const path = PlaitBoard.findPath(board, element);
|
|
232
|
+
const parents = [];
|
|
233
|
+
for (const p of Path.ancestors(path, { reverse: true })) {
|
|
234
|
+
const n = PlaitNode.get(board, p);
|
|
235
|
+
if (n && !PlaitBoard.isBoard(n)) {
|
|
236
|
+
parents.push(n);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return parents;
|
|
240
|
+
},
|
|
241
|
+
getNode(element) {
|
|
242
|
+
const node = ELEMENT_TO_NODE.get(element);
|
|
243
|
+
if (!node) {
|
|
244
|
+
throw new Error(`can not get node from ${JSON.stringify(element)}`);
|
|
245
|
+
}
|
|
246
|
+
return node;
|
|
247
|
+
},
|
|
248
|
+
hasEmojis(element) {
|
|
249
|
+
if (element.data.emojis) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
getEmojis(element) {
|
|
257
|
+
return element.data.emojis;
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const MindNode = {
|
|
262
|
+
get(root, path) {
|
|
263
|
+
let node = root;
|
|
264
|
+
for (let i = 0; i < path.length; i++) {
|
|
265
|
+
const p = path[i];
|
|
266
|
+
if (!node || !node.children || !node.children[p]) {
|
|
267
|
+
throw new Error(`Cannot find a descendant at path [${path}]`);
|
|
268
|
+
}
|
|
269
|
+
node = node.children[p];
|
|
270
|
+
}
|
|
271
|
+
return node;
|
|
272
|
+
},
|
|
273
|
+
isEquals(node, otherNode) {
|
|
274
|
+
const hasSameSize = node.x === otherNode.x && node.y === otherNode.y && node.width === otherNode.width && node.height === otherNode.height;
|
|
275
|
+
const hasSameOrigin = node.origin === otherNode.origin;
|
|
276
|
+
let hasSameParentOriginChildren = false;
|
|
277
|
+
if (node.parent && otherNode.parent) {
|
|
278
|
+
hasSameParentOriginChildren = node.parent.origin.children == otherNode.parent.origin.children;
|
|
279
|
+
}
|
|
280
|
+
return hasSameSize && hasSameOrigin && hasSameParentOriginChildren;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
var LayoutDirection;
|
|
285
|
+
(function (LayoutDirection) {
|
|
286
|
+
LayoutDirection["top"] = "top";
|
|
287
|
+
LayoutDirection["right"] = "right";
|
|
288
|
+
LayoutDirection["bottom"] = "bottom";
|
|
289
|
+
LayoutDirection["left"] = "left";
|
|
290
|
+
})(LayoutDirection || (LayoutDirection = {}));
|
|
291
|
+
const LayoutDirectionsMap = {
|
|
292
|
+
[MindLayoutType.right]: [LayoutDirection.right],
|
|
293
|
+
[MindLayoutType.left]: [LayoutDirection.left],
|
|
294
|
+
[MindLayoutType.upward]: [LayoutDirection.top],
|
|
295
|
+
[MindLayoutType.downward]: [LayoutDirection.bottom],
|
|
296
|
+
[MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
|
|
297
|
+
[MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
|
|
298
|
+
[MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
|
|
299
|
+
[MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
var AbstractHandlePosition;
|
|
303
|
+
(function (AbstractHandlePosition) {
|
|
304
|
+
AbstractHandlePosition["start"] = "start";
|
|
305
|
+
AbstractHandlePosition["end"] = "end";
|
|
306
|
+
})(AbstractHandlePosition || (AbstractHandlePosition = {}));
|
|
307
|
+
var AbstractResizeState;
|
|
308
|
+
(function (AbstractResizeState) {
|
|
309
|
+
AbstractResizeState["start"] = "start";
|
|
310
|
+
AbstractResizeState["resizing"] = "resizing";
|
|
311
|
+
AbstractResizeState["end"] = "end";
|
|
312
|
+
})(AbstractResizeState || (AbstractResizeState = {}));
|
|
313
|
+
|
|
71
314
|
const getBranchDirectionsByLayouts = (branchLayouts) => {
|
|
72
315
|
const branchDirections = [];
|
|
73
316
|
branchLayouts.forEach(l => {
|
|
@@ -171,1485 +414,1301 @@ const getRootLayout = (root) => {
|
|
|
171
414
|
return root.layout || getDefaultLayout();
|
|
172
415
|
};
|
|
173
416
|
|
|
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
|
-
};
|
|
417
|
+
function enterNodeEditing(element) {
|
|
418
|
+
const component = ELEMENT_TO_COMPONENT.get(element);
|
|
419
|
+
component.startEditText(false, false);
|
|
420
|
+
}
|
|
188
421
|
|
|
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
|
-
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
203
|
-
const layout = MindQueries.getCorrectLayoutByElement(node.origin);
|
|
204
|
-
if (isHorizontal) {
|
|
205
|
-
if (!isChildRight(node, child)) {
|
|
206
|
-
beginNode = child;
|
|
207
|
-
endNode = node;
|
|
208
|
-
}
|
|
209
|
-
beginX = beginNode.x + beginNode.width - beginNode.hGap;
|
|
210
|
-
beginY = beginNode.y + beginNode.height / 2;
|
|
211
|
-
endX = endNode.x + endNode.hGap;
|
|
212
|
-
endY = endNode.y + endNode.height / 2;
|
|
213
|
-
if (node.parent &&
|
|
214
|
-
isIndentedLayout(MindQueries.getLayoutByElement(node.parent?.origin)) &&
|
|
215
|
-
getNodeShapeByElement(node.origin) === MindNodeShape.underline) {
|
|
216
|
-
if (isChildRight(node, child)) {
|
|
217
|
-
beginY = node.y + node.height - node.vGap;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
endY = node.y + node.height - node.vGap;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
if (node.y > child.y) {
|
|
226
|
-
beginNode = child;
|
|
227
|
-
endNode = node;
|
|
228
|
-
}
|
|
229
|
-
beginX = beginNode.x + beginNode.width / 2;
|
|
230
|
-
beginY = beginNode.y + beginNode.height - beginNode.vGap;
|
|
231
|
-
endX = endNode.x + endNode.width / 2;
|
|
232
|
-
endY = endNode.y + endNode.vGap;
|
|
233
|
-
}
|
|
234
|
-
const stroke = defaultStroke || getLinkLineColorByMindElement(child.origin);
|
|
235
|
-
const strokeWidth = child.origin.linkLineWidth ? child.origin.linkLineWidth : STROKE_WIDTH;
|
|
236
|
-
if (endNode.origin.isRoot) {
|
|
237
|
-
if (layout === MindLayoutType.left || isStandardLayout(layout)) {
|
|
238
|
-
endX -= strokeWidth;
|
|
422
|
+
const separateChildren = (parentElement) => {
|
|
423
|
+
const rightNodeCount = parentElement.rightNodeCount;
|
|
424
|
+
const children = parentElement.children;
|
|
425
|
+
let rightChildren = [], leftChildren = [];
|
|
426
|
+
for (let i = 0; i < children.length; i++) {
|
|
427
|
+
const child = children[i];
|
|
428
|
+
if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
|
|
429
|
+
rightChildren.push(child);
|
|
430
|
+
continue;
|
|
239
431
|
}
|
|
240
|
-
if (
|
|
241
|
-
|
|
432
|
+
if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
|
|
433
|
+
leftChildren.push(child);
|
|
434
|
+
continue;
|
|
242
435
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (layout === MindLayoutType.right || isStandardLayout(layout)) {
|
|
246
|
-
beginX += strokeWidth;
|
|
436
|
+
if (i < rightNodeCount) {
|
|
437
|
+
rightChildren.push(child);
|
|
247
438
|
}
|
|
248
|
-
|
|
249
|
-
|
|
439
|
+
else {
|
|
440
|
+
leftChildren.push(child);
|
|
250
441
|
}
|
|
251
442
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const line = [
|
|
283
|
-
[beginX, beginY],
|
|
284
|
-
[beginX + 12, beginY],
|
|
285
|
-
[beginX + 12, beginY]
|
|
286
|
-
];
|
|
287
|
-
curve = [...line, ...curve];
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
if (needDrawUnderline && shape === MindNodeShape.underline) {
|
|
291
|
-
if (child.left) {
|
|
292
|
-
const underline = [
|
|
293
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
294
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
295
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY]
|
|
296
|
-
];
|
|
297
|
-
curve = [...underline, ...curve];
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
const underline = [
|
|
301
|
-
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
302
|
-
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
303
|
-
[endX + (endNode.width - endNode.hGap * 2), endY]
|
|
304
|
-
];
|
|
305
|
-
curve = [...curve, ...underline];
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
const points = pointsOnBezierCurves(curve);
|
|
309
|
-
return roughSVG.curve(points, { stroke, strokeWidth });
|
|
443
|
+
return { leftChildren, rightChildren };
|
|
444
|
+
};
|
|
445
|
+
const isSetAbstract = (element) => {
|
|
446
|
+
return !!getCorrespondingAbstract(element);
|
|
447
|
+
};
|
|
448
|
+
const canSetAbstract = (element) => {
|
|
449
|
+
return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
|
|
450
|
+
};
|
|
451
|
+
const setAbstract = (board, elements) => {
|
|
452
|
+
let elementGroup = filterChildElement(elements);
|
|
453
|
+
const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
|
|
454
|
+
abstractIncludedGroups.forEach((group, index) => {
|
|
455
|
+
const groupParent = parentElements[index];
|
|
456
|
+
setAbstractByElements(board, groupParent, group);
|
|
457
|
+
});
|
|
458
|
+
};
|
|
459
|
+
const setAbstractByElements = (board, groupParent, group) => {
|
|
460
|
+
const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
|
|
461
|
+
const rightNodeCount = groupParent?.rightNodeCount;
|
|
462
|
+
const start = indexArray[0], end = indexArray[indexArray.length - 1];
|
|
463
|
+
if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
|
|
464
|
+
rightNodeCount &&
|
|
465
|
+
start < rightNodeCount &&
|
|
466
|
+
end >= rightNodeCount) {
|
|
467
|
+
const childrenLength = groupParent.children.length;
|
|
468
|
+
const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
|
|
469
|
+
const leftChildren = indexArray.filter(index => index >= rightNodeCount);
|
|
470
|
+
const rightChildren = indexArray.filter(index => index < rightNodeCount);
|
|
471
|
+
insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
|
|
472
|
+
insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
|
|
310
473
|
}
|
|
311
474
|
else {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
315
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
316
|
-
[endX, endY]
|
|
317
|
-
];
|
|
318
|
-
if (!node.origin.isRoot) {
|
|
319
|
-
if (isTopLayout(layout)) {
|
|
320
|
-
curve = [
|
|
321
|
-
[beginX, beginY],
|
|
322
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
323
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
324
|
-
[endX, endY - 12]
|
|
325
|
-
];
|
|
326
|
-
const line = [
|
|
327
|
-
[endX, endY - 12],
|
|
328
|
-
[endX, endY - 12],
|
|
329
|
-
[endX, endY]
|
|
330
|
-
];
|
|
331
|
-
curve = [...curve, ...line];
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
curve = [
|
|
335
|
-
[beginX, beginY + 12],
|
|
336
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
337
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
338
|
-
[endX, endY]
|
|
339
|
-
];
|
|
340
|
-
const line = [
|
|
341
|
-
[beginX, beginY],
|
|
342
|
-
[beginX, beginY + 12],
|
|
343
|
-
[beginX, beginY + 12]
|
|
344
|
-
];
|
|
345
|
-
curve = [...line, ...curve];
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
const points = pointsOnBezierCurves(curve);
|
|
349
|
-
return roughSVG.curve(points, { stroke, strokeWidth });
|
|
475
|
+
const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
|
|
476
|
+
insertAbstractNode(board, path, start, end);
|
|
350
477
|
}
|
|
351
|
-
}
|
|
478
|
+
};
|
|
479
|
+
const insertAbstractNode = (board, path, start, end) => {
|
|
480
|
+
const mindElement = createMindElement('概要', 28, 20, {
|
|
481
|
+
strokeColor: GRAY_COLOR,
|
|
482
|
+
branchColor: GRAY_COLOR
|
|
483
|
+
});
|
|
484
|
+
mindElement.start = start;
|
|
485
|
+
mindElement.end = end;
|
|
486
|
+
Transforms.insertNode(board, mindElement, path);
|
|
487
|
+
};
|
|
488
|
+
const handleAbstractIncluded = (board, element) => {
|
|
489
|
+
const rightNodeCount = element.rightNodeCount;
|
|
490
|
+
const abstract = element.children.find(child => {
|
|
491
|
+
return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
|
|
492
|
+
});
|
|
493
|
+
if (abstract) {
|
|
494
|
+
const path = PlaitBoard.findPath(board, abstract);
|
|
495
|
+
Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
const getCorrespondingAbstract = (element) => {
|
|
499
|
+
const parent = MindElement.getParent(element);
|
|
500
|
+
if (!parent)
|
|
501
|
+
return undefined;
|
|
502
|
+
const elementIndex = parent.children.indexOf(element);
|
|
503
|
+
return parent.children.find(child => {
|
|
504
|
+
return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
const getBehindAbstracts = (element) => {
|
|
508
|
+
const parent = MindElement.getParent(element);
|
|
509
|
+
const index = parent.children.indexOf(element);
|
|
510
|
+
return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
|
|
511
|
+
};
|
|
512
|
+
const insertSiblingElementHandleAbstract = (board, selectedElement) => {
|
|
513
|
+
const abstract = getCorrespondingAbstract(selectedElement);
|
|
514
|
+
if (abstract) {
|
|
515
|
+
PlaitBoard.findPath(board, abstract);
|
|
516
|
+
Transforms.setNode(board, { end: abstract.end + 1 }, PlaitBoard.findPath(board, abstract));
|
|
517
|
+
}
|
|
518
|
+
const abstracts = getBehindAbstracts(selectedElement);
|
|
519
|
+
if (abstracts.length) {
|
|
520
|
+
moveAbstractPosition(board, abstracts, 1);
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
const moveAbstractPosition = (board, abstracts, step) => {
|
|
524
|
+
abstracts.forEach(abstract => {
|
|
525
|
+
Transforms.setNode(board, { start: abstract.start + step, end: abstract.end + step }, PlaitBoard.findPath(board, abstract));
|
|
526
|
+
});
|
|
527
|
+
};
|
|
352
528
|
|
|
353
|
-
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
drawStraightDropNodeG(targetRect, dropTarget.detectResult, targetComponent, roughSVG, fakeDropNodeG);
|
|
529
|
+
function findParentElement(element) {
|
|
530
|
+
const component = PlaitElement.getComponent(element);
|
|
531
|
+
if (component && component.parent) {
|
|
532
|
+
return component.parent.origin;
|
|
358
533
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
534
|
+
return undefined;
|
|
535
|
+
}
|
|
536
|
+
function findUpElement(element) {
|
|
537
|
+
let branch;
|
|
538
|
+
let root = element;
|
|
539
|
+
let parent = findParentElement(element);
|
|
540
|
+
while (parent) {
|
|
541
|
+
branch = root;
|
|
542
|
+
root = parent;
|
|
543
|
+
parent = findParentElement(parent);
|
|
363
544
|
}
|
|
545
|
+
return { root, branch };
|
|
546
|
+
}
|
|
547
|
+
const getChildrenCount = (element) => {
|
|
548
|
+
const count = element.children.reduce((p, c) => {
|
|
549
|
+
return p + getChildrenCount(c);
|
|
550
|
+
}, 0);
|
|
551
|
+
return count + element.children.length;
|
|
364
552
|
};
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
373
|
-
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
553
|
+
const isChildElement = (origin, child) => {
|
|
554
|
+
let parent = findParentElement(child);
|
|
555
|
+
while (parent) {
|
|
556
|
+
if (parent === origin) {
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
parent = findParentElement(parent);
|
|
374
560
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
386
|
-
}
|
|
387
|
-
const isLeftFirst = idx === rightNodeCount;
|
|
388
|
-
const isRightLast = idx === rightNodeCount - 1;
|
|
389
|
-
// 拖拽至左第一个节点的情况
|
|
390
|
-
if (detectResult === 'top' && isLeftFirst) {
|
|
391
|
-
fakeY = targetRect.y - targetRect.height;
|
|
392
|
-
}
|
|
393
|
-
if (detectResult === 'bottom' && isRightLast) {
|
|
394
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
395
|
-
}
|
|
561
|
+
return false;
|
|
562
|
+
};
|
|
563
|
+
const filterChildElement = (elements) => {
|
|
564
|
+
let result = [];
|
|
565
|
+
elements.forEach(element => {
|
|
566
|
+
const isChild = elements.some(node => {
|
|
567
|
+
return isChildElement(node, element);
|
|
568
|
+
});
|
|
569
|
+
if (!isChild) {
|
|
570
|
+
result.push(element);
|
|
396
571
|
}
|
|
397
|
-
|
|
398
|
-
|
|
572
|
+
});
|
|
573
|
+
return result;
|
|
574
|
+
};
|
|
575
|
+
const isChildRight = (node, child) => {
|
|
576
|
+
return node.x < child.x;
|
|
577
|
+
};
|
|
578
|
+
const isChildUp = (node, child) => {
|
|
579
|
+
return node.y > child.y;
|
|
580
|
+
};
|
|
581
|
+
const copyNewNode = (node) => {
|
|
582
|
+
const newNode = { ...node };
|
|
583
|
+
newNode.id = idCreator();
|
|
584
|
+
newNode.children = [];
|
|
585
|
+
for (const childNode of node.children) {
|
|
586
|
+
newNode.children.push(copyNewNode(childNode));
|
|
399
587
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
fakeRectangleStartX = fakeX + Math.ceil(parentComponent.node.width / 2) - parentComponent.node.hGap - Math.ceil(strokeWidth / 2);
|
|
415
|
-
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
416
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
588
|
+
return newNode;
|
|
589
|
+
};
|
|
590
|
+
const transformRootToNode = (board, node) => {
|
|
591
|
+
const newNode = { ...node };
|
|
592
|
+
delete newNode.isRoot;
|
|
593
|
+
delete newNode.rightNodeCount;
|
|
594
|
+
delete newNode.type;
|
|
595
|
+
const text = Node.string(node.data.topic.children[0]) || ' ';
|
|
596
|
+
const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT);
|
|
597
|
+
newNode.width = Math.max(width, NODE_MIN_WIDTH);
|
|
598
|
+
newNode.height = height;
|
|
599
|
+
if (newNode.layout === MindLayoutType.standard) {
|
|
600
|
+
delete newNode.layout;
|
|
417
601
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
602
|
+
return newNode;
|
|
603
|
+
};
|
|
604
|
+
const transformAbstractToNode = (node) => {
|
|
605
|
+
const newNode = { ...node };
|
|
606
|
+
delete newNode.start;
|
|
607
|
+
delete newNode.end;
|
|
608
|
+
return newNode;
|
|
609
|
+
};
|
|
610
|
+
const transformNodeToRoot = (board, node) => {
|
|
611
|
+
const newElement = { ...node };
|
|
612
|
+
let text = Node.string(newElement.data.topic);
|
|
613
|
+
if (!text) {
|
|
614
|
+
text = '思维导图';
|
|
615
|
+
newElement.data.topic = { children: [{ text }] };
|
|
616
|
+
}
|
|
617
|
+
delete newElement?.strokeColor;
|
|
618
|
+
delete newElement?.fill;
|
|
619
|
+
delete newElement?.shape;
|
|
620
|
+
delete newElement?.strokeWidth;
|
|
621
|
+
const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT, ROOT_TOPIC_FONT_SIZE);
|
|
622
|
+
newElement.width = Math.max(width, NODE_MIN_WIDTH);
|
|
623
|
+
newElement.height = height;
|
|
624
|
+
return {
|
|
625
|
+
...newElement,
|
|
626
|
+
layout: newElement.layout ?? MindLayoutType.right,
|
|
627
|
+
isCollapsed: false,
|
|
628
|
+
isRoot: true,
|
|
629
|
+
type: 'mindmap'
|
|
630
|
+
};
|
|
631
|
+
};
|
|
632
|
+
const extractNodesText = (node) => {
|
|
633
|
+
let str = '';
|
|
634
|
+
if (node) {
|
|
635
|
+
str += Node.string(node.data.topic.children[0]) + ' ';
|
|
636
|
+
for (const childNode of node.children) {
|
|
637
|
+
str += extractNodesText(childNode);
|
|
425
638
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
}
|
|
639
|
+
}
|
|
640
|
+
return str;
|
|
641
|
+
};
|
|
642
|
+
const changeRightNodeCount = (board, parentPath, changeNumber) => {
|
|
643
|
+
const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
|
|
644
|
+
Transforms.setNode(board, {
|
|
645
|
+
rightNodeCount: changeNumber >= 0
|
|
646
|
+
? _rightNodeCount + changeNumber
|
|
647
|
+
: _rightNodeCount + changeNumber < 0
|
|
648
|
+
? 0
|
|
649
|
+
: _rightNodeCount + changeNumber
|
|
650
|
+
}, parentPath);
|
|
651
|
+
};
|
|
652
|
+
const shouldChangeRightNodeCount = (selectedElement) => {
|
|
653
|
+
const parentElement = findParentElement(selectedElement);
|
|
654
|
+
if (parentElement) {
|
|
655
|
+
const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
|
|
656
|
+
if (parentElement.isRoot &&
|
|
657
|
+
getRootLayout(parentElement) === MindLayoutType.standard &&
|
|
658
|
+
parentElement.rightNodeCount &&
|
|
659
|
+
nodeIndex <= parentElement.rightNodeCount - 1) {
|
|
660
|
+
return true;
|
|
450
661
|
}
|
|
451
|
-
fakeRectangleStartX = fakeX;
|
|
452
|
-
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
453
|
-
fakeRectangleStartY = fakeY;
|
|
454
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
455
662
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
fillStyle: 'solid'
|
|
663
|
+
return false;
|
|
664
|
+
};
|
|
665
|
+
const createDefaultMindMapElement = (point, rightNodeCount, layout) => {
|
|
666
|
+
const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle, layout });
|
|
667
|
+
root.rightNodeCount = rightNodeCount;
|
|
668
|
+
root.isRoot = true;
|
|
669
|
+
root.type = 'mindmap';
|
|
670
|
+
root.points = [point];
|
|
671
|
+
const children = [1, 1, 1].map(() => {
|
|
672
|
+
return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle });
|
|
467
673
|
});
|
|
468
|
-
|
|
469
|
-
|
|
674
|
+
root.children = children;
|
|
675
|
+
return root;
|
|
470
676
|
};
|
|
471
|
-
const
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
let startRectanglePointY = y + height / 2 - 6;
|
|
479
|
-
let endRectanglePointY = y + height / 2 - 6 + 12;
|
|
480
|
-
if (detectResult === 'left') {
|
|
481
|
-
startLinePoint = x - lineLength;
|
|
482
|
-
endLinePoint = x;
|
|
483
|
-
startRectanglePointX = x - lineLength - 30;
|
|
484
|
-
endRectanglePointX = x - lineLength;
|
|
485
|
-
}
|
|
486
|
-
let fakeY = targetComponent.node.y;
|
|
487
|
-
let fakeX = targetRect.x;
|
|
488
|
-
const strokeWidth = targetComponent.node.origin.linkLineWidth ? targetComponent.node.origin.linkLineWidth : STROKE_WIDTH;
|
|
489
|
-
const pointOptions = {
|
|
490
|
-
fakeX,
|
|
491
|
-
fakeY,
|
|
492
|
-
x,
|
|
493
|
-
y,
|
|
677
|
+
const createMindElement = (text, width, height, options) => {
|
|
678
|
+
const newElement = {
|
|
679
|
+
id: idCreator(),
|
|
680
|
+
data: {
|
|
681
|
+
topic: { children: [{ text }] }
|
|
682
|
+
},
|
|
683
|
+
children: [],
|
|
494
684
|
width,
|
|
495
685
|
height,
|
|
496
|
-
|
|
686
|
+
fill: options.fill,
|
|
687
|
+
strokeColor: options.strokeColor,
|
|
688
|
+
strokeWidth: options.strokeWidth,
|
|
689
|
+
shape: options.shape
|
|
497
690
|
};
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
691
|
+
if (options.fill) {
|
|
692
|
+
newElement.fill = options.fill;
|
|
693
|
+
}
|
|
694
|
+
if (options.strokeColor) {
|
|
695
|
+
newElement.strokeColor = options.strokeColor;
|
|
696
|
+
}
|
|
697
|
+
if (!isNullOrUndefined(options.strokeWidth)) {
|
|
698
|
+
newElement.strokeWidth = options.strokeWidth;
|
|
699
|
+
}
|
|
700
|
+
if (options.shape) {
|
|
701
|
+
newElement.shape = options.shape;
|
|
702
|
+
}
|
|
703
|
+
if (options.layout) {
|
|
704
|
+
newElement.layout = options.layout;
|
|
705
|
+
}
|
|
706
|
+
if (options.branchColor) {
|
|
707
|
+
newElement.branchColor = options.branchColor;
|
|
708
|
+
}
|
|
709
|
+
return newElement;
|
|
710
|
+
};
|
|
711
|
+
// layoutLevel 用来表示插入兄弟节点还是子节点
|
|
712
|
+
const insertMindElement = (board, inheritNode, path) => {
|
|
713
|
+
let fill, strokeColor, strokeWidth, shape = MindNodeShape.roundRectangle;
|
|
714
|
+
if (!inheritNode.isRoot) {
|
|
715
|
+
fill = inheritNode.fill;
|
|
716
|
+
strokeColor = inheritNode.strokeColor;
|
|
717
|
+
strokeWidth = inheritNode.strokeWidth;
|
|
718
|
+
}
|
|
719
|
+
shape = inheritNode.shape;
|
|
720
|
+
const newElement = createMindElement('', NODE_MIN_WIDTH, TEXT_DEFAULT_HEIGHT, { fill, strokeColor, strokeWidth, shape });
|
|
721
|
+
Transforms.insertNode(board, newElement, path);
|
|
722
|
+
clearSelectedElement(board);
|
|
723
|
+
addSelectedElement(board, newElement);
|
|
724
|
+
setTimeout(() => {
|
|
725
|
+
enterNodeEditing(newElement);
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
const findLastChild = (child) => {
|
|
729
|
+
let result = child;
|
|
730
|
+
while (result.children.length !== 0) {
|
|
731
|
+
result = result.children[result.children.length - 1];
|
|
732
|
+
}
|
|
733
|
+
return result;
|
|
734
|
+
};
|
|
735
|
+
const deleteSelectedELements = (board, selectedElements) => {
|
|
736
|
+
//翻转,从下到上修改,防止找不到 path
|
|
737
|
+
const deletableElements = filterChildElement(selectedElements).reverse();
|
|
738
|
+
const relativeAbstracts = [];
|
|
739
|
+
const accumulativeProperties = new WeakMap();
|
|
740
|
+
deletableElements.forEach(node => {
|
|
741
|
+
if (!PlaitMind.isMind(node)) {
|
|
742
|
+
const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
|
|
743
|
+
if (behindAbstracts.length) {
|
|
744
|
+
behindAbstracts.forEach(abstract => {
|
|
745
|
+
let newProperties = accumulativeProperties.get(abstract);
|
|
746
|
+
if (!newProperties) {
|
|
747
|
+
newProperties = { start: abstract.start, end: abstract.end };
|
|
748
|
+
accumulativeProperties.set(abstract, newProperties);
|
|
749
|
+
relativeAbstracts.push(abstract);
|
|
550
750
|
}
|
|
551
|
-
|
|
751
|
+
newProperties.start = newProperties.start - 1;
|
|
752
|
+
newProperties.end = newProperties.end - 1;
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
const correspondingAbstract = getCorrespondingAbstract(node);
|
|
756
|
+
if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
|
|
757
|
+
let newProperties = accumulativeProperties.get(correspondingAbstract);
|
|
758
|
+
if (!newProperties) {
|
|
759
|
+
newProperties = { start: correspondingAbstract.start, end: correspondingAbstract.end };
|
|
760
|
+
accumulativeProperties.set(correspondingAbstract, newProperties);
|
|
761
|
+
relativeAbstracts.push(correspondingAbstract);
|
|
552
762
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
763
|
+
newProperties.end = newProperties.end - 1;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
const abstractHandles = relativeAbstracts.map(value => {
|
|
768
|
+
const newProperties = accumulativeProperties.get(value);
|
|
769
|
+
if (newProperties) {
|
|
770
|
+
const path = PlaitBoard.findPath(board, value);
|
|
771
|
+
return () => {
|
|
772
|
+
if (newProperties.start > newProperties.end) {
|
|
773
|
+
Transforms.removeNode(board, path);
|
|
557
774
|
}
|
|
558
|
-
|
|
559
|
-
|
|
775
|
+
else {
|
|
776
|
+
Transforms.setNode(board, newProperties, path);
|
|
560
777
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
return () => { };
|
|
781
|
+
});
|
|
782
|
+
const deletableHandles = deletableElements.map(node => {
|
|
783
|
+
const path = PlaitBoard.findPath(board, node);
|
|
784
|
+
return () => {
|
|
785
|
+
if (shouldChangeRightNodeCount(node)) {
|
|
786
|
+
changeRightNodeCount(board, path.slice(0, path.length - 1), -1);
|
|
566
787
|
}
|
|
788
|
+
Transforms.removeNode(board, path);
|
|
789
|
+
};
|
|
790
|
+
});
|
|
791
|
+
abstractHandles.forEach(action => action());
|
|
792
|
+
deletableHandles.forEach(action => action());
|
|
793
|
+
};
|
|
794
|
+
const divideElementByParent = (elements) => {
|
|
795
|
+
const abstractIncludedGroups = [];
|
|
796
|
+
const parentElements = [];
|
|
797
|
+
for (let i = 0; i < elements.length; i++) {
|
|
798
|
+
const parent = MindElement.getParent(elements[i]);
|
|
799
|
+
const parentIndex = parentElements.indexOf(parent);
|
|
800
|
+
if (parentIndex === -1) {
|
|
801
|
+
parentElements.push(parent);
|
|
802
|
+
abstractIncludedGroups.push([elements[i]]);
|
|
567
803
|
}
|
|
568
804
|
else {
|
|
569
|
-
|
|
570
|
-
fakeDropNodeG?.appendChild(linkSVGG);
|
|
571
|
-
}
|
|
572
|
-
// 构造一个矩形框坐标
|
|
573
|
-
let fakeRectangleG = drawRoundRectangle(roughSVG, startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
574
|
-
stroke: PRIMARY_COLOR,
|
|
575
|
-
strokeWidth: 2,
|
|
576
|
-
fill: PRIMARY_COLOR,
|
|
577
|
-
fillStyle: 'solid'
|
|
578
|
-
});
|
|
579
|
-
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
580
|
-
}
|
|
581
|
-
else {
|
|
582
|
-
// 混合布局画线逻辑
|
|
583
|
-
if (isHorizontalLogicLayout(parentLayout)) {
|
|
584
|
-
if (isIndentedLayout(layout)) {
|
|
585
|
-
const fakePoint = getIndentedFakePoint(layout, pointOptions);
|
|
586
|
-
drawIndentNodeG(fakeDropNodeG, roughSVG, fakePoint, targetComponent.node);
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
805
|
+
abstractIncludedGroups[parentIndex].push(elements[i]);
|
|
589
806
|
}
|
|
590
807
|
}
|
|
808
|
+
return { parentElements, abstractIncludedGroups };
|
|
591
809
|
};
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
if (targetIndex > 0) {
|
|
598
|
-
const previousComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex - 1]);
|
|
599
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
600
|
-
const topY = previousRect.y + previousRect.height;
|
|
601
|
-
fakeY = topY + (targetRect.y - topY) / 5;
|
|
602
|
-
}
|
|
810
|
+
|
|
811
|
+
const getNodeShapeByElement = (element) => {
|
|
812
|
+
let nodeShape = element.shape;
|
|
813
|
+
if (nodeShape) {
|
|
814
|
+
return nodeShape;
|
|
603
815
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if (
|
|
607
|
-
|
|
608
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
609
|
-
const topY = targetRect.y + targetRect.height;
|
|
610
|
-
fakeY = topY + (nextRect.y - topY) / 5;
|
|
611
|
-
}
|
|
612
|
-
if (targetIndex === parentNode.origin.children.length - 1) {
|
|
613
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
816
|
+
let parent = findParentElement(element);
|
|
817
|
+
while (parent) {
|
|
818
|
+
if (parent.shape) {
|
|
819
|
+
return parent.shape;
|
|
614
820
|
}
|
|
821
|
+
parent = findParentElement(parent);
|
|
615
822
|
}
|
|
616
|
-
return
|
|
823
|
+
return MindNodeShape.roundRectangle;
|
|
617
824
|
};
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
825
|
+
|
|
826
|
+
const getBranchColorByMindElement = (board, element) => {
|
|
827
|
+
const ancestors = MindElement.getAncestors(board, element);
|
|
828
|
+
ancestors.unshift(element);
|
|
829
|
+
const ancestor = ancestors.find(value => value.branchColor);
|
|
830
|
+
if (ancestor && ancestor.branchColor) {
|
|
831
|
+
return ancestor.branchColor;
|
|
832
|
+
}
|
|
833
|
+
const root = ancestors[ancestors.length - 1];
|
|
834
|
+
const branch = ancestors[ancestors.length - 2];
|
|
835
|
+
if (branch) {
|
|
836
|
+
const index = root.children.indexOf(branch);
|
|
837
|
+
const length = COLORS.length;
|
|
838
|
+
const remainder = index % length;
|
|
839
|
+
return COLORS[remainder];
|
|
626
840
|
}
|
|
627
|
-
|
|
628
|
-
|
|
841
|
+
else {
|
|
842
|
+
throw new Error('root element should not have branch color');
|
|
629
843
|
}
|
|
630
|
-
|
|
631
|
-
|
|
844
|
+
};
|
|
845
|
+
const getNextBranchColor = (root) => {
|
|
846
|
+
const index = root.children.length;
|
|
847
|
+
const length = COLORS.length;
|
|
848
|
+
const remainder = index % length;
|
|
849
|
+
return COLORS[remainder];
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
const getStrokeByMindElement = (board, element) => {
|
|
853
|
+
const ancestors = MindElement.getAncestors(board, element);
|
|
854
|
+
ancestors.unshift(element);
|
|
855
|
+
const ancestor = ancestors.find(value => value.strokeColor);
|
|
856
|
+
if (ancestor && ancestor.strokeColor) {
|
|
857
|
+
return ancestor.strokeColor;
|
|
858
|
+
}
|
|
859
|
+
const root = ancestors[ancestors.length - 1];
|
|
860
|
+
const branch = ancestors[ancestors.length - 2];
|
|
861
|
+
if (branch) {
|
|
862
|
+
const index = root.children.indexOf(branch);
|
|
863
|
+
const length = COLORS.length;
|
|
864
|
+
const remainder = index % length;
|
|
865
|
+
return COLORS[remainder];
|
|
632
866
|
}
|
|
633
|
-
|
|
634
|
-
|
|
867
|
+
else {
|
|
868
|
+
return ROOT_NODE_STROKE;
|
|
635
869
|
}
|
|
636
|
-
return { fakeX, fakeY };
|
|
637
|
-
};
|
|
638
|
-
const drawIndentNodeG = (fakeDropNodeG, roughSVG, fakePoint, node) => {
|
|
639
|
-
const { fakeX, fakeY } = fakePoint;
|
|
640
|
-
const fakeNode = { ...node, x: fakeX, y: fakeY, width: 30, height: 12 };
|
|
641
|
-
const linkSVGG = drawIndentedLink(roughSVG, node, fakeNode, PRIMARY_COLOR, false);
|
|
642
|
-
const startRectanglePointX = fakeX, startRectanglePointY = fakeY, endRectanglePointX = fakeX + 30, endRectanglePointY = fakeY + 12;
|
|
643
|
-
const fakeRectangleG = drawRoundRectangle(roughSVG, startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
644
|
-
stroke: PRIMARY_COLOR,
|
|
645
|
-
strokeWidth: 2,
|
|
646
|
-
fill: PRIMARY_COLOR,
|
|
647
|
-
fillStyle: 'solid'
|
|
648
|
-
});
|
|
649
|
-
fakeDropNodeG?.appendChild(linkSVGG);
|
|
650
|
-
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
651
870
|
};
|
|
652
871
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
if (centerPoint[0] > xCenter && centerPoint[0] < right) {
|
|
674
|
-
direction.push('right');
|
|
872
|
+
function isVirtualKey(e) {
|
|
873
|
+
const isMod = e.ctrlKey || e.metaKey;
|
|
874
|
+
const isAlt = isKeyHotkey('alt', e);
|
|
875
|
+
const isShift = isKeyHotkey('shift', e);
|
|
876
|
+
const isCapsLock = e.key.includes('CapsLock');
|
|
877
|
+
const isTab = e.key.includes('Tab');
|
|
878
|
+
const isEsc = e.key.includes('Escape');
|
|
879
|
+
const isF = e.key.startsWith('F');
|
|
880
|
+
const isArrow = e.key.includes('Arrow') ? true : false;
|
|
881
|
+
return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function drawLink(board, node, child, defaultStroke = null, isHorizontal = true, needDrawUnderline = true) {
|
|
885
|
+
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
886
|
+
const layout = MindQueries.getCorrectLayoutByElement(node.origin);
|
|
887
|
+
if (isHorizontal) {
|
|
888
|
+
if (!isChildRight(node, child)) {
|
|
889
|
+
beginNode = child;
|
|
890
|
+
endNode = node;
|
|
675
891
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
892
|
+
beginX = beginNode.x + beginNode.width - beginNode.hGap;
|
|
893
|
+
beginY = beginNode.y + beginNode.height / 2;
|
|
894
|
+
endX = endNode.x + endNode.hGap;
|
|
895
|
+
endY = endNode.y + endNode.height / 2;
|
|
896
|
+
if (node.parent &&
|
|
897
|
+
isIndentedLayout(MindQueries.getLayoutByElement(node.parent?.origin)) &&
|
|
898
|
+
getNodeShapeByElement(node.origin) === MindNodeShape.underline) {
|
|
899
|
+
if (isChildRight(node, child)) {
|
|
900
|
+
beginY = node.y + node.height - node.vGap;
|
|
680
901
|
}
|
|
681
902
|
else {
|
|
682
|
-
|
|
903
|
+
endY = node.y + node.height - node.vGap;
|
|
683
904
|
}
|
|
684
905
|
}
|
|
685
|
-
return direction.length ? direction : null;
|
|
686
906
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
if (centerPoint[1] > yCenter && centerPoint[1] < bottom) {
|
|
693
|
-
direction.push('bottom');
|
|
694
|
-
}
|
|
695
|
-
if ((centerPoint[1] > y && centerPoint[1] < y + height) || (centerPoint[1] > yCenter && centerPoint[1] < y + height)) {
|
|
696
|
-
if (centerPoint[0] < xCenter) {
|
|
697
|
-
direction.push('left');
|
|
698
|
-
}
|
|
699
|
-
else {
|
|
700
|
-
direction.push('right');
|
|
701
|
-
}
|
|
907
|
+
else {
|
|
908
|
+
if (node.y > child.y) {
|
|
909
|
+
beginNode = child;
|
|
910
|
+
endNode = node;
|
|
702
911
|
}
|
|
703
|
-
|
|
912
|
+
beginX = beginNode.x + beginNode.width / 2;
|
|
913
|
+
beginY = beginNode.y + beginNode.height - beginNode.vGap;
|
|
914
|
+
endX = endNode.x + endNode.width / 2;
|
|
915
|
+
endY = endNode.y + endNode.vGap;
|
|
704
916
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
const parentlayout = MindQueries.getCorrectLayoutByElement(node?.parent.origin);
|
|
711
|
-
if (isStandardLayout(parentlayout)) {
|
|
712
|
-
const idx = node.parent.children.findIndex(x => x === node);
|
|
713
|
-
const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
|
|
714
|
-
return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
|
|
715
|
-
}
|
|
716
|
-
if (isLeftLayout(parentlayout)) {
|
|
717
|
-
return getAllowedDirection(detectResults, ['right']);
|
|
718
|
-
}
|
|
719
|
-
if (isRightLayout(parentlayout)) {
|
|
720
|
-
return getAllowedDirection(detectResults, ['left']);
|
|
721
|
-
}
|
|
722
|
-
if (parentlayout === MindLayoutType.upward) {
|
|
723
|
-
return getAllowedDirection(detectResults, ['bottom']);
|
|
917
|
+
const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
|
|
918
|
+
const strokeWidth = child.origin.branchWidth ? child.origin.branchWidth : STROKE_WIDTH;
|
|
919
|
+
if (endNode.origin.isRoot) {
|
|
920
|
+
if (layout === MindLayoutType.left || isStandardLayout(layout)) {
|
|
921
|
+
endX -= strokeWidth;
|
|
724
922
|
}
|
|
725
|
-
if (
|
|
726
|
-
|
|
923
|
+
if (layout === MindLayoutType.upward) {
|
|
924
|
+
endY -= strokeWidth;
|
|
727
925
|
}
|
|
728
926
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
return getAllowedDirection(detectResults, ['top', 'bottom']);
|
|
733
|
-
}
|
|
734
|
-
if (isTopLayout(layout)) {
|
|
735
|
-
return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
|
|
736
|
-
}
|
|
737
|
-
if (isBottomLayout(layout)) {
|
|
738
|
-
return getAllowedDirection(detectResults, ['left', 'right', 'top']);
|
|
739
|
-
}
|
|
740
|
-
if (layout === MindLayoutType.left) {
|
|
741
|
-
return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
|
|
927
|
+
if (beginNode.origin.isRoot) {
|
|
928
|
+
if (layout === MindLayoutType.right || isStandardLayout(layout)) {
|
|
929
|
+
beginX += strokeWidth;
|
|
742
930
|
}
|
|
743
|
-
if (layout === MindLayoutType.
|
|
744
|
-
|
|
931
|
+
if (layout === MindLayoutType.downward) {
|
|
932
|
+
beginY += strokeWidth;
|
|
745
933
|
}
|
|
746
934
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
if (!isMixedLayout(parentLayout, layout)) {
|
|
770
|
-
if (targetComponent.node.origin.isRoot) {
|
|
771
|
-
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
772
|
-
// 标准布局,根节点
|
|
773
|
-
if (isStandardLayout(layout)) {
|
|
774
|
-
const rightNodeCount = targetComponent.node.origin.rightNodeCount;
|
|
775
|
-
if (detectResult === 'left') {
|
|
776
|
-
// 作为左的第一个节点
|
|
777
|
-
if (targetComponent.node.children.length === rightNodeCount) {
|
|
778
|
-
return newDropTarget;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
else {
|
|
782
|
-
// 作为右的第一个节点或最后一个节点
|
|
783
|
-
if (rightNodeCount === 0) {
|
|
784
|
-
newDropTarget.target = target;
|
|
785
|
-
}
|
|
786
|
-
else {
|
|
787
|
-
newDropTarget.target = targetComponent.node.children[rightNodeCount - 1].origin;
|
|
788
|
-
newDropTarget.detectResult = 'bottom';
|
|
789
|
-
}
|
|
790
|
-
return newDropTarget;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
// 缩进布局探测到第一个子节点
|
|
795
|
-
if (isIndentedLayout(parentLayout)) {
|
|
796
|
-
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
797
|
-
newDropTarget.detectResult = isTopLayout(parentLayout) ? 'bottom' : 'top';
|
|
798
|
-
return newDropTarget;
|
|
799
|
-
}
|
|
800
|
-
// 上下布局的根节点只可以探测到上或者下,子节点的左右探测不处理,跳过。
|
|
801
|
-
if (isVerticalLogicLayout(parentLayout)) {
|
|
802
|
-
return newDropTarget;
|
|
803
|
-
}
|
|
804
|
-
// 剩下是水平布局的默认情况:插入最后一个子节点的下方
|
|
805
|
-
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
806
|
-
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
807
|
-
newDropTarget.detectResult = 'bottom';
|
|
935
|
+
if (isHorizontal) {
|
|
936
|
+
let curve = [
|
|
937
|
+
[beginX, beginY],
|
|
938
|
+
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
939
|
+
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
940
|
+
[endX, endY]
|
|
941
|
+
];
|
|
942
|
+
const shape = getNodeShapeByElement(child.origin);
|
|
943
|
+
if (!node.origin.isRoot) {
|
|
944
|
+
if (node.x > child.x) {
|
|
945
|
+
curve = [
|
|
946
|
+
[beginX, beginY],
|
|
947
|
+
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
948
|
+
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
949
|
+
[endX - 12, endY]
|
|
950
|
+
];
|
|
951
|
+
const line = [
|
|
952
|
+
[endX - 12, endY],
|
|
953
|
+
[endX - 12, endY],
|
|
954
|
+
[endX, endY]
|
|
955
|
+
];
|
|
956
|
+
curve = [...curve, ...line];
|
|
808
957
|
}
|
|
809
958
|
else {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
959
|
+
curve = [
|
|
960
|
+
[beginX + 12, beginY],
|
|
961
|
+
[beginX + (beginNode.hGap + endNode.hGap) / 2, beginY],
|
|
962
|
+
[endX - (beginNode.hGap + endNode.hGap) / 3, endY],
|
|
963
|
+
[endX, endY]
|
|
964
|
+
];
|
|
965
|
+
const line = [
|
|
966
|
+
[beginX, beginY],
|
|
967
|
+
[beginX + 12, beginY],
|
|
968
|
+
[beginX + 12, beginY]
|
|
969
|
+
];
|
|
970
|
+
curve = [...line, ...curve];
|
|
819
971
|
}
|
|
820
972
|
}
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
973
|
+
if (needDrawUnderline && shape === MindNodeShape.underline) {
|
|
974
|
+
if (child.left) {
|
|
975
|
+
const underline = [
|
|
976
|
+
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
977
|
+
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
978
|
+
[beginX - (beginNode.width - beginNode.hGap * 2), beginY]
|
|
979
|
+
];
|
|
980
|
+
curve = [...underline, ...curve];
|
|
827
981
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
982
|
+
else {
|
|
983
|
+
const underline = [
|
|
984
|
+
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
985
|
+
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
986
|
+
[endX + (endNode.width - endNode.hGap * 2), endY]
|
|
987
|
+
];
|
|
988
|
+
curve = [...curve, ...underline];
|
|
835
989
|
}
|
|
836
990
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
return dropTarget;
|
|
840
|
-
};
|
|
841
|
-
|
|
842
|
-
const separateChildren = (parentElement) => {
|
|
843
|
-
const rightNodeCount = parentElement.rightNodeCount;
|
|
844
|
-
const children = parentElement.children;
|
|
845
|
-
let rightChildren = [], leftChildren = [];
|
|
846
|
-
for (let i = 0; i < children.length; i++) {
|
|
847
|
-
const child = children[i];
|
|
848
|
-
if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
|
|
849
|
-
rightChildren.push(child);
|
|
850
|
-
continue;
|
|
851
|
-
}
|
|
852
|
-
if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
|
|
853
|
-
leftChildren.push(child);
|
|
854
|
-
continue;
|
|
855
|
-
}
|
|
856
|
-
if (i < rightNodeCount) {
|
|
857
|
-
rightChildren.push(child);
|
|
858
|
-
}
|
|
859
|
-
else {
|
|
860
|
-
leftChildren.push(child);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
return { leftChildren, rightChildren };
|
|
864
|
-
};
|
|
865
|
-
const isSetAbstract = (element) => {
|
|
866
|
-
const component = PlaitElement.getComponent(element);
|
|
867
|
-
const parent = component.parent;
|
|
868
|
-
if (!parent)
|
|
869
|
-
return false;
|
|
870
|
-
const elementIndex = parent.children.indexOf(component.node);
|
|
871
|
-
return parent.children.some(child => {
|
|
872
|
-
return AbstractNode.isAbstract(child.origin) && elementIndex >= child.origin.start && elementIndex <= child.origin.end;
|
|
873
|
-
});
|
|
874
|
-
};
|
|
875
|
-
const canSetAbstract = (element) => {
|
|
876
|
-
return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
|
|
877
|
-
};
|
|
878
|
-
const setAbstract = (board, elements) => {
|
|
879
|
-
let elementGroup = filterChildElement(elements);
|
|
880
|
-
const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
|
|
881
|
-
abstractIncludedGroups.forEach((group, index) => {
|
|
882
|
-
const groupParent = parentElements[index];
|
|
883
|
-
setAbstractByElements(board, groupParent, group);
|
|
884
|
-
});
|
|
885
|
-
};
|
|
886
|
-
const setAbstractByElements = (board, groupParent, group) => {
|
|
887
|
-
const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
|
|
888
|
-
const rightNodeCount = groupParent?.rightNodeCount;
|
|
889
|
-
const start = indexArray[0], end = indexArray[indexArray.length - 1];
|
|
890
|
-
if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
|
|
891
|
-
rightNodeCount &&
|
|
892
|
-
start < rightNodeCount &&
|
|
893
|
-
end >= rightNodeCount) {
|
|
894
|
-
const childrenLength = groupParent.children.length;
|
|
895
|
-
const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
|
|
896
|
-
const leftChildren = indexArray.filter(index => index >= rightNodeCount);
|
|
897
|
-
const rightCHildren = indexArray.filter(index => index < rightNodeCount);
|
|
898
|
-
insetAbstractNode(board, path, rightCHildren[0], rightCHildren[rightCHildren.length - 1]);
|
|
899
|
-
insetAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
|
|
991
|
+
const points = pointsOnBezierCurves(curve);
|
|
992
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
900
993
|
}
|
|
901
994
|
else {
|
|
902
|
-
|
|
903
|
-
|
|
995
|
+
let curve = [
|
|
996
|
+
[beginX, beginY],
|
|
997
|
+
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
998
|
+
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
999
|
+
[endX, endY]
|
|
1000
|
+
];
|
|
1001
|
+
if (!node.origin.isRoot) {
|
|
1002
|
+
if (isTopLayout(layout)) {
|
|
1003
|
+
curve = [
|
|
1004
|
+
[beginX, beginY],
|
|
1005
|
+
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
1006
|
+
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
1007
|
+
[endX, endY - 12]
|
|
1008
|
+
];
|
|
1009
|
+
const line = [
|
|
1010
|
+
[endX, endY - 12],
|
|
1011
|
+
[endX, endY - 12],
|
|
1012
|
+
[endX, endY]
|
|
1013
|
+
];
|
|
1014
|
+
curve = [...curve, ...line];
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
curve = [
|
|
1018
|
+
[beginX, beginY + 12],
|
|
1019
|
+
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
1020
|
+
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
1021
|
+
[endX, endY]
|
|
1022
|
+
];
|
|
1023
|
+
const line = [
|
|
1024
|
+
[beginX, beginY],
|
|
1025
|
+
[beginX, beginY + 12],
|
|
1026
|
+
[beginX, beginY + 12]
|
|
1027
|
+
];
|
|
1028
|
+
curve = [...line, ...curve];
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
const points = pointsOnBezierCurves(curve);
|
|
1032
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
904
1033
|
}
|
|
905
|
-
}
|
|
906
|
-
const insetAbstractNode = (board, path, start, end) => {
|
|
907
|
-
const mindElement = createMindElement('概要', 28, 20, {
|
|
908
|
-
strokeColor: GRAY_COLOR,
|
|
909
|
-
linkLineColor: GRAY_COLOR
|
|
910
|
-
});
|
|
911
|
-
mindElement.start = start;
|
|
912
|
-
mindElement.end = end;
|
|
913
|
-
Transforms.insertNode(board, mindElement, path);
|
|
914
|
-
};
|
|
1034
|
+
}
|
|
915
1035
|
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
y: location,
|
|
922
|
-
height: abstractRectangle.height + abstractRectangle.y - location
|
|
923
|
-
};
|
|
924
|
-
}
|
|
925
|
-
else {
|
|
926
|
-
return {
|
|
927
|
-
...abstractRectangle,
|
|
928
|
-
height: location - abstractRectangle.y
|
|
929
|
-
};
|
|
930
|
-
}
|
|
1036
|
+
const drawPlaceholderDropNodeG = (board, dropTarget, fakeDropNodeG) => {
|
|
1037
|
+
const targetComponent = PlaitElement.getComponent(dropTarget.target);
|
|
1038
|
+
const targetRect = getRectangleByNode(targetComponent.node);
|
|
1039
|
+
if (dropTarget.detectResult && ['right', 'left'].includes(dropTarget.detectResult)) {
|
|
1040
|
+
drawStraightDropNodeG(board, targetRect, dropTarget.detectResult, targetComponent, fakeDropNodeG);
|
|
931
1041
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
x: location,
|
|
937
|
-
width: abstractRectangle.width + abstractRectangle.x - location
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
else {
|
|
941
|
-
return {
|
|
942
|
-
...abstractRectangle,
|
|
943
|
-
width: location - abstractRectangle.x
|
|
944
|
-
};
|
|
945
|
-
}
|
|
1042
|
+
if (targetComponent.parent && dropTarget.detectResult && ['top', 'bottom'].includes(dropTarget.detectResult)) {
|
|
1043
|
+
const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
1044
|
+
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
1045
|
+
drawCurvePlaceholderDropNodeG(board, targetRect, dropTarget.detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG);
|
|
946
1046
|
}
|
|
947
1047
|
};
|
|
948
|
-
const
|
|
949
|
-
const
|
|
950
|
-
const
|
|
951
|
-
const
|
|
952
|
-
|
|
953
|
-
if (
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1048
|
+
const drawCurvePlaceholderDropNodeG = (board, targetRect, detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG) => {
|
|
1049
|
+
const parentNodeLayout = MindQueries.getCorrectLayoutByElement(parentComponent.node.origin);
|
|
1050
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.parent.origin);
|
|
1051
|
+
const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
|
|
1052
|
+
let fakeX = targetComponent.node.x, fakeY = targetRect.y - 30, fakeRectangleStartX = targetRect.x, fakeRectangleEndX = targetRect.x + 30, fakeRectangleStartY = fakeY, fakeRectangleEndY = fakeRectangleStartY + 12, width = 30;
|
|
1053
|
+
if (isLeftLayout(layout)) {
|
|
1054
|
+
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
1055
|
+
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
1056
|
+
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
1057
|
+
}
|
|
1058
|
+
if (isHorizontalLogicLayout(parentNodeLayout)) {
|
|
1059
|
+
fakeY = getHorizontalFakeY(detectResult, targetIndex, parentComponent.node, targetRect, layout, fakeY);
|
|
1060
|
+
if (isStandardLayout(parentNodeLayout)) {
|
|
1061
|
+
const rightNodeCount = parentComponent.node.origin.rightNodeCount || 0;
|
|
1062
|
+
const idx = parentComponent.node.children.findIndex(x => x === targetComponent.node);
|
|
1063
|
+
const isLeft = idx >= rightNodeCount;
|
|
1064
|
+
// 标准布局的左,需要调整 x
|
|
1065
|
+
if (isLeft) {
|
|
1066
|
+
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
1067
|
+
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
1068
|
+
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
1069
|
+
}
|
|
1070
|
+
const isLeftFirst = idx === rightNodeCount;
|
|
1071
|
+
const isRightLast = idx === rightNodeCount - 1;
|
|
1072
|
+
// 拖拽至左第一个节点的情况
|
|
1073
|
+
if (detectResult === 'top' && isLeftFirst) {
|
|
1074
|
+
fakeY = targetRect.y - targetRect.height;
|
|
1075
|
+
}
|
|
1076
|
+
if (detectResult === 'bottom' && isRightLast) {
|
|
1077
|
+
fakeY = targetRect.y + targetRect.height + 30;
|
|
1078
|
+
}
|
|
967
1079
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1080
|
+
fakeRectangleStartY = fakeY;
|
|
1081
|
+
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1082
|
+
}
|
|
1083
|
+
if (isVerticalLogicLayout(layout)) {
|
|
1084
|
+
parentComponent = targetComponent;
|
|
1085
|
+
targetComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
1086
|
+
fakeX = parentComponent.node.x;
|
|
1087
|
+
width = parentComponent.node.width;
|
|
1088
|
+
const vGap = BASE * 6 + strokeWidth;
|
|
1089
|
+
if (isTopLayout(layout) && detectResult === 'top') {
|
|
1090
|
+
fakeY = targetRect.y - vGap;
|
|
1091
|
+
fakeRectangleStartY = fakeY - vGap + strokeWidth;
|
|
975
1092
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
980
|
-
};
|
|
1093
|
+
if (isBottomLayout(layout) && detectResult === 'bottom') {
|
|
1094
|
+
fakeY = targetRect.y + targetRect.height + vGap;
|
|
1095
|
+
fakeRectangleStartY = fakeY + vGap - strokeWidth;
|
|
981
1096
|
}
|
|
1097
|
+
fakeRectangleStartX = fakeX + Math.ceil(parentComponent.node.width / 2) - parentComponent.node.hGap - Math.ceil(strokeWidth / 2);
|
|
1098
|
+
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
1099
|
+
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
982
1100
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const index = abstractNode
|
|
988
|
-
.map(node => {
|
|
989
|
-
const { start } = getCorrectStartEnd(node, parent);
|
|
990
|
-
return start;
|
|
991
|
-
})
|
|
992
|
-
.sort((a, b) => a - b)[0];
|
|
993
|
-
maxNode = parentChildren[index - 1];
|
|
994
|
-
}
|
|
995
|
-
else {
|
|
996
|
-
const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
|
|
997
|
-
maxNode = parentChildren[children.length - 1];
|
|
1101
|
+
if (isIndentedLayout(layout)) {
|
|
1102
|
+
// 偏移一个 Gap
|
|
1103
|
+
if (isLeftLayout(layout)) {
|
|
1104
|
+
fakeX -= BASE * 4;
|
|
998
1105
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
if (isHorizontal) {
|
|
1002
|
-
return {
|
|
1003
|
-
max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1004
|
-
min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1005
|
-
};
|
|
1106
|
+
if (isRightLayout(layout)) {
|
|
1107
|
+
fakeX += BASE * 4;
|
|
1006
1108
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1109
|
+
if (isTopLayout(layout)) {
|
|
1110
|
+
if (detectResult === 'top') {
|
|
1111
|
+
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
1112
|
+
if (isLastNode) {
|
|
1113
|
+
fakeY = targetRect.y - targetRect.height - BASE;
|
|
1114
|
+
}
|
|
1115
|
+
else {
|
|
1116
|
+
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1117
|
+
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1118
|
+
fakeY = targetRect.y - Math.abs((nextRect.y + nextRect.height - targetRect.y) / 2);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
if (detectResult === 'bottom') {
|
|
1122
|
+
const isFirstNode = targetIndex === 0;
|
|
1123
|
+
if (isFirstNode) {
|
|
1124
|
+
const parentRect = getRectangleByNode(parentComponent.node);
|
|
1125
|
+
fakeY = parentRect.y - parentRect.height / 2 - BASE;
|
|
1126
|
+
}
|
|
1127
|
+
else {
|
|
1128
|
+
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1129
|
+
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1130
|
+
fakeY = previousRect.y - Math.abs((targetRect.y + targetRect.height - previousRect.y) / 2);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1012
1133
|
}
|
|
1134
|
+
fakeRectangleStartX = fakeX;
|
|
1135
|
+
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
1136
|
+
fakeRectangleStartY = fakeY;
|
|
1137
|
+
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1013
1138
|
}
|
|
1139
|
+
// 构造一条曲线
|
|
1140
|
+
const fakeNode = { ...targetComponent.node, x: fakeX, y: fakeY, width, height: 12 };
|
|
1141
|
+
const linkSVGG = isIndentedLayout(layout)
|
|
1142
|
+
? drawIndentedLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false)
|
|
1143
|
+
: drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, isHorizontalLayout(layout), false);
|
|
1144
|
+
// 构造一个矩形框坐标
|
|
1145
|
+
const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), fakeRectangleStartX, fakeRectangleStartY, fakeRectangleEndX, fakeRectangleEndY, {
|
|
1146
|
+
stroke: PRIMARY_COLOR,
|
|
1147
|
+
strokeWidth: 2,
|
|
1148
|
+
fill: PRIMARY_COLOR,
|
|
1149
|
+
fillStyle: 'solid'
|
|
1150
|
+
});
|
|
1151
|
+
fakeDropNodeG?.appendChild(linkSVGG);
|
|
1152
|
+
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
1014
1153
|
};
|
|
1015
|
-
const
|
|
1016
|
-
const
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
let
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
return null;
|
|
1030
|
-
};
|
|
1031
|
-
const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
|
|
1032
|
-
let result;
|
|
1033
|
-
if (position === AbstractHandlePosition.start) {
|
|
1034
|
-
const location = isHorizontal ? rectangle.y : rectangle.x;
|
|
1035
|
-
result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
|
|
1036
|
-
result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1037
|
-
}
|
|
1038
|
-
else {
|
|
1039
|
-
const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
|
|
1040
|
-
result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
|
|
1041
|
-
result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1154
|
+
const drawStraightDropNodeG = (board, targetRect, detectResult, targetComponent, fakeDropNodeG) => {
|
|
1155
|
+
const { x, y, width, height } = targetRect;
|
|
1156
|
+
const lineLength = 40;
|
|
1157
|
+
let startLinePoint = x + width;
|
|
1158
|
+
let endLinePoint = x + width + lineLength;
|
|
1159
|
+
let startRectanglePointX = x + width + lineLength;
|
|
1160
|
+
let endRectanglePointX = x + lineLength + width + 30;
|
|
1161
|
+
let startRectanglePointY = y + height / 2 - 6;
|
|
1162
|
+
let endRectanglePointY = y + height / 2 - 6 + 12;
|
|
1163
|
+
if (detectResult === 'left') {
|
|
1164
|
+
startLinePoint = x - lineLength;
|
|
1165
|
+
endLinePoint = x;
|
|
1166
|
+
startRectanglePointX = x - lineLength - 30;
|
|
1167
|
+
endRectanglePointX = x - lineLength;
|
|
1042
1168
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
const
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
x: firstRec.x - firstRec.width,
|
|
1055
|
-
y: firstRec.y - firstRec.height,
|
|
1056
|
-
width: firstRec.width,
|
|
1057
|
-
height: firstRec.height
|
|
1058
|
-
};
|
|
1059
|
-
const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
|
|
1060
|
-
const fakeRightRec = {
|
|
1061
|
-
x: lastRec.x + lastRec.width,
|
|
1062
|
-
y: lastRec.y + lastRec.height,
|
|
1063
|
-
width: lastRec.width,
|
|
1064
|
-
height: lastRec.height
|
|
1169
|
+
let fakeY = targetComponent.node.y;
|
|
1170
|
+
let fakeX = targetRect.x;
|
|
1171
|
+
const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
|
|
1172
|
+
const pointOptions = {
|
|
1173
|
+
fakeX,
|
|
1174
|
+
fakeY,
|
|
1175
|
+
x,
|
|
1176
|
+
y,
|
|
1177
|
+
width,
|
|
1178
|
+
height,
|
|
1179
|
+
strokeWidth
|
|
1065
1180
|
};
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1079
|
-
let touchedHandle;
|
|
1080
|
-
const abstract = getSelectedElements(board)
|
|
1081
|
-
.filter(element => AbstractNode.isAbstract(element))
|
|
1082
|
-
.find(element => {
|
|
1083
|
-
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1084
|
-
return touchedHandle;
|
|
1085
|
-
});
|
|
1086
|
-
if (touchedAbstract === abstract) {
|
|
1087
|
-
return touchedAbstract;
|
|
1088
|
-
}
|
|
1089
|
-
if (touchedAbstract) {
|
|
1090
|
-
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1091
|
-
component.updateAbstractIncludedOutline();
|
|
1092
|
-
touchedAbstract = undefined;
|
|
1093
|
-
}
|
|
1094
|
-
if (abstract) {
|
|
1095
|
-
touchedAbstract = abstract;
|
|
1096
|
-
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1097
|
-
component.updateAbstractIncludedOutline(touchedHandle);
|
|
1098
|
-
}
|
|
1099
|
-
return touchedAbstract;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
/**
|
|
1103
|
-
* get correctly layout:
|
|
1104
|
-
* 1. root is standard -> left or right
|
|
1105
|
-
* 2. correct layout by incorrect layout direction
|
|
1106
|
-
* @param element
|
|
1107
|
-
*/
|
|
1108
|
-
const getCorrectLayoutByElement = (element) => {
|
|
1109
|
-
const { root } = findUpElement(element);
|
|
1110
|
-
const rootLayout = root.layout || getDefaultLayout();
|
|
1111
|
-
let correctRootLayout = rootLayout;
|
|
1112
|
-
if (element.isRoot) {
|
|
1113
|
-
return correctRootLayout;
|
|
1114
|
-
}
|
|
1115
|
-
const component = PlaitElement.getComponent(element);
|
|
1116
|
-
let layout = element.layout;
|
|
1117
|
-
let parentComponent = null;
|
|
1118
|
-
let parent = component.parent.origin;
|
|
1119
|
-
while (!layout && parent) {
|
|
1120
|
-
parentComponent = PlaitElement.getComponent(parent);
|
|
1121
|
-
layout = parentComponent.node.origin.layout;
|
|
1122
|
-
parent = parentComponent.parent?.origin;
|
|
1123
|
-
}
|
|
1124
|
-
if ((AbstractNode.isAbstract(element) || isChildOfAbstract(MindElement.getNode(element))) &&
|
|
1125
|
-
isIndentedLayout(layout)) {
|
|
1126
|
-
return getAbstractLayout(layout);
|
|
1127
|
-
}
|
|
1128
|
-
// handle root standard
|
|
1129
|
-
if (rootLayout === MindLayoutType.standard) {
|
|
1130
|
-
correctRootLayout = component?.node.left ? MindLayoutType.left : MindLayoutType.right;
|
|
1131
|
-
}
|
|
1132
|
-
if (parentComponent && parentComponent.node.origin.isRoot) {
|
|
1133
|
-
return correctRootLayout;
|
|
1134
|
-
}
|
|
1135
|
-
if (layout) {
|
|
1136
|
-
const incorrectDirection = getInCorrectLayoutDirection(correctRootLayout, layout);
|
|
1137
|
-
if (incorrectDirection) {
|
|
1138
|
-
return correctLayoutByDirection(layout, incorrectDirection);
|
|
1139
|
-
}
|
|
1140
|
-
else {
|
|
1141
|
-
return layout;
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
else {
|
|
1145
|
-
return correctRootLayout;
|
|
1146
|
-
}
|
|
1147
|
-
};
|
|
1148
|
-
|
|
1149
|
-
const getBranchLayouts = (element) => {
|
|
1150
|
-
const layouts = [];
|
|
1151
|
-
if (element.layout) {
|
|
1152
|
-
//getCorrectLayoutByElement含有递归操作,getBranchMindmapLayouts本身也有递归操作,有待优化
|
|
1153
|
-
layouts.unshift(getCorrectLayoutByElement(element));
|
|
1154
|
-
}
|
|
1155
|
-
let parent = findParentElement(element);
|
|
1156
|
-
while (parent) {
|
|
1157
|
-
if (parent.layout) {
|
|
1158
|
-
layouts.unshift(parent.layout);
|
|
1159
|
-
}
|
|
1160
|
-
parent = findParentElement(parent);
|
|
1161
|
-
}
|
|
1162
|
-
return layouts;
|
|
1163
|
-
};
|
|
1164
|
-
|
|
1165
|
-
/**
|
|
1166
|
-
* get available sub layouts by element
|
|
1167
|
-
* @param element
|
|
1168
|
-
* @returns MindLayoutType[]
|
|
1169
|
-
*/
|
|
1170
|
-
const getAvailableSubLayoutsByElement = (element) => {
|
|
1171
|
-
const parentElement = findParentElement(element);
|
|
1172
|
-
if (parentElement) {
|
|
1173
|
-
const branchLayouts = getBranchLayouts(parentElement);
|
|
1174
|
-
if (branchLayouts[0] === MindLayoutType.standard) {
|
|
1175
|
-
const node = MindElement.getNode(element);
|
|
1176
|
-
branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
|
|
1177
|
-
}
|
|
1178
|
-
const currentLayoutDirections = getBranchDirectionsByLayouts(branchLayouts);
|
|
1179
|
-
let availableSubLayouts = getAvailableSubLayoutsByLayoutDirections(currentLayoutDirections);
|
|
1180
|
-
const parentLayout = [branchLayouts[branchLayouts.length - 1]];
|
|
1181
|
-
const parentDirections = getBranchDirectionsByLayouts(parentLayout);
|
|
1182
|
-
const parentAvailableSubLayouts = getAvailableSubLayoutsByLayoutDirections(parentDirections);
|
|
1183
|
-
availableSubLayouts = availableSubLayouts.filter(layout => parentAvailableSubLayouts.some(parentAvailableSubLayout => parentAvailableSubLayout === layout));
|
|
1184
|
-
return availableSubLayouts;
|
|
1185
|
-
}
|
|
1186
|
-
return undefined;
|
|
1187
|
-
};
|
|
1188
|
-
|
|
1189
|
-
/**
|
|
1190
|
-
* 获取父节点布局类型
|
|
1191
|
-
* @param element
|
|
1192
|
-
* @returns MindLayoutType
|
|
1193
|
-
*/
|
|
1194
|
-
const getLayoutParentByElement = (element) => {
|
|
1195
|
-
let parent = findParentElement(element);
|
|
1196
|
-
while (parent) {
|
|
1197
|
-
if (parent.layout) {
|
|
1198
|
-
return parent.layout;
|
|
1181
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1182
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1183
|
+
if (!isMixedLayout(parentLayout, layout)) {
|
|
1184
|
+
// 构造一条直线
|
|
1185
|
+
let linePoints = [
|
|
1186
|
+
[startLinePoint, y + height / 2],
|
|
1187
|
+
[endLinePoint, y + height / 2]
|
|
1188
|
+
];
|
|
1189
|
+
if (isIndentedLayout(parentLayout)) {
|
|
1190
|
+
const fakePoint = getIndentedFakePoint(parentLayout, pointOptions);
|
|
1191
|
+
drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
|
|
1192
|
+
return;
|
|
1199
1193
|
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1194
|
+
else if (isVerticalLogicLayout(parentLayout)) {
|
|
1195
|
+
if (!targetComponent.node.origin.isRoot) {
|
|
1196
|
+
/**
|
|
1197
|
+
* 计算逻辑:
|
|
1198
|
+
* 1. 移动到左侧:当前节点 startX - 偏移值,偏移值计算如下:
|
|
1199
|
+
* a. 第一个节点: 固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
|
|
1200
|
+
* b. 第二个节点到最后一个节点之间:上一个节点到当前节点间距的一半((当前节点 startX - 上一个节点的 endX) / 2),endX = 当前节点的 startX + width;
|
|
1201
|
+
* 2. 移动到右侧:当前节点 x + width + 偏移值,偏移值计算如下:
|
|
1202
|
+
* a. 第二个节点到最后一个节点之间的右侧:当前节点到下一个节点间距的一半((下一个节点 startX - 当前节点的 endX) / 2),endX = 当前节点的 startX + width;
|
|
1203
|
+
* b. 最后一个节点的右侧:固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
|
|
1204
|
+
*/
|
|
1205
|
+
fakeY = targetComponent.node.y;
|
|
1206
|
+
const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
|
|
1207
|
+
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
1208
|
+
if (detectResult === 'left') {
|
|
1209
|
+
let offsetX = 0;
|
|
1210
|
+
const isFirstNode = targetIndex === 0;
|
|
1211
|
+
if (isFirstNode) {
|
|
1212
|
+
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex - 1]);
|
|
1216
|
+
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1217
|
+
const space = targetRect.x - (previousRect.x + previousRect.width);
|
|
1218
|
+
offsetX = space / 2;
|
|
1219
|
+
}
|
|
1220
|
+
fakeX = targetRect.x - offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
1221
|
+
}
|
|
1222
|
+
if (detectResult === 'right') {
|
|
1223
|
+
let offsetX = 0;
|
|
1224
|
+
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
1225
|
+
if (isLastNode) {
|
|
1226
|
+
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1230
|
+
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1231
|
+
const space = nextRect.x - (targetRect.x + targetRect.width);
|
|
1232
|
+
offsetX = space / 2;
|
|
1233
|
+
}
|
|
1234
|
+
fakeX = targetRect.x + width + offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
1235
|
+
}
|
|
1236
|
+
startRectanglePointX = fakeX;
|
|
1237
|
+
if (isTopLayout(parentLayout)) {
|
|
1238
|
+
// 因为矩形是从左上角为起点向下画的,所以需要向上偏移一个矩形的高度(-12)
|
|
1239
|
+
startRectanglePointY = fakeY + height + targetComponent.node.vGap - 12;
|
|
1240
|
+
}
|
|
1241
|
+
if (isBottomLayout(parentLayout)) {
|
|
1242
|
+
startRectanglePointY = fakeY + targetComponent.node.vGap;
|
|
1243
|
+
}
|
|
1244
|
+
endRectanglePointX = startRectanglePointX + 30;
|
|
1245
|
+
endRectanglePointY = startRectanglePointY + 12;
|
|
1246
|
+
const fakeNode = { ...targetComponent.node, x: fakeX, y: fakeY, width: 30 };
|
|
1247
|
+
const linkSVGG = drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false, false);
|
|
1248
|
+
fakeDropNodeG?.appendChild(linkSVGG);
|
|
1249
|
+
}
|
|
1245
1250
|
}
|
|
1246
1251
|
else {
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
},
|
|
1250
|
-
getParent(node) {
|
|
1251
|
-
if (PlaitMind.isMind(node)) {
|
|
1252
|
-
throw new Error('mind root node can not get parent');
|
|
1252
|
+
let linkSVGG = PlaitBoard.getRoughSVG(board).linearPath(linePoints, { stroke: PRIMARY_COLOR, strokeWidth });
|
|
1253
|
+
fakeDropNodeG?.appendChild(linkSVGG);
|
|
1253
1254
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1255
|
+
// 构造一个矩形框坐标
|
|
1256
|
+
let fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
1257
|
+
stroke: PRIMARY_COLOR,
|
|
1258
|
+
strokeWidth: 2,
|
|
1259
|
+
fill: PRIMARY_COLOR,
|
|
1260
|
+
fillStyle: 'solid'
|
|
1261
|
+
});
|
|
1262
|
+
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
1263
|
+
}
|
|
1264
|
+
else {
|
|
1265
|
+
// 混合布局画线逻辑
|
|
1266
|
+
if (isHorizontalLogicLayout(parentLayout)) {
|
|
1267
|
+
if (isIndentedLayout(layout)) {
|
|
1268
|
+
const fakePoint = getIndentedFakePoint(layout, pointOptions);
|
|
1269
|
+
drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1265
1272
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
const getHorizontalFakeY = (detectResult, targetIndex, parentNode, targetRect, layout, fakeY) => {
|
|
1276
|
+
if (detectResult === 'top') {
|
|
1277
|
+
if (targetIndex === 0 && isTopLayout(layout)) {
|
|
1278
|
+
fakeY = targetRect.y + targetRect.height;
|
|
1271
1279
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1280
|
+
if (targetIndex > 0) {
|
|
1281
|
+
const previousComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex - 1]);
|
|
1282
|
+
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1283
|
+
const topY = previousRect.y + previousRect.height;
|
|
1284
|
+
fakeY = topY + (targetRect.y - topY) / 5;
|
|
1274
1285
|
}
|
|
1275
|
-
},
|
|
1276
|
-
getEmojis(element) {
|
|
1277
|
-
return element.data.emojis;
|
|
1278
1286
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
if (!node || !node.children || !node.children[p]) {
|
|
1287
|
-
throw new Error(`Cannot find a descendant at path [${path}]`);
|
|
1288
|
-
}
|
|
1289
|
-
node = node.children[p];
|
|
1287
|
+
if (detectResult === 'bottom') {
|
|
1288
|
+
fakeY = targetRect.y + targetRect.height + 30;
|
|
1289
|
+
if (targetIndex < parentNode.origin.children.length - 1) {
|
|
1290
|
+
const nextComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex + 1]);
|
|
1291
|
+
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1292
|
+
const topY = targetRect.y + targetRect.height;
|
|
1293
|
+
fakeY = topY + (nextRect.y - topY) / 5;
|
|
1290
1294
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
isEquals(node, otherNode) {
|
|
1294
|
-
const hasSameSize = node.x === otherNode.x && node.y === otherNode.y && node.width === otherNode.width && node.height === otherNode.height;
|
|
1295
|
-
const hasSameOrigin = node.origin === otherNode.origin;
|
|
1296
|
-
let hasSameParentOriginChildren = false;
|
|
1297
|
-
if (node.parent && otherNode.parent) {
|
|
1298
|
-
hasSameParentOriginChildren = node.parent.origin.children == otherNode.parent.origin.children;
|
|
1295
|
+
if (targetIndex === parentNode.origin.children.length - 1) {
|
|
1296
|
+
fakeY = targetRect.y + targetRect.height + 30;
|
|
1299
1297
|
}
|
|
1300
|
-
return hasSameSize && hasSameOrigin && hasSameParentOriginChildren;
|
|
1301
1298
|
}
|
|
1299
|
+
return fakeY;
|
|
1302
1300
|
};
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
const LayoutDirectionsMap = {
|
|
1312
|
-
[MindLayoutType.right]: [LayoutDirection.right],
|
|
1313
|
-
[MindLayoutType.left]: [LayoutDirection.left],
|
|
1314
|
-
[MindLayoutType.upward]: [LayoutDirection.top],
|
|
1315
|
-
[MindLayoutType.downward]: [LayoutDirection.bottom],
|
|
1316
|
-
[MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
|
|
1317
|
-
[MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
|
|
1318
|
-
[MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
|
|
1319
|
-
[MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
|
|
1320
|
-
};
|
|
1321
|
-
|
|
1322
|
-
var AbstractHandlePosition;
|
|
1323
|
-
(function (AbstractHandlePosition) {
|
|
1324
|
-
AbstractHandlePosition["start"] = "start";
|
|
1325
|
-
AbstractHandlePosition["end"] = "end";
|
|
1326
|
-
})(AbstractHandlePosition || (AbstractHandlePosition = {}));
|
|
1327
|
-
var AbstractResizeState;
|
|
1328
|
-
(function (AbstractResizeState) {
|
|
1329
|
-
AbstractResizeState["start"] = "start";
|
|
1330
|
-
AbstractResizeState["resizing"] = "resizing";
|
|
1331
|
-
AbstractResizeState["end"] = "end";
|
|
1332
|
-
})(AbstractResizeState || (AbstractResizeState = {}));
|
|
1333
|
-
|
|
1334
|
-
function enterNodeEditing(element) {
|
|
1335
|
-
const component = ELEMENT_TO_COMPONENT.get(element);
|
|
1336
|
-
component.startEditText(false, false);
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
function findParentElement(element) {
|
|
1340
|
-
const component = PlaitElement.getComponent(element);
|
|
1341
|
-
if (component && component.parent) {
|
|
1342
|
-
return component.parent.origin;
|
|
1301
|
+
const getIndentedFakePoint = (layout, pointOptions) => {
|
|
1302
|
+
let { fakeX, fakeY, x, y, width, height, strokeWidth } = pointOptions;
|
|
1303
|
+
const hGap = BASE * 4;
|
|
1304
|
+
const vGap = BASE * 6;
|
|
1305
|
+
const offsetX = hGap + width / 2 + strokeWidth;
|
|
1306
|
+
const offsetY = vGap + height / 2 + strokeWidth;
|
|
1307
|
+
if (isLeftLayout(layout)) {
|
|
1308
|
+
fakeX = x - offsetX;
|
|
1343
1309
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
function findUpElement(element) {
|
|
1347
|
-
let branch;
|
|
1348
|
-
let root = element;
|
|
1349
|
-
let parent = findParentElement(element);
|
|
1350
|
-
while (parent) {
|
|
1351
|
-
branch = root;
|
|
1352
|
-
root = parent;
|
|
1353
|
-
parent = findParentElement(parent);
|
|
1310
|
+
if (isRightLayout(layout)) {
|
|
1311
|
+
fakeX = x + offsetX;
|
|
1354
1312
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
const getChildrenCount = (element) => {
|
|
1358
|
-
const count = element.children.reduce((p, c) => {
|
|
1359
|
-
return p + getChildrenCount(c);
|
|
1360
|
-
}, 0);
|
|
1361
|
-
return count + element.children.length;
|
|
1362
|
-
};
|
|
1363
|
-
const isChildElement = (origin, child) => {
|
|
1364
|
-
let parent = findParentElement(child);
|
|
1365
|
-
while (parent) {
|
|
1366
|
-
if (parent === origin) {
|
|
1367
|
-
return true;
|
|
1368
|
-
}
|
|
1369
|
-
parent = findParentElement(parent);
|
|
1313
|
+
if (isTopLayout(layout)) {
|
|
1314
|
+
fakeY = y - offsetY;
|
|
1370
1315
|
}
|
|
1371
|
-
|
|
1316
|
+
if (isBottomLayout(layout)) {
|
|
1317
|
+
fakeY = y + height + offsetY;
|
|
1318
|
+
}
|
|
1319
|
+
return { fakeX, fakeY };
|
|
1372
1320
|
};
|
|
1373
|
-
const
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1321
|
+
const drawIndentNodeG = (board, fakeDropNodeG, fakePoint, node) => {
|
|
1322
|
+
const { fakeX, fakeY } = fakePoint;
|
|
1323
|
+
const fakeNode = { ...node, x: fakeX, y: fakeY, width: 30, height: 12 };
|
|
1324
|
+
const linkSVGG = drawIndentedLink(board, node, fakeNode, PRIMARY_COLOR, false);
|
|
1325
|
+
const startRectanglePointX = fakeX, startRectanglePointY = fakeY, endRectanglePointX = fakeX + 30, endRectanglePointY = fakeY + 12;
|
|
1326
|
+
const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
1327
|
+
stroke: PRIMARY_COLOR,
|
|
1328
|
+
strokeWidth: 2,
|
|
1329
|
+
fill: PRIMARY_COLOR,
|
|
1330
|
+
fillStyle: 'solid'
|
|
1382
1331
|
});
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
const isChildRight = (node, child) => {
|
|
1386
|
-
return node.x < child.x;
|
|
1387
|
-
};
|
|
1388
|
-
const isChildUp = (node, child) => {
|
|
1389
|
-
return node.y > child.y;
|
|
1390
|
-
};
|
|
1391
|
-
const copyNewNode = (node) => {
|
|
1392
|
-
const newNode = { ...node };
|
|
1393
|
-
newNode.id = idCreator();
|
|
1394
|
-
newNode.children = [];
|
|
1395
|
-
for (const childNode of node.children) {
|
|
1396
|
-
newNode.children.push(copyNewNode(childNode));
|
|
1397
|
-
}
|
|
1398
|
-
return newNode;
|
|
1332
|
+
fakeDropNodeG?.appendChild(linkSVGG);
|
|
1333
|
+
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
1399
1334
|
};
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1335
|
+
|
|
1336
|
+
/**
|
|
1337
|
+
*
|
|
1338
|
+
* @param targetNode
|
|
1339
|
+
* @param centerPoint
|
|
1340
|
+
* @returns DetectResult[] | null
|
|
1341
|
+
*/
|
|
1342
|
+
const directionDetector = (targetNode, centerPoint) => {
|
|
1343
|
+
const { x, y, width, height } = getRectangleByNode(targetNode);
|
|
1344
|
+
const yCenter = y + height / 2;
|
|
1345
|
+
const xCenter = x + width / 2;
|
|
1346
|
+
const top = targetNode.y;
|
|
1347
|
+
const bottom = targetNode.y + targetNode.height;
|
|
1348
|
+
const left = targetNode.x;
|
|
1349
|
+
const right = targetNode.x + targetNode.width;
|
|
1350
|
+
const direction = [];
|
|
1351
|
+
// x 轴
|
|
1352
|
+
if (centerPoint[1] > y && centerPoint[1] < y + height) {
|
|
1353
|
+
if (centerPoint[0] > left && centerPoint[0] < xCenter) {
|
|
1354
|
+
direction.push('left');
|
|
1355
|
+
}
|
|
1356
|
+
if (centerPoint[0] > xCenter && centerPoint[0] < right) {
|
|
1357
|
+
direction.push('right');
|
|
1358
|
+
}
|
|
1359
|
+
// 重合区域,返回两个方向
|
|
1360
|
+
if ((centerPoint[0] > x && centerPoint[0] < xCenter) || (centerPoint[0] > xCenter && centerPoint[0] < x + width)) {
|
|
1361
|
+
if (centerPoint[1] < yCenter) {
|
|
1362
|
+
direction.push('top');
|
|
1363
|
+
}
|
|
1364
|
+
else {
|
|
1365
|
+
direction.push('bottom');
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return direction.length ? direction : null;
|
|
1411
1369
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1370
|
+
// y 轴
|
|
1371
|
+
if (centerPoint[0] > x && centerPoint[0] < x + width) {
|
|
1372
|
+
if (centerPoint[1] > top && centerPoint[1] < yCenter) {
|
|
1373
|
+
direction.push('top');
|
|
1374
|
+
}
|
|
1375
|
+
if (centerPoint[1] > yCenter && centerPoint[1] < bottom) {
|
|
1376
|
+
direction.push('bottom');
|
|
1377
|
+
}
|
|
1378
|
+
if ((centerPoint[1] > y && centerPoint[1] < y + height) || (centerPoint[1] > yCenter && centerPoint[1] < y + height)) {
|
|
1379
|
+
if (centerPoint[0] < xCenter) {
|
|
1380
|
+
direction.push('left');
|
|
1381
|
+
}
|
|
1382
|
+
else {
|
|
1383
|
+
direction.push('right');
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
return direction.length ? direction : null;
|
|
1420
1387
|
}
|
|
1421
|
-
|
|
1422
|
-
delete newElement?.fill;
|
|
1423
|
-
delete newElement?.shape;
|
|
1424
|
-
delete newElement?.strokeWidth;
|
|
1425
|
-
const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT, ROOT_TOPIC_FONT_SIZE);
|
|
1426
|
-
newElement.width = Math.max(width, NODE_MIN_WIDTH);
|
|
1427
|
-
newElement.height = height;
|
|
1428
|
-
return {
|
|
1429
|
-
...newElement,
|
|
1430
|
-
layout: newElement.layout ?? MindLayoutType.right,
|
|
1431
|
-
isCollapsed: false,
|
|
1432
|
-
isRoot: true,
|
|
1433
|
-
type: 'mindmap'
|
|
1434
|
-
};
|
|
1388
|
+
return null;
|
|
1435
1389
|
};
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
if (node) {
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1390
|
+
|
|
1391
|
+
const directionCorrector = (node, detectResults) => {
|
|
1392
|
+
if (!node.origin.isRoot) {
|
|
1393
|
+
const parentlayout = MindQueries.getCorrectLayoutByElement(node?.parent.origin);
|
|
1394
|
+
if (isStandardLayout(parentlayout)) {
|
|
1395
|
+
const idx = node.parent.children.findIndex(x => x === node);
|
|
1396
|
+
const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
|
|
1397
|
+
return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
|
|
1398
|
+
}
|
|
1399
|
+
if (isLeftLayout(parentlayout)) {
|
|
1400
|
+
return getAllowedDirection(detectResults, ['right']);
|
|
1401
|
+
}
|
|
1402
|
+
if (isRightLayout(parentlayout)) {
|
|
1403
|
+
return getAllowedDirection(detectResults, ['left']);
|
|
1404
|
+
}
|
|
1405
|
+
if (parentlayout === MindLayoutType.upward) {
|
|
1406
|
+
return getAllowedDirection(detectResults, ['bottom']);
|
|
1407
|
+
}
|
|
1408
|
+
if (parentlayout === MindLayoutType.downward) {
|
|
1409
|
+
return getAllowedDirection(detectResults, ['top']);
|
|
1442
1410
|
}
|
|
1443
1411
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
if (parentElement.isRoot &&
|
|
1461
|
-
getRootLayout(parentElement) === MindLayoutType.standard &&
|
|
1462
|
-
parentElement.rightNodeCount &&
|
|
1463
|
-
nodeIndex <= parentElement.rightNodeCount - 1) {
|
|
1464
|
-
return true;
|
|
1412
|
+
else {
|
|
1413
|
+
const layout = MindQueries.getCorrectLayoutByElement(node?.origin);
|
|
1414
|
+
if (isStandardLayout(layout)) {
|
|
1415
|
+
return getAllowedDirection(detectResults, ['top', 'bottom']);
|
|
1416
|
+
}
|
|
1417
|
+
if (isTopLayout(layout)) {
|
|
1418
|
+
return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
|
|
1419
|
+
}
|
|
1420
|
+
if (isBottomLayout(layout)) {
|
|
1421
|
+
return getAllowedDirection(detectResults, ['left', 'right', 'top']);
|
|
1422
|
+
}
|
|
1423
|
+
if (layout === MindLayoutType.left) {
|
|
1424
|
+
return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
|
|
1425
|
+
}
|
|
1426
|
+
if (layout === MindLayoutType.right) {
|
|
1427
|
+
return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
|
|
1465
1428
|
}
|
|
1466
1429
|
}
|
|
1467
|
-
return
|
|
1430
|
+
return null;
|
|
1468
1431
|
};
|
|
1469
|
-
const
|
|
1470
|
-
const
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle });
|
|
1432
|
+
const getAllowedDirection = (detectResults, illegalDirections) => {
|
|
1433
|
+
const directions = detectResults;
|
|
1434
|
+
illegalDirections.forEach(item => {
|
|
1435
|
+
const bottomDirectionIndex = directions.findIndex(direction => direction === item);
|
|
1436
|
+
if (bottomDirectionIndex !== -1) {
|
|
1437
|
+
directions.splice(bottomDirectionIndex, 1);
|
|
1438
|
+
}
|
|
1477
1439
|
});
|
|
1478
|
-
|
|
1479
|
-
return root;
|
|
1440
|
+
return directions.length ? directions : null;
|
|
1480
1441
|
};
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1442
|
+
|
|
1443
|
+
/* 根据布局调整 target 以及 direction */
|
|
1444
|
+
const readjustmentDropTarget = (dropTarget) => {
|
|
1445
|
+
const { target, detectResult } = dropTarget;
|
|
1446
|
+
const newDropTarget = { target, detectResult };
|
|
1447
|
+
const targetComponent = PlaitElement.getComponent(target);
|
|
1448
|
+
if (targetComponent.node.children.length > 0 && dropTarget.detectResult) {
|
|
1449
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1450
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1451
|
+
if (['right', 'left'].includes(dropTarget.detectResult)) {
|
|
1452
|
+
if (!isMixedLayout(parentLayout, layout)) {
|
|
1453
|
+
if (targetComponent.node.origin.isRoot) {
|
|
1454
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1455
|
+
// 标准布局,根节点
|
|
1456
|
+
if (isStandardLayout(layout)) {
|
|
1457
|
+
const rightNodeCount = targetComponent.node.origin.rightNodeCount;
|
|
1458
|
+
if (detectResult === 'left') {
|
|
1459
|
+
// 作为左的第一个节点
|
|
1460
|
+
if (targetComponent.node.children.length === rightNodeCount) {
|
|
1461
|
+
return newDropTarget;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
else {
|
|
1465
|
+
// 作为右的第一个节点或最后一个节点
|
|
1466
|
+
if (rightNodeCount === 0) {
|
|
1467
|
+
newDropTarget.target = target;
|
|
1468
|
+
}
|
|
1469
|
+
else {
|
|
1470
|
+
newDropTarget.target = targetComponent.node.children[rightNodeCount - 1].origin;
|
|
1471
|
+
newDropTarget.detectResult = 'bottom';
|
|
1472
|
+
}
|
|
1473
|
+
return newDropTarget;
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
// 缩进布局探测到第一个子节点
|
|
1478
|
+
if (isIndentedLayout(parentLayout)) {
|
|
1479
|
+
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
1480
|
+
newDropTarget.detectResult = isTopLayout(parentLayout) ? 'bottom' : 'top';
|
|
1481
|
+
return newDropTarget;
|
|
1482
|
+
}
|
|
1483
|
+
// 上下布局的根节点只可以探测到上或者下,子节点的左右探测不处理,跳过。
|
|
1484
|
+
if (isVerticalLogicLayout(parentLayout)) {
|
|
1485
|
+
return newDropTarget;
|
|
1486
|
+
}
|
|
1487
|
+
// 剩下是水平布局的默认情况:插入最后一个子节点的下方
|
|
1488
|
+
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
1489
|
+
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
1490
|
+
newDropTarget.detectResult = 'bottom';
|
|
1491
|
+
}
|
|
1492
|
+
else {
|
|
1493
|
+
// 处理左右布局下的混合布局
|
|
1494
|
+
if ([MindLayoutType.left, MindLayoutType.right].includes(parentLayout)) {
|
|
1495
|
+
const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
|
|
1496
|
+
if (isIndentedLayout(layout)) {
|
|
1497
|
+
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
1498
|
+
newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
|
|
1499
|
+
return newDropTarget;
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
if (['top', 'bottom'].includes(dropTarget.detectResult)) {
|
|
1505
|
+
// 缩进布局移动至第一个节点
|
|
1506
|
+
if (targetComponent.node.origin.isRoot && isIndentedLayout(layout)) {
|
|
1507
|
+
newDropTarget.target = targetComponent.node.children[0].origin;
|
|
1508
|
+
newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
|
|
1509
|
+
return newDropTarget;
|
|
1510
|
+
}
|
|
1511
|
+
// 上下布局,插到右边
|
|
1512
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1513
|
+
if (isVerticalLogicLayout(parentLayout)) {
|
|
1514
|
+
const lastChildNodeIndex = targetComponent.node.children.length - 1;
|
|
1515
|
+
newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
|
|
1516
|
+
newDropTarget.detectResult = 'right';
|
|
1517
|
+
return newDropTarget;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return newDropTarget;
|
|
1512
1521
|
}
|
|
1513
|
-
return
|
|
1522
|
+
return dropTarget;
|
|
1514
1523
|
};
|
|
1515
|
-
|
|
1516
|
-
const
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1524
|
+
|
|
1525
|
+
const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
|
|
1526
|
+
if (isHorizontal) {
|
|
1527
|
+
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
1528
|
+
return {
|
|
1529
|
+
...abstractRectangle,
|
|
1530
|
+
y: location,
|
|
1531
|
+
height: abstractRectangle.height + abstractRectangle.y - location
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
else {
|
|
1535
|
+
return {
|
|
1536
|
+
...abstractRectangle,
|
|
1537
|
+
height: location - abstractRectangle.y
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1530
1540
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
};
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1541
|
+
else {
|
|
1542
|
+
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
1543
|
+
return {
|
|
1544
|
+
...abstractRectangle,
|
|
1545
|
+
x: location,
|
|
1546
|
+
width: abstractRectangle.width + abstractRectangle.x - location
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
else {
|
|
1550
|
+
return {
|
|
1551
|
+
...abstractRectangle,
|
|
1552
|
+
width: location - abstractRectangle.x
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1542
1555
|
}
|
|
1543
|
-
return result;
|
|
1544
1556
|
};
|
|
1545
|
-
const
|
|
1546
|
-
|
|
1547
|
-
const
|
|
1548
|
-
const
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
const
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
accumulativeProperties.set(abstractNode, newProperties);
|
|
1562
|
-
relativeAbstracts.push(abstractNode);
|
|
1563
|
-
}
|
|
1564
|
-
newProperties.end = newProperties.end - 1;
|
|
1565
|
-
}
|
|
1566
|
-
});
|
|
1557
|
+
const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
|
|
1558
|
+
const node = MindElement.getNode(element);
|
|
1559
|
+
const { start, end } = getCorrectStartEnd(node.origin, parent);
|
|
1560
|
+
const startNode = parentChildren[start];
|
|
1561
|
+
const endNode = parentChildren[end];
|
|
1562
|
+
if (handlePosition === AbstractHandlePosition.start) {
|
|
1563
|
+
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
|
|
1564
|
+
let minNode;
|
|
1565
|
+
if (abstractNode.length) {
|
|
1566
|
+
const index = abstractNode
|
|
1567
|
+
.map(node => {
|
|
1568
|
+
const { end } = getCorrectStartEnd(node, parent);
|
|
1569
|
+
return end;
|
|
1570
|
+
})
|
|
1571
|
+
.sort((a, b) => b - a)[0];
|
|
1572
|
+
minNode = parentChildren[index + 1];
|
|
1567
1573
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
else {
|
|
1578
|
-
Transforms.setNode(board, newProperties, path);
|
|
1579
|
-
}
|
|
1574
|
+
else {
|
|
1575
|
+
minNode = parentChildren[0];
|
|
1576
|
+
}
|
|
1577
|
+
const minNodeRectangle = getRectangleByElements(board, [minNode], true);
|
|
1578
|
+
const endNodeRectangle = getRectangleByElements(board, [endNode], false);
|
|
1579
|
+
if (isHorizontal) {
|
|
1580
|
+
return {
|
|
1581
|
+
max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1582
|
+
min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1580
1583
|
};
|
|
1581
1584
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
};
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
const parent = MindElement.getParent(elements[i]);
|
|
1601
|
-
const parentIndex = parentElements.indexOf(parent);
|
|
1602
|
-
if (parentIndex === -1) {
|
|
1603
|
-
parentElements.push(parent);
|
|
1604
|
-
abstractIncludedGroups.push([elements[i]]);
|
|
1585
|
+
else {
|
|
1586
|
+
return {
|
|
1587
|
+
max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1588
|
+
min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
else {
|
|
1593
|
+
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
|
|
1594
|
+
let maxNode;
|
|
1595
|
+
if (abstractNode.length) {
|
|
1596
|
+
const index = abstractNode
|
|
1597
|
+
.map(node => {
|
|
1598
|
+
const { start } = getCorrectStartEnd(node, parent);
|
|
1599
|
+
return start;
|
|
1600
|
+
})
|
|
1601
|
+
.sort((a, b) => a - b)[0];
|
|
1602
|
+
maxNode = parentChildren[index - 1];
|
|
1605
1603
|
}
|
|
1606
1604
|
else {
|
|
1607
|
-
|
|
1605
|
+
const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
|
|
1606
|
+
maxNode = parentChildren[children.length - 1];
|
|
1607
|
+
}
|
|
1608
|
+
const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
|
|
1609
|
+
const startNodeRectangle = getRectangleByElements(board, [startNode], false);
|
|
1610
|
+
if (isHorizontal) {
|
|
1611
|
+
return {
|
|
1612
|
+
max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1613
|
+
min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
else {
|
|
1617
|
+
return {
|
|
1618
|
+
max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1619
|
+
min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1620
|
+
};
|
|
1608
1621
|
}
|
|
1609
1622
|
}
|
|
1610
|
-
return { parentElements, abstractIncludedGroups };
|
|
1611
1623
|
};
|
|
1612
|
-
|
|
1613
|
-
const
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
return
|
|
1624
|
+
const getHitAbstractHandle = (board, element, point) => {
|
|
1625
|
+
const nodeLayout = MindQueries.getCorrectLayoutByElement(element);
|
|
1626
|
+
const isHorizontal = isHorizontalLayout(nodeLayout);
|
|
1627
|
+
const parentElement = MindElement.getParent(element);
|
|
1628
|
+
const includedElements = parentElement.children.slice(element.start, element.end + 1);
|
|
1629
|
+
let abstractRectangle = getRectangleByElements(board, includedElements, true);
|
|
1630
|
+
abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
|
|
1631
|
+
const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
|
|
1632
|
+
const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
|
|
1633
|
+
const pointRec = RectangleClient.toRectangleClient([point, point]);
|
|
1634
|
+
if (RectangleClient.isHit(pointRec, startHandleRec))
|
|
1635
|
+
return AbstractHandlePosition.start;
|
|
1636
|
+
if (RectangleClient.isHit(pointRec, endHandleRec))
|
|
1637
|
+
return AbstractHandlePosition.end;
|
|
1638
|
+
return undefined;
|
|
1639
|
+
};
|
|
1640
|
+
const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
|
|
1641
|
+
let result;
|
|
1642
|
+
if (position === AbstractHandlePosition.start) {
|
|
1643
|
+
const location = isHorizontal ? rectangle.y : rectangle.x;
|
|
1644
|
+
result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
|
|
1645
|
+
result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1624
1646
|
}
|
|
1625
1647
|
else {
|
|
1626
|
-
|
|
1648
|
+
const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
|
|
1649
|
+
result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
|
|
1650
|
+
result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1627
1651
|
}
|
|
1652
|
+
return result;
|
|
1628
1653
|
};
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1654
|
+
function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
|
|
1655
|
+
const children = parentChildren.filter(child => {
|
|
1656
|
+
return !AbstractNode.isAbstract(child);
|
|
1657
|
+
});
|
|
1658
|
+
const recArray = children.map(child => {
|
|
1659
|
+
return getRectangleByElements(board, [child], false);
|
|
1660
|
+
});
|
|
1661
|
+
const firstRec = getRectangleByElements(board, [children[0]], true);
|
|
1662
|
+
const fakeLeftRec = {
|
|
1663
|
+
x: firstRec.x - firstRec.width,
|
|
1664
|
+
y: firstRec.y - firstRec.height,
|
|
1665
|
+
width: firstRec.width,
|
|
1666
|
+
height: firstRec.height
|
|
1667
|
+
};
|
|
1668
|
+
const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
|
|
1669
|
+
const fakeRightRec = {
|
|
1670
|
+
x: lastRec.x + lastRec.width,
|
|
1671
|
+
y: lastRec.y + lastRec.height,
|
|
1672
|
+
width: lastRec.width,
|
|
1673
|
+
height: lastRec.height
|
|
1674
|
+
};
|
|
1675
|
+
recArray.push(fakeRightRec);
|
|
1676
|
+
recArray.unshift(fakeLeftRec);
|
|
1677
|
+
for (let i = 0; i < recArray.length - 1; i++) {
|
|
1678
|
+
const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
|
|
1679
|
+
const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
|
|
1680
|
+
if (location >= recXOrY + recWidthOrHeight / 2 &&
|
|
1681
|
+
location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
|
|
1682
|
+
return i - 1;
|
|
1683
|
+
}
|
|
1633
1684
|
}
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1685
|
+
return 0;
|
|
1686
|
+
}
|
|
1687
|
+
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1688
|
+
let touchedHandle;
|
|
1689
|
+
const abstract = getSelectedElements(board)
|
|
1690
|
+
.filter(element => AbstractNode.isAbstract(element))
|
|
1691
|
+
.find(element => {
|
|
1692
|
+
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1693
|
+
return touchedHandle;
|
|
1694
|
+
});
|
|
1695
|
+
if (touchedAbstract === abstract) {
|
|
1696
|
+
return touchedAbstract;
|
|
1640
1697
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1698
|
+
if (touchedAbstract) {
|
|
1699
|
+
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1700
|
+
component.updateAbstractIncludedOutline();
|
|
1701
|
+
touchedAbstract = undefined;
|
|
1643
1702
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
return
|
|
1650
|
-
}
|
|
1703
|
+
if (abstract) {
|
|
1704
|
+
touchedAbstract = abstract;
|
|
1705
|
+
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1706
|
+
component.updateAbstractIncludedOutline(touchedHandle);
|
|
1707
|
+
}
|
|
1708
|
+
return touchedAbstract;
|
|
1709
|
+
}
|
|
1651
1710
|
|
|
1652
|
-
function drawIndentedLink(
|
|
1711
|
+
function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true) {
|
|
1653
1712
|
const isUnderlineShap = getNodeShapeByElement(child.origin) === MindNodeShape.underline;
|
|
1654
1713
|
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
1655
1714
|
const beginRectangle = getRectangleByNode(beginNode);
|
|
@@ -1661,7 +1720,7 @@ function drawIndentedLink(roughSVG, node, child, defaultStroke = null, needDrawU
|
|
|
1661
1720
|
//根据位置,设置正负参数
|
|
1662
1721
|
let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
|
|
1663
1722
|
const layout = MindQueries.getCorrectLayoutByElement(node.origin);
|
|
1664
|
-
const strokeWidth = child.origin.
|
|
1723
|
+
const strokeWidth = child.origin.branchWidth ? child.origin.branchWidth : STROKE_WIDTH;
|
|
1665
1724
|
if (beginNode.origin.isRoot) {
|
|
1666
1725
|
if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
|
|
1667
1726
|
beginY += strokeWidth;
|
|
@@ -1682,9 +1741,9 @@ function drawIndentedLink(roughSVG, node, child, defaultStroke = null, needDrawU
|
|
|
1682
1741
|
isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
|
|
1683
1742
|
isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
|
|
1684
1743
|
];
|
|
1685
|
-
const stroke = defaultStroke ||
|
|
1744
|
+
const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
|
|
1686
1745
|
const points = pointsOnBezierCurves(curve);
|
|
1687
|
-
return
|
|
1746
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
1688
1747
|
}
|
|
1689
1748
|
|
|
1690
1749
|
var HorizontalPlacement;
|
|
@@ -1797,9 +1856,9 @@ const transformPlacement = (placement, direction) => {
|
|
|
1797
1856
|
}
|
|
1798
1857
|
};
|
|
1799
1858
|
|
|
1800
|
-
function drawLogicLink(
|
|
1801
|
-
const
|
|
1802
|
-
const strokeWidth = node.origin.
|
|
1859
|
+
function drawLogicLink(board, node, parent, isHorizontal) {
|
|
1860
|
+
const branchColor = getBranchColorByMindElement(board, node.origin);
|
|
1861
|
+
const strokeWidth = node.origin.branchWidth ? node.origin.branchWidth : STROKE_WIDTH;
|
|
1803
1862
|
const hasStraightLine = !parent.origin.isRoot;
|
|
1804
1863
|
const hasUnderlineShape = node.origin.shape === MindNodeShape.underline;
|
|
1805
1864
|
const hasUnderlineShapeOfParent = parent.origin.shape === MindNodeShape.underline;
|
|
@@ -1839,7 +1898,7 @@ function drawLogicLink(roughSVG, node, parent, isHorizontal) {
|
|
|
1839
1898
|
const underlineEnd = movePoint(endPoint, nodeClient.width, linkDirection);
|
|
1840
1899
|
const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
|
|
1841
1900
|
const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
|
|
1842
|
-
return
|
|
1901
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth });
|
|
1843
1902
|
}
|
|
1844
1903
|
|
|
1845
1904
|
function getEmojisRectangle(element) {
|
|
@@ -1961,7 +2020,7 @@ function getRichtextRectangleByNode(node) {
|
|
|
1961
2020
|
function drawRectangleNode(board, node) {
|
|
1962
2021
|
const { x, y, width, height } = getRectangleByNode(node);
|
|
1963
2022
|
const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? ROOT_NODE_FILL : NODE_FILL;
|
|
1964
|
-
const stroke = getStrokeByMindElement(node.origin);
|
|
2023
|
+
const stroke = getStrokeByMindElement(board, node.origin);
|
|
1965
2024
|
const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : STROKE_WIDTH;
|
|
1966
2025
|
const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), x, y, x + width, y + height, {
|
|
1967
2026
|
stroke,
|
|
@@ -2020,6 +2079,7 @@ class EmojiDrawer {
|
|
|
2020
2079
|
const componentType = this.board.drawEmoji(emoji, element);
|
|
2021
2080
|
this.componentRef = this.viewContainerRef.createComponent(componentType);
|
|
2022
2081
|
this.componentRef.instance.emojiItem = emoji;
|
|
2082
|
+
this.componentRef.instance.board = this.board;
|
|
2023
2083
|
const fontSize = PlaitMind.isMind(element) ? 18 : 14;
|
|
2024
2084
|
this.componentRef.instance.fontSize = fontSize;
|
|
2025
2085
|
}
|
|
@@ -2084,6 +2144,10 @@ class EmojisDrawer {
|
|
|
2084
2144
|
|
|
2085
2145
|
const setLayout = (board, layout, path) => {
|
|
2086
2146
|
correctLogicLayoutNode(board, layout, path);
|
|
2147
|
+
const element = PlaitNode.get(board, path);
|
|
2148
|
+
if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
|
|
2149
|
+
handleAbstractIncluded(board, element);
|
|
2150
|
+
}
|
|
2087
2151
|
Transforms.setNode(board, { layout }, path);
|
|
2088
2152
|
};
|
|
2089
2153
|
const correctLogicLayoutNode = (board, layout, path) => {
|
|
@@ -2250,6 +2314,14 @@ function hasAfterDraw(value) {
|
|
|
2250
2314
|
return false;
|
|
2251
2315
|
}
|
|
2252
2316
|
|
|
2317
|
+
function findNewChildNodePath(board, element) {
|
|
2318
|
+
return PlaitBoard.findPath(board, element).concat((element.children || []).filter(child => !AbstractNode.isAbstract(child)).length);
|
|
2319
|
+
}
|
|
2320
|
+
function findNewSiblingNodePath(board, element) {
|
|
2321
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2322
|
+
return Path$1.next(path);
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2253
2325
|
class QuickInsertDrawer extends BaseDrawer {
|
|
2254
2326
|
canDraw(element) {
|
|
2255
2327
|
if (PlaitBoard.isReadonly(this.board) || element?.isCollapsed) {
|
|
@@ -2273,7 +2345,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2273
2345
|
*/
|
|
2274
2346
|
const shape = getNodeShapeByElement(element);
|
|
2275
2347
|
// 形状是矩形要偏移边框的线宽
|
|
2276
|
-
const strokeWidth = element.
|
|
2348
|
+
const strokeWidth = element.branchWidth ? element.branchWidth : STROKE_WIDTH;
|
|
2277
2349
|
let offsetBorderLineWidth = 0;
|
|
2278
2350
|
if (shape === MindNodeShape.roundRectangle && offset === 0) {
|
|
2279
2351
|
offsetBorderLineWidth = strokeWidth;
|
|
@@ -2381,7 +2453,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2381
2453
|
underlineCoordinates[MindLayoutType.right].startY -= height * 0.5;
|
|
2382
2454
|
underlineCoordinates[MindLayoutType.right].endY -= height * 0.5;
|
|
2383
2455
|
}
|
|
2384
|
-
const
|
|
2456
|
+
const branchColor = PlaitMind.isMind(element) ? getNextBranchColor(element) : getBranchColorByMindElement(this.board, element);
|
|
2385
2457
|
let nodeLayout = MindQueries.getCorrectLayoutByElement(element);
|
|
2386
2458
|
if (element.isRoot && isStandardLayout(nodeLayout)) {
|
|
2387
2459
|
const root = element;
|
|
@@ -2389,7 +2461,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2389
2461
|
}
|
|
2390
2462
|
const underlineCoordinate = underlineCoordinates[nodeLayout];
|
|
2391
2463
|
if (underlineCoordinate) {
|
|
2392
|
-
const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke, strokeWidth });
|
|
2464
|
+
const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke: branchColor, strokeWidth });
|
|
2393
2465
|
const circleCoordinates = {
|
|
2394
2466
|
startX: underlineCoordinate.endX,
|
|
2395
2467
|
startY: underlineCoordinate.endY
|
|
@@ -2440,7 +2512,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2440
2512
|
fromEvent(this.g, 'mouseup')
|
|
2441
2513
|
.pipe(take(1))
|
|
2442
2514
|
.subscribe(() => {
|
|
2443
|
-
const path =
|
|
2515
|
+
const path = findNewChildNodePath(this.board, element);
|
|
2444
2516
|
insertMindElement(this.board, element, path);
|
|
2445
2517
|
});
|
|
2446
2518
|
}
|
|
@@ -2555,10 +2627,10 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2555
2627
|
this.linkG = drawAbstractLink(this.board, this.node, isHorizontalLayout(layout));
|
|
2556
2628
|
}
|
|
2557
2629
|
else if (MindElement.isIndentedLayout(this.parent.origin)) {
|
|
2558
|
-
this.linkG = drawIndentedLink(this.
|
|
2630
|
+
this.linkG = drawIndentedLink(this.board, this.parent, this.node);
|
|
2559
2631
|
}
|
|
2560
2632
|
else {
|
|
2561
|
-
this.linkG = drawLogicLink(this.
|
|
2633
|
+
this.linkG = drawLogicLink(this.board, this.node, this.parent, isHorizontalLayout(layout));
|
|
2562
2634
|
}
|
|
2563
2635
|
this.g.append(this.linkG);
|
|
2564
2636
|
}
|
|
@@ -2715,8 +2787,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2715
2787
|
Transforms.setNode(this.board, newElement, path);
|
|
2716
2788
|
});
|
|
2717
2789
|
const { x, y, width, height } = getRectangleByNode(this.node);
|
|
2718
|
-
const stroke =
|
|
2719
|
-
const strokeWidth = this.node.origin.
|
|
2790
|
+
const stroke = getBranchColorByMindElement(this.board, this.element);
|
|
2791
|
+
const strokeWidth = this.node.origin.branchWidth ? this.node.origin.branchWidth : STROKE_WIDTH;
|
|
2720
2792
|
const extendY = y + height / 2;
|
|
2721
2793
|
const nodeLayout = MindQueries.getCorrectLayoutByElement(this.element);
|
|
2722
2794
|
let extendLineXY = [
|
|
@@ -3217,7 +3289,7 @@ const withDnd = (board) => {
|
|
|
3217
3289
|
});
|
|
3218
3290
|
if (dropTarget?.target) {
|
|
3219
3291
|
dropTarget = readjustmentDropTarget(dropTarget);
|
|
3220
|
-
drawPlaceholderDropNodeG(
|
|
3292
|
+
drawPlaceholderDropNodeG(board, dropTarget, fakeDropNodeG);
|
|
3221
3293
|
}
|
|
3222
3294
|
}
|
|
3223
3295
|
mousemove(event);
|
|
@@ -3376,7 +3448,7 @@ const setIsDragging = (board, state) => {
|
|
|
3376
3448
|
|
|
3377
3449
|
const buildClipboardData = (board, selectedElements) => {
|
|
3378
3450
|
let result = [];
|
|
3379
|
-
const selectedMindNodes = selectedElements.map(
|
|
3451
|
+
const selectedMindNodes = selectedElements.map(value => MindElement.getNode(value));
|
|
3380
3452
|
const nodesRectangle = getRectangleByElements(board, selectedElements, true);
|
|
3381
3453
|
selectedElements.forEach((node, index) => {
|
|
3382
3454
|
const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
|
|
@@ -3415,12 +3487,18 @@ const insertClipboardData = (board, elements, targetPoint) => {
|
|
|
3415
3487
|
if (item.isRoot) {
|
|
3416
3488
|
newElement = transformRootToNode(board, newElement);
|
|
3417
3489
|
}
|
|
3490
|
+
if (AbstractNode.isAbstract(item)) {
|
|
3491
|
+
newElement = transformAbstractToNode(newElement);
|
|
3492
|
+
}
|
|
3418
3493
|
const selectedElementPath = PlaitBoard.findPath(board, selectedElements[0]);
|
|
3419
3494
|
path = selectedElementPath.concat((selectedElements[0].children || []).length + index);
|
|
3420
3495
|
}
|
|
3421
3496
|
else {
|
|
3422
3497
|
const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
|
|
3423
3498
|
newElement.points = [point];
|
|
3499
|
+
if (AbstractNode.isAbstract(item)) {
|
|
3500
|
+
newElement = transformAbstractToNode(newElement);
|
|
3501
|
+
}
|
|
3424
3502
|
if (!item.isRoot) {
|
|
3425
3503
|
newElement = transformNodeToRoot(board, newElement);
|
|
3426
3504
|
}
|
|
@@ -3439,15 +3517,6 @@ const insertClipboardText = (board, parentElement, text, width, height) => {
|
|
|
3439
3517
|
return;
|
|
3440
3518
|
};
|
|
3441
3519
|
|
|
3442
|
-
function findNewChildNodePath(board, element) {
|
|
3443
|
-
const path = PlaitBoard.findPath(board, element);
|
|
3444
|
-
return path.concat((element.children || []).length);
|
|
3445
|
-
}
|
|
3446
|
-
function findNewSiblingNodePath(board, element) {
|
|
3447
|
-
const path = PlaitBoard.findPath(board, element);
|
|
3448
|
-
return Path$1.next(path);
|
|
3449
|
-
}
|
|
3450
|
-
|
|
3451
3520
|
const withEmoji = (board) => {
|
|
3452
3521
|
const newBoard = board;
|
|
3453
3522
|
newBoard.drawEmoji = (emoji, element) => {
|
|
@@ -3535,7 +3604,7 @@ const withAbstract = (board) => {
|
|
|
3535
3604
|
};
|
|
3536
3605
|
board.mouseup = (event) => {
|
|
3537
3606
|
startPoint = undefined;
|
|
3538
|
-
abstractHandlePosition =
|
|
3607
|
+
abstractHandlePosition = undefined;
|
|
3539
3608
|
if (activeAbstractElement) {
|
|
3540
3609
|
if (newBoard?.abstractResize) {
|
|
3541
3610
|
newBoard.abstractResize(AbstractResizeState.end);
|
|
@@ -3618,6 +3687,7 @@ const withMind = (board) => {
|
|
|
3618
3687
|
if (shouldChangeRightNodeCount(selectedElement)) {
|
|
3619
3688
|
changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
|
|
3620
3689
|
}
|
|
3690
|
+
insertSiblingElementHandleAbstract(board, selectedElement);
|
|
3621
3691
|
insertMindElement(board, selectedElement, findNewSiblingNodePath(board, selectedElement));
|
|
3622
3692
|
}
|
|
3623
3693
|
return;
|
|
@@ -3734,13 +3804,15 @@ class MindEmojiBaseComponent {
|
|
|
3734
3804
|
}
|
|
3735
3805
|
}
|
|
3736
3806
|
MindEmojiBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
3737
|
-
MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem" }, ngImport: i0 });
|
|
3807
|
+
MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem", board: "board" }, ngImport: i0 });
|
|
3738
3808
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, decorators: [{
|
|
3739
3809
|
type: Directive
|
|
3740
3810
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { fontSize: [{
|
|
3741
3811
|
type: Input
|
|
3742
3812
|
}], emojiItem: [{
|
|
3743
3813
|
type: Input
|
|
3814
|
+
}], board: [{
|
|
3815
|
+
type: Input
|
|
3744
3816
|
}] } });
|
|
3745
3817
|
|
|
3746
3818
|
/*
|
|
@@ -3751,5 +3823,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3751
3823
|
* Generated bundle index. Do not edit.
|
|
3752
3824
|
*/
|
|
3753
3825
|
|
|
3754
|
-
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,
|
|
3826
|
+
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 };
|
|
3755
3827
|
//# sourceMappingURL=plait-mind.mjs.map
|