@plait/mind 0.2.2 → 0.3.1
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/{drawer/base/base.d.ts → base/base.drawer.d.ts} +1 -1
- package/{plugins/emoji → base}/emoji-base.component.d.ts +2 -2
- package/{plugins/emoji → base}/index.d.ts +1 -1
- package/draw/abstract.d.ts +2 -1
- package/draw/indented-link.d.ts +1 -1
- package/draw/link/logic-link.d.ts +1 -1
- package/draw/node.d.ts +5 -0
- package/draw/topic.d.ts +16 -0
- package/{plugins/emoji → drawer}/emoji.drawer.d.ts +3 -3
- package/drawer/quick-insert.drawer.d.ts +1 -1
- package/esm2020/base/base.drawer.mjs +17 -0
- package/esm2020/base/emoji-base.component.mjs +33 -0
- package/esm2020/base/index.mjs +3 -0
- package/esm2020/draw/abstract.mjs +8 -7
- package/esm2020/draw/indented-link.mjs +3 -3
- package/esm2020/draw/link/abstract-link.mjs +9 -15
- package/esm2020/draw/link/logic-link.mjs +9 -9
- package/esm2020/draw/node.mjs +21 -0
- package/esm2020/draw/topic.mjs +32 -0
- package/esm2020/drawer/emoji.drawer.mjs +73 -0
- package/esm2020/drawer/quick-insert.drawer.mjs +3 -3
- package/esm2020/interfaces/index.mjs +2 -2
- package/esm2020/interfaces/pointer.mjs +5 -0
- package/esm2020/mind.component.mjs +2 -2
- package/esm2020/mind.module.mjs +5 -5
- package/esm2020/node.component.mjs +11 -10
- package/esm2020/plugins/with-abstract-resize.board.mjs +12 -0
- package/esm2020/plugins/with-abstract-resize.mjs +107 -0
- package/esm2020/plugins/with-mind-create.mjs +85 -0
- package/esm2020/plugins/with-mind-extend.mjs +11 -0
- package/esm2020/plugins/with-mind.board.mjs +2 -0
- package/esm2020/plugins/with-mind.mjs +30 -16
- package/esm2020/plugins/with-node-dnd.mjs +162 -0
- package/esm2020/public-api.mjs +5 -3
- package/esm2020/transforms/abstract-node.mjs +3 -2
- package/esm2020/transforms/emoji.mjs +37 -0
- package/esm2020/transforms/index.mjs +7 -3
- package/esm2020/transforms/node.mjs +40 -33
- package/esm2020/utils/abstract/common.mjs +64 -31
- package/esm2020/utils/abstract/resize.mjs +3 -2
- package/esm2020/utils/clipboard.mjs +16 -18
- package/esm2020/utils/dnd/common.mjs +35 -0
- package/esm2020/utils/dnd/detector.mjs +268 -0
- package/esm2020/utils/dnd/draw.mjs +161 -0
- package/esm2020/utils/index.mjs +6 -6
- package/esm2020/utils/mind.mjs +6 -129
- package/esm2020/utils/node/adjust-node.mjs +49 -0
- package/esm2020/utils/node/common.mjs +6 -0
- package/esm2020/utils/node/create-node.mjs +61 -0
- package/esm2020/utils/node/index.mjs +4 -0
- package/esm2020/utils/point-placement.mjs +22 -2
- package/esm2020/utils/position/emoji.mjs +31 -0
- package/esm2020/utils/position/index.mjs +4 -0
- package/esm2020/utils/position/node.mjs +34 -0
- package/esm2020/utils/position/topic.mjs +14 -0
- package/esm2020/utils/space/emoji.mjs +19 -0
- package/esm2020/utils/space/layout-options.mjs +72 -0
- package/esm2020/utils/space/node-space.mjs +77 -0
- package/fesm2015/plait-mind.mjs +1464 -1631
- package/fesm2015/plait-mind.mjs.map +1 -1
- package/fesm2020/plait-mind.mjs +1486 -1642
- package/fesm2020/plait-mind.mjs.map +1 -1
- package/interfaces/index.d.ts +1 -1
- package/interfaces/pointer.d.ts +3 -0
- package/mind.module.d.ts +2 -2
- package/node.component.d.ts +3 -3
- package/package.json +3 -3
- package/{interfaces/abstract.d.ts → plugins/with-abstract-resize.board.d.ts} +2 -2
- package/plugins/with-mind-create.d.ts +11 -0
- package/plugins/with-mind-extend.d.ts +3 -0
- package/plugins/{with-extend-mind.d.ts → with-mind.board.d.ts} +4 -4
- package/plugins/with-mind.d.ts +1 -1
- package/public-api.d.ts +4 -2
- package/styles/styles.scss +5 -2
- package/transforms/abstract-node.d.ts +1 -1
- package/transforms/emoji.d.ts +6 -0
- package/transforms/index.d.ts +3 -0
- package/transforms/node.d.ts +5 -5
- package/utils/abstract/common.d.ts +19 -4
- package/utils/abstract/resize.d.ts +2 -1
- package/utils/dnd/common.d.ts +7 -0
- package/utils/dnd/detector.d.ts +31 -0
- package/utils/dnd/draw.d.ts +9 -0
- package/utils/index.d.ts +5 -5
- package/utils/mind.d.ts +3 -22
- package/utils/node/adjust-node.d.ts +5 -0
- package/utils/{node.d.ts → node/common.d.ts} +1 -1
- package/utils/node/create-node.d.ts +14 -0
- package/utils/node/index.d.ts +3 -0
- package/utils/point-placement.d.ts +8 -1
- package/utils/position/emoji.d.ts +7 -0
- package/utils/position/index.d.ts +3 -0
- package/utils/position/node.d.ts +12 -0
- package/utils/position/topic.d.ts +16 -0
- package/utils/space/emoji.d.ts +7 -0
- package/{layout-option.d.ts → utils/space/layout-options.d.ts} +1 -1
- package/utils/{node-space.d.ts → space/node-space.d.ts} +4 -4
- package/draw/link.d.ts +0 -3
- package/draw/richtext.d.ts +0 -15
- package/draw/shape.d.ts +0 -3
- package/esm2020/draw/link.mjs +0 -160
- package/esm2020/draw/richtext.mjs +0 -39
- package/esm2020/draw/shape.mjs +0 -18
- package/esm2020/drawer/base/base.mjs +0 -17
- package/esm2020/interfaces/abstract.mjs +0 -12
- package/esm2020/layout-option.mjs +0 -72
- package/esm2020/plugins/emoji/emoji-base.component.mjs +0 -33
- package/esm2020/plugins/emoji/emoji.drawer.mjs +0 -72
- package/esm2020/plugins/emoji/emoji.mjs +0 -47
- package/esm2020/plugins/emoji/index.mjs +0 -3
- package/esm2020/plugins/with-abstract.mjs +0 -106
- package/esm2020/plugins/with-dnd.mjs +0 -179
- package/esm2020/plugins/with-extend-mind.mjs +0 -11
- package/esm2020/utils/direction-corrector.mjs +0 -54
- package/esm2020/utils/direction-detector.mjs +0 -56
- package/esm2020/utils/dnd.mjs +0 -122
- package/esm2020/utils/draw-placeholder.mjs +0 -313
- package/esm2020/utils/drop-target-corrector.mjs +0 -87
- package/esm2020/utils/graph.mjs +0 -24
- package/esm2020/utils/node-space.mjs +0 -77
- package/esm2020/utils/node.mjs +0 -6
- package/plugins/emoji/emoji.d.ts +0 -11
- package/utils/direction-corrector.d.ts +0 -4
- package/utils/direction-detector.d.ts +0 -9
- package/utils/dnd.d.ts +0 -16
- package/utils/draw-placeholder.d.ts +0 -42
- package/utils/drop-target-corrector.d.ts +0 -9
- package/utils/graph.d.ts +0 -5
- /package/plugins/{with-abstract.d.ts → with-abstract-resize.d.ts} +0 -0
- /package/plugins/{with-dnd.d.ts → with-node-dnd.d.ts} +0 -0
package/fesm2020/plait-mind.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
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 {
|
|
5
|
-
import { MindLayoutType, AbstractNode, getAbstractLayout, isIndentedLayout, isStandardLayout,
|
|
6
|
-
import { getSizeByText, ROOT_DEFAULT_HEIGHT, TEXT_DEFAULT_HEIGHT,
|
|
4
|
+
import { PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, distanceBetweenPointAndRectangle, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, depthFirstRecursion, drawRoundRectangle, createG, getRectangleByElements, getSelectedElements, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, PlaitModule, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, throttleRAF, updateForeignObject as updateForeignObject$1, BoardTransforms, Selection, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
|
|
5
|
+
import { MindLayoutType, AbstractNode, getAbstractLayout, isIndentedLayout, isStandardLayout, isLeftLayout, isRightLayout, getNonAbstractChildren, isTopLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, ConnectingPosition, GlobalLayout } from '@plait/layouts';
|
|
6
|
+
import { getSizeByText, ROOT_DEFAULT_HEIGHT, TEXT_DEFAULT_HEIGHT, updateForeignObject, drawRichtext, 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
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';
|
|
13
|
-
import {
|
|
13
|
+
import { CommonModule } from '@angular/common';
|
|
14
14
|
|
|
15
15
|
const ELEMENT_TO_NODE = new WeakMap();
|
|
16
16
|
|
|
@@ -56,27 +56,42 @@ const ABSTRACT_INCLUDED_OUTLINE_OFFSET = 3.5;
|
|
|
56
56
|
const ABSTRACT_HANDLE_LENGTH = 10;
|
|
57
57
|
const ABSTRACT_HANDLE_MASK_WIDTH = 8;
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
function hitMindElement(board, point, element) {
|
|
72
|
-
const node = ELEMENT_TO_NODE.get(element);
|
|
73
|
-
if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
return false;
|
|
59
|
+
const MindNode = {
|
|
60
|
+
get(root, path) {
|
|
61
|
+
let node = root;
|
|
62
|
+
for (let i = 0; i < path.length; i++) {
|
|
63
|
+
const p = path[i];
|
|
64
|
+
if (!node || !node.children || !node.children[p]) {
|
|
65
|
+
throw new Error(`Cannot find a descendant at path [${path}]`);
|
|
66
|
+
}
|
|
67
|
+
node = node.children[p];
|
|
68
|
+
}
|
|
69
|
+
return node;
|
|
78
70
|
}
|
|
79
|
-
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
var LayoutDirection;
|
|
74
|
+
(function (LayoutDirection) {
|
|
75
|
+
LayoutDirection["top"] = "top";
|
|
76
|
+
LayoutDirection["right"] = "right";
|
|
77
|
+
LayoutDirection["bottom"] = "bottom";
|
|
78
|
+
LayoutDirection["left"] = "left";
|
|
79
|
+
})(LayoutDirection || (LayoutDirection = {}));
|
|
80
|
+
const LayoutDirectionsMap = {
|
|
81
|
+
[MindLayoutType.right]: [LayoutDirection.right],
|
|
82
|
+
[MindLayoutType.left]: [LayoutDirection.left],
|
|
83
|
+
[MindLayoutType.upward]: [LayoutDirection.top],
|
|
84
|
+
[MindLayoutType.downward]: [LayoutDirection.bottom],
|
|
85
|
+
[MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
|
|
86
|
+
[MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
|
|
87
|
+
[MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
|
|
88
|
+
[MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
var MindPointerType;
|
|
92
|
+
(function (MindPointerType) {
|
|
93
|
+
MindPointerType["mind"] = "mind";
|
|
94
|
+
})(MindPointerType || (MindPointerType = {}));
|
|
80
95
|
|
|
81
96
|
/**
|
|
82
97
|
* get correctly layout:
|
|
@@ -368,396 +383,172 @@ var MindElementShape;
|
|
|
368
383
|
MindElementShape["underline"] = "underline";
|
|
369
384
|
})(MindElementShape || (MindElementShape = {}));
|
|
370
385
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
386
|
+
function getEmojisWidthHeight(board, element) {
|
|
387
|
+
const options = board.getMindOptions();
|
|
388
|
+
const count = element.data.emojis.length;
|
|
389
|
+
const fontSize = getEmojiFontSize(element);
|
|
390
|
+
return {
|
|
391
|
+
width: fontSize * count + count * 2 * options.emojiPadding + (count - 1) * options.spaceBetweenEmojis,
|
|
392
|
+
height: element.height
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function getEmojiFontSize(element) {
|
|
396
|
+
if (PlaitMind.isMind(element)) {
|
|
397
|
+
return 18 + 2;
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
return 14 + 2;
|
|
382
401
|
}
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
var LayoutDirection;
|
|
386
|
-
(function (LayoutDirection) {
|
|
387
|
-
LayoutDirection["top"] = "top";
|
|
388
|
-
LayoutDirection["right"] = "right";
|
|
389
|
-
LayoutDirection["bottom"] = "bottom";
|
|
390
|
-
LayoutDirection["left"] = "left";
|
|
391
|
-
})(LayoutDirection || (LayoutDirection = {}));
|
|
392
|
-
const LayoutDirectionsMap = {
|
|
393
|
-
[MindLayoutType.right]: [LayoutDirection.right],
|
|
394
|
-
[MindLayoutType.left]: [LayoutDirection.left],
|
|
395
|
-
[MindLayoutType.upward]: [LayoutDirection.top],
|
|
396
|
-
[MindLayoutType.downward]: [LayoutDirection.bottom],
|
|
397
|
-
[MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
|
|
398
|
-
[MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
|
|
399
|
-
[MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
|
|
400
|
-
[MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
var AbstractHandlePosition;
|
|
404
|
-
(function (AbstractHandlePosition) {
|
|
405
|
-
AbstractHandlePosition["start"] = "start";
|
|
406
|
-
AbstractHandlePosition["end"] = "end";
|
|
407
|
-
})(AbstractHandlePosition || (AbstractHandlePosition = {}));
|
|
408
|
-
var AbstractResizeState;
|
|
409
|
-
(function (AbstractResizeState) {
|
|
410
|
-
AbstractResizeState["start"] = "start";
|
|
411
|
-
AbstractResizeState["resizing"] = "resizing";
|
|
412
|
-
AbstractResizeState["end"] = "end";
|
|
413
|
-
})(AbstractResizeState || (AbstractResizeState = {}));
|
|
414
|
-
|
|
415
|
-
function enterNodeEditing(element) {
|
|
416
|
-
const component = ELEMENT_TO_COMPONENT.get(element);
|
|
417
|
-
component.startEditText(false, false);
|
|
418
402
|
}
|
|
419
403
|
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
rightChildren.push(child);
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
430
|
-
if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
|
|
431
|
-
leftChildren.push(child);
|
|
432
|
-
continue;
|
|
433
|
-
}
|
|
434
|
-
if (i < rightNodeCount) {
|
|
435
|
-
rightChildren.push(child);
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
leftChildren.push(child);
|
|
439
|
-
}
|
|
404
|
+
const NodeDefaultSpace = {
|
|
405
|
+
horizontal: {
|
|
406
|
+
nodeAndText: BASE * 3,
|
|
407
|
+
emojiAndText: BASE * 1.5
|
|
408
|
+
},
|
|
409
|
+
vertical: {
|
|
410
|
+
nodeAndText: BASE * 1.5
|
|
440
411
|
}
|
|
441
|
-
return { leftChildren, rightChildren };
|
|
442
412
|
};
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
413
|
+
const RootDefaultSpace = {
|
|
414
|
+
horizontal: {
|
|
415
|
+
nodeAndText: BASE * 4,
|
|
416
|
+
emojiAndText: BASE * 2
|
|
417
|
+
},
|
|
418
|
+
vertical: {
|
|
419
|
+
nodeAndText: BASE * 2
|
|
420
|
+
}
|
|
446
421
|
};
|
|
447
|
-
const
|
|
448
|
-
|
|
422
|
+
const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
|
|
423
|
+
const isMind = PlaitMind.isMind(element);
|
|
424
|
+
const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
|
|
425
|
+
return nodeAndText;
|
|
449
426
|
};
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
return parent.children.find(child => {
|
|
455
|
-
return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
|
|
456
|
-
});
|
|
427
|
+
const getVerticalSpaceBetweenNodeAndText = (element) => {
|
|
428
|
+
const isMind = PlaitMind.isMind(element);
|
|
429
|
+
const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
|
|
430
|
+
return nodeAndText;
|
|
457
431
|
};
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
|
|
432
|
+
const getSpaceEmojiAndText = (element) => {
|
|
433
|
+
const isMind = PlaitMind.isMind(element);
|
|
434
|
+
const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
|
|
435
|
+
return emojiAndText;
|
|
461
436
|
};
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const parent = MindElement.getParent(value);
|
|
472
|
-
const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
|
|
473
|
-
if (isOverall) {
|
|
474
|
-
overallAbstracts.push(abstract);
|
|
475
|
-
}
|
|
437
|
+
const NodeSpace = {
|
|
438
|
+
getNodeWidth(board, element) {
|
|
439
|
+
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
440
|
+
if (MindElement.hasEmojis(element)) {
|
|
441
|
+
return (NodeSpace.getEmojiLeftSpace(board, element) +
|
|
442
|
+
getEmojisWidthHeight(board, element).width +
|
|
443
|
+
getSpaceEmojiAndText(element) +
|
|
444
|
+
element.width +
|
|
445
|
+
nodeAndText);
|
|
476
446
|
}
|
|
477
|
-
|
|
478
|
-
|
|
447
|
+
return nodeAndText + element.width + nodeAndText;
|
|
448
|
+
},
|
|
449
|
+
getNodeHeight(board, element) {
|
|
450
|
+
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
451
|
+
return nodeAndText + element.height + nodeAndText;
|
|
452
|
+
},
|
|
453
|
+
getTextLeftSpace(board, element) {
|
|
454
|
+
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
455
|
+
if (MindElement.hasEmojis(element)) {
|
|
456
|
+
return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
return nodeAndText;
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
getTextTopSpace(element) {
|
|
463
|
+
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
464
|
+
return nodeAndText;
|
|
465
|
+
},
|
|
466
|
+
getEmojiLeftSpace(board, element) {
|
|
467
|
+
const options = board.getMindOptions();
|
|
468
|
+
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
469
|
+
return nodeAndText - options.emojiPadding;
|
|
470
|
+
},
|
|
471
|
+
getEmojiTopSpace(element) {
|
|
472
|
+
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
473
|
+
return nodeAndText;
|
|
474
|
+
}
|
|
479
475
|
};
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
476
|
+
|
|
477
|
+
function getRectangleByNode(node) {
|
|
478
|
+
const x = node.x + node.hGap;
|
|
479
|
+
let y = node.y + node.vGap;
|
|
480
|
+
const width = node.width - node.hGap * 2;
|
|
481
|
+
const height = node.height - node.vGap * 2;
|
|
482
|
+
return {
|
|
483
|
+
x,
|
|
484
|
+
y,
|
|
485
|
+
width,
|
|
486
|
+
height
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function getRectangleByElement(board, originPoint, element) {
|
|
490
|
+
const nodeRectangle = {
|
|
491
|
+
x: originPoint[0],
|
|
492
|
+
y: originPoint[1],
|
|
493
|
+
width: NodeSpace.getNodeWidth(board, element),
|
|
494
|
+
height: NodeSpace.getNodeHeight(board, element)
|
|
495
|
+
};
|
|
496
|
+
return nodeRectangle;
|
|
497
|
+
}
|
|
498
|
+
function isHitMindElement(board, point, element) {
|
|
499
|
+
const node = MindElement.getNode(element);
|
|
500
|
+
if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
|
|
501
|
+
return true;
|
|
488
502
|
}
|
|
489
503
|
else {
|
|
490
|
-
|
|
491
|
-
behindAbstracts = getBehindAbstracts(parent, selectedElement);
|
|
492
|
-
}
|
|
493
|
-
if (behindAbstracts.length) {
|
|
494
|
-
behindAbstracts.forEach(abstract => {
|
|
495
|
-
let newProperties = abstractRefs.get(abstract);
|
|
496
|
-
if (!newProperties) {
|
|
497
|
-
newProperties = { start: 0, end: 0 };
|
|
498
|
-
abstractRefs.set(abstract, newProperties);
|
|
499
|
-
}
|
|
500
|
-
newProperties.start = newProperties.start + 1;
|
|
501
|
-
newProperties.end = newProperties.end + 1;
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
if (!hasPreviousNode) {
|
|
505
|
-
return abstractRefs;
|
|
504
|
+
return false;
|
|
506
505
|
}
|
|
507
|
-
|
|
508
|
-
const correspondingAbstract = getCorrespondingAbstract(parent, selectedElement);
|
|
509
|
-
const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
|
|
510
|
-
if (correspondingAbstract && !isDragToLast) {
|
|
511
|
-
let newProperties = abstractRefs.get(correspondingAbstract);
|
|
512
|
-
if (!newProperties) {
|
|
513
|
-
newProperties = { start: 0, end: 0 };
|
|
514
|
-
abstractRefs.set(correspondingAbstract, newProperties);
|
|
515
|
-
}
|
|
516
|
-
newProperties.end = newProperties.end + 1;
|
|
517
|
-
}
|
|
518
|
-
return abstractRefs;
|
|
519
|
-
};
|
|
520
|
-
const deleteElementHandleAbstract = (board, deletableElements, abstractRefs = new Map()) => {
|
|
521
|
-
deletableElements.forEach(node => {
|
|
522
|
-
if (!PlaitMind.isMind(node)) {
|
|
523
|
-
const parent = PlaitNode.parent(board, PlaitBoard.findPath(board, node));
|
|
524
|
-
const behindAbstracts = getBehindAbstracts(parent, node).filter(abstract => !deletableElements.includes(abstract));
|
|
525
|
-
if (behindAbstracts.length) {
|
|
526
|
-
behindAbstracts.forEach(abstract => {
|
|
527
|
-
let newProperties = abstractRefs.get(abstract);
|
|
528
|
-
if (!newProperties) {
|
|
529
|
-
newProperties = { start: 0, end: 0 };
|
|
530
|
-
abstractRefs.set(abstract, newProperties);
|
|
531
|
-
}
|
|
532
|
-
newProperties.start = newProperties.start - 1;
|
|
533
|
-
newProperties.end = newProperties.end - 1;
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
const correspondingAbstract = getCorrespondingAbstract(parent, node);
|
|
537
|
-
if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
|
|
538
|
-
let newProperties = abstractRefs.get(correspondingAbstract);
|
|
539
|
-
if (!newProperties) {
|
|
540
|
-
newProperties = { start: 0, end: 0 };
|
|
541
|
-
abstractRefs.set(correspondingAbstract, newProperties);
|
|
542
|
-
}
|
|
543
|
-
newProperties.end = newProperties.end - 1;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
return abstractRefs;
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
const setAbstractsByRefs = (board, abstractRefs) => {
|
|
551
|
-
abstractRefs.forEach((newProperty, element) => {
|
|
552
|
-
const start = element.start + newProperty.start;
|
|
553
|
-
const end = element.end + newProperty.end;
|
|
554
|
-
const path = PlaitBoard.findPath(board, element);
|
|
555
|
-
if (start > end) {
|
|
556
|
-
Transforms.removeNode(board, path);
|
|
557
|
-
}
|
|
558
|
-
else {
|
|
559
|
-
Transforms.setNode(board, { start, end }, path);
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
};
|
|
563
|
-
const setAbstractByStandardLayout = (board, element) => {
|
|
564
|
-
const rightNodeCount = element.rightNodeCount;
|
|
565
|
-
const abstract = element.children.find(child => {
|
|
566
|
-
return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
|
|
567
|
-
});
|
|
568
|
-
if (abstract) {
|
|
569
|
-
const path = PlaitBoard.findPath(board, abstract);
|
|
570
|
-
Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
const insertAbstract = (board, elements) => {
|
|
574
|
-
let elementGroup = getFirstLevelElement(elements);
|
|
575
|
-
const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
|
|
576
|
-
abstractIncludedGroups.forEach((group, index) => {
|
|
577
|
-
const groupParent = parentElements[index];
|
|
578
|
-
setAbstractByElements(board, groupParent, group);
|
|
579
|
-
});
|
|
580
|
-
};
|
|
581
|
-
const setAbstractByElements = (board, groupParent, group) => {
|
|
582
|
-
const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
|
|
583
|
-
const rightNodeCount = groupParent?.rightNodeCount;
|
|
584
|
-
const start = indexArray[0], end = indexArray[indexArray.length - 1];
|
|
585
|
-
if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
|
|
586
|
-
rightNodeCount &&
|
|
587
|
-
start < rightNodeCount &&
|
|
588
|
-
end >= rightNodeCount) {
|
|
589
|
-
const childrenLength = groupParent.children.length;
|
|
590
|
-
const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
|
|
591
|
-
const leftChildren = indexArray.filter(index => index >= rightNodeCount);
|
|
592
|
-
const rightChildren = indexArray.filter(index => index < rightNodeCount);
|
|
593
|
-
insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
|
|
594
|
-
insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
|
|
595
|
-
}
|
|
596
|
-
else {
|
|
597
|
-
const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
|
|
598
|
-
insertAbstractNode(board, path, start, end);
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
const insertAbstractNode = (board, path, start, end) => {
|
|
602
|
-
const mindElement = createMindElement('概要', 28, 20, {
|
|
603
|
-
strokeColor: DefaultAbstractNodeStyle.strokeColor,
|
|
604
|
-
strokeWidth: DefaultAbstractNodeStyle.branchWidth,
|
|
605
|
-
branchColor: DefaultAbstractNodeStyle.branchColor,
|
|
606
|
-
branchWidth: DefaultAbstractNodeStyle.branchWidth
|
|
607
|
-
});
|
|
608
|
-
mindElement.start = start;
|
|
609
|
-
mindElement.end = end;
|
|
610
|
-
Transforms.insertNode(board, mindElement, path);
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
const setLayout = (board, layout, path) => {
|
|
614
|
-
correctLogicLayoutNode(board, layout, path);
|
|
615
|
-
const element = PlaitNode.get(board, path);
|
|
616
|
-
if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
|
|
617
|
-
MindTransforms.setAbstractByStandardLayout(board, element);
|
|
618
|
-
}
|
|
619
|
-
Transforms.setNode(board, { layout }, path);
|
|
620
|
-
};
|
|
621
|
-
const correctLogicLayoutNode = (board, layout, path) => {
|
|
622
|
-
const node = PlaitNode.get(board, path);
|
|
623
|
-
if (node && layout) {
|
|
624
|
-
node.children?.forEach((value, index) => {
|
|
625
|
-
if (value.layout) {
|
|
626
|
-
if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
|
|
627
|
-
(isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
|
|
628
|
-
Transforms.setNode(board, { layout: null }, [...path, index]);
|
|
629
|
-
}
|
|
630
|
-
if (value.children?.length) {
|
|
631
|
-
correctLogicLayoutNode(board, layout, [...path, index]);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
};
|
|
506
|
+
}
|
|
637
507
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
const path = PlaitBoard.findPath(board, element);
|
|
648
|
-
Transforms.setNode(board, newElement, path);
|
|
649
|
-
};
|
|
650
|
-
const setTopicSize = (board, element, width, height) => {
|
|
651
|
-
const newElement = {
|
|
652
|
-
width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
|
|
653
|
-
height: height / board.viewport.zoom
|
|
654
|
-
};
|
|
655
|
-
const path = PlaitBoard.findPath(board, element);
|
|
656
|
-
Transforms.setNode(board, newElement, path);
|
|
657
|
-
};
|
|
658
|
-
const addEmoji = (board, element, emojiItem) => {
|
|
659
|
-
const emojis = element.data.emojis || [];
|
|
660
|
-
const newEmojis = [...emojis];
|
|
661
|
-
newEmojis.push(emojiItem);
|
|
662
|
-
const newElement = {
|
|
663
|
-
data: { topic: element.data.topic, emojis: newEmojis }
|
|
664
|
-
};
|
|
665
|
-
const path = PlaitBoard.findPath(board, element);
|
|
666
|
-
Transforms.setNode(board, newElement, path);
|
|
667
|
-
};
|
|
668
|
-
const removeEmoji = (board, element, emojiItem) => {
|
|
669
|
-
const emojis = element.data.emojis.filter(value => value !== emojiItem);
|
|
670
|
-
const newElement = {
|
|
671
|
-
data: { topic: element.data.topic }
|
|
508
|
+
function getEmojiRectangle(board, element) {
|
|
509
|
+
let { x, y } = getRectangleByNode(MindElement.getNode(element));
|
|
510
|
+
x = x + NodeSpace.getEmojiLeftSpace(board, element);
|
|
511
|
+
const { width, height } = getEmojisWidthHeight(board, element);
|
|
512
|
+
return {
|
|
513
|
+
x,
|
|
514
|
+
y,
|
|
515
|
+
width,
|
|
516
|
+
height
|
|
672
517
|
};
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
518
|
+
}
|
|
519
|
+
function getEmojiForeignRectangle(board, element) {
|
|
520
|
+
let { x, y } = getRectangleByNode(MindElement.getNode(element));
|
|
521
|
+
x = x + NodeSpace.getEmojiLeftSpace(board, element);
|
|
522
|
+
const { width, height } = getEmojisWidthHeight(board, element);
|
|
523
|
+
return {
|
|
524
|
+
x,
|
|
525
|
+
y,
|
|
526
|
+
width,
|
|
527
|
+
height: height + NodeSpace.getEmojiTopSpace(element) * 2
|
|
682
528
|
};
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
}
|
|
687
|
-
return value;
|
|
688
|
-
});
|
|
689
|
-
newElement.data.emojis = newEmojis;
|
|
690
|
-
const path = PlaitBoard.findPath(board, element);
|
|
691
|
-
Transforms.setNode(board, newElement, path);
|
|
529
|
+
}
|
|
530
|
+
const isHitEmojis = (board, element, point) => {
|
|
531
|
+
return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
|
|
692
532
|
};
|
|
693
533
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
534
|
+
function getTopicRectangleByNode(board, node) {
|
|
535
|
+
let nodeRectangle = getRectangleByNode(node);
|
|
536
|
+
return getTopicRectangleByElement(board, nodeRectangle, node.origin);
|
|
537
|
+
}
|
|
538
|
+
function getTopicRectangleByElement(board, nodeRectangle, element) {
|
|
539
|
+
const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
|
|
540
|
+
const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
|
|
541
|
+
const width = Math.ceil(element.width);
|
|
542
|
+
const height = Math.ceil(element.height);
|
|
543
|
+
return { height, width, x, y };
|
|
544
|
+
}
|
|
705
545
|
|
|
706
|
-
function
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
let parent = MindElement.findParent(element);
|
|
710
|
-
while (parent) {
|
|
711
|
-
branch = root;
|
|
712
|
-
root = parent;
|
|
713
|
-
parent = MindElement.findParent(parent);
|
|
714
|
-
}
|
|
715
|
-
return { root, branch };
|
|
546
|
+
function enterNodeEditing(element) {
|
|
547
|
+
const component = PlaitElement.getComponent(element);
|
|
548
|
+
component.startEditText(false, false);
|
|
716
549
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
return p + getChildrenCount(c);
|
|
720
|
-
}, 0);
|
|
721
|
-
return count + element.children.length;
|
|
722
|
-
};
|
|
723
|
-
const isChildElement = (origin, child) => {
|
|
724
|
-
let parent = MindElement.findParent(child);
|
|
725
|
-
while (parent) {
|
|
726
|
-
if (parent === origin) {
|
|
727
|
-
return true;
|
|
728
|
-
}
|
|
729
|
-
parent = MindElement.findParent(parent);
|
|
730
|
-
}
|
|
731
|
-
return false;
|
|
732
|
-
};
|
|
733
|
-
const getFirstLevelElement = (elements) => {
|
|
734
|
-
let result = [];
|
|
735
|
-
elements.forEach(element => {
|
|
736
|
-
const isChild = elements.some(node => {
|
|
737
|
-
return isChildElement(node, element);
|
|
738
|
-
});
|
|
739
|
-
if (!isChild) {
|
|
740
|
-
result.push(element);
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
return result;
|
|
744
|
-
};
|
|
745
|
-
const isChildRight = (node, child) => {
|
|
746
|
-
return node.x < child.x;
|
|
747
|
-
};
|
|
748
|
-
const isChildUp = (node, child) => {
|
|
749
|
-
return node.y > child.y;
|
|
750
|
-
};
|
|
751
|
-
const copyNewNode = (node) => {
|
|
752
|
-
const newNode = { ...node };
|
|
753
|
-
newNode.id = idCreator();
|
|
754
|
-
newNode.children = [];
|
|
755
|
-
for (const childNode of node.children) {
|
|
756
|
-
newNode.children.push(copyNewNode(childNode));
|
|
757
|
-
}
|
|
758
|
-
return newNode;
|
|
759
|
-
};
|
|
760
|
-
const transformRootToNode = (board, node) => {
|
|
550
|
+
|
|
551
|
+
const adjustRootToNode = (board, node) => {
|
|
761
552
|
const newNode = { ...node };
|
|
762
553
|
delete newNode.isRoot;
|
|
763
554
|
delete newNode.rightNodeCount;
|
|
@@ -771,13 +562,13 @@ const transformRootToNode = (board, node) => {
|
|
|
771
562
|
}
|
|
772
563
|
return newNode;
|
|
773
564
|
};
|
|
774
|
-
const
|
|
565
|
+
const adjustAbstractToNode = (node) => {
|
|
775
566
|
const newNode = { ...node };
|
|
776
567
|
delete newNode.start;
|
|
777
568
|
delete newNode.end;
|
|
778
569
|
return newNode;
|
|
779
570
|
};
|
|
780
|
-
const
|
|
571
|
+
const adjustNodeToRoot = (board, node) => {
|
|
781
572
|
const newElement = { ...node };
|
|
782
573
|
let text = Node.string(newElement.data.topic);
|
|
783
574
|
if (!text) {
|
|
@@ -799,40 +590,14 @@ const transformNodeToRoot = (board, node) => {
|
|
|
799
590
|
type: 'mindmap'
|
|
800
591
|
};
|
|
801
592
|
};
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
return str;
|
|
811
|
-
};
|
|
812
|
-
const changeRightNodeCount = (board, parentPath, changeNumber) => {
|
|
813
|
-
const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
|
|
814
|
-
Transforms.setNode(board, {
|
|
815
|
-
rightNodeCount: changeNumber >= 0
|
|
816
|
-
? _rightNodeCount + changeNumber
|
|
817
|
-
: _rightNodeCount + changeNumber < 0
|
|
818
|
-
? 0
|
|
819
|
-
: _rightNodeCount + changeNumber
|
|
820
|
-
}, parentPath);
|
|
821
|
-
};
|
|
822
|
-
const shouldChangeRightNodeCount = (selectedElement) => {
|
|
823
|
-
const parentElement = MindElement.findParent(selectedElement);
|
|
824
|
-
if (parentElement) {
|
|
825
|
-
const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
|
|
826
|
-
if (parentElement.isRoot &&
|
|
827
|
-
getRootLayout(parentElement) === MindLayoutType.standard &&
|
|
828
|
-
parentElement.rightNodeCount &&
|
|
829
|
-
nodeIndex <= parentElement.rightNodeCount - 1) {
|
|
830
|
-
return true;
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
return false;
|
|
593
|
+
|
|
594
|
+
const createEmptyMind = (board, point) => {
|
|
595
|
+
const element = createMindElement('', 0, 0, { layout: MindLayoutType.right });
|
|
596
|
+
const rootElement = adjustNodeToRoot(board, element);
|
|
597
|
+
rootElement.points = [point];
|
|
598
|
+
return rootElement;
|
|
834
599
|
};
|
|
835
|
-
const
|
|
600
|
+
const createDefaultMind = (point, rightNodeCount, layout) => {
|
|
836
601
|
const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle, layout });
|
|
837
602
|
root.rightNodeCount = rightNodeCount;
|
|
838
603
|
root.isRoot = true;
|
|
@@ -881,6 +646,83 @@ const createMindElement = (text, width, height, options) => {
|
|
|
881
646
|
}
|
|
882
647
|
return newElement;
|
|
883
648
|
};
|
|
649
|
+
|
|
650
|
+
const getChildrenCount = (element) => {
|
|
651
|
+
const count = element.children.reduce((p, c) => {
|
|
652
|
+
return p + getChildrenCount(c);
|
|
653
|
+
}, 0);
|
|
654
|
+
return count + element.children.length;
|
|
655
|
+
};
|
|
656
|
+
const isChildElement = (origin, child) => {
|
|
657
|
+
let parent = MindElement.findParent(child);
|
|
658
|
+
while (parent) {
|
|
659
|
+
if (parent === origin) {
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
parent = MindElement.findParent(parent);
|
|
663
|
+
}
|
|
664
|
+
return false;
|
|
665
|
+
};
|
|
666
|
+
const getFirstLevelElement = (elements) => {
|
|
667
|
+
let result = [];
|
|
668
|
+
elements.forEach(element => {
|
|
669
|
+
const isChild = elements.some(node => {
|
|
670
|
+
return isChildElement(node, element);
|
|
671
|
+
});
|
|
672
|
+
if (!isChild) {
|
|
673
|
+
result.push(element);
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
return result;
|
|
677
|
+
};
|
|
678
|
+
const isChildRight = (node, child) => {
|
|
679
|
+
return node.x < child.x;
|
|
680
|
+
};
|
|
681
|
+
const isChildUp = (node, child) => {
|
|
682
|
+
return node.y > child.y;
|
|
683
|
+
};
|
|
684
|
+
const copyNewNode = (node) => {
|
|
685
|
+
const newNode = { ...node };
|
|
686
|
+
newNode.id = idCreator();
|
|
687
|
+
newNode.children = [];
|
|
688
|
+
for (const childNode of node.children) {
|
|
689
|
+
newNode.children.push(copyNewNode(childNode));
|
|
690
|
+
}
|
|
691
|
+
return newNode;
|
|
692
|
+
};
|
|
693
|
+
const extractNodesText = (node) => {
|
|
694
|
+
let str = '';
|
|
695
|
+
if (node) {
|
|
696
|
+
str += Node.string(node.data.topic.children[0]) + ' ';
|
|
697
|
+
for (const childNode of node.children) {
|
|
698
|
+
str += extractNodesText(childNode);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return str;
|
|
702
|
+
};
|
|
703
|
+
const changeRightNodeCount = (board, parentPath, changeNumber) => {
|
|
704
|
+
const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
|
|
705
|
+
Transforms.setNode(board, {
|
|
706
|
+
rightNodeCount: changeNumber >= 0
|
|
707
|
+
? _rightNodeCount + changeNumber
|
|
708
|
+
: _rightNodeCount + changeNumber < 0
|
|
709
|
+
? 0
|
|
710
|
+
: _rightNodeCount + changeNumber
|
|
711
|
+
}, parentPath);
|
|
712
|
+
};
|
|
713
|
+
const isInRightBranchOfStandardLayout = (selectedElement) => {
|
|
714
|
+
const parentElement = MindElement.findParent(selectedElement);
|
|
715
|
+
if (parentElement) {
|
|
716
|
+
const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
|
|
717
|
+
if (parentElement.isRoot &&
|
|
718
|
+
getRootLayout(parentElement) === MindLayoutType.standard &&
|
|
719
|
+
parentElement.rightNodeCount &&
|
|
720
|
+
nodeIndex <= parentElement.rightNodeCount - 1) {
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
return false;
|
|
725
|
+
};
|
|
884
726
|
// layoutLevel 用来表示插入兄弟节点还是子节点
|
|
885
727
|
const insertMindElement = (board, inheritNode, path) => {
|
|
886
728
|
let fill, strokeColor, strokeWidth, shape = MindElementShape.roundRectangle;
|
|
@@ -905,25 +747,6 @@ const findLastChild = (child) => {
|
|
|
905
747
|
}
|
|
906
748
|
return result;
|
|
907
749
|
};
|
|
908
|
-
const deleteSelectedELements = (board, selectedElements) => {
|
|
909
|
-
const deletableElements = getFirstLevelElement(selectedElements).reverse();
|
|
910
|
-
const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
|
|
911
|
-
MindTransforms.setAbstractsByRefs(board, abstractRefs);
|
|
912
|
-
//翻转,从下到上修改,防止找不到 path
|
|
913
|
-
deletableElements
|
|
914
|
-
.map(element => {
|
|
915
|
-
const path = PlaitBoard.findPath(board, element);
|
|
916
|
-
return () => {
|
|
917
|
-
if (shouldChangeRightNodeCount(element)) {
|
|
918
|
-
changeRightNodeCount(board, path.slice(0, 1), -1);
|
|
919
|
-
}
|
|
920
|
-
Transforms.removeNode(board, path);
|
|
921
|
-
};
|
|
922
|
-
})
|
|
923
|
-
.forEach(action => {
|
|
924
|
-
action();
|
|
925
|
-
});
|
|
926
|
-
};
|
|
927
750
|
const divideElementByParent = (elements) => {
|
|
928
751
|
const abstractIncludedGroups = [];
|
|
929
752
|
const parentElements = [];
|
|
@@ -1019,466 +842,123 @@ function isVirtualKey(e) {
|
|
|
1019
842
|
return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
|
|
1020
843
|
}
|
|
1021
844
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
const
|
|
1025
|
-
if (
|
|
1026
|
-
|
|
1027
|
-
beginNode = child;
|
|
1028
|
-
endNode = node;
|
|
1029
|
-
}
|
|
1030
|
-
beginX = beginNode.x + beginNode.width - beginNode.hGap;
|
|
1031
|
-
beginY = beginNode.y + beginNode.height / 2;
|
|
1032
|
-
endX = endNode.x + endNode.hGap;
|
|
1033
|
-
endY = endNode.y + endNode.height / 2;
|
|
1034
|
-
if (node.parent &&
|
|
1035
|
-
isIndentedLayout(MindQueries.getLayoutByElement(node.parent?.origin)) &&
|
|
1036
|
-
getShapeByElement(board, node.origin) === MindElementShape.underline) {
|
|
1037
|
-
if (isChildRight(node, child)) {
|
|
1038
|
-
beginY = node.y + node.height - node.vGap;
|
|
1039
|
-
}
|
|
1040
|
-
else {
|
|
1041
|
-
endY = node.y + node.height - node.vGap;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
845
|
+
const IS_DRAGGING = new WeakMap();
|
|
846
|
+
const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
|
|
847
|
+
const activeComponent = PlaitElement.getComponent(activeElement);
|
|
848
|
+
if (isOrigin) {
|
|
849
|
+
activeComponent.g.classList.add('dragging-origin');
|
|
1044
850
|
}
|
|
1045
851
|
else {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
852
|
+
activeComponent.g.classList.add('dragging-child');
|
|
853
|
+
}
|
|
854
|
+
!activeElement.isCollapsed &&
|
|
855
|
+
activeElement.children.forEach(child => {
|
|
856
|
+
addActiveOnDragOrigin(child, false);
|
|
857
|
+
});
|
|
858
|
+
};
|
|
859
|
+
const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
|
|
860
|
+
const activeComponent = PlaitElement.getComponent(activeElement);
|
|
861
|
+
if (isOrigin) {
|
|
862
|
+
activeComponent.g.classList.remove('dragging-origin');
|
|
1054
863
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
864
|
+
else {
|
|
865
|
+
activeComponent.g.classList.remove('dragging-child');
|
|
866
|
+
}
|
|
867
|
+
!activeElement.isCollapsed &&
|
|
868
|
+
activeElement.children.forEach(child => {
|
|
869
|
+
removeActiveOnDragOrigin(child, false);
|
|
870
|
+
});
|
|
871
|
+
};
|
|
872
|
+
const isDragging = (board) => {
|
|
873
|
+
return !!IS_DRAGGING.get(board);
|
|
874
|
+
};
|
|
875
|
+
const setIsDragging = (board, state) => {
|
|
876
|
+
IS_DRAGGING.set(board, state);
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
*
|
|
881
|
+
* @param targetNode
|
|
882
|
+
* @param centerPoint
|
|
883
|
+
* @returns DetectResult[] | null
|
|
884
|
+
*/
|
|
885
|
+
const directionCorrector = (board, node, detectResults) => {
|
|
886
|
+
if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
|
|
887
|
+
const parentLayout = MindQueries.getCorrectLayoutByElement(board, node?.parent.origin);
|
|
888
|
+
if (isStandardLayout(parentLayout)) {
|
|
889
|
+
const idx = node.parent.children.findIndex(x => x === node);
|
|
890
|
+
const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
|
|
891
|
+
return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
|
|
1060
892
|
}
|
|
1061
|
-
if (
|
|
1062
|
-
|
|
893
|
+
if (isLeftLayout(parentLayout)) {
|
|
894
|
+
return getAllowedDirection(detectResults, ['right']);
|
|
1063
895
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
if (layout === MindLayoutType.right || isStandardLayout(layout)) {
|
|
1067
|
-
beginX += strokeWidth;
|
|
896
|
+
if (isRightLayout(parentLayout)) {
|
|
897
|
+
return getAllowedDirection(detectResults, ['left']);
|
|
1068
898
|
}
|
|
1069
|
-
if (
|
|
1070
|
-
|
|
899
|
+
if (parentLayout === MindLayoutType.upward) {
|
|
900
|
+
return getAllowedDirection(detectResults, ['bottom']);
|
|
1071
901
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
let curve = [
|
|
1075
|
-
[beginX, beginY],
|
|
1076
|
-
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
1077
|
-
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
1078
|
-
[endX, endY]
|
|
1079
|
-
];
|
|
1080
|
-
const shape = getShapeByElement(board, child.origin);
|
|
1081
|
-
if (!node.origin.isRoot) {
|
|
1082
|
-
if (node.x > child.x) {
|
|
1083
|
-
curve = [
|
|
1084
|
-
[beginX, beginY],
|
|
1085
|
-
[beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
|
|
1086
|
-
[endX - (beginNode.hGap + endNode.hGap) / 2, endY],
|
|
1087
|
-
[endX - 12, endY]
|
|
1088
|
-
];
|
|
1089
|
-
const line = [
|
|
1090
|
-
[endX - 12, endY],
|
|
1091
|
-
[endX - 12, endY],
|
|
1092
|
-
[endX, endY]
|
|
1093
|
-
];
|
|
1094
|
-
curve = [...curve, ...line];
|
|
1095
|
-
}
|
|
1096
|
-
else {
|
|
1097
|
-
curve = [
|
|
1098
|
-
[beginX + 12, beginY],
|
|
1099
|
-
[beginX + (beginNode.hGap + endNode.hGap) / 2, beginY],
|
|
1100
|
-
[endX - (beginNode.hGap + endNode.hGap) / 3, endY],
|
|
1101
|
-
[endX, endY]
|
|
1102
|
-
];
|
|
1103
|
-
const line = [
|
|
1104
|
-
[beginX, beginY],
|
|
1105
|
-
[beginX + 12, beginY],
|
|
1106
|
-
[beginX + 12, beginY]
|
|
1107
|
-
];
|
|
1108
|
-
curve = [...line, ...curve];
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
if (needDrawUnderline && shape === MindElementShape.underline) {
|
|
1112
|
-
if (child.left) {
|
|
1113
|
-
const underline = [
|
|
1114
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
1115
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY],
|
|
1116
|
-
[beginX - (beginNode.width - beginNode.hGap * 2), beginY]
|
|
1117
|
-
];
|
|
1118
|
-
curve = [...underline, ...curve];
|
|
1119
|
-
}
|
|
1120
|
-
else {
|
|
1121
|
-
const underline = [
|
|
1122
|
-
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
1123
|
-
[endX + (endNode.width - endNode.hGap * 2), endY],
|
|
1124
|
-
[endX + (endNode.width - endNode.hGap * 2), endY]
|
|
1125
|
-
];
|
|
1126
|
-
curve = [...curve, ...underline];
|
|
1127
|
-
}
|
|
902
|
+
if (parentLayout === MindLayoutType.downward) {
|
|
903
|
+
return getAllowedDirection(detectResults, ['top']);
|
|
1128
904
|
}
|
|
1129
|
-
const points = pointsOnBezierCurves(curve);
|
|
1130
|
-
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
1131
905
|
}
|
|
1132
906
|
else {
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
1144
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
1145
|
-
[endX, endY - 12]
|
|
1146
|
-
];
|
|
1147
|
-
const line = [
|
|
1148
|
-
[endX, endY - 12],
|
|
1149
|
-
[endX, endY - 12],
|
|
1150
|
-
[endX, endY]
|
|
1151
|
-
];
|
|
1152
|
-
curve = [...curve, ...line];
|
|
1153
|
-
}
|
|
1154
|
-
else {
|
|
1155
|
-
curve = [
|
|
1156
|
-
[beginX, beginY + 12],
|
|
1157
|
-
[beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
|
|
1158
|
-
[endX, endY - (beginNode.vGap + endNode.vGap) / 2],
|
|
1159
|
-
[endX, endY]
|
|
1160
|
-
];
|
|
1161
|
-
const line = [
|
|
1162
|
-
[beginX, beginY],
|
|
1163
|
-
[beginX, beginY + 12],
|
|
1164
|
-
[beginX, beginY + 12]
|
|
1165
|
-
];
|
|
1166
|
-
curve = [...line, ...curve];
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
const points = pointsOnBezierCurves(curve);
|
|
1170
|
-
return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
const drawPlaceholderDropNodeG = (board, dropTarget, fakeDropNodeG) => {
|
|
1175
|
-
const targetComponent = PlaitElement.getComponent(dropTarget.target);
|
|
1176
|
-
const targetRect = getRectangleByNode(targetComponent.node);
|
|
1177
|
-
if (dropTarget.detectResult && ['right', 'left'].includes(dropTarget.detectResult)) {
|
|
1178
|
-
drawStraightDropNodeG(board, targetRect, dropTarget.detectResult, targetComponent, fakeDropNodeG);
|
|
1179
|
-
}
|
|
1180
|
-
const targetParent = MindElement.findParent(targetComponent.element);
|
|
1181
|
-
if (targetParent && dropTarget.detectResult && ['top', 'bottom'].includes(dropTarget.detectResult)) {
|
|
1182
|
-
const parentComponent = PlaitElement.getComponent(targetParent);
|
|
1183
|
-
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
1184
|
-
drawCurvePlaceholderDropNodeG(board, targetRect, dropTarget.detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG);
|
|
1185
|
-
}
|
|
1186
|
-
};
|
|
1187
|
-
const drawCurvePlaceholderDropNodeG = (board, targetRect, detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG) => {
|
|
1188
|
-
const parentNodeLayout = MindQueries.getCorrectLayoutByElement(board, parentComponent.node.origin);
|
|
1189
|
-
const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.parent.origin);
|
|
1190
|
-
const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
|
|
1191
|
-
let fakeX = targetComponent.node.x, fakeY = targetRect.y - 30, fakeRectangleStartX = targetRect.x, fakeRectangleEndX = targetRect.x + 30, fakeRectangleStartY = fakeY, fakeRectangleEndY = fakeRectangleStartY + 12, width = 30;
|
|
1192
|
-
if (isLeftLayout(layout)) {
|
|
1193
|
-
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
1194
|
-
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
1195
|
-
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
1196
|
-
}
|
|
1197
|
-
if (isHorizontalLogicLayout(parentNodeLayout)) {
|
|
1198
|
-
fakeY = getHorizontalFakeY(detectResult, targetIndex, parentComponent.node, targetRect, layout, fakeY);
|
|
1199
|
-
if (isStandardLayout(parentNodeLayout)) {
|
|
1200
|
-
const rightNodeCount = parentComponent.node.origin.rightNodeCount || 0;
|
|
1201
|
-
const idx = parentComponent.node.children.findIndex(x => x === targetComponent.node);
|
|
1202
|
-
const isLeft = idx >= rightNodeCount;
|
|
1203
|
-
// 标准布局的左,需要调整 x
|
|
1204
|
-
if (isLeft) {
|
|
1205
|
-
fakeX = targetComponent.node.x + targetComponent.node.width - 30;
|
|
1206
|
-
fakeRectangleStartX = targetRect.x + targetRect.width - 30;
|
|
1207
|
-
fakeRectangleEndX = targetRect.x + targetRect.width;
|
|
1208
|
-
}
|
|
1209
|
-
const isLeftFirst = idx === rightNodeCount;
|
|
1210
|
-
const isRightLast = idx === rightNodeCount - 1;
|
|
1211
|
-
// 拖拽至左第一个节点的情况
|
|
1212
|
-
if (detectResult === 'top' && isLeftFirst) {
|
|
1213
|
-
fakeY = targetRect.y - targetRect.height;
|
|
1214
|
-
}
|
|
1215
|
-
if (detectResult === 'bottom' && isRightLast) {
|
|
1216
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
fakeRectangleStartY = fakeY;
|
|
1220
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1221
|
-
}
|
|
1222
|
-
if (isVerticalLogicLayout(layout)) {
|
|
1223
|
-
parentComponent = targetComponent;
|
|
1224
|
-
targetComponent = PlaitElement.getComponent(MindElement.getParent(targetComponent.element));
|
|
1225
|
-
fakeX = parentComponent.node.x;
|
|
1226
|
-
width = parentComponent.node.width;
|
|
1227
|
-
const vGap = BASE * 6 + strokeWidth;
|
|
1228
|
-
if (isTopLayout(layout) && detectResult === 'top') {
|
|
1229
|
-
fakeY = targetRect.y - vGap;
|
|
1230
|
-
fakeRectangleStartY = fakeY - vGap + strokeWidth;
|
|
1231
|
-
}
|
|
1232
|
-
if (isBottomLayout(layout) && detectResult === 'bottom') {
|
|
1233
|
-
fakeY = targetRect.y + targetRect.height + vGap;
|
|
1234
|
-
fakeRectangleStartY = fakeY + vGap - strokeWidth;
|
|
1235
|
-
}
|
|
1236
|
-
fakeRectangleStartX = fakeX + Math.ceil(parentComponent.node.width / 2) - parentComponent.node.hGap - Math.ceil(strokeWidth / 2);
|
|
1237
|
-
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
1238
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1239
|
-
}
|
|
1240
|
-
if (isIndentedLayout(layout)) {
|
|
1241
|
-
// 偏移一个 Gap
|
|
907
|
+
const layout = MindQueries.getCorrectLayoutByElement(board, node?.origin);
|
|
908
|
+
if (isStandardLayout(layout)) {
|
|
909
|
+
return getAllowedDirection(detectResults, ['top', 'bottom']);
|
|
910
|
+
}
|
|
911
|
+
if (layout === MindLayoutType.upward) {
|
|
912
|
+
return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
|
|
913
|
+
}
|
|
914
|
+
if (layout === MindLayoutType.downward) {
|
|
915
|
+
return getAllowedDirection(detectResults, ['left', 'right', 'top']);
|
|
916
|
+
}
|
|
1242
917
|
if (isLeftLayout(layout)) {
|
|
1243
|
-
|
|
918
|
+
return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
|
|
1244
919
|
}
|
|
1245
920
|
if (isRightLayout(layout)) {
|
|
1246
|
-
|
|
1247
|
-
}
|
|
1248
|
-
if (isTopLayout(layout)) {
|
|
1249
|
-
if (detectResult === 'top') {
|
|
1250
|
-
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
1251
|
-
if (isLastNode) {
|
|
1252
|
-
fakeY = targetRect.y - targetRect.height - BASE;
|
|
1253
|
-
}
|
|
1254
|
-
else {
|
|
1255
|
-
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1256
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1257
|
-
fakeY = targetRect.y - Math.abs((nextRect.y + nextRect.height - targetRect.y) / 2);
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
if (detectResult === 'bottom') {
|
|
1261
|
-
const isFirstNode = targetIndex === 0;
|
|
1262
|
-
if (isFirstNode) {
|
|
1263
|
-
const parentRect = getRectangleByNode(parentComponent.node);
|
|
1264
|
-
fakeY = parentRect.y - parentRect.height / 2 - BASE;
|
|
1265
|
-
}
|
|
1266
|
-
else {
|
|
1267
|
-
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1268
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1269
|
-
fakeY = previousRect.y - Math.abs((targetRect.y + targetRect.height - previousRect.y) / 2);
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
921
|
+
return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
|
|
1272
922
|
}
|
|
1273
|
-
fakeRectangleStartX = fakeX;
|
|
1274
|
-
fakeRectangleEndX = fakeRectangleStartX + 30;
|
|
1275
|
-
fakeRectangleStartY = fakeY;
|
|
1276
|
-
fakeRectangleEndY = fakeRectangleStartY + 12;
|
|
1277
923
|
}
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
fill: PRIMARY_COLOR,
|
|
1288
|
-
fillStyle: 'solid'
|
|
924
|
+
return null;
|
|
925
|
+
};
|
|
926
|
+
const getAllowedDirection = (detectResults, illegalDirections) => {
|
|
927
|
+
const directions = detectResults;
|
|
928
|
+
illegalDirections.forEach(item => {
|
|
929
|
+
const bottomDirectionIndex = directions.findIndex(direction => direction === item);
|
|
930
|
+
if (bottomDirectionIndex !== -1) {
|
|
931
|
+
directions.splice(bottomDirectionIndex, 1);
|
|
932
|
+
}
|
|
1289
933
|
});
|
|
1290
|
-
|
|
1291
|
-
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
934
|
+
return directions.length ? directions : null;
|
|
1292
935
|
};
|
|
1293
|
-
const
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
let endLinePoint = x + width + lineLength;
|
|
1298
|
-
let startRectanglePointX = x + width + lineLength;
|
|
1299
|
-
let endRectanglePointX = x + lineLength + width + 30;
|
|
1300
|
-
let startRectanglePointY = y + height / 2 - 6;
|
|
1301
|
-
let endRectanglePointY = y + height / 2 - 6 + 12;
|
|
1302
|
-
if (detectResult === 'left') {
|
|
1303
|
-
startLinePoint = x - lineLength;
|
|
1304
|
-
endLinePoint = x;
|
|
1305
|
-
startRectanglePointX = x - lineLength - 30;
|
|
1306
|
-
endRectanglePointX = x - lineLength;
|
|
1307
|
-
}
|
|
1308
|
-
let fakeY = targetComponent.node.y;
|
|
1309
|
-
let fakeX = targetRect.x;
|
|
1310
|
-
const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
|
|
1311
|
-
const pointOptions = {
|
|
1312
|
-
fakeX,
|
|
1313
|
-
fakeY,
|
|
1314
|
-
x,
|
|
1315
|
-
y,
|
|
1316
|
-
width,
|
|
1317
|
-
height,
|
|
1318
|
-
strokeWidth
|
|
1319
|
-
};
|
|
1320
|
-
const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
|
|
1321
|
-
const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
|
|
1322
|
-
if (!isMixedLayout(parentLayout, layout)) {
|
|
1323
|
-
// 构造一条直线
|
|
1324
|
-
let linePoints = [
|
|
1325
|
-
[startLinePoint, y + height / 2],
|
|
1326
|
-
[endLinePoint, y + height / 2]
|
|
1327
|
-
];
|
|
1328
|
-
if (isIndentedLayout(parentLayout)) {
|
|
1329
|
-
const fakePoint = getIndentedFakePoint(parentLayout, pointOptions);
|
|
1330
|
-
drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
|
|
936
|
+
const detectDropTarget = (board, detectPoint, dropTarget, activeElements) => {
|
|
937
|
+
let detectResult = null;
|
|
938
|
+
depthFirstRecursion(board, element => {
|
|
939
|
+
if (!MindElement.isMindElement(board, element) || detectResult) {
|
|
1331
940
|
return;
|
|
1332
941
|
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
|
|
1347
|
-
if (detectResult === 'left') {
|
|
1348
|
-
let offsetX = 0;
|
|
1349
|
-
const isFirstNode = targetIndex === 0;
|
|
1350
|
-
if (isFirstNode) {
|
|
1351
|
-
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
1352
|
-
}
|
|
1353
|
-
else {
|
|
1354
|
-
const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex - 1]);
|
|
1355
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1356
|
-
const space = targetRect.x - (previousRect.x + previousRect.width);
|
|
1357
|
-
offsetX = space / 2;
|
|
1358
|
-
}
|
|
1359
|
-
fakeX = targetRect.x - offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
1360
|
-
}
|
|
1361
|
-
if (detectResult === 'right') {
|
|
1362
|
-
let offsetX = 0;
|
|
1363
|
-
const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
|
|
1364
|
-
if (isLastNode) {
|
|
1365
|
-
offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
|
|
1366
|
-
}
|
|
1367
|
-
else {
|
|
1368
|
-
const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
|
|
1369
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1370
|
-
const space = nextRect.x - (targetRect.x + targetRect.width);
|
|
1371
|
-
offsetX = space / 2;
|
|
1372
|
-
}
|
|
1373
|
-
fakeX = targetRect.x + width + offsetX - width / 2 - Math.ceil(strokeWidth / 2);
|
|
1374
|
-
}
|
|
1375
|
-
startRectanglePointX = fakeX;
|
|
1376
|
-
if (isTopLayout(parentLayout)) {
|
|
1377
|
-
// 因为矩形是从左上角为起点向下画的,所以需要向上偏移一个矩形的高度(-12)
|
|
1378
|
-
startRectanglePointY = fakeY + height + targetComponent.node.vGap - 12;
|
|
1379
|
-
}
|
|
1380
|
-
if (isBottomLayout(parentLayout)) {
|
|
1381
|
-
startRectanglePointY = fakeY + targetComponent.node.vGap;
|
|
1382
|
-
}
|
|
1383
|
-
endRectanglePointX = startRectanglePointX + 30;
|
|
1384
|
-
endRectanglePointY = startRectanglePointY + 12;
|
|
1385
|
-
const fakeNode = { ...targetComponent.node, x: fakeX, y: fakeY, width: 30 };
|
|
1386
|
-
const linkSVGG = drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false, false);
|
|
1387
|
-
fakeDropNodeG?.appendChild(linkSVGG);
|
|
1388
|
-
}
|
|
942
|
+
const node = MindElement.getNode(element);
|
|
943
|
+
const directions = directionDetector(node, detectPoint);
|
|
944
|
+
if (directions) {
|
|
945
|
+
detectResult = directionCorrector(board, node, directions);
|
|
946
|
+
}
|
|
947
|
+
dropTarget = null;
|
|
948
|
+
const isValid = activeElements.every(element => isValidTarget(element, node.origin));
|
|
949
|
+
if (detectResult && isValid) {
|
|
950
|
+
dropTarget = { target: node.origin, detectResult: detectResult[0] };
|
|
951
|
+
}
|
|
952
|
+
}, node => {
|
|
953
|
+
if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
|
|
954
|
+
return true;
|
|
1389
955
|
}
|
|
1390
956
|
else {
|
|
1391
|
-
|
|
1392
|
-
fakeDropNodeG?.appendChild(linkSVGG);
|
|
957
|
+
return false;
|
|
1393
958
|
}
|
|
1394
|
-
// 构造一个矩形框坐标
|
|
1395
|
-
let fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
1396
|
-
stroke: PRIMARY_COLOR,
|
|
1397
|
-
strokeWidth: 2,
|
|
1398
|
-
fill: PRIMARY_COLOR,
|
|
1399
|
-
fillStyle: 'solid'
|
|
1400
|
-
});
|
|
1401
|
-
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
1402
|
-
}
|
|
1403
|
-
else {
|
|
1404
|
-
// 混合布局画线逻辑
|
|
1405
|
-
if (isHorizontalLogicLayout(parentLayout)) {
|
|
1406
|
-
if (isIndentedLayout(layout)) {
|
|
1407
|
-
const fakePoint = getIndentedFakePoint(layout, pointOptions);
|
|
1408
|
-
drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
|
|
1409
|
-
return;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
};
|
|
1414
|
-
const getHorizontalFakeY = (detectResult, targetIndex, parentNode, targetRect, layout, fakeY) => {
|
|
1415
|
-
const childrenLength = getNonAbstractChildren(parentNode).length;
|
|
1416
|
-
if (detectResult === 'top') {
|
|
1417
|
-
if (targetIndex === 0 && isTopLayout(layout)) {
|
|
1418
|
-
fakeY = targetRect.y + targetRect.height;
|
|
1419
|
-
}
|
|
1420
|
-
if (targetIndex > 0) {
|
|
1421
|
-
const previousComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex - 1]);
|
|
1422
|
-
const previousRect = getRectangleByNode(previousComponent.node);
|
|
1423
|
-
const topY = previousRect.y + previousRect.height;
|
|
1424
|
-
fakeY = topY + (targetRect.y - topY) / 5;
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
if (detectResult === 'bottom') {
|
|
1428
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
1429
|
-
if (targetIndex < childrenLength - 1) {
|
|
1430
|
-
const nextComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex + 1]);
|
|
1431
|
-
const nextRect = getRectangleByNode(nextComponent.node);
|
|
1432
|
-
const topY = targetRect.y + targetRect.height;
|
|
1433
|
-
fakeY = topY + (nextRect.y - topY) / 5;
|
|
1434
|
-
}
|
|
1435
|
-
if (targetIndex === childrenLength - 1) {
|
|
1436
|
-
fakeY = targetRect.y + targetRect.height + 30;
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
return fakeY;
|
|
1440
|
-
};
|
|
1441
|
-
const getIndentedFakePoint = (layout, pointOptions) => {
|
|
1442
|
-
let { fakeX, fakeY, x, y, width, height, strokeWidth } = pointOptions;
|
|
1443
|
-
const hGap = BASE * 4;
|
|
1444
|
-
const vGap = BASE * 6;
|
|
1445
|
-
const offsetX = hGap + width / 2 + strokeWidth;
|
|
1446
|
-
const offsetY = vGap + height / 2 + strokeWidth;
|
|
1447
|
-
if (isLeftLayout(layout)) {
|
|
1448
|
-
fakeX = x - offsetX;
|
|
1449
|
-
}
|
|
1450
|
-
if (isRightLayout(layout)) {
|
|
1451
|
-
fakeX = x + offsetX;
|
|
1452
|
-
}
|
|
1453
|
-
if (isTopLayout(layout)) {
|
|
1454
|
-
fakeY = y - offsetY;
|
|
1455
|
-
}
|
|
1456
|
-
if (isBottomLayout(layout)) {
|
|
1457
|
-
fakeY = y + height + offsetY;
|
|
1458
|
-
}
|
|
1459
|
-
return { fakeX, fakeY };
|
|
1460
|
-
};
|
|
1461
|
-
const drawIndentNodeG = (board, fakeDropNodeG, fakePoint, node) => {
|
|
1462
|
-
const { fakeX, fakeY } = fakePoint;
|
|
1463
|
-
const fakeNode = { ...node, x: fakeX, y: fakeY, width: 30, height: 12 };
|
|
1464
|
-
const linkSVGG = drawIndentedLink(board, node, fakeNode, PRIMARY_COLOR, false);
|
|
1465
|
-
const startRectanglePointX = fakeX, startRectanglePointY = fakeY, endRectanglePointX = fakeX + 30, endRectanglePointY = fakeY + 12;
|
|
1466
|
-
const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
|
|
1467
|
-
stroke: PRIMARY_COLOR,
|
|
1468
|
-
strokeWidth: 2,
|
|
1469
|
-
fill: PRIMARY_COLOR,
|
|
1470
|
-
fillStyle: 'solid'
|
|
1471
959
|
});
|
|
1472
|
-
|
|
1473
|
-
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
960
|
+
return dropTarget;
|
|
1474
961
|
};
|
|
1475
|
-
|
|
1476
|
-
/**
|
|
1477
|
-
*
|
|
1478
|
-
* @param targetNode
|
|
1479
|
-
* @param centerPoint
|
|
1480
|
-
* @returns DetectResult[] | null
|
|
1481
|
-
*/
|
|
1482
962
|
const directionDetector = (targetNode, centerPoint) => {
|
|
1483
963
|
const { x, y, width, height } = getRectangleByNode(targetNode);
|
|
1484
964
|
const yCenter = y + height / 2;
|
|
@@ -1527,59 +1007,6 @@ const directionDetector = (targetNode, centerPoint) => {
|
|
|
1527
1007
|
}
|
|
1528
1008
|
return null;
|
|
1529
1009
|
};
|
|
1530
|
-
|
|
1531
|
-
const directionCorrector = (board, node, detectResults) => {
|
|
1532
|
-
if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
|
|
1533
|
-
const parentLayout = MindQueries.getCorrectLayoutByElement(board, node?.parent.origin);
|
|
1534
|
-
if (isStandardLayout(parentLayout)) {
|
|
1535
|
-
const idx = node.parent.children.findIndex(x => x === node);
|
|
1536
|
-
const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
|
|
1537
|
-
return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
|
|
1538
|
-
}
|
|
1539
|
-
if (isLeftLayout(parentLayout)) {
|
|
1540
|
-
return getAllowedDirection(detectResults, ['right']);
|
|
1541
|
-
}
|
|
1542
|
-
if (isRightLayout(parentLayout)) {
|
|
1543
|
-
return getAllowedDirection(detectResults, ['left']);
|
|
1544
|
-
}
|
|
1545
|
-
if (parentLayout === MindLayoutType.upward) {
|
|
1546
|
-
return getAllowedDirection(detectResults, ['bottom']);
|
|
1547
|
-
}
|
|
1548
|
-
if (parentLayout === MindLayoutType.downward) {
|
|
1549
|
-
return getAllowedDirection(detectResults, ['top']);
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
else {
|
|
1553
|
-
const layout = MindQueries.getCorrectLayoutByElement(board, node?.origin);
|
|
1554
|
-
if (isStandardLayout(layout)) {
|
|
1555
|
-
return getAllowedDirection(detectResults, ['top', 'bottom']);
|
|
1556
|
-
}
|
|
1557
|
-
if (isTopLayout(layout)) {
|
|
1558
|
-
return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
|
|
1559
|
-
}
|
|
1560
|
-
if (isBottomLayout(layout)) {
|
|
1561
|
-
return getAllowedDirection(detectResults, ['left', 'right', 'top']);
|
|
1562
|
-
}
|
|
1563
|
-
if (layout === MindLayoutType.left) {
|
|
1564
|
-
return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
|
|
1565
|
-
}
|
|
1566
|
-
if (layout === MindLayoutType.right) {
|
|
1567
|
-
return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
return null;
|
|
1571
|
-
};
|
|
1572
|
-
const getAllowedDirection = (detectResults, illegalDirections) => {
|
|
1573
|
-
const directions = detectResults;
|
|
1574
|
-
illegalDirections.forEach(item => {
|
|
1575
|
-
const bottomDirectionIndex = directions.findIndex(direction => direction === item);
|
|
1576
|
-
if (bottomDirectionIndex !== -1) {
|
|
1577
|
-
directions.splice(bottomDirectionIndex, 1);
|
|
1578
|
-
}
|
|
1579
|
-
});
|
|
1580
|
-
return directions.length ? directions : null;
|
|
1581
|
-
};
|
|
1582
|
-
|
|
1583
1010
|
/* 根据布局调整 target 以及 direction */
|
|
1584
1011
|
const readjustmentDropTarget = (board, dropTarget) => {
|
|
1585
1012
|
const { target, detectResult } = dropTarget;
|
|
@@ -1662,276 +1089,126 @@ const readjustmentDropTarget = (board, dropTarget) => {
|
|
|
1662
1089
|
}
|
|
1663
1090
|
return dropTarget;
|
|
1664
1091
|
};
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1092
|
+
const isValidTarget = (origin, target) => {
|
|
1093
|
+
return origin !== target && !isChildElement(origin, target);
|
|
1094
|
+
};
|
|
1095
|
+
const getPathByDropTarget = (board, dropTarget) => {
|
|
1096
|
+
let targetPath = PlaitBoard.findPath(board, dropTarget?.target);
|
|
1097
|
+
const layout = PlaitMind.isMind(dropTarget?.target)
|
|
1098
|
+
? getRootLayout(dropTarget?.target)
|
|
1099
|
+
: MindQueries.getCorrectLayoutByElement(board, MindElement.getParent(dropTarget?.target));
|
|
1100
|
+
const children = getNonAbstractChildren(dropTarget.target);
|
|
1101
|
+
// 上下布局:左右是兄弟节点,上下是子节点
|
|
1102
|
+
if (isVerticalLogicLayout(layout)) {
|
|
1103
|
+
if (dropTarget.detectResult === 'top' || dropTarget.detectResult === 'bottom') {
|
|
1104
|
+
targetPath.push(children.length);
|
|
1674
1105
|
}
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
height: location - abstractRectangle.y
|
|
1679
|
-
};
|
|
1106
|
+
// 如果是左,位置不变,右则插入到下一个兄弟节点
|
|
1107
|
+
if (dropTarget.detectResult === 'right') {
|
|
1108
|
+
targetPath = Path.next(targetPath);
|
|
1680
1109
|
}
|
|
1681
1110
|
}
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
x: location,
|
|
1687
|
-
width: abstractRectangle.width + abstractRectangle.x - location
|
|
1688
|
-
};
|
|
1111
|
+
// 水平布局/标准布局:上下是兄弟节点,左右是子节点
|
|
1112
|
+
if (isHorizontalLogicLayout(layout)) {
|
|
1113
|
+
if (dropTarget.detectResult === 'right' || dropTarget.detectResult === 'left') {
|
|
1114
|
+
targetPath.push(children.length);
|
|
1689
1115
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
width: location - abstractRectangle.x
|
|
1694
|
-
};
|
|
1116
|
+
// 如果是上,位置不变,下插入到下一个兄弟节点
|
|
1117
|
+
if (dropTarget.detectResult === 'bottom') {
|
|
1118
|
+
targetPath = Path.next(targetPath);
|
|
1695
1119
|
}
|
|
1696
1120
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
const startNode = parentChildren[start];
|
|
1702
|
-
const endNode = parentChildren[end];
|
|
1703
|
-
if (handlePosition === AbstractHandlePosition.start) {
|
|
1704
|
-
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
|
|
1705
|
-
let minNode;
|
|
1706
|
-
if (abstractNode.length) {
|
|
1707
|
-
const index = abstractNode
|
|
1708
|
-
.map(node => {
|
|
1709
|
-
const { end } = getCorrectStartEnd(node, parent);
|
|
1710
|
-
return end;
|
|
1711
|
-
})
|
|
1712
|
-
.sort((a, b) => b - a)[0];
|
|
1713
|
-
minNode = parentChildren[index + 1];
|
|
1121
|
+
// 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
|
|
1122
|
+
if (isIndentedLayout(layout)) {
|
|
1123
|
+
if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
|
|
1124
|
+
targetPath = Path.next(targetPath);
|
|
1714
1125
|
}
|
|
1715
|
-
|
|
1716
|
-
|
|
1126
|
+
if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
|
|
1127
|
+
targetPath = Path.next(targetPath);
|
|
1717
1128
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
if (isHorizontal) {
|
|
1721
|
-
return {
|
|
1722
|
-
max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1723
|
-
min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1724
|
-
};
|
|
1129
|
+
if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
|
|
1130
|
+
targetPath.push(children.length);
|
|
1725
1131
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1729
|
-
min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1730
|
-
};
|
|
1132
|
+
if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
|
|
1133
|
+
targetPath.push(children.length);
|
|
1731
1134
|
}
|
|
1732
1135
|
}
|
|
1136
|
+
return targetPath;
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
function drawRoundRectangleByNode(board, node) {
|
|
1140
|
+
const rectangle = getRectangleByNode(node);
|
|
1141
|
+
return drawRoundRectangleByElement(board, rectangle, node.origin);
|
|
1142
|
+
}
|
|
1143
|
+
function drawRoundRectangleByElement(board, nodeRectangle, element) {
|
|
1144
|
+
const fill = element.fill ? element.fill : element.isRoot ? DefaultRootStyle.fill : DefaultNodeStyle.fill;
|
|
1145
|
+
const stroke = getStrokeByMindElement(board, element);
|
|
1146
|
+
const strokeWidth = element.strokeWidth ? element.strokeWidth : DefaultNodeStyle.strokeWidth;
|
|
1147
|
+
const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), nodeRectangle.x, nodeRectangle.y, nodeRectangle.x + nodeRectangle.width, nodeRectangle.y + nodeRectangle.height, {
|
|
1148
|
+
stroke,
|
|
1149
|
+
strokeWidth,
|
|
1150
|
+
fill,
|
|
1151
|
+
fillStyle: 'solid'
|
|
1152
|
+
});
|
|
1153
|
+
return nodeG;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
var HorizontalPlacement;
|
|
1157
|
+
(function (HorizontalPlacement) {
|
|
1158
|
+
HorizontalPlacement["left"] = "left";
|
|
1159
|
+
HorizontalPlacement["center"] = "center";
|
|
1160
|
+
HorizontalPlacement["right"] = "right";
|
|
1161
|
+
})(HorizontalPlacement || (HorizontalPlacement = {}));
|
|
1162
|
+
var VerticalPlacement;
|
|
1163
|
+
(function (VerticalPlacement) {
|
|
1164
|
+
VerticalPlacement["top"] = "top";
|
|
1165
|
+
VerticalPlacement["middle"] = "middle";
|
|
1166
|
+
VerticalPlacement["bottom"] = "bottom";
|
|
1167
|
+
})(VerticalPlacement || (VerticalPlacement = {}));
|
|
1168
|
+
|
|
1169
|
+
const getPointByPlacement = (client, placement) => {
|
|
1170
|
+
let x = client.x;
|
|
1171
|
+
let y = client.y;
|
|
1172
|
+
if (placement[0] === HorizontalPlacement.center) {
|
|
1173
|
+
x = client.x + client.width / 2;
|
|
1174
|
+
}
|
|
1175
|
+
if (placement[0] === HorizontalPlacement.right) {
|
|
1176
|
+
x = client.x + client.width;
|
|
1177
|
+
}
|
|
1178
|
+
if (placement[1] === VerticalPlacement.middle) {
|
|
1179
|
+
y = client.y + client.height / 2;
|
|
1180
|
+
}
|
|
1181
|
+
if (placement[1] === VerticalPlacement.bottom) {
|
|
1182
|
+
y = client.y + client.height;
|
|
1183
|
+
}
|
|
1184
|
+
return [x, y];
|
|
1185
|
+
};
|
|
1186
|
+
const getXDistanceBetweenPoint = (point1, point2, isHorizontalLayout) => {
|
|
1187
|
+
if (isHorizontalLayout) {
|
|
1188
|
+
return Math.abs(point1[0] - point2[0]);
|
|
1189
|
+
}
|
|
1733
1190
|
else {
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1191
|
+
return Math.abs(point1[1] - point2[1]);
|
|
1192
|
+
}
|
|
1193
|
+
};
|
|
1194
|
+
const getYDistanceBetweenPoint = (point1, point2, isHorizontalLayout) => {
|
|
1195
|
+
getXDistanceBetweenPoint(point1, point2, !isHorizontalLayout);
|
|
1196
|
+
};
|
|
1197
|
+
const getLayoutDirection = (node, isHorizontal) => {
|
|
1198
|
+
if (isHorizontal) {
|
|
1199
|
+
if (node.left) {
|
|
1200
|
+
return LayoutDirection.left;
|
|
1744
1201
|
}
|
|
1745
1202
|
else {
|
|
1746
|
-
|
|
1747
|
-
maxNode = parentChildren[children.length - 1];
|
|
1203
|
+
return LayoutDirection.right;
|
|
1748
1204
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
if (
|
|
1752
|
-
return
|
|
1753
|
-
max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1754
|
-
min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1755
|
-
};
|
|
1205
|
+
}
|
|
1206
|
+
else {
|
|
1207
|
+
if (node.up) {
|
|
1208
|
+
return LayoutDirection.top;
|
|
1756
1209
|
}
|
|
1757
1210
|
else {
|
|
1758
|
-
return
|
|
1759
|
-
max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1760
|
-
min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1761
|
-
};
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
};
|
|
1765
|
-
const getHitAbstractHandle = (board, element, point) => {
|
|
1766
|
-
const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
|
|
1767
|
-
const isHorizontal = isHorizontalLayout(nodeLayout);
|
|
1768
|
-
const parentElement = MindElement.getParent(element);
|
|
1769
|
-
const includedElements = parentElement.children.slice(element.start, element.end + 1);
|
|
1770
|
-
let abstractRectangle = getRectangleByElements(board, includedElements, true);
|
|
1771
|
-
abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
|
|
1772
|
-
const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
|
|
1773
|
-
const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
|
|
1774
|
-
const pointRec = RectangleClient.toRectangleClient([point, point]);
|
|
1775
|
-
if (RectangleClient.isHit(pointRec, startHandleRec))
|
|
1776
|
-
return AbstractHandlePosition.start;
|
|
1777
|
-
if (RectangleClient.isHit(pointRec, endHandleRec))
|
|
1778
|
-
return AbstractHandlePosition.end;
|
|
1779
|
-
return undefined;
|
|
1780
|
-
};
|
|
1781
|
-
const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
|
|
1782
|
-
let result;
|
|
1783
|
-
if (position === AbstractHandlePosition.start) {
|
|
1784
|
-
const location = isHorizontal ? rectangle.y : rectangle.x;
|
|
1785
|
-
result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
|
|
1786
|
-
result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1787
|
-
}
|
|
1788
|
-
else {
|
|
1789
|
-
const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
|
|
1790
|
-
result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
|
|
1791
|
-
result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1792
|
-
}
|
|
1793
|
-
return result;
|
|
1794
|
-
};
|
|
1795
|
-
function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
|
|
1796
|
-
const children = parentChildren.filter(child => {
|
|
1797
|
-
return !AbstractNode.isAbstract(child);
|
|
1798
|
-
});
|
|
1799
|
-
const recArray = children.map(child => {
|
|
1800
|
-
return getRectangleByElements(board, [child], false);
|
|
1801
|
-
});
|
|
1802
|
-
const firstRec = getRectangleByElements(board, [children[0]], true);
|
|
1803
|
-
const fakeLeftRec = {
|
|
1804
|
-
x: firstRec.x - firstRec.width,
|
|
1805
|
-
y: firstRec.y - firstRec.height,
|
|
1806
|
-
width: firstRec.width,
|
|
1807
|
-
height: firstRec.height
|
|
1808
|
-
};
|
|
1809
|
-
const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
|
|
1810
|
-
const fakeRightRec = {
|
|
1811
|
-
x: lastRec.x + lastRec.width,
|
|
1812
|
-
y: lastRec.y + lastRec.height,
|
|
1813
|
-
width: lastRec.width,
|
|
1814
|
-
height: lastRec.height
|
|
1815
|
-
};
|
|
1816
|
-
recArray.push(fakeRightRec);
|
|
1817
|
-
recArray.unshift(fakeLeftRec);
|
|
1818
|
-
for (let i = 0; i < recArray.length - 1; i++) {
|
|
1819
|
-
const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
|
|
1820
|
-
const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
|
|
1821
|
-
if (location >= recXOrY + recWidthOrHeight / 2 &&
|
|
1822
|
-
location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
|
|
1823
|
-
return i - 1;
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
return 0;
|
|
1827
|
-
}
|
|
1828
|
-
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1829
|
-
let touchedHandle;
|
|
1830
|
-
const abstract = getSelectedElements(board)
|
|
1831
|
-
.filter(element => AbstractNode.isAbstract(element))
|
|
1832
|
-
.find(element => {
|
|
1833
|
-
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1834
|
-
return touchedHandle;
|
|
1835
|
-
});
|
|
1836
|
-
if (touchedAbstract === abstract) {
|
|
1837
|
-
return touchedAbstract;
|
|
1838
|
-
}
|
|
1839
|
-
if (touchedAbstract) {
|
|
1840
|
-
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1841
|
-
component.updateAbstractIncludedOutline();
|
|
1842
|
-
touchedAbstract = undefined;
|
|
1843
|
-
}
|
|
1844
|
-
if (abstract) {
|
|
1845
|
-
touchedAbstract = abstract;
|
|
1846
|
-
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1847
|
-
component.updateAbstractIncludedOutline(touchedHandle);
|
|
1848
|
-
}
|
|
1849
|
-
return touchedAbstract;
|
|
1850
|
-
}
|
|
1851
|
-
|
|
1852
|
-
function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true) {
|
|
1853
|
-
const branchWidth = getBranchWidthByMindElement(board, child.origin);
|
|
1854
|
-
const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
|
|
1855
|
-
const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
|
|
1856
|
-
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
1857
|
-
const beginRectangle = getRectangleByNode(beginNode);
|
|
1858
|
-
const endRectangle = getRectangleByNode(endNode);
|
|
1859
|
-
beginX = beginNode.x + beginNode.width / 2;
|
|
1860
|
-
beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
|
|
1861
|
-
endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
|
|
1862
|
-
endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
|
|
1863
|
-
//根据位置,设置正负参数
|
|
1864
|
-
let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
|
|
1865
|
-
const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
|
|
1866
|
-
if (beginNode.origin.isRoot) {
|
|
1867
|
-
if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
|
|
1868
|
-
beginY += branchWidth;
|
|
1869
|
-
}
|
|
1870
|
-
if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
|
|
1871
|
-
beginY -= branchWidth;
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
let curve = [
|
|
1875
|
-
[beginX, beginY],
|
|
1876
|
-
[beginX, beginY],
|
|
1877
|
-
[beginX, beginY],
|
|
1878
|
-
[beginX, endY - (endNode.hGap * 3 * plusMinus[1]) / 5],
|
|
1879
|
-
[beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
|
|
1880
|
-
[beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
|
|
1881
|
-
[beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
|
|
1882
|
-
isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
|
|
1883
|
-
isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
|
|
1884
|
-
isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
|
|
1885
|
-
];
|
|
1886
|
-
const points = pointsOnBezierCurves(curve);
|
|
1887
|
-
return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
var HorizontalPlacement;
|
|
1891
|
-
(function (HorizontalPlacement) {
|
|
1892
|
-
HorizontalPlacement["left"] = "left";
|
|
1893
|
-
HorizontalPlacement["center"] = "center";
|
|
1894
|
-
HorizontalPlacement["right"] = "right";
|
|
1895
|
-
})(HorizontalPlacement || (HorizontalPlacement = {}));
|
|
1896
|
-
var VerticalPlacement;
|
|
1897
|
-
(function (VerticalPlacement) {
|
|
1898
|
-
VerticalPlacement["top"] = "top";
|
|
1899
|
-
VerticalPlacement["middle"] = "middle";
|
|
1900
|
-
VerticalPlacement["bottom"] = "bottom";
|
|
1901
|
-
})(VerticalPlacement || (VerticalPlacement = {}));
|
|
1902
|
-
|
|
1903
|
-
const getPointByPlacement = (client, placement) => {
|
|
1904
|
-
let x = client.x;
|
|
1905
|
-
let y = client.y;
|
|
1906
|
-
if (placement[0] === HorizontalPlacement.center) {
|
|
1907
|
-
x = client.x + client.width / 2;
|
|
1908
|
-
}
|
|
1909
|
-
if (placement[0] === HorizontalPlacement.right) {
|
|
1910
|
-
x = client.x + client.width;
|
|
1911
|
-
}
|
|
1912
|
-
if (placement[1] === VerticalPlacement.middle) {
|
|
1913
|
-
y = client.y + client.height / 2;
|
|
1914
|
-
}
|
|
1915
|
-
if (placement[1] === VerticalPlacement.bottom) {
|
|
1916
|
-
y = client.y + client.height;
|
|
1917
|
-
}
|
|
1918
|
-
return [x, y];
|
|
1919
|
-
};
|
|
1920
|
-
const getLayoutDirection = (node, isHorizontal) => {
|
|
1921
|
-
if (isHorizontal) {
|
|
1922
|
-
if (node.left) {
|
|
1923
|
-
return LayoutDirection.left;
|
|
1924
|
-
}
|
|
1925
|
-
else {
|
|
1926
|
-
return LayoutDirection.right;
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
else {
|
|
1930
|
-
if (node.up) {
|
|
1931
|
-
return LayoutDirection.top;
|
|
1932
|
-
}
|
|
1933
|
-
else {
|
|
1934
|
-
return LayoutDirection.bottom;
|
|
1211
|
+
return LayoutDirection.bottom;
|
|
1935
1212
|
}
|
|
1936
1213
|
}
|
|
1937
1214
|
};
|
|
@@ -1945,7 +1222,7 @@ const getLayoutDirection = (node, isHorizontal) => {
|
|
|
1945
1222
|
// 下 -> 上:
|
|
1946
1223
|
// 1. 终点 -> 起点/终点 -> 起点
|
|
1947
1224
|
// 2. 加 -> 减
|
|
1948
|
-
const
|
|
1225
|
+
const moveXOfPoint = (point, distance, direction = LayoutDirection.right) => {
|
|
1949
1226
|
if (direction === LayoutDirection.left) {
|
|
1950
1227
|
return [point[0] - distance, point[1]];
|
|
1951
1228
|
}
|
|
@@ -1957,6 +1234,15 @@ const movePoint = (point, distance, direction = LayoutDirection.right) => {
|
|
|
1957
1234
|
}
|
|
1958
1235
|
return [point[0] + distance, point[1]];
|
|
1959
1236
|
};
|
|
1237
|
+
const moveYOfPoint = (point, distance, direction = LayoutDirection.right) => {
|
|
1238
|
+
if (direction === LayoutDirection.bottom) {
|
|
1239
|
+
return [point[0] + distance, point[1]];
|
|
1240
|
+
}
|
|
1241
|
+
if (direction === LayoutDirection.top) {
|
|
1242
|
+
return [point[0] + distance, point[1]];
|
|
1243
|
+
}
|
|
1244
|
+
return [point[0], point[1] + distance];
|
|
1245
|
+
};
|
|
1960
1246
|
const transformPlacement = (placement, direction) => {
|
|
1961
1247
|
// to left
|
|
1962
1248
|
if (direction === LayoutDirection.left) {
|
|
@@ -1997,9 +1283,9 @@ const transformPlacement = (placement, direction) => {
|
|
|
1997
1283
|
}
|
|
1998
1284
|
};
|
|
1999
1285
|
|
|
2000
|
-
function drawLogicLink(board, node, parent, isHorizontal) {
|
|
2001
|
-
const branchColor = getBranchColorByMindElement(board, node.origin);
|
|
2002
|
-
const branchWidth = getBranchWidthByMindElement(board, node.origin);
|
|
1286
|
+
function drawLogicLink(board, node, parent, isHorizontal, defaultStroke = null, defaultStrokeWidth) {
|
|
1287
|
+
const branchColor = defaultStroke || getBranchColorByMindElement(board, node.origin);
|
|
1288
|
+
const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, node.origin);
|
|
2003
1289
|
const hasStraightLine = !parent.origin.isRoot;
|
|
2004
1290
|
const parentShape = getShapeByElement(board, parent.origin);
|
|
2005
1291
|
const shape = node.origin.shape ? node.origin.shape : parentShape;
|
|
@@ -2026,158 +1312,589 @@ function drawLogicLink(board, node, parent, isHorizontal) {
|
|
|
2026
1312
|
// ② 确定凸出直线,从起始点开始画一条直线,从直线的结束位置绘制曲线,保证收起图标可以完美覆盖起始连线,根节点不需要这条直线
|
|
2027
1313
|
// 绘制贝塞尔曲线要求,需要增加三个点,正常两个点就可以确定这条直线
|
|
2028
1314
|
const straightLineDistance = 8;
|
|
2029
|
-
const beginPoint2 = hasStraightLine ?
|
|
1315
|
+
const beginPoint2 = hasStraightLine ? moveXOfPoint(beginPoint, straightLineDistance, linkDirection) : beginPoint;
|
|
2030
1316
|
let straightLine = hasStraightLine ? [beginPoint, beginPoint2, beginPoint2] : [];
|
|
2031
1317
|
// ③ 确定曲线
|
|
2032
1318
|
const beginBufferDistance = (parent.hGap + node.hGap) / 3;
|
|
2033
1319
|
const endBufferDistance = -(parent.hGap + node.hGap) / 2.4;
|
|
2034
1320
|
let curve = [
|
|
2035
1321
|
beginPoint2,
|
|
2036
|
-
|
|
2037
|
-
|
|
1322
|
+
moveXOfPoint(beginPoint2, beginBufferDistance, linkDirection),
|
|
1323
|
+
moveXOfPoint(endPoint, endBufferDistance, linkDirection),
|
|
2038
1324
|
endPoint
|
|
2039
1325
|
];
|
|
2040
1326
|
// ④ 下划线绘制,underline shape and horizontal
|
|
2041
|
-
const underlineEnd =
|
|
1327
|
+
const underlineEnd = moveXOfPoint(endPoint, nodeClient.width, linkDirection);
|
|
2042
1328
|
const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
|
|
2043
1329
|
const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
|
|
2044
1330
|
return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
|
|
2045
1331
|
}
|
|
2046
1332
|
|
|
2047
|
-
|
|
2048
|
-
const
|
|
2049
|
-
|
|
2050
|
-
const
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
1333
|
+
const drawFakeDragNode = (board, activeComponent, offsetX, offsetY) => {
|
|
1334
|
+
const dragFakeNodeG = createG();
|
|
1335
|
+
dragFakeNodeG.classList.add('dragging', 'fake-node', 'plait-board-attached');
|
|
1336
|
+
const fakeDraggingNode = {
|
|
1337
|
+
...activeComponent.node,
|
|
1338
|
+
children: [],
|
|
1339
|
+
x: activeComponent.node.x + offsetX,
|
|
1340
|
+
y: activeComponent.node.y + offsetY
|
|
2054
1341
|
};
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
1342
|
+
const textRectangle = getTopicRectangleByNode(board, activeComponent.node);
|
|
1343
|
+
const fakeNodeG = drawRoundRectangleByNode(board, fakeDraggingNode);
|
|
1344
|
+
const richtextG = activeComponent.richtextG?.cloneNode(true);
|
|
1345
|
+
updateForeignObject(richtextG, textRectangle.width + BASE * 10, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
|
|
1346
|
+
dragFakeNodeG?.append(fakeNodeG);
|
|
1347
|
+
dragFakeNodeG?.append(richtextG);
|
|
1348
|
+
return dragFakeNodeG;
|
|
1349
|
+
};
|
|
1350
|
+
const drawFakeDropNodeByPath = (board, target, path) => {
|
|
1351
|
+
const fakeDropNodeG = createG();
|
|
1352
|
+
const parent = PlaitNode.get(board, Path.parent(path));
|
|
1353
|
+
const layout = MindQueries.getLayoutByElement(parent);
|
|
1354
|
+
const isHorizontal = isHorizontalLayout(layout);
|
|
1355
|
+
const { hasNextNode, hasPreviousNode } = getPreviousAndNextByPath(parent, target, path);
|
|
1356
|
+
const width = 30;
|
|
1357
|
+
const height = 12;
|
|
1358
|
+
let fakeNode, centerPoint, basicNode, linkDirection;
|
|
1359
|
+
if (!hasPreviousNode && !hasNextNode) {
|
|
1360
|
+
const parentNode = MindElement.getNode(parent);
|
|
1361
|
+
const parentRect = getRectangleByNode(parentNode);
|
|
1362
|
+
linkDirection = getLayoutDirection(parentNode, isHorizontal);
|
|
1363
|
+
basicNode = parentNode;
|
|
1364
|
+
const placement = [HorizontalPlacement.right, VerticalPlacement.middle];
|
|
1365
|
+
transformPlacement(placement, linkDirection);
|
|
1366
|
+
const parentCenterPoint = getPointByPlacement(parentRect, placement);
|
|
1367
|
+
if (isIndentedLayout(layout)) {
|
|
1368
|
+
const placement = [
|
|
1369
|
+
HorizontalPlacement.center,
|
|
1370
|
+
isTopLayout(layout) ? VerticalPlacement.top : VerticalPlacement.bottom
|
|
1371
|
+
];
|
|
1372
|
+
const parentCenterPoint = getPointByPlacement(parentRect, placement);
|
|
1373
|
+
centerPoint = moveXOfPoint(parentCenterPoint, height, linkDirection);
|
|
1374
|
+
centerPoint[1] = isTopLayout(layout) ? centerPoint[1] - height : centerPoint[1] + height;
|
|
1375
|
+
}
|
|
1376
|
+
else {
|
|
1377
|
+
centerPoint = moveXOfPoint(parentCenterPoint, width, linkDirection);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
else if (!hasPreviousNode && hasNextNode) {
|
|
1381
|
+
const nextElement = PlaitNode.get(board, path);
|
|
1382
|
+
basicNode = MindElement.getNode(nextElement);
|
|
1383
|
+
const nextRect = getRectangleByNode(basicNode);
|
|
1384
|
+
linkDirection = getLayoutDirection(basicNode, isHorizontal);
|
|
1385
|
+
const placement = [HorizontalPlacement.left, VerticalPlacement.top];
|
|
1386
|
+
transformPlacement(placement, linkDirection);
|
|
1387
|
+
let offset = -height;
|
|
1388
|
+
if (MindElement.isIndentedLayout(parent)) {
|
|
1389
|
+
offset = isTopLayout(layout) ? offset / 2 + basicNode.height - basicNode.vGap : 0;
|
|
1390
|
+
}
|
|
1391
|
+
centerPoint = getPointByPlacement(nextRect, placement);
|
|
1392
|
+
centerPoint = moveYOfPoint(centerPoint, offset, linkDirection);
|
|
1393
|
+
}
|
|
1394
|
+
else if (hasPreviousNode && !hasNextNode) {
|
|
1395
|
+
const previousElement = PlaitNode.get(board, Path.previous(path));
|
|
1396
|
+
basicNode = MindElement.getNode(previousElement);
|
|
1397
|
+
const previousRect = getRectangleByNode(basicNode);
|
|
1398
|
+
linkDirection = getLayoutDirection(basicNode, isHorizontal);
|
|
1399
|
+
const placement = [HorizontalPlacement.left, VerticalPlacement.bottom];
|
|
1400
|
+
transformPlacement(placement, linkDirection);
|
|
1401
|
+
let offset = height;
|
|
1402
|
+
if (MindElement.isIndentedLayout(parent)) {
|
|
1403
|
+
offset = isTopLayout(layout) ? -offset - (basicNode.height - basicNode.vGap) : offset;
|
|
1404
|
+
}
|
|
1405
|
+
centerPoint = getPointByPlacement(previousRect, placement);
|
|
1406
|
+
centerPoint = moveYOfPoint(centerPoint, offset, linkDirection);
|
|
2059
1407
|
}
|
|
2060
1408
|
else {
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
1409
|
+
const previousElement = PlaitNode.get(board, Path.previous(path));
|
|
1410
|
+
basicNode = MindElement.getNode(previousElement);
|
|
1411
|
+
const previousRect = getRectangleByNode(basicNode);
|
|
1412
|
+
const nextElement = PlaitNode.get(board, path);
|
|
1413
|
+
const nextNode = MindElement.getNode(nextElement);
|
|
1414
|
+
const nextRect = getRectangleByNode(nextNode);
|
|
1415
|
+
const beginPlacement = [HorizontalPlacement.left, VerticalPlacement.bottom];
|
|
1416
|
+
const endPlacement = [HorizontalPlacement.left, VerticalPlacement.top];
|
|
1417
|
+
linkDirection = getLayoutDirection(basicNode, isHorizontal);
|
|
1418
|
+
transformPlacement(beginPlacement, linkDirection);
|
|
1419
|
+
transformPlacement(endPlacement, linkDirection);
|
|
1420
|
+
const previousPoint = getPointByPlacement(previousRect, beginPlacement);
|
|
1421
|
+
const nextPoint = getPointByPlacement(nextRect, endPlacement);
|
|
1422
|
+
centerPoint = [(previousPoint[0] + nextPoint[0]) / 2, (previousPoint[1] + nextPoint[1]) / 2];
|
|
1423
|
+
}
|
|
1424
|
+
let cornerPoint = centerPoint, oppositePoint = centerPoint;
|
|
1425
|
+
const offsetY = isHorizontal ? height : width;
|
|
1426
|
+
const offsetX = isHorizontal ? width : height;
|
|
1427
|
+
cornerPoint = moveYOfPoint(cornerPoint, -offsetY / 2, linkDirection);
|
|
1428
|
+
oppositePoint = moveYOfPoint(oppositePoint, offsetY / 2, linkDirection);
|
|
1429
|
+
oppositePoint = moveXOfPoint(oppositePoint, offsetX, linkDirection);
|
|
1430
|
+
const x = Math.min(cornerPoint[0], oppositePoint[0]);
|
|
1431
|
+
const y = Math.min(cornerPoint[1], oppositePoint[1]);
|
|
1432
|
+
fakeNode = {
|
|
1433
|
+
...basicNode,
|
|
2069
1434
|
x,
|
|
2070
1435
|
y,
|
|
2071
1436
|
width,
|
|
2072
|
-
height
|
|
1437
|
+
height,
|
|
1438
|
+
hGap: MindElement.isIndentedLayout(parent) ? BASE * 4 + (basicNode.origin.strokeWidth || STROKE_WIDTH) : 0,
|
|
1439
|
+
vGap: MindElement.isIndentedLayout(parent) ? BASE : 0
|
|
2073
1440
|
};
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
1441
|
+
const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), fakeNode.x, fakeNode.y, fakeNode.x + width, fakeNode.y + height, {
|
|
1442
|
+
stroke: PRIMARY_COLOR,
|
|
1443
|
+
strokeWidth: 2,
|
|
1444
|
+
fill: PRIMARY_COLOR,
|
|
1445
|
+
fillStyle: 'solid'
|
|
1446
|
+
});
|
|
1447
|
+
const link = MindElement.isIndentedLayout(parent)
|
|
1448
|
+
? drawIndentedLink(board, MindElement.getNode(parent), fakeNode, PRIMARY_COLOR, false, STROKE_WIDTH)
|
|
1449
|
+
: drawLogicLink(board, fakeNode, MindElement.getNode(parent), isHorizontal, PRIMARY_COLOR, STROKE_WIDTH);
|
|
1450
|
+
fakeDropNodeG?.appendChild(link);
|
|
1451
|
+
fakeDropNodeG?.appendChild(fakeRectangleG);
|
|
1452
|
+
return fakeDropNodeG;
|
|
1453
|
+
};
|
|
1454
|
+
const getPreviousAndNextByPath = (parent, target, path) => {
|
|
1455
|
+
const children = getNonAbstractChildren(parent);
|
|
1456
|
+
let hasPreviousNode = path[path.length - 1] !== 0;
|
|
1457
|
+
let hasNextNode = path[path.length - 1] !== (children?.length || 0);
|
|
1458
|
+
if (PlaitMind.isMind(parent) && isStandardLayout(getRootLayout(parent))) {
|
|
1459
|
+
const dropStandardRightBottom = target === parent.children[parent.rightNodeCount - 1] && path[path.length - 1] === parent.rightNodeCount;
|
|
1460
|
+
const dropStandardLeftTop = target === parent.children[parent.rightNodeCount] && path[path.length - 1] === parent.rightNodeCount;
|
|
1461
|
+
if (dropStandardRightBottom) {
|
|
1462
|
+
hasPreviousNode = true;
|
|
1463
|
+
hasNextNode = false;
|
|
1464
|
+
}
|
|
1465
|
+
if (dropStandardLeftTop) {
|
|
1466
|
+
hasPreviousNode = false;
|
|
1467
|
+
hasNextNode = true;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
if (parent.isCollapsed) {
|
|
1471
|
+
hasNextNode = false;
|
|
1472
|
+
hasPreviousNode = false;
|
|
1473
|
+
}
|
|
2079
1474
|
return {
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
width,
|
|
2083
|
-
height: height + NodeSpace.getEmojiTopSpace(element) * 2
|
|
1475
|
+
hasPreviousNode,
|
|
1476
|
+
hasNextNode
|
|
2084
1477
|
};
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
const separateChildren = (parentElement) => {
|
|
1481
|
+
const rightNodeCount = parentElement.rightNodeCount;
|
|
1482
|
+
const children = parentElement.children;
|
|
1483
|
+
let rightChildren = [], leftChildren = [];
|
|
1484
|
+
for (let i = 0; i < children.length; i++) {
|
|
1485
|
+
const child = children[i];
|
|
1486
|
+
if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
|
|
1487
|
+
rightChildren.push(child);
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
|
|
1491
|
+
leftChildren.push(child);
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
if (i < rightNodeCount) {
|
|
1495
|
+
rightChildren.push(child);
|
|
1496
|
+
}
|
|
1497
|
+
else {
|
|
1498
|
+
leftChildren.push(child);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
return { leftChildren, rightChildren };
|
|
1502
|
+
};
|
|
1503
|
+
const isSetAbstract = (element) => {
|
|
1504
|
+
return !!getCorrespondingAbstract(element);
|
|
1505
|
+
};
|
|
1506
|
+
const canSetAbstract = (element) => {
|
|
1507
|
+
return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
|
|
1508
|
+
};
|
|
1509
|
+
const getCorrespondingAbstract = (element) => {
|
|
1510
|
+
const parent = MindElement.findParent(element);
|
|
1511
|
+
if (!parent)
|
|
1512
|
+
return undefined;
|
|
1513
|
+
const elementIndex = parent.children.indexOf(element);
|
|
1514
|
+
return parent.children.find(child => {
|
|
1515
|
+
return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
|
|
1516
|
+
});
|
|
1517
|
+
};
|
|
1518
|
+
const getBehindAbstracts = (element) => {
|
|
1519
|
+
const parent = MindElement.findParent(element);
|
|
1520
|
+
if (!parent)
|
|
1521
|
+
return [];
|
|
1522
|
+
const index = parent.children.indexOf(element);
|
|
1523
|
+
return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
|
|
1524
|
+
};
|
|
1525
|
+
/**
|
|
1526
|
+
* return corresponding abstract that is not child of elements
|
|
1527
|
+
*/
|
|
1528
|
+
const getOverallAbstracts = (board, elements) => {
|
|
1529
|
+
const overallAbstracts = [];
|
|
1530
|
+
elements
|
|
1531
|
+
.filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
|
|
1532
|
+
.forEach(value => {
|
|
1533
|
+
const abstract = getCorrespondingAbstract(value);
|
|
1534
|
+
if (abstract && elements.indexOf(abstract) === -1 && overallAbstracts.indexOf(abstract) === -1) {
|
|
1535
|
+
const { start, end } = abstract;
|
|
1536
|
+
const parent = MindElement.getParent(value);
|
|
1537
|
+
const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
|
|
1538
|
+
if (isOverall) {
|
|
1539
|
+
overallAbstracts.push(abstract);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
return overallAbstracts;
|
|
1544
|
+
};
|
|
1545
|
+
/**
|
|
1546
|
+
* abstract node is valid when elements contains at least one element it is referenced with
|
|
1547
|
+
*/
|
|
1548
|
+
const getValidAbstractRefs = (board, elements) => {
|
|
1549
|
+
const validAbstractRefs = [];
|
|
1550
|
+
elements
|
|
1551
|
+
.filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
|
|
1552
|
+
.forEach(value => {
|
|
1553
|
+
const abstract = getCorrespondingAbstract(value);
|
|
1554
|
+
if (abstract && elements.indexOf(abstract) > 0) {
|
|
1555
|
+
const index = validAbstractRefs.findIndex(value => value.abstract === abstract);
|
|
1556
|
+
if (index === -1) {
|
|
1557
|
+
validAbstractRefs.push({
|
|
1558
|
+
abstract: abstract,
|
|
1559
|
+
references: [value]
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
else {
|
|
1563
|
+
validAbstractRefs[index].references.push(value);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
return validAbstractRefs;
|
|
1568
|
+
};
|
|
1569
|
+
function getRelativeStartEndByAbstractRef(abstractRef, elements) {
|
|
1570
|
+
const start = elements.indexOf(abstractRef.references[0]);
|
|
1571
|
+
const end = elements.indexOf(abstractRef.references[abstractRef.references.length - 1]);
|
|
1572
|
+
return { start, end };
|
|
2085
1573
|
}
|
|
2086
|
-
const
|
|
2087
|
-
|
|
1574
|
+
const insertElementHandleAbstract = (board, path, step = 1,
|
|
1575
|
+
//由此区分拖拽和新增到概要概括最后一个节点
|
|
1576
|
+
isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
|
|
1577
|
+
const parent = PlaitNode.parent(board, path);
|
|
1578
|
+
const hasPreviousNode = path[path.length - 1] !== 0;
|
|
1579
|
+
let behindAbstracts;
|
|
1580
|
+
if (!hasPreviousNode) {
|
|
1581
|
+
behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
|
|
1582
|
+
}
|
|
1583
|
+
else {
|
|
1584
|
+
const selectedElement = PlaitNode.get(board, Path.previous(path));
|
|
1585
|
+
behindAbstracts = getBehindAbstracts(selectedElement);
|
|
1586
|
+
}
|
|
1587
|
+
if (behindAbstracts.length) {
|
|
1588
|
+
behindAbstracts.forEach(abstract => {
|
|
1589
|
+
let newProperties = effectedAbstracts.get(abstract);
|
|
1590
|
+
if (!newProperties) {
|
|
1591
|
+
newProperties = { start: 0, end: 0 };
|
|
1592
|
+
effectedAbstracts.set(abstract, newProperties);
|
|
1593
|
+
}
|
|
1594
|
+
newProperties.start = newProperties.start + step;
|
|
1595
|
+
newProperties.end = newProperties.end + step;
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
if (!hasPreviousNode) {
|
|
1599
|
+
return effectedAbstracts;
|
|
1600
|
+
}
|
|
1601
|
+
const selectedElement = PlaitNode.get(board, Path.previous(path));
|
|
1602
|
+
const correspondingAbstract = getCorrespondingAbstract(selectedElement);
|
|
1603
|
+
const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
|
|
1604
|
+
if (correspondingAbstract && !isDragToLast) {
|
|
1605
|
+
let newProperties = effectedAbstracts.get(correspondingAbstract);
|
|
1606
|
+
if (!newProperties) {
|
|
1607
|
+
newProperties = { start: 0, end: 0 };
|
|
1608
|
+
effectedAbstracts.set(correspondingAbstract, newProperties);
|
|
1609
|
+
}
|
|
1610
|
+
newProperties.end = newProperties.end + step;
|
|
1611
|
+
}
|
|
1612
|
+
return effectedAbstracts;
|
|
1613
|
+
};
|
|
1614
|
+
const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
|
|
1615
|
+
deletableElements.forEach(node => {
|
|
1616
|
+
if (!PlaitMind.isMind(node)) {
|
|
1617
|
+
const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
|
|
1618
|
+
if (behindAbstracts.length) {
|
|
1619
|
+
behindAbstracts.forEach(abstract => {
|
|
1620
|
+
let newProperties = effectedAbstracts.get(abstract);
|
|
1621
|
+
if (!newProperties) {
|
|
1622
|
+
newProperties = { start: 0, end: 0 };
|
|
1623
|
+
effectedAbstracts.set(abstract, newProperties);
|
|
1624
|
+
}
|
|
1625
|
+
newProperties.start = newProperties.start - 1;
|
|
1626
|
+
newProperties.end = newProperties.end - 1;
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
const correspondingAbstract = getCorrespondingAbstract(node);
|
|
1630
|
+
if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
|
|
1631
|
+
let newProperties = effectedAbstracts.get(correspondingAbstract);
|
|
1632
|
+
if (!newProperties) {
|
|
1633
|
+
newProperties = { start: 0, end: 0 };
|
|
1634
|
+
effectedAbstracts.set(correspondingAbstract, newProperties);
|
|
1635
|
+
}
|
|
1636
|
+
newProperties.end = newProperties.end - 1;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
});
|
|
1640
|
+
return effectedAbstracts;
|
|
2088
1641
|
};
|
|
2089
1642
|
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
1643
|
+
var AbstractHandlePosition;
|
|
1644
|
+
(function (AbstractHandlePosition) {
|
|
1645
|
+
AbstractHandlePosition["start"] = "start";
|
|
1646
|
+
AbstractHandlePosition["end"] = "end";
|
|
1647
|
+
})(AbstractHandlePosition || (AbstractHandlePosition = {}));
|
|
1648
|
+
var AbstractResizeState;
|
|
1649
|
+
(function (AbstractResizeState) {
|
|
1650
|
+
AbstractResizeState["start"] = "start";
|
|
1651
|
+
AbstractResizeState["resizing"] = "resizing";
|
|
1652
|
+
AbstractResizeState["end"] = "end";
|
|
1653
|
+
})(AbstractResizeState || (AbstractResizeState = {}));
|
|
1654
|
+
|
|
1655
|
+
const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
|
|
1656
|
+
if (isHorizontal) {
|
|
1657
|
+
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
1658
|
+
return {
|
|
1659
|
+
...abstractRectangle,
|
|
1660
|
+
y: location,
|
|
1661
|
+
height: abstractRectangle.height + abstractRectangle.y - location
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
else {
|
|
1665
|
+
return {
|
|
1666
|
+
...abstractRectangle,
|
|
1667
|
+
height: location - abstractRectangle.y
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
else {
|
|
1672
|
+
if (activeHandlePosition === AbstractHandlePosition.start) {
|
|
1673
|
+
return {
|
|
1674
|
+
...abstractRectangle,
|
|
1675
|
+
x: location,
|
|
1676
|
+
width: abstractRectangle.width + abstractRectangle.x - location
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
else {
|
|
1680
|
+
return {
|
|
1681
|
+
...abstractRectangle,
|
|
1682
|
+
width: location - abstractRectangle.x
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
|
|
1688
|
+
const node = MindElement.getNode(element);
|
|
1689
|
+
const { start, end } = getCorrectStartEnd(node.origin, parent);
|
|
1690
|
+
const startNode = parentChildren[start];
|
|
1691
|
+
const endNode = parentChildren[end];
|
|
1692
|
+
if (handlePosition === AbstractHandlePosition.start) {
|
|
1693
|
+
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
|
|
1694
|
+
let minNode;
|
|
1695
|
+
if (abstractNode.length) {
|
|
1696
|
+
const index = abstractNode
|
|
1697
|
+
.map(node => {
|
|
1698
|
+
const { end } = getCorrectStartEnd(node, parent);
|
|
1699
|
+
return end;
|
|
1700
|
+
})
|
|
1701
|
+
.sort((a, b) => b - a)[0];
|
|
1702
|
+
minNode = parentChildren[index + 1];
|
|
1703
|
+
}
|
|
1704
|
+
else {
|
|
1705
|
+
minNode = parentChildren[0];
|
|
1706
|
+
}
|
|
1707
|
+
const minNodeRectangle = getRectangleByElements(board, [minNode], true);
|
|
1708
|
+
const endNodeRectangle = getRectangleByElements(board, [endNode], false);
|
|
1709
|
+
if (isHorizontal) {
|
|
1710
|
+
return {
|
|
1711
|
+
max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1712
|
+
min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
else {
|
|
1716
|
+
return {
|
|
1717
|
+
max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1718
|
+
min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
else {
|
|
1723
|
+
const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
|
|
1724
|
+
let maxNode;
|
|
1725
|
+
if (abstractNode.length) {
|
|
1726
|
+
const index = abstractNode
|
|
1727
|
+
.map(node => {
|
|
1728
|
+
const { start } = getCorrectStartEnd(node, parent);
|
|
1729
|
+
return start;
|
|
1730
|
+
})
|
|
1731
|
+
.sort((a, b) => a - b)[0];
|
|
1732
|
+
maxNode = parentChildren[index - 1];
|
|
1733
|
+
}
|
|
1734
|
+
else {
|
|
1735
|
+
const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
|
|
1736
|
+
maxNode = parentChildren[children.length - 1];
|
|
1737
|
+
}
|
|
1738
|
+
const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
|
|
1739
|
+
const startNodeRectangle = getRectangleByElements(board, [startNode], false);
|
|
1740
|
+
if (isHorizontal) {
|
|
1741
|
+
return {
|
|
1742
|
+
max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1743
|
+
min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
else {
|
|
1747
|
+
return {
|
|
1748
|
+
max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
|
|
1749
|
+
min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
};
|
|
1754
|
+
const getHitAbstractHandle = (board, element, point) => {
|
|
1755
|
+
const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
|
|
1756
|
+
const isHorizontal = isHorizontalLayout(nodeLayout);
|
|
1757
|
+
const parentElement = MindElement.getParent(element);
|
|
1758
|
+
const includedElements = parentElement.children.slice(element.start, element.end + 1);
|
|
1759
|
+
let abstractRectangle = getRectangleByElements(board, includedElements, true);
|
|
1760
|
+
abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
|
|
1761
|
+
const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
|
|
1762
|
+
const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
|
|
1763
|
+
const pointRec = RectangleClient.toRectangleClient([point, point]);
|
|
1764
|
+
if (RectangleClient.isHit(pointRec, startHandleRec))
|
|
1765
|
+
return AbstractHandlePosition.start;
|
|
1766
|
+
if (RectangleClient.isHit(pointRec, endHandleRec))
|
|
1767
|
+
return AbstractHandlePosition.end;
|
|
1768
|
+
return undefined;
|
|
1769
|
+
};
|
|
1770
|
+
const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
|
|
1771
|
+
let result;
|
|
1772
|
+
if (position === AbstractHandlePosition.start) {
|
|
1773
|
+
const location = isHorizontal ? rectangle.y : rectangle.x;
|
|
1774
|
+
result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
|
|
1775
|
+
result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1776
|
+
}
|
|
1777
|
+
else {
|
|
1778
|
+
const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
|
|
1779
|
+
result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
|
|
1780
|
+
result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
|
|
1781
|
+
}
|
|
1782
|
+
return result;
|
|
1783
|
+
};
|
|
1784
|
+
function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
|
|
1785
|
+
const children = parentChildren.filter(child => {
|
|
1786
|
+
return !AbstractNode.isAbstract(child);
|
|
1787
|
+
});
|
|
1788
|
+
const recArray = children.map(child => {
|
|
1789
|
+
return getRectangleByElements(board, [child], false);
|
|
1790
|
+
});
|
|
1791
|
+
const firstRec = getRectangleByElements(board, [children[0]], true);
|
|
1792
|
+
const fakeLeftRec = {
|
|
1793
|
+
x: firstRec.x - firstRec.width,
|
|
1794
|
+
y: firstRec.y - firstRec.height,
|
|
1795
|
+
width: firstRec.width,
|
|
1796
|
+
height: firstRec.height
|
|
1797
|
+
};
|
|
1798
|
+
const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
|
|
1799
|
+
const fakeRightRec = {
|
|
1800
|
+
x: lastRec.x + lastRec.width,
|
|
1801
|
+
y: lastRec.y + lastRec.height,
|
|
1802
|
+
width: lastRec.width,
|
|
1803
|
+
height: lastRec.height
|
|
1804
|
+
};
|
|
1805
|
+
recArray.push(fakeRightRec);
|
|
1806
|
+
recArray.unshift(fakeLeftRec);
|
|
1807
|
+
for (let i = 0; i < recArray.length - 1; i++) {
|
|
1808
|
+
const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
|
|
1809
|
+
const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
|
|
1810
|
+
if (location >= recXOrY + recWidthOrHeight / 2 &&
|
|
1811
|
+
location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
|
|
1812
|
+
return i - 1;
|
|
1813
|
+
}
|
|
2097
1814
|
}
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
1815
|
+
return 0;
|
|
1816
|
+
}
|
|
1817
|
+
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1818
|
+
let touchedHandle;
|
|
1819
|
+
const abstract = getSelectedElements(board)
|
|
1820
|
+
.filter(element => AbstractNode.isAbstract(element))
|
|
1821
|
+
.find(element => {
|
|
1822
|
+
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1823
|
+
return touchedHandle;
|
|
1824
|
+
});
|
|
1825
|
+
if (touchedAbstract === abstract) {
|
|
1826
|
+
return touchedAbstract;
|
|
2106
1827
|
}
|
|
2107
|
-
|
|
2108
|
-
const
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
const
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
return nodeAndText + element.height + nodeAndText;
|
|
2138
|
-
},
|
|
2139
|
-
getTextLeftSpace(board, element) {
|
|
2140
|
-
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
2141
|
-
if (MindElement.hasEmojis(element)) {
|
|
2142
|
-
return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
|
|
1828
|
+
if (touchedAbstract) {
|
|
1829
|
+
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1830
|
+
component.updateAbstractIncludedOutline();
|
|
1831
|
+
touchedAbstract = undefined;
|
|
1832
|
+
}
|
|
1833
|
+
if (abstract) {
|
|
1834
|
+
touchedAbstract = abstract;
|
|
1835
|
+
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1836
|
+
component.updateAbstractIncludedOutline(touchedHandle);
|
|
1837
|
+
}
|
|
1838
|
+
return touchedAbstract;
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true, defaultStrokeWidth) {
|
|
1842
|
+
const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, child.origin);
|
|
1843
|
+
const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
|
|
1844
|
+
const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
|
|
1845
|
+
let beginX, beginY, endX, endY, beginNode = node, endNode = child;
|
|
1846
|
+
const beginRectangle = getRectangleByNode(beginNode);
|
|
1847
|
+
const endRectangle = getRectangleByNode(endNode);
|
|
1848
|
+
beginX = beginNode.x + beginNode.width / 2;
|
|
1849
|
+
beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
|
|
1850
|
+
endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
|
|
1851
|
+
endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
|
|
1852
|
+
//根据位置,设置正负参数
|
|
1853
|
+
let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
|
|
1854
|
+
const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
|
|
1855
|
+
if (beginNode.origin.isRoot) {
|
|
1856
|
+
if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
|
|
1857
|
+
beginY += branchWidth;
|
|
2143
1858
|
}
|
|
2144
|
-
|
|
2145
|
-
|
|
1859
|
+
if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
|
|
1860
|
+
beginY -= branchWidth;
|
|
2146
1861
|
}
|
|
2147
|
-
},
|
|
2148
|
-
getTextTopSpace(element) {
|
|
2149
|
-
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
2150
|
-
return nodeAndText;
|
|
2151
|
-
},
|
|
2152
|
-
getEmojiLeftSpace(board, element) {
|
|
2153
|
-
const options = board.getMindOptions();
|
|
2154
|
-
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
2155
|
-
return nodeAndText - options.emojiPadding;
|
|
2156
|
-
},
|
|
2157
|
-
getEmojiTopSpace(element) {
|
|
2158
|
-
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
2159
|
-
return nodeAndText;
|
|
2160
1862
|
}
|
|
2161
|
-
|
|
1863
|
+
let curve = [
|
|
1864
|
+
[beginX, beginY],
|
|
1865
|
+
[beginX, beginY],
|
|
1866
|
+
[beginX, beginY],
|
|
1867
|
+
[beginX, endY - (endNode.hGap * 3 * plusMinus[1]) / 5],
|
|
1868
|
+
[beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
|
|
1869
|
+
[beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
|
|
1870
|
+
[beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
|
|
1871
|
+
isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
|
|
1872
|
+
isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
|
|
1873
|
+
isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
|
|
1874
|
+
];
|
|
1875
|
+
const points = pointsOnBezierCurves(curve);
|
|
1876
|
+
return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
|
|
1877
|
+
}
|
|
2162
1878
|
|
|
2163
|
-
function
|
|
2164
|
-
const
|
|
1879
|
+
function drawTopicByNode(board, node, viewContainerRef) {
|
|
1880
|
+
const rectangle = getTopicRectangleByNode(board, node);
|
|
1881
|
+
return drawTopicByElement(board, rectangle, node.origin, viewContainerRef);
|
|
1882
|
+
}
|
|
1883
|
+
function drawTopicByElement(board, rectangle, element, viewContainerRef) {
|
|
1884
|
+
const containerRef = viewContainerRef || PlaitBoard.getComponent(board).viewContainerRef;
|
|
2165
1885
|
const classList = [];
|
|
2166
|
-
if (
|
|
1886
|
+
if (element.isRoot) {
|
|
2167
1887
|
classList.push('root-node');
|
|
2168
1888
|
classList.push('font-size-18');
|
|
2169
1889
|
}
|
|
2170
|
-
else if (node.parent?.origin?.isRoot) {
|
|
2171
|
-
classList.push('root-child-node');
|
|
2172
|
-
}
|
|
2173
1890
|
else {
|
|
2174
1891
|
classList.push('child-node');
|
|
2175
1892
|
}
|
|
2176
1893
|
// COMPAT: last character can not show in safari browser
|
|
2177
|
-
return drawRichtext(x, y, width, height,
|
|
1894
|
+
return drawRichtext(rectangle.x, rectangle.y, rectangle.width, rectangle.height, element.data.topic, containerRef, classList);
|
|
2178
1895
|
}
|
|
2179
1896
|
function updateMindNodeTopicSize(board, node, g, isEditable) {
|
|
2180
|
-
const { x, y, width, height } =
|
|
1897
|
+
const { x, y, width, height } = getTopicRectangleByNode(board, node);
|
|
2181
1898
|
if (isEditable) {
|
|
2182
1899
|
// add 999, avoid changing lines when paste more text
|
|
2183
1900
|
updateForeignObject(g, width + 999, height + 999, x, y);
|
|
@@ -2187,28 +1904,6 @@ function updateMindNodeTopicSize(board, node, g, isEditable) {
|
|
|
2187
1904
|
updateForeignObject(g, width, height, x, y);
|
|
2188
1905
|
}
|
|
2189
1906
|
}
|
|
2190
|
-
function getRichtextRectangleByNode(board, node) {
|
|
2191
|
-
let { x, y } = getRectangleByNode(node);
|
|
2192
|
-
x = x + NodeSpace.getTextLeftSpace(board, node.origin);
|
|
2193
|
-
y = y + NodeSpace.getTextTopSpace(node.origin);
|
|
2194
|
-
const width = Math.ceil(node.origin.width);
|
|
2195
|
-
const height = Math.ceil(node.origin.height);
|
|
2196
|
-
return { height, width, x, y };
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
|
-
function drawRectangleNode(board, node) {
|
|
2200
|
-
const { x, y, width, height } = getRectangleByNode(node);
|
|
2201
|
-
const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? DefaultRootStyle.fill : DefaultNodeStyle.fill;
|
|
2202
|
-
const stroke = getStrokeByMindElement(board, node.origin);
|
|
2203
|
-
const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : DefaultNodeStyle.strokeWidth;
|
|
2204
|
-
const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), x, y, x + width, y + height, {
|
|
2205
|
-
stroke,
|
|
2206
|
-
strokeWidth,
|
|
2207
|
-
fill,
|
|
2208
|
-
fillStyle: 'solid'
|
|
2209
|
-
});
|
|
2210
|
-
return nodeG;
|
|
2211
|
-
}
|
|
2212
1907
|
|
|
2213
1908
|
function drawAbstractLink(board, node, isHorizontal) {
|
|
2214
1909
|
const linkPadding = 15;
|
|
@@ -2230,18 +1925,12 @@ function drawAbstractLink(board, node, isHorizontal) {
|
|
|
2230
1925
|
let bezierBeginPoint = getPointByPlacement(includedElementsRectangle, bezierBeginPlacement);
|
|
2231
1926
|
let bezierEndPoint = getPointByPlacement(includedElementsRectangle, bezierEndPlacement);
|
|
2232
1927
|
let abstractConnectorPoint = getPointByPlacement(abstractRectangle, abstractConnectorPlacement);
|
|
2233
|
-
let curveDistance =
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
}
|
|
2240
|
-
bezierBeginPoint = movePoint(bezierBeginPoint, linkPadding, linkDirection);
|
|
2241
|
-
let c1 = movePoint(bezierBeginPoint, curveDistance, linkDirection);
|
|
2242
|
-
bezierEndPoint = movePoint(bezierEndPoint, linkPadding, linkDirection);
|
|
2243
|
-
let c2 = movePoint(bezierEndPoint, curveDistance, linkDirection);
|
|
2244
|
-
let bezierConnectorPoint = movePoint(abstractConnectorPoint, -linkPadding, linkDirection);
|
|
1928
|
+
let curveDistance = getXDistanceBetweenPoint(abstractConnectorPoint, bezierBeginPoint, isHorizontal) - linkPadding * 2;
|
|
1929
|
+
bezierBeginPoint = moveXOfPoint(bezierBeginPoint, linkPadding, linkDirection);
|
|
1930
|
+
let c1 = moveXOfPoint(bezierBeginPoint, curveDistance, linkDirection);
|
|
1931
|
+
bezierEndPoint = moveXOfPoint(bezierEndPoint, linkPadding, linkDirection);
|
|
1932
|
+
let c2 = moveXOfPoint(bezierEndPoint, curveDistance, linkDirection);
|
|
1933
|
+
let bezierConnectorPoint = moveXOfPoint(abstractConnectorPoint, -linkPadding, linkDirection);
|
|
2245
1934
|
const link = PlaitBoard.getRoughSVG(board).path(`M${bezierBeginPoint[0]},${bezierBeginPoint[1]} Q${c1[0]},${c1[1]} ${bezierConnectorPoint[0]},${bezierConnectorPoint[1]} Q${c2[0]},${c2[1]} ${bezierEndPoint[0]},${bezierEndPoint[1]} M${abstractConnectorPoint[0]},${abstractConnectorPoint[1]} L${bezierConnectorPoint[0]},${bezierConnectorPoint[1]}`, {
|
|
2246
1935
|
stroke: branchColor,
|
|
2247
1936
|
strokeWidth: branchWidth
|
|
@@ -2285,37 +1974,236 @@ class EmojisDrawer {
|
|
|
2285
1974
|
this.viewContainerRef = viewContainerRef;
|
|
2286
1975
|
this.emojiDrawers = [];
|
|
2287
1976
|
}
|
|
2288
|
-
drawEmojis(element) {
|
|
2289
|
-
this.destroy();
|
|
2290
|
-
if (MindElement.hasEmojis(element)) {
|
|
2291
|
-
this.g = createG();
|
|
2292
|
-
this.g.classList.add('emojis');
|
|
2293
|
-
const foreignRectangle = getEmojiForeignRectangle(this.board, element);
|
|
2294
|
-
const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
|
|
2295
|
-
this.g.append(foreignObject);
|
|
2296
|
-
const container = document.createElement('div');
|
|
2297
|
-
container.classList.add('node-emojis-container');
|
|
2298
|
-
foreignObject.append(container);
|
|
2299
|
-
this.emojiDrawers = element.data.emojis.map(emojiItem => {
|
|
2300
|
-
const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
|
|
2301
|
-
drawer.draw(emojiItem, element);
|
|
2302
|
-
return drawer;
|
|
2303
|
-
});
|
|
2304
|
-
this.emojiDrawers.forEach(drawer => {
|
|
2305
|
-
container.append(drawer.nativeElement);
|
|
2306
|
-
});
|
|
2307
|
-
return this.g;
|
|
1977
|
+
drawEmojis(element) {
|
|
1978
|
+
this.destroy();
|
|
1979
|
+
if (MindElement.hasEmojis(element)) {
|
|
1980
|
+
this.g = createG();
|
|
1981
|
+
this.g.classList.add('emojis');
|
|
1982
|
+
const foreignRectangle = getEmojiForeignRectangle(this.board, element);
|
|
1983
|
+
const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
|
|
1984
|
+
this.g.append(foreignObject);
|
|
1985
|
+
const container = document.createElement('div');
|
|
1986
|
+
container.classList.add('node-emojis-container');
|
|
1987
|
+
foreignObject.append(container);
|
|
1988
|
+
this.emojiDrawers = element.data.emojis.map(emojiItem => {
|
|
1989
|
+
const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
|
|
1990
|
+
drawer.draw(emojiItem, element);
|
|
1991
|
+
return drawer;
|
|
1992
|
+
});
|
|
1993
|
+
this.emojiDrawers.forEach(drawer => {
|
|
1994
|
+
container.append(drawer.nativeElement);
|
|
1995
|
+
});
|
|
1996
|
+
return this.g;
|
|
1997
|
+
}
|
|
1998
|
+
return undefined;
|
|
1999
|
+
}
|
|
2000
|
+
destroy() {
|
|
2001
|
+
if (this.g) {
|
|
2002
|
+
this.g.remove();
|
|
2003
|
+
}
|
|
2004
|
+
this.emojiDrawers.forEach(drawer => drawer.destroy());
|
|
2005
|
+
this.emojiDrawers = [];
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
const setAbstractsByRefs = (board, abstractRefs) => {
|
|
2010
|
+
abstractRefs.forEach((newProperty, element) => {
|
|
2011
|
+
const start = element.start + newProperty.start;
|
|
2012
|
+
const end = element.end + newProperty.end;
|
|
2013
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2014
|
+
if (start > end) {
|
|
2015
|
+
Transforms.removeNode(board, path);
|
|
2016
|
+
}
|
|
2017
|
+
else {
|
|
2018
|
+
Transforms.setNode(board, { start, end }, path);
|
|
2019
|
+
}
|
|
2020
|
+
});
|
|
2021
|
+
};
|
|
2022
|
+
const setAbstractByStandardLayout = (board, element) => {
|
|
2023
|
+
const rightNodeCount = element.rightNodeCount;
|
|
2024
|
+
const abstract = element.children.find(child => {
|
|
2025
|
+
return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
|
|
2026
|
+
});
|
|
2027
|
+
if (abstract) {
|
|
2028
|
+
const path = PlaitBoard.findPath(board, abstract);
|
|
2029
|
+
Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
2032
|
+
const insertAbstract = (board, elements) => {
|
|
2033
|
+
let elementGroup = getFirstLevelElement(elements);
|
|
2034
|
+
const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
|
|
2035
|
+
abstractIncludedGroups.forEach((group, index) => {
|
|
2036
|
+
const groupParent = parentElements[index];
|
|
2037
|
+
setAbstractByElements(board, groupParent, group);
|
|
2038
|
+
});
|
|
2039
|
+
};
|
|
2040
|
+
const setAbstractByElements = (board, groupParent, group) => {
|
|
2041
|
+
const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
|
|
2042
|
+
const rightNodeCount = groupParent?.rightNodeCount;
|
|
2043
|
+
const start = indexArray[0], end = indexArray[indexArray.length - 1];
|
|
2044
|
+
if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
|
|
2045
|
+
rightNodeCount &&
|
|
2046
|
+
start < rightNodeCount &&
|
|
2047
|
+
end >= rightNodeCount) {
|
|
2048
|
+
const childrenLength = groupParent.children.length;
|
|
2049
|
+
const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
|
|
2050
|
+
const leftChildren = indexArray.filter(index => index >= rightNodeCount);
|
|
2051
|
+
const rightChildren = indexArray.filter(index => index < rightNodeCount);
|
|
2052
|
+
insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
|
|
2053
|
+
insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
|
|
2054
|
+
}
|
|
2055
|
+
else {
|
|
2056
|
+
const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
|
|
2057
|
+
insertAbstractNode(board, path, start, end);
|
|
2058
|
+
}
|
|
2059
|
+
};
|
|
2060
|
+
const insertAbstractNode = (board, path, start, end) => {
|
|
2061
|
+
const mindElement = createMindElement('概要', 28, 20, {
|
|
2062
|
+
strokeColor: DefaultAbstractNodeStyle.strokeColor,
|
|
2063
|
+
strokeWidth: DefaultAbstractNodeStyle.branchWidth,
|
|
2064
|
+
branchColor: DefaultAbstractNodeStyle.branchColor,
|
|
2065
|
+
branchWidth: DefaultAbstractNodeStyle.branchWidth
|
|
2066
|
+
});
|
|
2067
|
+
mindElement.start = start;
|
|
2068
|
+
mindElement.end = end;
|
|
2069
|
+
Transforms.insertNode(board, mindElement, path);
|
|
2070
|
+
};
|
|
2071
|
+
|
|
2072
|
+
const setLayout = (board, layout, path) => {
|
|
2073
|
+
correctLogicLayoutNode(board, layout, path);
|
|
2074
|
+
const element = PlaitNode.get(board, path);
|
|
2075
|
+
if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
|
|
2076
|
+
MindTransforms.setAbstractByStandardLayout(board, element);
|
|
2077
|
+
}
|
|
2078
|
+
Transforms.setNode(board, { layout }, path);
|
|
2079
|
+
};
|
|
2080
|
+
const correctLogicLayoutNode = (board, layout, path) => {
|
|
2081
|
+
const node = PlaitNode.get(board, path);
|
|
2082
|
+
if (node && layout) {
|
|
2083
|
+
node.children?.forEach((value, index) => {
|
|
2084
|
+
if (value.layout) {
|
|
2085
|
+
if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
|
|
2086
|
+
(isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
|
|
2087
|
+
Transforms.setNode(board, { layout: null }, [...path, index]);
|
|
2088
|
+
}
|
|
2089
|
+
if (value.children?.length) {
|
|
2090
|
+
correctLogicLayoutNode(board, layout, [...path, index]);
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
|
|
2097
|
+
const setTopic = (board, element, topic, width, height) => {
|
|
2098
|
+
const newElement = {
|
|
2099
|
+
data: { topic },
|
|
2100
|
+
width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
|
|
2101
|
+
height: height / board.viewport.zoom
|
|
2102
|
+
};
|
|
2103
|
+
if (MindElement.hasEmojis(element)) {
|
|
2104
|
+
newElement.data.emojis = element.data.emojis;
|
|
2105
|
+
}
|
|
2106
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2107
|
+
Transforms.setNode(board, newElement, path);
|
|
2108
|
+
};
|
|
2109
|
+
const setTopicSize = (board, element, width, height) => {
|
|
2110
|
+
const newElement = {
|
|
2111
|
+
width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
|
|
2112
|
+
height: height / board.viewport.zoom
|
|
2113
|
+
};
|
|
2114
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2115
|
+
Transforms.setNode(board, newElement, path);
|
|
2116
|
+
};
|
|
2117
|
+
const removeElements = (board, elements) => {
|
|
2118
|
+
const deletableElements = getFirstLevelElement(elements).reverse();
|
|
2119
|
+
//翻转,从下到上修改,防止找不到 path
|
|
2120
|
+
deletableElements
|
|
2121
|
+
.map(element => {
|
|
2122
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2123
|
+
return () => {
|
|
2124
|
+
if (isInRightBranchOfStandardLayout(element)) {
|
|
2125
|
+
changeRightNodeCount(board, path.slice(0, 1), -1);
|
|
2126
|
+
}
|
|
2127
|
+
Transforms.removeNode(board, path);
|
|
2128
|
+
};
|
|
2129
|
+
})
|
|
2130
|
+
.forEach(action => {
|
|
2131
|
+
action();
|
|
2132
|
+
});
|
|
2133
|
+
};
|
|
2134
|
+
const insertNodes = (board, elements, path) => {
|
|
2135
|
+
const pathRef = board.pathRef(path);
|
|
2136
|
+
elements.forEach(element => {
|
|
2137
|
+
if (pathRef.current) {
|
|
2138
|
+
Transforms.insertNode(board, element, pathRef.current);
|
|
2308
2139
|
}
|
|
2309
|
-
|
|
2140
|
+
});
|
|
2141
|
+
pathRef.unref();
|
|
2142
|
+
};
|
|
2143
|
+
const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
|
|
2144
|
+
const parent = PlaitNode.get(board, Path$1.parent(path));
|
|
2145
|
+
const abstractPath = [...Path$1.parent(path), parent.children?.length];
|
|
2146
|
+
const abstracts = validAbstractRefs.map(refs => {
|
|
2147
|
+
const { start, end } = getRelativeStartEndByAbstractRef(refs, elements);
|
|
2148
|
+
return {
|
|
2149
|
+
...refs.abstract,
|
|
2150
|
+
start: start + path[path.length - 1],
|
|
2151
|
+
end: end + path[path.length - 1]
|
|
2152
|
+
};
|
|
2153
|
+
});
|
|
2154
|
+
insertNodes(board, abstracts, abstractPath);
|
|
2155
|
+
};
|
|
2156
|
+
|
|
2157
|
+
const addEmoji = (board, element, emojiItem) => {
|
|
2158
|
+
const emojis = element.data.emojis || [];
|
|
2159
|
+
const newEmojis = [...emojis];
|
|
2160
|
+
newEmojis.push(emojiItem);
|
|
2161
|
+
const newElement = {
|
|
2162
|
+
data: { topic: element.data.topic, emojis: newEmojis }
|
|
2163
|
+
};
|
|
2164
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2165
|
+
Transforms.setNode(board, newElement, path);
|
|
2166
|
+
};
|
|
2167
|
+
const removeEmoji = (board, element, emojiItem) => {
|
|
2168
|
+
const emojis = element.data.emojis.filter(value => value !== emojiItem);
|
|
2169
|
+
const newElement = {
|
|
2170
|
+
data: { topic: element.data.topic }
|
|
2171
|
+
};
|
|
2172
|
+
if (emojis.length > 0) {
|
|
2173
|
+
newElement.data.emojis = emojis;
|
|
2310
2174
|
}
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2175
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2176
|
+
Transforms.setNode(board, newElement, path);
|
|
2177
|
+
};
|
|
2178
|
+
const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
|
|
2179
|
+
const newElement = {
|
|
2180
|
+
data: { topic: element.data.topic }
|
|
2181
|
+
};
|
|
2182
|
+
const newEmojis = element.data.emojis.map(value => {
|
|
2183
|
+
if (value === oldEmoji) {
|
|
2184
|
+
return newEmoji;
|
|
2314
2185
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2186
|
+
return value;
|
|
2187
|
+
});
|
|
2188
|
+
newElement.data.emojis = newEmojis;
|
|
2189
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2190
|
+
Transforms.setNode(board, newElement, path);
|
|
2191
|
+
};
|
|
2192
|
+
|
|
2193
|
+
const MindTransforms = {
|
|
2194
|
+
setLayout,
|
|
2195
|
+
setTopic,
|
|
2196
|
+
setTopicSize,
|
|
2197
|
+
addEmoji,
|
|
2198
|
+
removeEmoji,
|
|
2199
|
+
replaceEmoji,
|
|
2200
|
+
insertAbstract,
|
|
2201
|
+
setAbstractsByRefs,
|
|
2202
|
+
setAbstractByStandardLayout,
|
|
2203
|
+
removeElements,
|
|
2204
|
+
insertNodes,
|
|
2205
|
+
insertAbstractNodes
|
|
2206
|
+
};
|
|
2319
2207
|
|
|
2320
2208
|
function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
|
|
2321
2209
|
const abstractIncludedG = createG();
|
|
@@ -2340,10 +2228,10 @@ function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosit
|
|
|
2340
2228
|
transformPlacement(endPlacement, linkDirection);
|
|
2341
2229
|
let startCenterPoint = getPointByPlacement(abstractRectangle, startPlacement);
|
|
2342
2230
|
let endCenterPoint = getPointByPlacement(abstractRectangle, endPlacement);
|
|
2343
|
-
const startPoint1 =
|
|
2344
|
-
const startPoint2 =
|
|
2345
|
-
const endPoint1 =
|
|
2346
|
-
const endPoint2 =
|
|
2231
|
+
const startPoint1 = moveXOfPoint(startCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2232
|
+
const startPoint2 = moveXOfPoint(startCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2233
|
+
const endPoint1 = moveXOfPoint(endCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2234
|
+
const endPoint2 = moveXOfPoint(endCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2347
2235
|
const startHandle = roughSVG.line(startPoint1[0], startPoint1[1], startPoint2[0], startPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.start));
|
|
2348
2236
|
const endHandle = roughSVG.line(endPoint1[0], endPoint1[1], endPoint2[0], endPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.end));
|
|
2349
2237
|
changeBoardClass(board, activeHandlePosition, isHorizontal);
|
|
@@ -2694,7 +2582,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2694
2582
|
const shape = getShapeByElement(this.board, this.node.origin);
|
|
2695
2583
|
switch (shape) {
|
|
2696
2584
|
case MindElementShape.roundRectangle:
|
|
2697
|
-
this.shapeG =
|
|
2585
|
+
this.shapeG = drawRoundRectangleByNode(this.board, this.node);
|
|
2698
2586
|
this.g.prepend(this.shapeG);
|
|
2699
2587
|
break;
|
|
2700
2588
|
default:
|
|
@@ -2850,7 +2738,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2850
2738
|
}
|
|
2851
2739
|
}
|
|
2852
2740
|
drawRichtext() {
|
|
2853
|
-
const { richtextG, richtextComponentRef, foreignObject } =
|
|
2741
|
+
const { richtextG, richtextComponentRef, foreignObject } = drawTopicByNode(this.board, this.node, this.viewContainerRef);
|
|
2854
2742
|
this.richtextComponentRef = richtextComponentRef;
|
|
2855
2743
|
this.richtextG = richtextG;
|
|
2856
2744
|
this.foreignObject = foreignObject;
|
|
@@ -2871,7 +2759,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2871
2759
|
}
|
|
2872
2760
|
// interactive
|
|
2873
2761
|
fromEvent(collapseG, 'mouseup')
|
|
2874
|
-
.pipe(filter(() => !this.handActive || this.board
|
|
2762
|
+
.pipe(filter(() => !this.handActive || !PlaitBoard.isReadonly(this.board)), take(1))
|
|
2875
2763
|
.subscribe(() => {
|
|
2876
2764
|
const isCollapsed = !this.node.origin.isCollapsed;
|
|
2877
2765
|
const newElement = { isCollapsed };
|
|
@@ -3052,7 +2940,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
3052
2940
|
});
|
|
3053
2941
|
const mousedown$ = fromEvent(document, 'mousedown').subscribe((event) => {
|
|
3054
2942
|
const point = transformPoint(this.board, toPoint(event.x, event.y, PlaitBoard.getHost(this.board)));
|
|
3055
|
-
const clickInNode =
|
|
2943
|
+
const clickInNode = isHitMindElement(this.board, point, this.element);
|
|
3056
2944
|
if (clickInNode && !hasEditableTarget(richtextInstance.editor, event.target)) {
|
|
3057
2945
|
event.preventDefault();
|
|
3058
2946
|
}
|
|
@@ -3115,6 +3003,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
3115
3003
|
super.ngOnDestroy();
|
|
3116
3004
|
this.abstractIncludedOutlineG?.remove();
|
|
3117
3005
|
this.destroyRichtext();
|
|
3006
|
+
this.emojisDrawer.destroy();
|
|
3118
3007
|
this.destroy$.next();
|
|
3119
3008
|
this.destroy$.complete();
|
|
3120
3009
|
if (ELEMENT_TO_NODE.get(this.element) === this.node) {
|
|
@@ -3169,7 +3058,7 @@ const getLayoutOptions = (board) => {
|
|
|
3169
3058
|
}
|
|
3170
3059
|
return {
|
|
3171
3060
|
getHeight(element) {
|
|
3172
|
-
return NodeSpace.getNodeHeight(element);
|
|
3061
|
+
return NodeSpace.getNodeHeight(board, element);
|
|
3173
3062
|
},
|
|
3174
3063
|
getWidth(element) {
|
|
3175
3064
|
return NodeSpace.getNodeWidth(board, element);
|
|
@@ -3260,141 +3149,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3260
3149
|
class MindModule {
|
|
3261
3150
|
}
|
|
3262
3151
|
MindModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3263
|
-
MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [
|
|
3264
|
-
MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [
|
|
3152
|
+
MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [CommonModule, RichtextModule, PlaitModule], exports: [PlaitMindComponent, MindNodeComponent] });
|
|
3153
|
+
MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [CommonModule, RichtextModule, PlaitModule] });
|
|
3265
3154
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, decorators: [{
|
|
3266
3155
|
type: NgModule,
|
|
3267
3156
|
args: [{
|
|
3268
3157
|
declarations: [PlaitMindComponent, MindNodeComponent],
|
|
3269
|
-
imports: [
|
|
3158
|
+
imports: [CommonModule, RichtextModule, PlaitModule],
|
|
3270
3159
|
exports: [PlaitMindComponent, MindNodeComponent]
|
|
3271
3160
|
}]
|
|
3272
3161
|
}] });
|
|
3273
3162
|
|
|
3274
|
-
const isValidTarget = (origin, target) => {
|
|
3275
|
-
return origin !== target && !isChildElement(origin, target);
|
|
3276
|
-
};
|
|
3277
|
-
const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
|
|
3278
|
-
const activeComponent = PlaitElement.getComponent(activeElement);
|
|
3279
|
-
if (isOrigin) {
|
|
3280
|
-
activeComponent.g.classList.add('dragging-origin');
|
|
3281
|
-
}
|
|
3282
|
-
else {
|
|
3283
|
-
activeComponent.g.classList.add('dragging-child');
|
|
3284
|
-
}
|
|
3285
|
-
!activeElement.isCollapsed &&
|
|
3286
|
-
activeElement.children.forEach(child => {
|
|
3287
|
-
addActiveOnDragOrigin(child, false);
|
|
3288
|
-
});
|
|
3289
|
-
};
|
|
3290
|
-
const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
|
|
3291
|
-
const activeComponent = PlaitElement.getComponent(activeElement);
|
|
3292
|
-
if (isOrigin) {
|
|
3293
|
-
activeComponent.g.classList.remove('dragging-origin');
|
|
3294
|
-
}
|
|
3295
|
-
else {
|
|
3296
|
-
activeComponent.g.classList.remove('dragging-child');
|
|
3297
|
-
}
|
|
3298
|
-
!activeElement.isCollapsed &&
|
|
3299
|
-
activeElement.children.forEach(child => {
|
|
3300
|
-
removeActiveOnDragOrigin(child, false);
|
|
3301
|
-
});
|
|
3302
|
-
};
|
|
3303
|
-
const updatePathByLayoutAndDropTarget = (targetPath, layout, dropTarget) => {
|
|
3304
|
-
// 上下布局:左右是兄弟节点,上下是子节点
|
|
3305
|
-
if (isVerticalLogicLayout(layout)) {
|
|
3306
|
-
if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
|
|
3307
|
-
targetPath.push(dropTarget.target.children.length);
|
|
3308
|
-
}
|
|
3309
|
-
if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
|
|
3310
|
-
targetPath.push(dropTarget.target.children.length);
|
|
3311
|
-
}
|
|
3312
|
-
// 如果是左,位置不变,右则插入到下一个兄弟节点
|
|
3313
|
-
if (dropTarget.detectResult === 'right') {
|
|
3314
|
-
targetPath = Path.next(targetPath);
|
|
3315
|
-
}
|
|
3316
|
-
}
|
|
3317
|
-
// 水平布局/标准布局:上下是兄弟节点,左右是子节点
|
|
3318
|
-
if (isHorizontalLogicLayout(layout)) {
|
|
3319
|
-
if (dropTarget.detectResult === 'right') {
|
|
3320
|
-
targetPath.push(dropTarget.target.children.length);
|
|
3321
|
-
}
|
|
3322
|
-
if (dropTarget.detectResult === 'left') {
|
|
3323
|
-
targetPath.push(dropTarget.target.children.length);
|
|
3324
|
-
}
|
|
3325
|
-
// 如果是上,位置不变,下插入到下一个兄弟节点
|
|
3326
|
-
if (dropTarget.detectResult === 'bottom') {
|
|
3327
|
-
targetPath = Path.next(targetPath);
|
|
3328
|
-
}
|
|
3329
|
-
}
|
|
3330
|
-
// 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
|
|
3331
|
-
if (isIndentedLayout(layout)) {
|
|
3332
|
-
if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
|
|
3333
|
-
targetPath = Path.next(targetPath);
|
|
3334
|
-
}
|
|
3335
|
-
if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
|
|
3336
|
-
targetPath = Path.next(targetPath);
|
|
3337
|
-
}
|
|
3338
|
-
if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
|
|
3339
|
-
targetPath.push(dropTarget.target.children.length);
|
|
3340
|
-
}
|
|
3341
|
-
if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
|
|
3342
|
-
targetPath.push(dropTarget.target.children.length);
|
|
3343
|
-
}
|
|
3344
|
-
}
|
|
3345
|
-
return targetPath;
|
|
3346
|
-
};
|
|
3347
|
-
const updateRightNodeCount = (board, activeComponent, targetComponent, detectResult) => {
|
|
3348
|
-
let rightNodeCount;
|
|
3349
|
-
const mindElement = findUpElement(targetComponent.node.origin).root;
|
|
3350
|
-
const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
|
|
3351
|
-
const activeIndex = mindComponent?.root.children.indexOf(activeComponent.node);
|
|
3352
|
-
const targetIndex = mindComponent?.root.children.indexOf(targetComponent.node);
|
|
3353
|
-
const activeParent = MindElement.getParent(activeComponent.element);
|
|
3354
|
-
const targetParent = MindElement.findParent(targetComponent.element);
|
|
3355
|
-
const isActiveOnRight = activeIndex !== -1 && activeIndex <= activeParent.rightNodeCount - 1;
|
|
3356
|
-
const isTargetOnRight = targetParent && targetIndex !== -1 && targetIndex <= targetParent.rightNodeCount - 1;
|
|
3357
|
-
const isBothOnRight = isActiveOnRight && isTargetOnRight;
|
|
3358
|
-
const rootChildCount = mindComponent.root.children?.length;
|
|
3359
|
-
const rootRightNodeCount = mindComponent?.root.origin.rightNodeCount;
|
|
3360
|
-
if (!isBothOnRight) {
|
|
3361
|
-
if (isActiveOnRight) {
|
|
3362
|
-
rightNodeCount = rootChildCount < rootRightNodeCount ? rootChildCount - 1 : rootRightNodeCount - 1;
|
|
3363
|
-
Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, activeParent));
|
|
3364
|
-
}
|
|
3365
|
-
if (isTargetOnRight && detectResult !== 'right') {
|
|
3366
|
-
rightNodeCount = rootChildCount < rootRightNodeCount ? rootRightNodeCount : rootRightNodeCount + 1;
|
|
3367
|
-
const parent = MindElement.getParent(targetComponent.element);
|
|
3368
|
-
Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, parent));
|
|
3369
|
-
}
|
|
3370
|
-
//二级子节点拖动到根节点左侧
|
|
3371
|
-
if (targetComponent.node.origin.isRoot && detectResult === 'left' && activeIndex === -1) {
|
|
3372
|
-
rightNodeCount = rootChildCount;
|
|
3373
|
-
Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.element));
|
|
3374
|
-
}
|
|
3375
|
-
}
|
|
3376
|
-
};
|
|
3377
|
-
const IS_DRAGGING = new WeakMap();
|
|
3378
|
-
const isDragging = (board) => {
|
|
3379
|
-
return !!IS_DRAGGING.get(board);
|
|
3380
|
-
};
|
|
3381
|
-
const setIsDragging = (board, state) => {
|
|
3382
|
-
IS_DRAGGING.set(board, state);
|
|
3383
|
-
};
|
|
3384
|
-
const updateAbstractInDnd = (board, deletableElements, originPath) => {
|
|
3385
|
-
const refs = insertElementHandleAbstract(board, originPath, false);
|
|
3386
|
-
deleteElementHandleAbstract(board, deletableElements, refs);
|
|
3387
|
-
MindTransforms.setAbstractsByRefs(board, refs);
|
|
3388
|
-
};
|
|
3389
|
-
|
|
3390
3163
|
const DRAG_MOVE_BUFFER = 5;
|
|
3391
3164
|
const withDnd = (board) => {
|
|
3392
|
-
const { mousedown, mousemove, globalMouseup
|
|
3393
|
-
let
|
|
3165
|
+
const { mousedown, mousemove, globalMouseup } = board;
|
|
3166
|
+
let activeElements = [];
|
|
3167
|
+
let correspondingElements = [];
|
|
3394
3168
|
let startPoint;
|
|
3395
|
-
let
|
|
3169
|
+
let dragFakeNodeG;
|
|
3396
3170
|
let fakeDropNodeG;
|
|
3397
3171
|
let dropTarget = null;
|
|
3172
|
+
let targetPath;
|
|
3398
3173
|
board.mousedown = (event) => {
|
|
3399
3174
|
if (board.options.readonly || IS_TEXT_EDITABLE.get(board) || event.button === 2) {
|
|
3400
3175
|
mousedown(event);
|
|
@@ -3403,156 +3178,137 @@ const withDnd = (board) => {
|
|
|
3403
3178
|
// 确认是否 hit 节点
|
|
3404
3179
|
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3405
3180
|
const selectedElements = getSelectedElements(board);
|
|
3406
|
-
board
|
|
3407
|
-
if (
|
|
3181
|
+
depthFirstRecursion(board, element => {
|
|
3182
|
+
if (activeElements.length || !MindElement.isMindElement(board, element)) {
|
|
3408
3183
|
return;
|
|
3409
3184
|
}
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3185
|
+
const isHitElement = isHitMindElement(board, point, element) && !element.isRoot && !AbstractNode.isAbstract(element);
|
|
3186
|
+
const isAllMindElement = selectedElements.every(element => MindElement.isMindElement(board, element));
|
|
3187
|
+
const isMultiple = isHitElement && selectedElements.length > 1 && selectedElements.includes(element) && isAllMindElement;
|
|
3188
|
+
const isSingle = isHitElement && !(selectedElements.length > 1 && selectedElements.includes(element));
|
|
3189
|
+
if (isSingle) {
|
|
3190
|
+
activeElements = [element];
|
|
3191
|
+
startPoint = point;
|
|
3192
|
+
}
|
|
3193
|
+
else if (isMultiple) {
|
|
3194
|
+
activeElements = getFirstLevelElement(selectedElements);
|
|
3195
|
+
startPoint = point;
|
|
3196
|
+
}
|
|
3197
|
+
}, node => {
|
|
3198
|
+
if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
|
|
3199
|
+
return true;
|
|
3200
|
+
}
|
|
3201
|
+
else {
|
|
3202
|
+
return false;
|
|
3426
3203
|
}
|
|
3427
3204
|
});
|
|
3428
|
-
if (
|
|
3429
|
-
|
|
3205
|
+
if (activeElements.length) {
|
|
3206
|
+
correspondingElements = getOverallAbstracts(board, activeElements);
|
|
3430
3207
|
}
|
|
3431
3208
|
mousedown(event);
|
|
3432
3209
|
};
|
|
3433
3210
|
board.mousemove = (event) => {
|
|
3434
|
-
if (!board.options.readonly &&
|
|
3211
|
+
if (!board.options.readonly && activeElements?.length && startPoint) {
|
|
3435
3212
|
const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3436
3213
|
const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
|
|
3437
3214
|
if (distance < DRAG_MOVE_BUFFER) {
|
|
3438
3215
|
return;
|
|
3439
3216
|
}
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3217
|
+
setIsDragging(board, true);
|
|
3218
|
+
fakeDropNodeG?.remove();
|
|
3219
|
+
const detectPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3220
|
+
dropTarget = detectDropTarget(board, detectPoint, dropTarget, [...activeElements, ...correspondingElements]);
|
|
3221
|
+
if (dropTarget?.target) {
|
|
3222
|
+
targetPath = getPathByDropTarget(board, dropTarget);
|
|
3223
|
+
fakeDropNodeG = drawFakeDropNodeByPath(board, dropTarget.target, targetPath);
|
|
3446
3224
|
PlaitBoard.getHost(board).appendChild(fakeDropNodeG);
|
|
3447
|
-
PlaitBoard.getHost(board).appendChild(fakeDragNodeG);
|
|
3448
|
-
}
|
|
3449
|
-
else {
|
|
3450
|
-
if (fakeDragNodeG) {
|
|
3451
|
-
fakeDragNodeG.innerHTML = '';
|
|
3452
|
-
}
|
|
3453
|
-
fakeDropNodeG?.childNodes.forEach(node => {
|
|
3454
|
-
node.remove();
|
|
3455
|
-
});
|
|
3456
3225
|
}
|
|
3457
|
-
// fake dragging origin node
|
|
3458
3226
|
const offsetX = endPoint[0] - startPoint[0];
|
|
3459
3227
|
const offsetY = endPoint[1] - startPoint[1];
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
const fakeNodeG = drawRectangleNode(board, fakeDraggingNode);
|
|
3469
|
-
const richtextG = activeComponent.richtextG?.cloneNode(true);
|
|
3470
|
-
updateForeignObject$1(richtextG, textRectangle.width, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
|
|
3471
|
-
fakeDragNodeG?.append(fakeNodeG);
|
|
3472
|
-
fakeDragNodeG?.append(richtextG);
|
|
3473
|
-
// draw emojis
|
|
3474
|
-
if (MindElement.hasEmojis(activeElement)) {
|
|
3475
|
-
const fakeEmojisG = activeComponent.emojisDrawer.g.cloneNode(true);
|
|
3476
|
-
const foreignRectangle = getEmojiForeignRectangle(board, activeElement);
|
|
3477
|
-
updateForeignObject$1(fakeEmojisG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
|
|
3478
|
-
fakeDragNodeG?.append(fakeEmojisG);
|
|
3479
|
-
}
|
|
3480
|
-
// drop position detect
|
|
3481
|
-
const { x, y } = getRectangleByNode(fakeDraggingNode);
|
|
3482
|
-
const detectCenterPoint = [x + textRectangle.width / 2, y + textRectangle.height / 2];
|
|
3483
|
-
let detectResult = null;
|
|
3484
|
-
board.children.forEach((value) => {
|
|
3485
|
-
if (detectResult) {
|
|
3486
|
-
return;
|
|
3487
|
-
}
|
|
3488
|
-
if (PlaitMind.isMind(value)) {
|
|
3489
|
-
const mindmapComponent = ELEMENT_TO_COMPONENT.get(value);
|
|
3490
|
-
const root = mindmapComponent?.root;
|
|
3491
|
-
root.eachNode((node) => {
|
|
3492
|
-
if (detectResult) {
|
|
3493
|
-
return;
|
|
3494
|
-
}
|
|
3495
|
-
const directions = directionDetector(node, detectCenterPoint);
|
|
3496
|
-
if (directions) {
|
|
3497
|
-
detectResult = directionCorrector(board, node, directions);
|
|
3498
|
-
}
|
|
3499
|
-
dropTarget = null;
|
|
3500
|
-
if (detectResult && isValidTarget(activeComponent.node.origin, node.origin)) {
|
|
3501
|
-
dropTarget = { target: node.origin, detectResult: detectResult[0] };
|
|
3502
|
-
}
|
|
3503
|
-
});
|
|
3228
|
+
dragFakeNodeG?.remove();
|
|
3229
|
+
dragFakeNodeG = createG();
|
|
3230
|
+
[...activeElements, ...correspondingElements].forEach(element => {
|
|
3231
|
+
addActiveOnDragOrigin(element);
|
|
3232
|
+
if (activeElements.includes(element)) {
|
|
3233
|
+
const activeComponent = PlaitElement.getComponent(element);
|
|
3234
|
+
const nodeG = drawFakeDragNode(board, activeComponent, offsetX, offsetY);
|
|
3235
|
+
dragFakeNodeG?.appendChild(nodeG);
|
|
3504
3236
|
}
|
|
3505
3237
|
});
|
|
3506
|
-
|
|
3507
|
-
dropTarget = readjustmentDropTarget(board, dropTarget);
|
|
3508
|
-
drawPlaceholderDropNodeG(board, dropTarget, fakeDropNodeG);
|
|
3509
|
-
}
|
|
3238
|
+
PlaitBoard.getHost(board).appendChild(dragFakeNodeG);
|
|
3510
3239
|
}
|
|
3511
3240
|
mousemove(event);
|
|
3512
3241
|
};
|
|
3513
3242
|
board.globalMouseup = (event) => {
|
|
3514
|
-
if (!board.options.readonly &&
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
const
|
|
3521
|
-
const
|
|
3522
|
-
|
|
3523
|
-
const
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
targetPath = PlaitBoard.findPath(board, targetComponent.element);
|
|
3532
|
-
targetPath.push(0);
|
|
3533
|
-
const rightNodeCount = targetComponent.node.origin.rightNodeCount + 1;
|
|
3534
|
-
newElement = { isCollapsed: false, rightNodeCount };
|
|
3243
|
+
if (!board.options.readonly && activeElements?.length) {
|
|
3244
|
+
const elements = [...activeElements, ...correspondingElements];
|
|
3245
|
+
if (isDragging(board)) {
|
|
3246
|
+
elements.forEach(element => removeActiveOnDragOrigin(element));
|
|
3247
|
+
}
|
|
3248
|
+
if (dropTarget) {
|
|
3249
|
+
const targetPathRef = board.pathRef(targetPath);
|
|
3250
|
+
const targetElementPathRef = board.pathRef(PlaitBoard.findPath(board, dropTarget.target));
|
|
3251
|
+
const abstractRefs = getValidAbstractRefs(board, elements);
|
|
3252
|
+
const normalElements = elements
|
|
3253
|
+
.filter(element => !abstractRefs.some(refs => refs.abstract === element))
|
|
3254
|
+
.map(element => {
|
|
3255
|
+
if (AbstractNode.isAbstract(element)) {
|
|
3256
|
+
return adjustAbstractToNode(element);
|
|
3257
|
+
}
|
|
3258
|
+
if (PlaitMind.isMind(element)) {
|
|
3259
|
+
return adjustRootToNode(board, element);
|
|
3535
3260
|
}
|
|
3536
|
-
|
|
3261
|
+
return element;
|
|
3262
|
+
});
|
|
3263
|
+
const effectedAbstracts = deleteElementHandleAbstract(board, elements);
|
|
3264
|
+
insertElementHandleAbstract(board, targetPath, normalElements.length, false, effectedAbstracts);
|
|
3265
|
+
MindTransforms.setAbstractsByRefs(board, effectedAbstracts);
|
|
3266
|
+
MindTransforms.removeElements(board, elements);
|
|
3267
|
+
let insertPath = targetPathRef.current;
|
|
3268
|
+
const parentPath = Path.parent(targetPathRef.current || targetPath);
|
|
3269
|
+
if (!insertPath) {
|
|
3270
|
+
const parent = PlaitNode.get(board, parentPath);
|
|
3271
|
+
const children = getNonAbstractChildren(parent);
|
|
3272
|
+
insertPath = [...parentPath, children.length || 0];
|
|
3537
3273
|
}
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3274
|
+
MindTransforms.insertNodes(board, normalElements, insertPath);
|
|
3275
|
+
if (abstractRefs.length) {
|
|
3276
|
+
MindTransforms.insertAbstractNodes(board, abstractRefs, normalElements, insertPath);
|
|
3277
|
+
}
|
|
3278
|
+
const shouldChangeRoot = isInRightBranchOfStandardLayout(dropTarget?.target) &&
|
|
3279
|
+
targetElementPathRef.current &&
|
|
3280
|
+
(Path.isSibling(targetPath, targetElementPathRef.current) || Path.equals(targetPath, targetElementPathRef.current));
|
|
3281
|
+
if (shouldChangeRoot && targetElementPathRef.current) {
|
|
3282
|
+
changeRightNodeCount(board, targetElementPathRef.current.slice(0, 1), normalElements.length);
|
|
3283
|
+
}
|
|
3284
|
+
if (targetElementPathRef.current &&
|
|
3285
|
+
targetPathRef.current &&
|
|
3286
|
+
Path.isAncestor(targetElementPathRef.current, targetPathRef.current) &&
|
|
3287
|
+
dropTarget.target.isCollapsed) {
|
|
3288
|
+
Transforms.setNode(board, { isCollapsed: false }, targetElementPathRef.current);
|
|
3289
|
+
}
|
|
3290
|
+
targetElementPathRef.unref();
|
|
3291
|
+
targetPathRef.unref();
|
|
3292
|
+
const selectedElements = getSelectedElements(board);
|
|
3293
|
+
let setActiveElements = [];
|
|
3294
|
+
depthFirstRecursion(board, node => {
|
|
3295
|
+
const isSelected = selectedElements.some(element => element.id === node.id);
|
|
3296
|
+
if (isSelected) {
|
|
3297
|
+
setActiveElements.push(node);
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
Transforms.setSelectionWithTemporaryElements(board, setActiveElements);
|
|
3542
3301
|
}
|
|
3543
3302
|
setIsDragging(board, false);
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3303
|
+
activeElements = [];
|
|
3304
|
+
dragFakeNodeG?.remove();
|
|
3305
|
+
dragFakeNodeG = undefined;
|
|
3547
3306
|
fakeDropNodeG?.remove();
|
|
3548
3307
|
fakeDropNodeG = undefined;
|
|
3549
3308
|
dropTarget = null;
|
|
3550
3309
|
}
|
|
3551
3310
|
globalMouseup(event);
|
|
3552
3311
|
};
|
|
3553
|
-
board.keydown = (event) => {
|
|
3554
|
-
keydown(event);
|
|
3555
|
-
};
|
|
3556
3312
|
return board;
|
|
3557
3313
|
};
|
|
3558
3314
|
|
|
@@ -3560,16 +3316,11 @@ const buildClipboardData = (board, selectedElements) => {
|
|
|
3560
3316
|
let result = [];
|
|
3561
3317
|
// get overall abstract
|
|
3562
3318
|
const overallAbstracts = getOverallAbstracts(board, selectedElements);
|
|
3319
|
+
// get valid abstract refs
|
|
3320
|
+
const validAbstractRefs = getValidAbstractRefs(board, [...selectedElements, ...overallAbstracts]);
|
|
3563
3321
|
// keep correct order
|
|
3564
|
-
const newSelectedElements = selectedElements.filter(
|
|
3565
|
-
newSelectedElements.push(...
|
|
3566
|
-
// get correct start and end in selected elements
|
|
3567
|
-
function getCorrectStartEnd(abstract) {
|
|
3568
|
-
const parent = MindElement.getParent(abstract);
|
|
3569
|
-
const startElement = parent.children[abstract.start];
|
|
3570
|
-
const index = selectedElements.indexOf(startElement);
|
|
3571
|
-
return { start: index, end: index + (abstract.end - abstract.start) };
|
|
3572
|
-
}
|
|
3322
|
+
const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
|
|
3323
|
+
newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
|
|
3573
3324
|
const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
|
|
3574
3325
|
const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
|
|
3575
3326
|
newSelectedElements.forEach((element, index) => {
|
|
@@ -3577,8 +3328,9 @@ const buildClipboardData = (board, selectedElements) => {
|
|
|
3577
3328
|
const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
|
|
3578
3329
|
const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
|
|
3579
3330
|
// handle invalid abstract
|
|
3580
|
-
|
|
3581
|
-
|
|
3331
|
+
const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
|
|
3332
|
+
if (AbstractNode.isAbstract(element) && abstractRef) {
|
|
3333
|
+
const { start, end } = getRelativeStartEndByAbstractRef(abstractRef, newSelectedElements);
|
|
3582
3334
|
result.push({
|
|
3583
3335
|
...element,
|
|
3584
3336
|
points,
|
|
@@ -3633,7 +3385,7 @@ const insertClipboardData = (board, elements, targetPoint) => {
|
|
|
3633
3385
|
newElement = copyNewNode(item);
|
|
3634
3386
|
if (hasTargetParent) {
|
|
3635
3387
|
if (item.isRoot) {
|
|
3636
|
-
newElement =
|
|
3388
|
+
newElement = adjustRootToNode(board, newElement);
|
|
3637
3389
|
}
|
|
3638
3390
|
// handle abstract start and end
|
|
3639
3391
|
if (AbstractNode.isAbstract(newElement)) {
|
|
@@ -3646,10 +3398,10 @@ const insertClipboardData = (board, elements, targetPoint) => {
|
|
|
3646
3398
|
const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
|
|
3647
3399
|
newElement.points = [point];
|
|
3648
3400
|
if (AbstractNode.isAbstract(item)) {
|
|
3649
|
-
newElement =
|
|
3401
|
+
newElement = adjustAbstractToNode(newElement);
|
|
3650
3402
|
}
|
|
3651
3403
|
if (!item.isRoot) {
|
|
3652
|
-
newElement =
|
|
3404
|
+
newElement = adjustNodeToRoot(board, newElement);
|
|
3653
3405
|
}
|
|
3654
3406
|
path = [board.children.length];
|
|
3655
3407
|
}
|
|
@@ -3680,8 +3432,8 @@ const withAbstract = (board) => {
|
|
|
3680
3432
|
const point = transformPoint(board, toPoint(event.x, event.y, host));
|
|
3681
3433
|
activeAbstractElement = activeAbstractElements.find(element => {
|
|
3682
3434
|
abstractHandlePosition = getHitAbstractHandle(board, element, point);
|
|
3683
|
-
if (newBoard?.
|
|
3684
|
-
newBoard.
|
|
3435
|
+
if (newBoard?.onAbstractResize) {
|
|
3436
|
+
newBoard.onAbstractResize(AbstractResizeState.start);
|
|
3685
3437
|
}
|
|
3686
3438
|
return abstractHandlePosition;
|
|
3687
3439
|
});
|
|
@@ -3715,8 +3467,8 @@ const withAbstract = (board) => {
|
|
|
3715
3467
|
children = leftChildren;
|
|
3716
3468
|
}
|
|
3717
3469
|
}
|
|
3718
|
-
if (newBoard?.
|
|
3719
|
-
newBoard.
|
|
3470
|
+
if (newBoard?.onAbstractResize) {
|
|
3471
|
+
newBoard.onAbstractResize(AbstractResizeState.resizing);
|
|
3720
3472
|
}
|
|
3721
3473
|
const resizingLocation = isHorizontal ? endPoint[1] : endPoint[0];
|
|
3722
3474
|
const parent = MindElement.getNode(parentElement);
|
|
@@ -3748,8 +3500,8 @@ const withAbstract = (board) => {
|
|
|
3748
3500
|
startPoint = undefined;
|
|
3749
3501
|
abstractHandlePosition = undefined;
|
|
3750
3502
|
if (activeAbstractElement) {
|
|
3751
|
-
if (newBoard?.
|
|
3752
|
-
newBoard.
|
|
3503
|
+
if (newBoard?.onAbstractResize) {
|
|
3504
|
+
newBoard.onAbstractResize(AbstractResizeState.end);
|
|
3753
3505
|
}
|
|
3754
3506
|
if (newProperty) {
|
|
3755
3507
|
const path = PlaitBoard.findPath(board, activeAbstractElement);
|
|
@@ -3766,7 +3518,7 @@ const withAbstract = (board) => {
|
|
|
3766
3518
|
return board;
|
|
3767
3519
|
};
|
|
3768
3520
|
|
|
3769
|
-
const
|
|
3521
|
+
const withMindExtend = (board) => {
|
|
3770
3522
|
const newBoard = board;
|
|
3771
3523
|
newBoard.drawEmoji = (emoji, element) => {
|
|
3772
3524
|
throw new Error('Not implement drawEmoji method error.');
|
|
@@ -3777,6 +3529,85 @@ const withExtendMind = (board) => {
|
|
|
3777
3529
|
return newBoard;
|
|
3778
3530
|
};
|
|
3779
3531
|
|
|
3532
|
+
const DefaultHotkey = 'm';
|
|
3533
|
+
const withCreateMind = (board) => {
|
|
3534
|
+
const newBoard = board;
|
|
3535
|
+
const { keydown, mousemove, mouseup } = board;
|
|
3536
|
+
let fakeCreateNodeRef = null;
|
|
3537
|
+
newBoard.mousemove = (event) => {
|
|
3538
|
+
if (PlaitBoard.isReadonly(board)) {
|
|
3539
|
+
mousemove(event);
|
|
3540
|
+
return;
|
|
3541
|
+
}
|
|
3542
|
+
if (PlaitBoard.isPointer(board, MindPointerType.mind)) {
|
|
3543
|
+
throttleRAF(() => {
|
|
3544
|
+
const movingPoint = PlaitBoard.getMovingPoint(board);
|
|
3545
|
+
if (movingPoint) {
|
|
3546
|
+
const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
|
|
3547
|
+
const emptyMind = createEmptyMind(board, targetPoint);
|
|
3548
|
+
const nodeRectangle = getRectangleByElement(newBoard, targetPoint, emptyMind);
|
|
3549
|
+
const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
|
|
3550
|
+
const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
|
|
3551
|
+
if (!fakeCreateNodeRef) {
|
|
3552
|
+
const { richtextComponentRef, richtextG, foreignObject } = drawTopicByElement(newBoard, topicRectangle, emptyMind);
|
|
3553
|
+
fakeCreateNodeRef = {
|
|
3554
|
+
instanceRef: richtextComponentRef,
|
|
3555
|
+
nodeG,
|
|
3556
|
+
foreignObject,
|
|
3557
|
+
topicG: richtextG
|
|
3558
|
+
};
|
|
3559
|
+
richtextComponentRef.changeDetectorRef.detectChanges();
|
|
3560
|
+
PlaitBoard.getHost(board).append(...[fakeCreateNodeRef.nodeG, fakeCreateNodeRef.topicG]);
|
|
3561
|
+
}
|
|
3562
|
+
else {
|
|
3563
|
+
fakeCreateNodeRef.nodeG.remove();
|
|
3564
|
+
fakeCreateNodeRef.nodeG = nodeG;
|
|
3565
|
+
PlaitBoard.getHost(board).append(nodeG);
|
|
3566
|
+
PlaitBoard.getHost(board).append(fakeCreateNodeRef.topicG);
|
|
3567
|
+
updateForeignObject$1(fakeCreateNodeRef.topicG, topicRectangle.width, topicRectangle.height, topicRectangle.x, topicRectangle.y);
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
});
|
|
3571
|
+
}
|
|
3572
|
+
else {
|
|
3573
|
+
destroy();
|
|
3574
|
+
}
|
|
3575
|
+
mousemove(event);
|
|
3576
|
+
};
|
|
3577
|
+
newBoard.mouseup = (event) => {
|
|
3578
|
+
const movingPoint = PlaitBoard.getMovingPoint(board);
|
|
3579
|
+
if (movingPoint && fakeCreateNodeRef && PlaitBoard.isPointer(board, MindPointerType.mind)) {
|
|
3580
|
+
const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
|
|
3581
|
+
const emptyMind = createEmptyMind(board, targetPoint);
|
|
3582
|
+
Transforms.insertNode(board, emptyMind, [board.children.length]);
|
|
3583
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
3584
|
+
}
|
|
3585
|
+
destroy();
|
|
3586
|
+
mouseup(event);
|
|
3587
|
+
};
|
|
3588
|
+
board.keydown = (event) => {
|
|
3589
|
+
if (PlaitBoard.isReadonly(board) || getSelectedElements(board).length > 0) {
|
|
3590
|
+
keydown(event);
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3593
|
+
if (event.key === DefaultHotkey && !PlaitBoard.isPointer(board, MindPointerType.mind)) {
|
|
3594
|
+
BoardTransforms.updatePointerType(board, MindPointerType.mind);
|
|
3595
|
+
event.preventDefault();
|
|
3596
|
+
return;
|
|
3597
|
+
}
|
|
3598
|
+
keydown(event);
|
|
3599
|
+
};
|
|
3600
|
+
function destroy() {
|
|
3601
|
+
if (fakeCreateNodeRef) {
|
|
3602
|
+
fakeCreateNodeRef.instanceRef.destroy();
|
|
3603
|
+
fakeCreateNodeRef.nodeG.remove();
|
|
3604
|
+
fakeCreateNodeRef.topicG.remove();
|
|
3605
|
+
fakeCreateNodeRef = null;
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
return newBoard;
|
|
3609
|
+
};
|
|
3610
|
+
|
|
3780
3611
|
const withMind = (board) => {
|
|
3781
3612
|
const { drawElement, dblclick, keydown, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
|
|
3782
3613
|
board.drawElement = (context) => {
|
|
@@ -3818,7 +3649,7 @@ const withMind = (board) => {
|
|
|
3818
3649
|
return isMovable(element);
|
|
3819
3650
|
};
|
|
3820
3651
|
board.keydown = (event) => {
|
|
3821
|
-
if (
|
|
3652
|
+
if (PlaitBoard.isReadonly(board)) {
|
|
3822
3653
|
keydown(event);
|
|
3823
3654
|
return;
|
|
3824
3655
|
}
|
|
@@ -3841,7 +3672,7 @@ const withMind = (board) => {
|
|
|
3841
3672
|
insertMindElement(board, selectedElement, findNewChildNodePath(board, selectedElement));
|
|
3842
3673
|
}
|
|
3843
3674
|
else {
|
|
3844
|
-
if (
|
|
3675
|
+
if (isInRightBranchOfStandardLayout(selectedElement)) {
|
|
3845
3676
|
changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
|
|
3846
3677
|
}
|
|
3847
3678
|
const abstractRefs = insertElementHandleAbstract(board, Path.next(selectedElementPath));
|
|
@@ -3852,7 +3683,10 @@ const withMind = (board) => {
|
|
|
3852
3683
|
}
|
|
3853
3684
|
if (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event)) {
|
|
3854
3685
|
event.preventDefault();
|
|
3855
|
-
|
|
3686
|
+
const deletableElements = getFirstLevelElement(selectedElements).reverse();
|
|
3687
|
+
const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
|
|
3688
|
+
MindTransforms.setAbstractsByRefs(board, abstractRefs);
|
|
3689
|
+
MindTransforms.removeElements(board, selectedElements);
|
|
3856
3690
|
let activeElement;
|
|
3857
3691
|
const firstLevelElements = getFirstLevelElement(selectedElements);
|
|
3858
3692
|
if (AbstractNode.isAbstract(firstLevelElements[0])) {
|
|
@@ -3898,7 +3732,7 @@ const withMind = (board) => {
|
|
|
3898
3732
|
keydown(event);
|
|
3899
3733
|
};
|
|
3900
3734
|
board.dblclick = (event) => {
|
|
3901
|
-
if (
|
|
3735
|
+
if (PlaitBoard.isReadonly(board)) {
|
|
3902
3736
|
dblclick(event);
|
|
3903
3737
|
return;
|
|
3904
3738
|
}
|
|
@@ -3907,9 +3741,16 @@ const withMind = (board) => {
|
|
|
3907
3741
|
.filter(value => PlaitMind.isMind(value))
|
|
3908
3742
|
.forEach(mindMap => {
|
|
3909
3743
|
depthFirstRecursion(mindMap, node => {
|
|
3910
|
-
if (!PlaitBoard.hasBeenTextEditing(board) &&
|
|
3744
|
+
if (!PlaitBoard.hasBeenTextEditing(board) && isHitMindElement(board, point, node)) {
|
|
3911
3745
|
enterNodeEditing(node);
|
|
3912
3746
|
}
|
|
3747
|
+
}, node => {
|
|
3748
|
+
if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
|
|
3749
|
+
return true;
|
|
3750
|
+
}
|
|
3751
|
+
else {
|
|
3752
|
+
return false;
|
|
3753
|
+
}
|
|
3913
3754
|
});
|
|
3914
3755
|
});
|
|
3915
3756
|
if (PlaitBoard.hasBeenTextEditing(board)) {
|
|
@@ -3947,10 +3788,13 @@ const withMind = (board) => {
|
|
|
3947
3788
|
};
|
|
3948
3789
|
board.deleteFragment = (data) => {
|
|
3949
3790
|
const selectedElements = getSelectedElements(board);
|
|
3950
|
-
|
|
3791
|
+
const deletableElements = getFirstLevelElement(selectedElements).reverse();
|
|
3792
|
+
const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
|
|
3793
|
+
MindTransforms.setAbstractsByRefs(board, abstractRefs);
|
|
3794
|
+
MindTransforms.removeElements(board, selectedElements);
|
|
3951
3795
|
deleteFragment(data);
|
|
3952
3796
|
};
|
|
3953
|
-
return
|
|
3797
|
+
return withMindExtend(withCreateMind(withAbstract(withDnd(board))));
|
|
3954
3798
|
};
|
|
3955
3799
|
|
|
3956
3800
|
class MindEmojiBaseComponent {
|
|
@@ -3992,5 +3836,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3992
3836
|
* Generated bundle index. Do not edit.
|
|
3993
3837
|
*/
|
|
3994
3838
|
|
|
3995
|
-
export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_COLORS, BRANCH_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, DefaultRootStyle, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, LayoutDirection, LayoutDirectionsMap, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindQueries, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection,
|
|
3839
|
+
export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_COLORS, BRANCH_WIDTH, BaseDrawer, DefaultAbstractNodeStyle, DefaultNodeStyle, DefaultRootStyle, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, addActiveOnDragOrigin, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNodeByPath, enterNodeEditing, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getPreviousAndNextByPath, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, insertElementHandleAbstract, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isDragging, isHitEmojis, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, readjustmentDropTarget, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
|
|
3996
3840
|
//# sourceMappingURL=plait-mind.mjs.map
|