@plait/draw 0.58.0 → 0.60.0
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/constants/geometry.d.ts +82 -1
- package/engines/uml/activity-class.d.ts +2 -0
- package/engines/uml/deletion.d.ts +2 -0
- package/engines/uml/note.d.ts +2 -0
- package/esm2022/constants/geometry.mjs +64 -4
- package/esm2022/engines/index.mjs +15 -2
- package/esm2022/engines/table/table.mjs +3 -2
- package/esm2022/engines/uml/activity-class.mjs +47 -0
- package/esm2022/engines/uml/deletion.mjs +31 -0
- package/esm2022/engines/uml/note.mjs +58 -0
- package/esm2022/generators/text.generator.mjs +5 -13
- package/esm2022/interfaces/geometry.mjs +11 -1
- package/esm2022/interfaces/index.mjs +2 -2
- package/esm2022/plugins/with-draw-fragment.mjs +3 -2
- package/esm2022/plugins/with-draw-hotkey.mjs +3 -3
- package/esm2022/plugins/with-draw.mjs +1 -1
- package/esm2022/plugins/with-geometry-create.mjs +13 -4
- package/esm2022/plugins/with-geometry-resize.mjs +3 -2
- package/esm2022/table.component.mjs +5 -3
- package/esm2022/transforms/swimlane.mjs +23 -20
- package/esm2022/utils/common.mjs +50 -21
- package/esm2022/utils/geometry.mjs +21 -9
- package/esm2022/utils/index.mjs +2 -1
- package/esm2022/utils/multi-text-geometry.mjs +8 -8
- package/esm2022/utils/swimlane.mjs +8 -2
- package/esm2022/utils/table.mjs +1 -1
- package/esm2022/utils/uml.mjs +88 -0
- package/fesm2022/plait-draw.mjs +861 -526
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/generators/text.generator.d.ts +0 -1
- package/interfaces/geometry.d.ts +11 -1
- package/package.json +1 -1
- package/transforms/geometry.d.ts +2 -2
- package/transforms/index.d.ts +2 -2
- package/utils/common.d.ts +5 -0
- package/utils/geometry.d.ts +30 -2
- package/utils/index.d.ts +1 -0
- package/utils/multi-text-geometry.d.ts +2 -2
- package/utils/uml.d.ts +3 -0
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ACTIVE_STROKE_WIDTH, ThemeColorMode, RectangleClient, idCreator, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType,
|
|
2
|
-
import { WithTextPluginKey, ELEMENT_TO_TEXT_MANAGES, getMemorizedLatest, memorizeLatest,
|
|
1
|
+
import { ACTIVE_STROKE_WIDTH, ThemeColorMode, RectangleClient, idCreator, distanceBetweenPointAndSegments, HIT_DISTANCE_BUFFER, rotatePointsByElement, isPolylineHitRectangle, rotateAntiPointsByElement, distanceBetweenPointAndPoint, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, depthFirstRecursion, PlaitBoard, getIsRecursionFunc, createG, SNAPPING_STROKE_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, createDebugGenerator, Point, arrowPoints, createPath, drawLinearPath, rotate, catmullRomFitting, setStrokeLinecap, findElements, createMask, createRect, PlaitElement, getSelectedElements, getElementById, Path, Direction, PlaitNode, hasValidAngle, toViewBoxPoint, toHostPoint, rotatePoints, getRectangleByElements, getSelectionAngle, rotatedDataPoints, isAxisChangedByAngle, isSelectionMoving, drawRectangle, getRectangleByAngle, getSnapRectangles, getTripleAxis, getMinPointDelta, SNAP_TOLERANCE, drawPointSnapLines, drawSolidLines, isPointInPolygon, getNearestPointBetweenPointAndSegments, isPointInEllipse, getNearestPointBetweenPointAndEllipse, getEllipseTangentSlope, getVectorFromPointAndSlope, drawRoundRectangle, isPointInRoundRectangle, setPathStrokeLinecap, getCrossingPointsBetweenEllipseAndSegment, drawLine as drawLine$1, RgbaToHEX, getHitElementByPoint, preventTouchMove, WritableClipboardOperationType, createClipboardContext, WritableClipboardType, addClipboardContext, setAngleForG, CursorClass, temporaryDisableSelection, PRESS_AND_MOVE_BUFFER, isMainPointer, throttleRAF, getAngleBetweenPoints, normalizeAngle, degreesToRadians, rotateElements, MERGING, ROTATE_HANDLE_CLASS_NAME, SELECTION_RECTANGLE_CLASS_NAME, isSelectedElement } from '@plait/core';
|
|
2
|
+
import { WithTextPluginKey, ELEMENT_TO_TEXT_MANAGES, getMemorizedLatest, memorizeLatest, RESIZE_HANDLE_DIAMETER, getPointOnPolyline, TRANSPARENT, getTextEditorsByElement, Generator, removeDuplicatePoints, generateElbowLineRoute, simplifyOrthogonalPoints, getExtendPoint, getUnitVectorByPointAndPoint, getPointByVectorComponent, getFirstTextManage, ActiveGenerator, isSourceAndTargetIntersect, getPoints, DEFAULT_ROUTE_MARGIN, getDirectionByVector, normalizeShapePoints, getFirstTextEditor, resetPointsAfterResize, getRectangleResizeHandleRefs, getRotatedResizeCursorClassByAngle, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, isCornerHandle, getIndexByResizeHandle, withResize, drawHandle, getSymmetricHandleIndex, getResizeHandlePointByIndex, getDirectionFactorByDirectionComponent, getCrossingPointsBetweenPointAndSegment, isPointOnSegment, getDirectionByPointOfRectangle, getDirectionFactor, rotateVector, getOppositeDirection, rotateVectorAnti90, getSourceAndTargetOuterRectangle, getNextPoint, PRIMARY_COLOR, CommonElementFlavour, canResize, drawPrimaryHandle, drawFillPrimaryHandle, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, getElementsText, acceptImageTypes, getElementOfFocusedImage, buildImage, isResizingByCondition, getRatioByPoint, getTextManages, ImageGenerator, ResizeHandle, addRotating, removeRotating, drawRotateHandle } from '@plait/common';
|
|
3
3
|
import { Alignment, TextManage, buildText, DEFAULT_FONT_SIZE, getTextSize, AlignEditor } from '@plait/text';
|
|
4
4
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
5
5
|
import { isKeyHotkey } from 'is-hotkey';
|
|
@@ -71,8 +71,18 @@ var UMLSymbols;
|
|
|
71
71
|
UMLSymbols["actor"] = "actor";
|
|
72
72
|
UMLSymbols["useCase"] = "useCase";
|
|
73
73
|
UMLSymbols["container"] = "container";
|
|
74
|
+
UMLSymbols["note"] = "note";
|
|
75
|
+
UMLSymbols["simpleClass"] = "simpleClass";
|
|
76
|
+
UMLSymbols["activityClass"] = "activityClass";
|
|
77
|
+
UMLSymbols["branchMerge"] = "branchMerge";
|
|
78
|
+
UMLSymbols["port"] = "port";
|
|
74
79
|
UMLSymbols["package"] = "package";
|
|
75
80
|
UMLSymbols["combinedFragment"] = "combinedFragment";
|
|
81
|
+
UMLSymbols["class"] = "class";
|
|
82
|
+
UMLSymbols["interface"] = "interface";
|
|
83
|
+
UMLSymbols["object"] = "object";
|
|
84
|
+
UMLSymbols["activation"] = "activation";
|
|
85
|
+
UMLSymbols["deletion"] = "deletion";
|
|
76
86
|
})(UMLSymbols || (UMLSymbols = {}));
|
|
77
87
|
var MultipleTextGeometryCommonTextKeys;
|
|
78
88
|
(function (MultipleTextGeometryCommonTextKeys) {
|
|
@@ -201,6 +211,22 @@ const DefaultPackageProperty = {
|
|
|
201
211
|
}
|
|
202
212
|
]
|
|
203
213
|
};
|
|
214
|
+
const DefaultActivationProperty = {
|
|
215
|
+
width: 18,
|
|
216
|
+
height: 80
|
|
217
|
+
};
|
|
218
|
+
const DefaultObjectProperty = {
|
|
219
|
+
width: 120,
|
|
220
|
+
height: 60
|
|
221
|
+
};
|
|
222
|
+
const DefaultDeletionProperty = {
|
|
223
|
+
width: 40,
|
|
224
|
+
height: 40
|
|
225
|
+
};
|
|
226
|
+
const DefaultPortProperty = {
|
|
227
|
+
width: 20,
|
|
228
|
+
height: 20
|
|
229
|
+
};
|
|
204
230
|
const DefaultCombinedFragmentProperty = {
|
|
205
231
|
width: 400,
|
|
206
232
|
height: 280,
|
|
@@ -217,6 +243,32 @@ const DefaultCombinedFragmentProperty = {
|
|
|
217
243
|
}
|
|
218
244
|
]
|
|
219
245
|
};
|
|
246
|
+
const DefaultClassProperty = {
|
|
247
|
+
width: 230,
|
|
248
|
+
height: 180,
|
|
249
|
+
texts: [
|
|
250
|
+
{ text: 'Class', align: Alignment.center },
|
|
251
|
+
{
|
|
252
|
+
text: '+ attribute1:type defaultValue\n+ attribute2:type\n- attribute3:type',
|
|
253
|
+
align: Alignment.left
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
text: '+ operation1(params):returnType\n- operation2(params)\n- operation3()',
|
|
257
|
+
align: Alignment.left
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
};
|
|
261
|
+
const DefaultInterfaceProperty = {
|
|
262
|
+
width: 230,
|
|
263
|
+
height: 140,
|
|
264
|
+
texts: [
|
|
265
|
+
{ text: '<<interface>>\nInterface', align: Alignment.center },
|
|
266
|
+
{
|
|
267
|
+
text: '+ operation1(params):returnType\n- operation2(params)\n- operation3()',
|
|
268
|
+
align: Alignment.left
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
};
|
|
220
272
|
const DefaultSwimlaneVerticalProperty = {
|
|
221
273
|
width: 450,
|
|
222
274
|
height: 500
|
|
@@ -263,8 +315,18 @@ const DefaultUMLPropertyMap = {
|
|
|
263
315
|
[UMLSymbols.actor]: DefaultActorProperty,
|
|
264
316
|
[UMLSymbols.useCase]: DefaultDocumentProperty,
|
|
265
317
|
[UMLSymbols.container]: DefaultContainerProperty,
|
|
318
|
+
[UMLSymbols.note]: DefaultObjectProperty,
|
|
266
319
|
[UMLSymbols.package]: DefaultPackageProperty,
|
|
267
|
-
[UMLSymbols.combinedFragment]: DefaultCombinedFragmentProperty
|
|
320
|
+
[UMLSymbols.combinedFragment]: DefaultCombinedFragmentProperty,
|
|
321
|
+
[UMLSymbols.class]: DefaultClassProperty,
|
|
322
|
+
[UMLSymbols.interface]: DefaultInterfaceProperty,
|
|
323
|
+
[UMLSymbols.activation]: DefaultActivationProperty,
|
|
324
|
+
[UMLSymbols.object]: DefaultObjectProperty,
|
|
325
|
+
[UMLSymbols.deletion]: DefaultDeletionProperty,
|
|
326
|
+
[UMLSymbols.activityClass]: DefaultObjectProperty,
|
|
327
|
+
[UMLSymbols.simpleClass]: DefaultObjectProperty,
|
|
328
|
+
[UMLSymbols.port]: DefaultPortProperty,
|
|
329
|
+
[UMLSymbols.branchMerge]: DefaultDeletionProperty
|
|
268
330
|
};
|
|
269
331
|
const MultipleTextGeometryTextKeys = {
|
|
270
332
|
[UMLSymbols.package]: Object.keys(MultipleTextGeometryCommonTextKeys),
|
|
@@ -272,12 +334,20 @@ const MultipleTextGeometryTextKeys = {
|
|
|
272
334
|
};
|
|
273
335
|
const DefaultSwimlanePropertyMap = {
|
|
274
336
|
[SwimlaneSymbols.swimlaneHorizontal]: DefaultSwimlaneHorizontalProperty,
|
|
275
|
-
[SwimlaneSymbols.swimlaneVertical]: DefaultSwimlaneVerticalProperty
|
|
337
|
+
[SwimlaneSymbols.swimlaneVertical]: DefaultSwimlaneVerticalProperty
|
|
276
338
|
};
|
|
277
339
|
const LINE_HIT_GEOMETRY_BUFFER = 10;
|
|
278
340
|
const LINE_SNAPPING_BUFFER = 6;
|
|
279
341
|
const LINE_SNAPPING_CONNECTOR_BUFFER = 8;
|
|
280
|
-
const GEOMETRY_WITHOUT_TEXT = [
|
|
342
|
+
const GEOMETRY_WITHOUT_TEXT = [
|
|
343
|
+
FlowchartSymbols.or,
|
|
344
|
+
FlowchartSymbols.summingJunction,
|
|
345
|
+
UMLSymbols.activation,
|
|
346
|
+
UMLSymbols.deletion,
|
|
347
|
+
UMLSymbols.port,
|
|
348
|
+
UMLSymbols.branchMerge
|
|
349
|
+
];
|
|
350
|
+
const GEOMETRY_WITH_MULTIPLE_TEXT = [UMLSymbols.package, UMLSymbols.combinedFragment];
|
|
281
351
|
|
|
282
352
|
const getGeometryPointers = () => {
|
|
283
353
|
return [...Object.keys(BasicShapes), ...Object.keys(FlowchartSymbols), ...Object.keys(UMLSymbols)];
|
|
@@ -364,23 +434,15 @@ class TextGenerator {
|
|
|
364
434
|
const textPlugins = (this.board.getPluginOptions(WithTextPluginKey) || {}).textPlugins;
|
|
365
435
|
this.textManages = this.texts.map(text => {
|
|
366
436
|
const textManage = this.createTextManage(text, textPlugins);
|
|
367
|
-
setTextManage(this.
|
|
437
|
+
setTextManage(getTextKey(this.element, text), textManage);
|
|
368
438
|
return textManage;
|
|
369
439
|
});
|
|
370
440
|
ELEMENT_TO_TEXT_MANAGES.set(this.element, this.textManages);
|
|
371
441
|
}
|
|
372
|
-
getTextKey(text) {
|
|
373
|
-
if (isMultipleTextGeometry(this.element)) {
|
|
374
|
-
return `${this.element.id}-${text.key}`;
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
return text.key;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
442
|
draw(elementG) {
|
|
381
443
|
const centerPoint = RectangleClient.getCenterPoint(this.board.getRectangle(this.element));
|
|
382
444
|
this.texts.forEach(drawShapeText => {
|
|
383
|
-
const textManage = getTextManage(this.
|
|
445
|
+
const textManage = getTextManage(getTextKey(this.element, drawShapeText));
|
|
384
446
|
if (drawShapeText.text && textManage) {
|
|
385
447
|
textManage.draw(drawShapeText.text);
|
|
386
448
|
elementG.append(textManage.g);
|
|
@@ -409,7 +471,7 @@ class TextGenerator {
|
|
|
409
471
|
}
|
|
410
472
|
currentDrawShapeTexts.forEach(drawShapeText => {
|
|
411
473
|
if (drawShapeText.text) {
|
|
412
|
-
let textManage = getTextManage(this.
|
|
474
|
+
let textManage = getTextManage(getTextKey(this.element, drawShapeText));
|
|
413
475
|
if (!textManage) {
|
|
414
476
|
textManage = this.createTextManage(drawShapeText, textPlugins);
|
|
415
477
|
setTextManage(drawShapeText.key, textManage);
|
|
@@ -682,156 +744,443 @@ const getMemorizedLatestShape = (board) => {
|
|
|
682
744
|
return memorizedShape.get(board);
|
|
683
745
|
};
|
|
684
746
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
if (PlaitDrawElement.isText(element)) {
|
|
699
|
-
return 0;
|
|
700
|
-
}
|
|
701
|
-
const strokeWidth = element.strokeWidth || DefaultDrawStyle.strokeWidth;
|
|
702
|
-
return strokeWidth;
|
|
703
|
-
};
|
|
704
|
-
const insertElement = (board, element) => {
|
|
705
|
-
memorizeLatestShape(board, element.shape);
|
|
706
|
-
Transforms.insertNode(board, element, [board.children.length]);
|
|
707
|
-
clearSelectedElement(board);
|
|
708
|
-
addSelectedElement(board, element);
|
|
709
|
-
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
710
|
-
};
|
|
711
|
-
const isDrawElementsIncludeText = (elements) => {
|
|
712
|
-
return elements.some(item => {
|
|
713
|
-
if (PlaitDrawElement.isText(item)) {
|
|
714
|
-
return true;
|
|
715
|
-
}
|
|
716
|
-
if (PlaitDrawElement.isImage(item)) {
|
|
717
|
-
return false;
|
|
718
|
-
}
|
|
719
|
-
if (PlaitDrawElement.isGeometry(item)) {
|
|
720
|
-
return isGeometryIncludeText(item);
|
|
747
|
+
var LineResizeHandle;
|
|
748
|
+
(function (LineResizeHandle) {
|
|
749
|
+
LineResizeHandle["source"] = "source";
|
|
750
|
+
LineResizeHandle["target"] = "target";
|
|
751
|
+
LineResizeHandle["addHandle"] = "addHandle";
|
|
752
|
+
})(LineResizeHandle || (LineResizeHandle = {}));
|
|
753
|
+
const getHitLineResizeHandleRef = (board, element, point) => {
|
|
754
|
+
let dataPoints = PlaitLine.getPoints(board, element);
|
|
755
|
+
const index = getHitPointIndex(dataPoints, point);
|
|
756
|
+
if (index !== -1) {
|
|
757
|
+
const handleIndex = index;
|
|
758
|
+
if (index === 0) {
|
|
759
|
+
return { handle: LineResizeHandle.source, handleIndex };
|
|
721
760
|
}
|
|
722
|
-
if (
|
|
723
|
-
|
|
724
|
-
return editors.length > 0;
|
|
761
|
+
if (index === dataPoints.length - 1) {
|
|
762
|
+
return { handle: LineResizeHandle.target, handleIndex };
|
|
725
763
|
}
|
|
726
|
-
|
|
727
|
-
|
|
764
|
+
// elbow line, data points only verify source connection point and target connection point
|
|
765
|
+
if (element.shape !== LineShape.elbow) {
|
|
766
|
+
return { handleIndex };
|
|
728
767
|
}
|
|
729
|
-
|
|
768
|
+
}
|
|
769
|
+
const middlePoints = getMiddlePoints(board, element);
|
|
770
|
+
const indexOfMiddlePoints = getHitPointIndex(middlePoints, point);
|
|
771
|
+
if (indexOfMiddlePoints !== -1) {
|
|
772
|
+
return {
|
|
773
|
+
handle: LineResizeHandle.addHandle,
|
|
774
|
+
handleIndex: indexOfMiddlePoints
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
return undefined;
|
|
778
|
+
};
|
|
779
|
+
function getHitPointIndex(points, movingPoint) {
|
|
780
|
+
const rectangles = points.map(point => {
|
|
781
|
+
return {
|
|
782
|
+
x: point[0] - RESIZE_HANDLE_DIAMETER / 2,
|
|
783
|
+
y: point[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
784
|
+
width: RESIZE_HANDLE_DIAMETER,
|
|
785
|
+
height: RESIZE_HANDLE_DIAMETER
|
|
786
|
+
};
|
|
787
|
+
});
|
|
788
|
+
const rectangle = rectangles.find(rectangle => {
|
|
789
|
+
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([movingPoint, movingPoint]), rectangle);
|
|
790
|
+
});
|
|
791
|
+
return rectangle ? rectangles.indexOf(rectangle) : -1;
|
|
792
|
+
}
|
|
793
|
+
const getHitLineTextIndex = (board, element, point) => {
|
|
794
|
+
const texts = element.texts;
|
|
795
|
+
if (!texts.length)
|
|
796
|
+
return -1;
|
|
797
|
+
const points = getLinePoints(board, element);
|
|
798
|
+
return texts.findIndex(text => {
|
|
799
|
+
const center = getPointOnPolyline(points, text.position);
|
|
800
|
+
const rectangle = {
|
|
801
|
+
x: center[0] - text.width / 2,
|
|
802
|
+
y: center[1] - text.height / 2,
|
|
803
|
+
width: text.width,
|
|
804
|
+
height: text.height
|
|
805
|
+
};
|
|
806
|
+
return RectangleClient.isHit(rectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
730
807
|
});
|
|
731
808
|
};
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
const ref = getSnappingRef(board, hitElement, point);
|
|
736
|
-
if (ref.isHitConnector || ref.isHitEdge) {
|
|
737
|
-
return hitElement;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
return null;
|
|
809
|
+
|
|
810
|
+
const isMultipleTextShape = (shape) => {
|
|
811
|
+
return GEOMETRY_WITH_MULTIPLE_TEXT.includes(shape);
|
|
741
812
|
};
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
const connectorPoint = getHitConnectorPoint(rotatedPoint, hitElement);
|
|
745
|
-
const edgePoint = getNearestPoint(hitElement, rotatedPoint);
|
|
746
|
-
const isHitEdge = isHitEdgeOfShape(board, hitElement, rotatedPoint, LINE_SNAPPING_BUFFER);
|
|
747
|
-
return { isHitEdge, isHitConnector: !!connectorPoint, connectorPoint, edgePoint };
|
|
813
|
+
const isMultipleTextGeometry = (geometry) => {
|
|
814
|
+
return PlaitDrawElement.isGeometry(geometry) && isMultipleTextShape(geometry.shape);
|
|
748
815
|
};
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
traverseDrawShapes(board, (element) => {
|
|
752
|
-
if (hitShape === null && isInsideOfShape(board, element, rotateAntiPointsByElement(point, element) || point, offset * 2)) {
|
|
753
|
-
hitShape = element;
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
return hitShape;
|
|
816
|
+
const getMultipleTextGeometryTextKeys = (shape) => {
|
|
817
|
+
return MultipleTextGeometryTextKeys[shape];
|
|
757
818
|
};
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
819
|
+
const createMultipleTextGeometryElement = (shape, points, options = {}) => {
|
|
820
|
+
const id = idCreator();
|
|
821
|
+
const drawShapeTexts = buildDefaultTextsByShape(shape);
|
|
822
|
+
return {
|
|
823
|
+
id,
|
|
824
|
+
type: 'geometry',
|
|
825
|
+
shape,
|
|
826
|
+
angle: 0,
|
|
827
|
+
opacity: 1,
|
|
828
|
+
texts: drawShapeTexts,
|
|
829
|
+
points,
|
|
830
|
+
...options
|
|
831
|
+
};
|
|
764
832
|
};
|
|
765
|
-
const
|
|
766
|
-
|
|
833
|
+
const buildDefaultTextsByShape = (shape) => {
|
|
834
|
+
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
835
|
+
const textProperties = { ...memorizedLatest.textProperties };
|
|
836
|
+
const alignment = textProperties?.align;
|
|
837
|
+
const textHeight = textProperties?.textHeight || DefaultTextProperty.height;
|
|
838
|
+
delete textProperties?.align;
|
|
839
|
+
delete textProperties?.textHeight;
|
|
840
|
+
const defaultTexts = getDefaultGeometryProperty(shape)?.texts || [];
|
|
841
|
+
const textKeys = getMultipleTextGeometryTextKeys(shape);
|
|
842
|
+
return (textKeys || []).map((textKey) => {
|
|
843
|
+
const text = defaultTexts?.find((item) => item?.key === textKey);
|
|
844
|
+
return {
|
|
845
|
+
key: textKey,
|
|
846
|
+
text: buildText(text?.text || '', alignment || text?.align || Alignment.center, textProperties),
|
|
847
|
+
textHeight: textHeight
|
|
848
|
+
};
|
|
849
|
+
});
|
|
767
850
|
};
|
|
768
|
-
const
|
|
769
|
-
const
|
|
770
|
-
const rectangle = RectangleClient.getRectangleByPoints(
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
const strokeG = drawShape(board, activeRectangle, shape, {
|
|
778
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
779
|
-
strokeWidth: SNAPPING_STROKE_WIDTH
|
|
780
|
-
}, drawOptions);
|
|
781
|
-
g.appendChild(strokeG);
|
|
782
|
-
if (roughOptions.hasMask) {
|
|
783
|
-
const maskG = drawShape(board, activeRectangle, shape, {
|
|
784
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
785
|
-
strokeWidth: 0,
|
|
786
|
-
fill: SELECTION_FILL_COLOR,
|
|
787
|
-
fillStyle: 'solid'
|
|
788
|
-
}, drawOptions);
|
|
789
|
-
g.appendChild(maskG);
|
|
790
|
-
}
|
|
791
|
-
if (roughOptions.hasConnector) {
|
|
792
|
-
const connectorPoints = getEngine(shape).getConnectorPoints(rectangle);
|
|
793
|
-
connectorPoints.forEach(point => {
|
|
794
|
-
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), point, 8, {
|
|
795
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
796
|
-
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
797
|
-
fill: '#FFF',
|
|
798
|
-
fillStyle: 'solid'
|
|
799
|
-
});
|
|
800
|
-
g.appendChild(circleG);
|
|
851
|
+
const getHitMultipleGeometryText = (element, point) => {
|
|
852
|
+
const engine = getEngine(element.shape);
|
|
853
|
+
const rectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
854
|
+
let hitText;
|
|
855
|
+
if (engine.getTextRectangle) {
|
|
856
|
+
hitText = element.texts.find(text => {
|
|
857
|
+
const textRectangle = engine.getTextRectangle(element, { key: text.key });
|
|
858
|
+
return RectangleClient.isHit(rectangle, textRectangle);
|
|
801
859
|
});
|
|
802
860
|
}
|
|
803
|
-
return
|
|
861
|
+
return hitText;
|
|
804
862
|
};
|
|
805
863
|
|
|
806
|
-
const
|
|
807
|
-
const
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
};
|
|
811
|
-
const getFillByElement = (board, element) => {
|
|
812
|
-
const defaultFill = PlaitDrawElement.isFlowchart(element)
|
|
813
|
-
? getFlowchartDefaultFill(board.theme.themeColorMode)
|
|
814
|
-
: DefaultDrawStyle.fill;
|
|
815
|
-
const fill = element.fill || defaultFill;
|
|
816
|
-
return fill;
|
|
817
|
-
};
|
|
818
|
-
const getLineDashByElement = (element) => {
|
|
819
|
-
switch (element.strokeStyle) {
|
|
820
|
-
case StrokeStyle.dashed:
|
|
821
|
-
return [8, 8 + getStrokeWidthByElement(element)];
|
|
822
|
-
case StrokeStyle.dotted:
|
|
823
|
-
return [0, 4 + getStrokeWidthByElement(element)];
|
|
824
|
-
default:
|
|
825
|
-
return undefined;
|
|
864
|
+
const isTextExceedingBounds = (geometry) => {
|
|
865
|
+
const client = RectangleClient.getRectangleByPoints(geometry.points);
|
|
866
|
+
if (geometry.textHeight && geometry.textHeight > client.height) {
|
|
867
|
+
return true;
|
|
826
868
|
}
|
|
869
|
+
return false;
|
|
827
870
|
};
|
|
828
|
-
const
|
|
829
|
-
return element
|
|
871
|
+
const isHitLineText = (board, element, point) => {
|
|
872
|
+
return getHitLineTextIndex(board, element, point) !== -1;
|
|
830
873
|
};
|
|
831
|
-
|
|
832
|
-
const
|
|
833
|
-
|
|
834
|
-
|
|
874
|
+
const isHitPolyLine = (pathPoints, point) => {
|
|
875
|
+
const distance = distanceBetweenPointAndSegments(pathPoints, point);
|
|
876
|
+
return distance <= HIT_DISTANCE_BUFFER;
|
|
877
|
+
};
|
|
878
|
+
const isHitLine = (board, element, point) => {
|
|
879
|
+
const points = getLinePoints(board, element);
|
|
880
|
+
const isHitText = isHitLineText(board, element, point);
|
|
881
|
+
return isHitText || isHitPolyLine(points, point);
|
|
882
|
+
};
|
|
883
|
+
const isHitElementText = (element, point) => {
|
|
884
|
+
const engine = getEngine(element.shape);
|
|
885
|
+
if (isMultipleTextGeometry(element)) {
|
|
886
|
+
const texts = element.texts;
|
|
887
|
+
return texts.some(item => {
|
|
888
|
+
const textClient = engine.getTextRectangle(element, { key: item.key });
|
|
889
|
+
return RectangleClient.isPointInRectangle(textClient, point);
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
else {
|
|
893
|
+
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
894
|
+
return RectangleClient.isPointInRectangle(textClient, point);
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
const isRectangleHitElementText = (element, rectangle) => {
|
|
898
|
+
const engine = getEngine(element.shape);
|
|
899
|
+
if (isMultipleTextGeometry(element)) {
|
|
900
|
+
const texts = element.texts;
|
|
901
|
+
return texts.some(item => {
|
|
902
|
+
const textClient = engine.getTextRectangle(element, { key: item.key });
|
|
903
|
+
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(textClient), element) || RectangleClient.getCornerPoints(textClient);
|
|
904
|
+
return isPolylineHitRectangle(rotatedCornerPoints, rectangle);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
else {
|
|
908
|
+
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
909
|
+
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(textClient), element) || RectangleClient.getCornerPoints(textClient);
|
|
910
|
+
return isPolylineHitRectangle(rotatedCornerPoints, rectangle);
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
914
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([selection.anchor, selection.focus]);
|
|
915
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
916
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
917
|
+
let rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(client), element) || RectangleClient.getCornerPoints(client);
|
|
918
|
+
const isHitElement = isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
919
|
+
if (isHitElement) {
|
|
920
|
+
return isHitElement;
|
|
921
|
+
}
|
|
922
|
+
return isRectangleHitElementText(element, rangeRectangle);
|
|
923
|
+
}
|
|
924
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
925
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
926
|
+
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(client), element) || RectangleClient.getCornerPoints(client);
|
|
927
|
+
return isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
928
|
+
}
|
|
929
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
930
|
+
const points = getLinePoints(board, element);
|
|
931
|
+
return isPolylineHitRectangle(points, rangeRectangle);
|
|
932
|
+
}
|
|
933
|
+
return null;
|
|
934
|
+
};
|
|
935
|
+
const isHitDrawElement = (board, element, point) => {
|
|
936
|
+
const rectangle = board.getRectangle(element);
|
|
937
|
+
point = rotateAntiPointsByElement(point, element) || point;
|
|
938
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
939
|
+
const fill = getFillByElement(board, element);
|
|
940
|
+
if (isHitEdgeOfShape(board, element, point, HIT_DISTANCE_BUFFER)) {
|
|
941
|
+
return true;
|
|
942
|
+
}
|
|
943
|
+
const engine = getEngine(getElementShape(element));
|
|
944
|
+
// when shape equals text, fill is not allowed
|
|
945
|
+
if (fill !== DefaultDrawStyle.fill && fill !== TRANSPARENT && !PlaitDrawElement.isText(element)) {
|
|
946
|
+
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
947
|
+
if (isHitInside) {
|
|
948
|
+
return isHitInside;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
// if shape equals text, only check text rectangle
|
|
953
|
+
if (PlaitDrawElement.isText(element)) {
|
|
954
|
+
const textClient = getTextRectangle(element);
|
|
955
|
+
let isHitText = RectangleClient.isPointInRectangle(textClient, point);
|
|
956
|
+
return isHitText;
|
|
957
|
+
}
|
|
958
|
+
// check textRectangle of element
|
|
959
|
+
const isHitText = isHitElementText(element, point);
|
|
960
|
+
if (isHitText) {
|
|
961
|
+
return isHitText;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
966
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
967
|
+
return RectangleClient.isPointInRectangle(client, point);
|
|
968
|
+
}
|
|
969
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
970
|
+
return isHitLine(board, element, point);
|
|
971
|
+
}
|
|
972
|
+
return null;
|
|
973
|
+
};
|
|
974
|
+
const isHitEdgeOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
975
|
+
const nearestPoint = getNearestPoint(element, point);
|
|
976
|
+
const distance = distanceBetweenPointAndPoint(nearestPoint[0], nearestPoint[1], point[0], point[1]);
|
|
977
|
+
return distance <= hitDistanceBuffer;
|
|
978
|
+
};
|
|
979
|
+
const isInsideOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
980
|
+
const client = RectangleClient.inflate(RectangleClient.getRectangleByPoints(element.points), hitDistanceBuffer);
|
|
981
|
+
return getEngine(getElementShape(element)).isInsidePoint(client, point);
|
|
982
|
+
};
|
|
983
|
+
const isHitElementInside = (board, element, point) => {
|
|
984
|
+
const rectangle = board.getRectangle(element);
|
|
985
|
+
point = rotateAntiPointsByElement(point, element) || point;
|
|
986
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
987
|
+
const engine = getEngine(getElementShape(element));
|
|
988
|
+
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
989
|
+
if (isHitInside) {
|
|
990
|
+
return isHitInside;
|
|
991
|
+
}
|
|
992
|
+
if (engine.getTextRectangle) {
|
|
993
|
+
const isHitText = isHitElementText(element, point);
|
|
994
|
+
if (isHitText) {
|
|
995
|
+
return isHitText;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
1000
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1001
|
+
return RectangleClient.isPointInRectangle(client, point);
|
|
1002
|
+
}
|
|
1003
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
1004
|
+
return isHitLine(board, element, point);
|
|
1005
|
+
}
|
|
1006
|
+
return null;
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
const getTextRectangle = (element) => {
|
|
1010
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
1011
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1012
|
+
const height = element.textHeight;
|
|
1013
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
1014
|
+
return {
|
|
1015
|
+
height,
|
|
1016
|
+
width: width > 0 ? width : 0,
|
|
1017
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
1018
|
+
y: elementRectangle.y + (elementRectangle.height - height) / 2
|
|
1019
|
+
};
|
|
1020
|
+
};
|
|
1021
|
+
const getStrokeWidthByElement = (element) => {
|
|
1022
|
+
if (PlaitDrawElement.isText(element)) {
|
|
1023
|
+
return 0;
|
|
1024
|
+
}
|
|
1025
|
+
const strokeWidth = element.strokeWidth || DefaultDrawStyle.strokeWidth;
|
|
1026
|
+
return strokeWidth;
|
|
1027
|
+
};
|
|
1028
|
+
const insertElement = (board, element) => {
|
|
1029
|
+
memorizeLatestShape(board, element.shape);
|
|
1030
|
+
Transforms.insertNode(board, element, [board.children.length]);
|
|
1031
|
+
clearSelectedElement(board);
|
|
1032
|
+
addSelectedElement(board, element);
|
|
1033
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
1034
|
+
};
|
|
1035
|
+
const isDrawElementIncludeText = (element) => {
|
|
1036
|
+
if (PlaitDrawElement.isText(element)) {
|
|
1037
|
+
return true;
|
|
1038
|
+
}
|
|
1039
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
1043
|
+
return isGeometryIncludeText(element);
|
|
1044
|
+
}
|
|
1045
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
1046
|
+
const editors = getTextEditorsByElement(element);
|
|
1047
|
+
return editors.length > 0;
|
|
1048
|
+
}
|
|
1049
|
+
if (PlaitDrawElement.isTable(element)) {
|
|
1050
|
+
return element.cells.some(cell => isCellIncludeText(cell));
|
|
1051
|
+
}
|
|
1052
|
+
return true;
|
|
1053
|
+
};
|
|
1054
|
+
const isDrawElementsIncludeText = (elements) => {
|
|
1055
|
+
return elements.some(item => {
|
|
1056
|
+
return isDrawElementIncludeText(item);
|
|
1057
|
+
});
|
|
1058
|
+
};
|
|
1059
|
+
const getSnappingShape = (board, point) => {
|
|
1060
|
+
let hitElement = getHitShape(board, point);
|
|
1061
|
+
if (hitElement) {
|
|
1062
|
+
const ref = getSnappingRef(board, hitElement, point);
|
|
1063
|
+
if (ref.isHitConnector || ref.isHitEdge) {
|
|
1064
|
+
return hitElement;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return null;
|
|
1068
|
+
};
|
|
1069
|
+
const getSnappingRef = (board, hitElement, point) => {
|
|
1070
|
+
const rotatedPoint = rotateAntiPointsByElement(point, hitElement) || point;
|
|
1071
|
+
const connectorPoint = getHitConnectorPoint(rotatedPoint, hitElement);
|
|
1072
|
+
const edgePoint = getNearestPoint(hitElement, rotatedPoint);
|
|
1073
|
+
const isHitEdge = isHitEdgeOfShape(board, hitElement, rotatedPoint, LINE_SNAPPING_BUFFER);
|
|
1074
|
+
return { isHitEdge, isHitConnector: !!connectorPoint, connectorPoint, edgePoint };
|
|
1075
|
+
};
|
|
1076
|
+
const getHitShape = (board, point, offset = LINE_HIT_GEOMETRY_BUFFER) => {
|
|
1077
|
+
let hitShape = null;
|
|
1078
|
+
traverseDrawShapes(board, (element) => {
|
|
1079
|
+
if (hitShape === null && isInsideOfShape(board, element, rotateAntiPointsByElement(point, element) || point, offset * 2)) {
|
|
1080
|
+
hitShape = element;
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
return hitShape;
|
|
1084
|
+
};
|
|
1085
|
+
const traverseDrawShapes = (board, callback) => {
|
|
1086
|
+
depthFirstRecursion(board, node => {
|
|
1087
|
+
if (!PlaitBoard.isBoard(node) && PlaitDrawElement.isShapeElement(node)) {
|
|
1088
|
+
callback(node);
|
|
1089
|
+
}
|
|
1090
|
+
}, getIsRecursionFunc(board), true);
|
|
1091
|
+
};
|
|
1092
|
+
const drawShape = (board, outerRectangle, shape, roughOptions, drawOptions) => {
|
|
1093
|
+
return getEngine(shape).draw(board, outerRectangle, roughOptions, drawOptions);
|
|
1094
|
+
};
|
|
1095
|
+
const drawBoundReaction = (board, element, roughOptions = { hasMask: true, hasConnector: true }) => {
|
|
1096
|
+
const g = createG();
|
|
1097
|
+
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
1098
|
+
const activeRectangle = RectangleClient.inflate(rectangle, SNAPPING_STROKE_WIDTH);
|
|
1099
|
+
const shape = getElementShape(element);
|
|
1100
|
+
let drawOptions = {};
|
|
1101
|
+
if (PlaitDrawElement.isTable(element)) {
|
|
1102
|
+
drawOptions = { element };
|
|
1103
|
+
}
|
|
1104
|
+
const strokeG = drawShape(board, activeRectangle, shape, {
|
|
1105
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
1106
|
+
strokeWidth: SNAPPING_STROKE_WIDTH
|
|
1107
|
+
}, drawOptions);
|
|
1108
|
+
g.appendChild(strokeG);
|
|
1109
|
+
if (roughOptions.hasMask) {
|
|
1110
|
+
const maskG = drawShape(board, activeRectangle, shape, {
|
|
1111
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
1112
|
+
strokeWidth: 0,
|
|
1113
|
+
fill: SELECTION_FILL_COLOR,
|
|
1114
|
+
fillStyle: 'solid'
|
|
1115
|
+
}, drawOptions);
|
|
1116
|
+
g.appendChild(maskG);
|
|
1117
|
+
}
|
|
1118
|
+
if (roughOptions.hasConnector) {
|
|
1119
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(rectangle);
|
|
1120
|
+
connectorPoints.forEach(point => {
|
|
1121
|
+
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), point, 8, {
|
|
1122
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
1123
|
+
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
1124
|
+
fill: '#FFF',
|
|
1125
|
+
fillStyle: 'solid'
|
|
1126
|
+
});
|
|
1127
|
+
g.appendChild(circleG);
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
return g;
|
|
1131
|
+
};
|
|
1132
|
+
const getTextKey = (element, text) => {
|
|
1133
|
+
if (isMultipleTextGeometry(element)) {
|
|
1134
|
+
return `${element.id}-${text.key}`;
|
|
1135
|
+
}
|
|
1136
|
+
else {
|
|
1137
|
+
return text.key;
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
const getGeometryAlign = (element) => {
|
|
1141
|
+
if (isMultipleTextGeometry(element)) {
|
|
1142
|
+
const drawShapeText = element.texts.find(item => item.key.includes(MultipleTextGeometryCommonTextKeys.content));
|
|
1143
|
+
return drawShapeText?.text.align || Alignment.center;
|
|
1144
|
+
}
|
|
1145
|
+
if (isSingleTextGeometry(element)) {
|
|
1146
|
+
return element.text?.align || Alignment.center;
|
|
1147
|
+
}
|
|
1148
|
+
if (PlaitDrawElement.isTable(element)) {
|
|
1149
|
+
const firstTextCell = element.cells.find(item => item.text);
|
|
1150
|
+
return firstTextCell?.text?.align || Alignment.center;
|
|
1151
|
+
}
|
|
1152
|
+
return Alignment.center;
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
const getStrokeColorByElement = (board, element) => {
|
|
1156
|
+
const defaultColor = getDrawDefaultStrokeColor(board.theme.themeColorMode);
|
|
1157
|
+
const strokeColor = element.strokeColor || defaultColor;
|
|
1158
|
+
return strokeColor;
|
|
1159
|
+
};
|
|
1160
|
+
const getFillByElement = (board, element) => {
|
|
1161
|
+
const defaultFill = PlaitDrawElement.isFlowchart(element)
|
|
1162
|
+
? getFlowchartDefaultFill(board.theme.themeColorMode)
|
|
1163
|
+
: DefaultDrawStyle.fill;
|
|
1164
|
+
const fill = element.fill || defaultFill;
|
|
1165
|
+
return fill;
|
|
1166
|
+
};
|
|
1167
|
+
const getLineDashByElement = (element) => {
|
|
1168
|
+
switch (element.strokeStyle) {
|
|
1169
|
+
case StrokeStyle.dashed:
|
|
1170
|
+
return [8, 8 + getStrokeWidthByElement(element)];
|
|
1171
|
+
case StrokeStyle.dotted:
|
|
1172
|
+
return [0, 4 + getStrokeWidthByElement(element)];
|
|
1173
|
+
default:
|
|
1174
|
+
return undefined;
|
|
1175
|
+
}
|
|
1176
|
+
};
|
|
1177
|
+
const getStrokeStyleByElement = (element) => {
|
|
1178
|
+
return element.strokeStyle || StrokeStyle.solid;
|
|
1179
|
+
};
|
|
1180
|
+
|
|
1181
|
+
const DefaultLineStyle = {
|
|
1182
|
+
strokeWidth: 2,
|
|
1183
|
+
strokeColor: '#000'
|
|
835
1184
|
};
|
|
836
1185
|
const LINE_TEXT_SPACE = 4;
|
|
837
1186
|
const LINE_AUTO_COMPLETE_DIAMETER = 6;
|
|
@@ -1516,58 +1865,87 @@ function drawMask(board, element, id) {
|
|
|
1516
1865
|
return { mask, maskTargetFillRect };
|
|
1517
1866
|
}
|
|
1518
1867
|
|
|
1519
|
-
const
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
};
|
|
1525
|
-
const getMultipleTextGeometryTextKeys = (shape) => {
|
|
1526
|
-
return MultipleTextGeometryTextKeys[shape];
|
|
1527
|
-
};
|
|
1528
|
-
const createMultipleTextGeometryElement = (shape, points, options = {}) => {
|
|
1529
|
-
const id = idCreator();
|
|
1530
|
-
const drawShapeTexts = buildDefaultTextsByShape(shape, id);
|
|
1531
|
-
return {
|
|
1532
|
-
id,
|
|
1533
|
-
type: 'geometry',
|
|
1534
|
-
shape,
|
|
1868
|
+
const createUMLClassOrInterfaceGeometryElement = (board, shape, points) => {
|
|
1869
|
+
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
1870
|
+
const element = {
|
|
1871
|
+
id: idCreator(),
|
|
1872
|
+
type: 'table',
|
|
1535
1873
|
angle: 0,
|
|
1536
1874
|
opacity: 1,
|
|
1537
|
-
texts: drawShapeTexts,
|
|
1538
1875
|
points,
|
|
1539
|
-
|
|
1876
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth,
|
|
1877
|
+
...memorizedLatest.geometryProperties
|
|
1878
|
+
};
|
|
1879
|
+
let rows;
|
|
1880
|
+
let columns;
|
|
1881
|
+
if (shape === UMLSymbols.class) {
|
|
1882
|
+
rows = [
|
|
1883
|
+
{
|
|
1884
|
+
id: idCreator(),
|
|
1885
|
+
height: 30
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
id: idCreator()
|
|
1889
|
+
},
|
|
1890
|
+
{
|
|
1891
|
+
id: idCreator()
|
|
1892
|
+
}
|
|
1893
|
+
];
|
|
1894
|
+
columns = [
|
|
1895
|
+
{
|
|
1896
|
+
id: idCreator()
|
|
1897
|
+
}
|
|
1898
|
+
];
|
|
1899
|
+
}
|
|
1900
|
+
else {
|
|
1901
|
+
rows = [
|
|
1902
|
+
{
|
|
1903
|
+
id: idCreator(),
|
|
1904
|
+
height: 50
|
|
1905
|
+
},
|
|
1906
|
+
{
|
|
1907
|
+
id: idCreator()
|
|
1908
|
+
}
|
|
1909
|
+
];
|
|
1910
|
+
columns = [
|
|
1911
|
+
{
|
|
1912
|
+
id: idCreator()
|
|
1913
|
+
}
|
|
1914
|
+
];
|
|
1915
|
+
}
|
|
1916
|
+
return {
|
|
1917
|
+
...element,
|
|
1918
|
+
shape,
|
|
1919
|
+
rows,
|
|
1920
|
+
columns,
|
|
1921
|
+
cells: buildTableCellsForGeometry(board, rows, columns, shape)
|
|
1540
1922
|
};
|
|
1541
1923
|
};
|
|
1542
|
-
const
|
|
1924
|
+
const buildTableCellsForGeometry = (board, rows, columns, shape) => {
|
|
1543
1925
|
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
1544
|
-
const
|
|
1545
|
-
const
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
textHeight:
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
return RectangleClient.isHit(rectangle, textRectangle);
|
|
1568
|
-
});
|
|
1569
|
-
}
|
|
1570
|
-
return hitText;
|
|
1926
|
+
const cellCount = rows.length * columns.length;
|
|
1927
|
+
const defaultTexts = getDefaultGeometryProperty(shape)?.texts || [];
|
|
1928
|
+
const testHeights = defaultTexts.map((textItem) => {
|
|
1929
|
+
return getTextShapeProperty(board, textItem.text || DefaultTextProperty.text, memorizedLatest.textProperties['font-size']).height;
|
|
1930
|
+
});
|
|
1931
|
+
return new Array(cellCount).fill('').map((item, index) => {
|
|
1932
|
+
const rowIndex = Math.floor(index / columns.length);
|
|
1933
|
+
const columnIndex = index % columns.length;
|
|
1934
|
+
return {
|
|
1935
|
+
id: idCreator(),
|
|
1936
|
+
rowId: rows[rowIndex].id,
|
|
1937
|
+
columnId: columns[columnIndex].id,
|
|
1938
|
+
textHeight: testHeights[index],
|
|
1939
|
+
text: {
|
|
1940
|
+
children: [
|
|
1941
|
+
{
|
|
1942
|
+
text: defaultTexts[index].text
|
|
1943
|
+
}
|
|
1944
|
+
],
|
|
1945
|
+
align: defaultTexts[index].align
|
|
1946
|
+
}
|
|
1947
|
+
};
|
|
1948
|
+
});
|
|
1571
1949
|
};
|
|
1572
1950
|
|
|
1573
1951
|
const createGeometryElement = (shape, points, text, options = {}, textProperties = {}) => {
|
|
@@ -1755,6 +2133,9 @@ const createTextElement = (board, points, text = DefaultTextProperty.text, textH
|
|
|
1755
2133
|
const createDefaultGeometry = (board, points, shape) => {
|
|
1756
2134
|
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
1757
2135
|
const textHeight = getTextShapeProperty(board, DefaultTextProperty.text, memorizedLatest.textProperties['font-size']).height;
|
|
2136
|
+
if (PlaitDrawElement.isUMLClassOrInterface({ shape })) {
|
|
2137
|
+
return createUMLClassOrInterfaceGeometryElement(board, shape, points);
|
|
2138
|
+
}
|
|
1758
2139
|
if (isMultipleTextShape(shape)) {
|
|
1759
2140
|
return createMultipleTextGeometryElement(shape, points, {
|
|
1760
2141
|
strokeWidth: DefaultBasicShapeProperty.strokeWidth,
|
|
@@ -1770,12 +2151,14 @@ const createDefaultGeometry = (board, points, shape) => {
|
|
|
1770
2151
|
};
|
|
1771
2152
|
const editText = (board, element, text) => {
|
|
1772
2153
|
const textManage = text ? getTextManage(`${element.id}-${text.key}`) : getFirstTextManage(element);
|
|
1773
|
-
textManage
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
2154
|
+
if (textManage) {
|
|
2155
|
+
textManage.edit(() => {
|
|
2156
|
+
// delay to avoid blinking
|
|
2157
|
+
setTimeout(() => {
|
|
2158
|
+
rerenderGeometryActive(board, element);
|
|
2159
|
+
}, 200);
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
1779
2162
|
rerenderGeometryActive(board, element);
|
|
1780
2163
|
};
|
|
1781
2164
|
const rerenderGeometryActive = (board, element) => {
|
|
@@ -1785,7 +2168,13 @@ const rerenderGeometryActive = (board, element) => {
|
|
|
1785
2168
|
activeGenerator.processDrawing(element, PlaitBoard.getElementActiveHost(board), { selected });
|
|
1786
2169
|
};
|
|
1787
2170
|
const isGeometryIncludeText = (element) => {
|
|
1788
|
-
return
|
|
2171
|
+
return isSingleTextGeometry(element) || isMultipleTextGeometry(element);
|
|
2172
|
+
};
|
|
2173
|
+
const isSingleTextShape = (shape) => {
|
|
2174
|
+
return !GEOMETRY_WITHOUT_TEXT.includes(shape) && !isMultipleTextShape(shape);
|
|
2175
|
+
};
|
|
2176
|
+
const isSingleTextGeometry = (element) => {
|
|
2177
|
+
return PlaitDrawElement.isGeometry(element) && isSingleTextShape(element.shape);
|
|
1789
2178
|
};
|
|
1790
2179
|
|
|
1791
2180
|
const isSelfLoop = (element) => {
|
|
@@ -1844,292 +2233,84 @@ const getElbowPoints = (board, element) => {
|
|
|
1844
2233
|
// |
|
|
1845
2234
|
// nextPoint---sourcePoint---keyPoint1
|
|
1846
2235
|
// The correct rendering should be (nextPoint should be filtered out):
|
|
1847
|
-
// keyPoint2
|
|
1848
|
-
// |
|
|
1849
|
-
// |
|
|
1850
|
-
// sourcePoint---keyPoint1
|
|
1851
|
-
const ret = simplifyOrthogonalPoints(renderPoints);
|
|
1852
|
-
return ret;
|
|
1853
|
-
}
|
|
1854
|
-
};
|
|
1855
|
-
const getNextSourceAndTargetPoints = (board, element) => {
|
|
1856
|
-
const options = getElbowLineRouteOptions(board, element);
|
|
1857
|
-
return [options.nextSourcePoint, options.nextTargetPoint];
|
|
1858
|
-
};
|
|
1859
|
-
const getSourceAndTargetRectangle = (board, element, handleRefPair) => {
|
|
1860
|
-
let sourceElement = element.source.boundId ? getElementById(board, element.source.boundId) : undefined;
|
|
1861
|
-
let targetElement = element.target.boundId ? getElementById(board, element.target.boundId) : undefined;
|
|
1862
|
-
if (!sourceElement) {
|
|
1863
|
-
const source = handleRefPair.source;
|
|
1864
|
-
sourceElement = createFakeElement(source.point, source.vector);
|
|
1865
|
-
}
|
|
1866
|
-
if (!targetElement) {
|
|
1867
|
-
const target = handleRefPair.target;
|
|
1868
|
-
targetElement = createFakeElement(target.point, target.vector);
|
|
1869
|
-
}
|
|
1870
|
-
let sourceRectangle = RectangleClient.getRectangleByPoints(sourceElement.points);
|
|
1871
|
-
const rotatedSourceCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(sourceRectangle), sourceElement) ||
|
|
1872
|
-
RectangleClient.getCornerPoints(sourceRectangle);
|
|
1873
|
-
sourceRectangle = RectangleClient.getRectangleByPoints(rotatedSourceCornerPoints);
|
|
1874
|
-
sourceRectangle = RectangleClient.inflate(sourceRectangle, getStrokeWidthByElement(sourceElement) * 2);
|
|
1875
|
-
let targetRectangle = RectangleClient.getRectangleByPoints(targetElement.points);
|
|
1876
|
-
const rotatedTargetCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(targetRectangle), targetElement) ||
|
|
1877
|
-
RectangleClient.getCornerPoints(targetRectangle);
|
|
1878
|
-
targetRectangle = RectangleClient.getRectangleByPoints(rotatedTargetCornerPoints);
|
|
1879
|
-
targetRectangle = RectangleClient.inflate(targetRectangle, getStrokeWidthByElement(targetElement) * 2);
|
|
1880
|
-
return {
|
|
1881
|
-
sourceRectangle,
|
|
1882
|
-
targetRectangle
|
|
1883
|
-
};
|
|
1884
|
-
};
|
|
1885
|
-
const createFakeElement = (startPoint, vector) => {
|
|
1886
|
-
const point = getPointByVectorComponent(startPoint, vector, -25);
|
|
1887
|
-
const points = RectangleClient.getPoints(RectangleClient.getRectangleByCenterPoint(point, 50, 50));
|
|
1888
|
-
return createGeometryElement(BasicShapes.rectangle, points, '');
|
|
1889
|
-
};
|
|
1890
|
-
function getNextRenderPoints(board, element, renderPoints) {
|
|
1891
|
-
let newRenderKeyPoints = renderPoints ?? getElbowPoints(board, element);
|
|
1892
|
-
const [nextSourcePoint, nextTargetPoint] = getNextSourceAndTargetPoints(board, element);
|
|
1893
|
-
newRenderKeyPoints.splice(0, 1, nextSourcePoint);
|
|
1894
|
-
newRenderKeyPoints.splice(-1, 1, nextTargetPoint);
|
|
1895
|
-
return removeDuplicatePoints(newRenderKeyPoints);
|
|
1896
|
-
}
|
|
1897
|
-
|
|
1898
|
-
const getSelectedDrawElements = (board, elements) => {
|
|
1899
|
-
const selectedElements = elements?.length ? elements : getSelectedElements(board);
|
|
1900
|
-
return selectedElements.filter(value => PlaitDrawElement.isDrawElement(value));
|
|
1901
|
-
};
|
|
1902
|
-
const getSelectedGeometryElements = (board) => {
|
|
1903
|
-
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isGeometry(value));
|
|
1904
|
-
return selectedElements;
|
|
1905
|
-
};
|
|
1906
|
-
const getSelectedLineElements = (board) => {
|
|
1907
|
-
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isLine(value));
|
|
1908
|
-
return selectedElements;
|
|
1909
|
-
};
|
|
1910
|
-
const getSelectedImageElements = (board) => {
|
|
1911
|
-
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isImage(value));
|
|
1912
|
-
return selectedElements;
|
|
1913
|
-
};
|
|
1914
|
-
const isSingleSelectSwimlane = (board) => {
|
|
1915
|
-
const selectedElements = getSelectedElements(board);
|
|
1916
|
-
return selectedElements && selectedElements.length === 1 && PlaitDrawElement.isSwimlane(selectedElements[0]);
|
|
1917
|
-
};
|
|
1918
|
-
const isSingleSelectTable = (board) => {
|
|
1919
|
-
const selectedElements = getSelectedElements(board);
|
|
1920
|
-
return selectedElements && selectedElements.length === 1 && PlaitTableElement.isTable(selectedElements[0]);
|
|
1921
|
-
};
|
|
1922
|
-
const getSelectedTableElements = (board, elements) => {
|
|
1923
|
-
const selectedElements = elements?.length ? elements : getSelectedElements(board);
|
|
1924
|
-
return selectedElements.filter(value => PlaitTableElement.isTable(value));
|
|
1925
|
-
};
|
|
1926
|
-
|
|
1927
|
-
var LineResizeHandle;
|
|
1928
|
-
(function (LineResizeHandle) {
|
|
1929
|
-
LineResizeHandle["source"] = "source";
|
|
1930
|
-
LineResizeHandle["target"] = "target";
|
|
1931
|
-
LineResizeHandle["addHandle"] = "addHandle";
|
|
1932
|
-
})(LineResizeHandle || (LineResizeHandle = {}));
|
|
1933
|
-
const getHitLineResizeHandleRef = (board, element, point) => {
|
|
1934
|
-
let dataPoints = PlaitLine.getPoints(board, element);
|
|
1935
|
-
const index = getHitPointIndex(dataPoints, point);
|
|
1936
|
-
if (index !== -1) {
|
|
1937
|
-
const handleIndex = index;
|
|
1938
|
-
if (index === 0) {
|
|
1939
|
-
return { handle: LineResizeHandle.source, handleIndex };
|
|
1940
|
-
}
|
|
1941
|
-
if (index === dataPoints.length - 1) {
|
|
1942
|
-
return { handle: LineResizeHandle.target, handleIndex };
|
|
1943
|
-
}
|
|
1944
|
-
// elbow line, data points only verify source connection point and target connection point
|
|
1945
|
-
if (element.shape !== LineShape.elbow) {
|
|
1946
|
-
return { handleIndex };
|
|
1947
|
-
}
|
|
1948
|
-
}
|
|
1949
|
-
const middlePoints = getMiddlePoints(board, element);
|
|
1950
|
-
const indexOfMiddlePoints = getHitPointIndex(middlePoints, point);
|
|
1951
|
-
if (indexOfMiddlePoints !== -1) {
|
|
1952
|
-
return {
|
|
1953
|
-
handle: LineResizeHandle.addHandle,
|
|
1954
|
-
handleIndex: indexOfMiddlePoints
|
|
1955
|
-
};
|
|
1956
|
-
}
|
|
1957
|
-
return undefined;
|
|
1958
|
-
};
|
|
1959
|
-
function getHitPointIndex(points, movingPoint) {
|
|
1960
|
-
const rectangles = points.map(point => {
|
|
1961
|
-
return {
|
|
1962
|
-
x: point[0] - RESIZE_HANDLE_DIAMETER / 2,
|
|
1963
|
-
y: point[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
1964
|
-
width: RESIZE_HANDLE_DIAMETER,
|
|
1965
|
-
height: RESIZE_HANDLE_DIAMETER
|
|
1966
|
-
};
|
|
1967
|
-
});
|
|
1968
|
-
const rectangle = rectangles.find(rectangle => {
|
|
1969
|
-
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([movingPoint, movingPoint]), rectangle);
|
|
1970
|
-
});
|
|
1971
|
-
return rectangle ? rectangles.indexOf(rectangle) : -1;
|
|
1972
|
-
}
|
|
1973
|
-
const getHitLineTextIndex = (board, element, point) => {
|
|
1974
|
-
const texts = element.texts;
|
|
1975
|
-
if (!texts.length)
|
|
1976
|
-
return -1;
|
|
1977
|
-
const points = getLinePoints(board, element);
|
|
1978
|
-
return texts.findIndex(text => {
|
|
1979
|
-
const center = getPointOnPolyline(points, text.position);
|
|
1980
|
-
const rectangle = {
|
|
1981
|
-
x: center[0] - text.width / 2,
|
|
1982
|
-
y: center[1] - text.height / 2,
|
|
1983
|
-
width: text.width,
|
|
1984
|
-
height: text.height
|
|
1985
|
-
};
|
|
1986
|
-
return RectangleClient.isHit(rectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
1987
|
-
});
|
|
1988
|
-
};
|
|
1989
|
-
|
|
1990
|
-
const isTextExceedingBounds = (geometry) => {
|
|
1991
|
-
const client = RectangleClient.getRectangleByPoints(geometry.points);
|
|
1992
|
-
if (geometry.textHeight && geometry.textHeight > client.height) {
|
|
1993
|
-
return true;
|
|
1994
|
-
}
|
|
1995
|
-
return false;
|
|
1996
|
-
};
|
|
1997
|
-
const isHitLineText = (board, element, point) => {
|
|
1998
|
-
return getHitLineTextIndex(board, element, point) !== -1;
|
|
1999
|
-
};
|
|
2000
|
-
const isHitPolyLine = (pathPoints, point) => {
|
|
2001
|
-
const distance = distanceBetweenPointAndSegments(pathPoints, point);
|
|
2002
|
-
return distance <= HIT_DISTANCE_BUFFER;
|
|
2003
|
-
};
|
|
2004
|
-
const isHitLine = (board, element, point) => {
|
|
2005
|
-
const points = getLinePoints(board, element);
|
|
2006
|
-
const isHitText = isHitLineText(board, element, point);
|
|
2007
|
-
return isHitText || isHitPolyLine(points, point);
|
|
2008
|
-
};
|
|
2009
|
-
const isHitElementText = (element, point) => {
|
|
2010
|
-
const engine = getEngine(element.shape);
|
|
2011
|
-
if (isMultipleTextGeometry(element)) {
|
|
2012
|
-
const texts = element.texts;
|
|
2013
|
-
return texts.some(item => {
|
|
2014
|
-
const textClient = engine.getTextRectangle(element, { key: item.key });
|
|
2015
|
-
return RectangleClient.isPointInRectangle(textClient, point);
|
|
2016
|
-
});
|
|
2017
|
-
}
|
|
2018
|
-
else {
|
|
2019
|
-
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
2020
|
-
return RectangleClient.isPointInRectangle(textClient, point);
|
|
2021
|
-
}
|
|
2022
|
-
};
|
|
2023
|
-
const isRectangleHitElementText = (element, rectangle) => {
|
|
2024
|
-
const engine = getEngine(element.shape);
|
|
2025
|
-
if (isMultipleTextGeometry(element)) {
|
|
2026
|
-
const texts = element.texts;
|
|
2027
|
-
return texts.some(item => {
|
|
2028
|
-
const textClient = engine.getTextRectangle(element, { key: item.key });
|
|
2029
|
-
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(textClient), element) || RectangleClient.getCornerPoints(textClient);
|
|
2030
|
-
return isPolylineHitRectangle(rotatedCornerPoints, rectangle);
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
else {
|
|
2034
|
-
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
2035
|
-
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(textClient), element) || RectangleClient.getCornerPoints(textClient);
|
|
2036
|
-
return isPolylineHitRectangle(rotatedCornerPoints, rectangle);
|
|
2037
|
-
}
|
|
2038
|
-
};
|
|
2039
|
-
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
2040
|
-
const rangeRectangle = RectangleClient.getRectangleByPoints([selection.anchor, selection.focus]);
|
|
2041
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
2042
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
2043
|
-
let rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(client), element) || RectangleClient.getCornerPoints(client);
|
|
2044
|
-
const isHitElement = isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
2045
|
-
if (isHitElement) {
|
|
2046
|
-
return isHitElement;
|
|
2047
|
-
}
|
|
2048
|
-
return isRectangleHitElementText(element, rangeRectangle);
|
|
2049
|
-
}
|
|
2050
|
-
if (PlaitDrawElement.isImage(element)) {
|
|
2051
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
2052
|
-
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(client), element) || RectangleClient.getCornerPoints(client);
|
|
2053
|
-
return isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
2054
|
-
}
|
|
2055
|
-
if (PlaitDrawElement.isLine(element)) {
|
|
2056
|
-
const points = getLinePoints(board, element);
|
|
2057
|
-
return isPolylineHitRectangle(points, rangeRectangle);
|
|
2058
|
-
}
|
|
2059
|
-
return null;
|
|
2060
|
-
};
|
|
2061
|
-
const isHitDrawElement = (board, element, point) => {
|
|
2062
|
-
const rectangle = board.getRectangle(element);
|
|
2063
|
-
point = rotateAntiPointsByElement(point, element) || point;
|
|
2064
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
2065
|
-
const fill = getFillByElement(board, element);
|
|
2066
|
-
if (isHitEdgeOfShape(board, element, point, HIT_DISTANCE_BUFFER)) {
|
|
2067
|
-
return true;
|
|
2068
|
-
}
|
|
2069
|
-
const engine = getEngine(getElementShape(element));
|
|
2070
|
-
// when shape equals text, fill is not allowed
|
|
2071
|
-
if (fill !== DefaultDrawStyle.fill && fill !== TRANSPARENT && !PlaitDrawElement.isText(element)) {
|
|
2072
|
-
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
2073
|
-
if (isHitInside) {
|
|
2074
|
-
return isHitInside;
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
else {
|
|
2078
|
-
// if shape equals text, only check text rectangle
|
|
2079
|
-
if (PlaitDrawElement.isText(element)) {
|
|
2080
|
-
const textClient = getTextRectangle(element);
|
|
2081
|
-
let isHitText = RectangleClient.isPointInRectangle(textClient, point);
|
|
2082
|
-
return isHitText;
|
|
2083
|
-
}
|
|
2084
|
-
// check textRectangle of element
|
|
2085
|
-
const isHitText = isHitElementText(element, point);
|
|
2086
|
-
if (isHitText) {
|
|
2087
|
-
return isHitText;
|
|
2088
|
-
}
|
|
2089
|
-
}
|
|
2236
|
+
// keyPoint2
|
|
2237
|
+
// |
|
|
2238
|
+
// |
|
|
2239
|
+
// sourcePoint---keyPoint1
|
|
2240
|
+
const ret = simplifyOrthogonalPoints(renderPoints);
|
|
2241
|
+
return ret;
|
|
2090
2242
|
}
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2243
|
+
};
|
|
2244
|
+
const getNextSourceAndTargetPoints = (board, element) => {
|
|
2245
|
+
const options = getElbowLineRouteOptions(board, element);
|
|
2246
|
+
return [options.nextSourcePoint, options.nextTargetPoint];
|
|
2247
|
+
};
|
|
2248
|
+
const getSourceAndTargetRectangle = (board, element, handleRefPair) => {
|
|
2249
|
+
let sourceElement = element.source.boundId ? getElementById(board, element.source.boundId) : undefined;
|
|
2250
|
+
let targetElement = element.target.boundId ? getElementById(board, element.target.boundId) : undefined;
|
|
2251
|
+
if (!sourceElement) {
|
|
2252
|
+
const source = handleRefPair.source;
|
|
2253
|
+
sourceElement = createFakeElement(source.point, source.vector);
|
|
2094
2254
|
}
|
|
2095
|
-
if (
|
|
2096
|
-
|
|
2255
|
+
if (!targetElement) {
|
|
2256
|
+
const target = handleRefPair.target;
|
|
2257
|
+
targetElement = createFakeElement(target.point, target.vector);
|
|
2097
2258
|
}
|
|
2098
|
-
|
|
2259
|
+
let sourceRectangle = RectangleClient.getRectangleByPoints(sourceElement.points);
|
|
2260
|
+
const rotatedSourceCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(sourceRectangle), sourceElement) ||
|
|
2261
|
+
RectangleClient.getCornerPoints(sourceRectangle);
|
|
2262
|
+
sourceRectangle = RectangleClient.getRectangleByPoints(rotatedSourceCornerPoints);
|
|
2263
|
+
sourceRectangle = RectangleClient.inflate(sourceRectangle, getStrokeWidthByElement(sourceElement) * 2);
|
|
2264
|
+
let targetRectangle = RectangleClient.getRectangleByPoints(targetElement.points);
|
|
2265
|
+
const rotatedTargetCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(targetRectangle), targetElement) ||
|
|
2266
|
+
RectangleClient.getCornerPoints(targetRectangle);
|
|
2267
|
+
targetRectangle = RectangleClient.getRectangleByPoints(rotatedTargetCornerPoints);
|
|
2268
|
+
targetRectangle = RectangleClient.inflate(targetRectangle, getStrokeWidthByElement(targetElement) * 2);
|
|
2269
|
+
return {
|
|
2270
|
+
sourceRectangle,
|
|
2271
|
+
targetRectangle
|
|
2272
|
+
};
|
|
2099
2273
|
};
|
|
2100
|
-
const
|
|
2101
|
-
const
|
|
2102
|
-
const
|
|
2103
|
-
return
|
|
2274
|
+
const createFakeElement = (startPoint, vector) => {
|
|
2275
|
+
const point = getPointByVectorComponent(startPoint, vector, -25);
|
|
2276
|
+
const points = RectangleClient.getPoints(RectangleClient.getRectangleByCenterPoint(point, 50, 50));
|
|
2277
|
+
return createGeometryElement(BasicShapes.rectangle, points, '');
|
|
2104
2278
|
};
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2279
|
+
function getNextRenderPoints(board, element, renderPoints) {
|
|
2280
|
+
let newRenderKeyPoints = renderPoints ?? getElbowPoints(board, element);
|
|
2281
|
+
const [nextSourcePoint, nextTargetPoint] = getNextSourceAndTargetPoints(board, element);
|
|
2282
|
+
newRenderKeyPoints.splice(0, 1, nextSourcePoint);
|
|
2283
|
+
newRenderKeyPoints.splice(-1, 1, nextTargetPoint);
|
|
2284
|
+
return removeDuplicatePoints(newRenderKeyPoints);
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
const getSelectedDrawElements = (board, elements) => {
|
|
2288
|
+
const selectedElements = elements?.length ? elements : getSelectedElements(board);
|
|
2289
|
+
return selectedElements.filter(value => PlaitDrawElement.isDrawElement(value));
|
|
2108
2290
|
};
|
|
2109
|
-
const
|
|
2110
|
-
const
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
return null;
|
|
2291
|
+
const getSelectedGeometryElements = (board) => {
|
|
2292
|
+
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isGeometry(value));
|
|
2293
|
+
return selectedElements;
|
|
2294
|
+
};
|
|
2295
|
+
const getSelectedLineElements = (board) => {
|
|
2296
|
+
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isLine(value));
|
|
2297
|
+
return selectedElements;
|
|
2298
|
+
};
|
|
2299
|
+
const getSelectedImageElements = (board) => {
|
|
2300
|
+
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isImage(value));
|
|
2301
|
+
return selectedElements;
|
|
2302
|
+
};
|
|
2303
|
+
const isSingleSelectSwimlane = (board) => {
|
|
2304
|
+
const selectedElements = getSelectedElements(board);
|
|
2305
|
+
return selectedElements && selectedElements.length === 1 && PlaitDrawElement.isSwimlane(selectedElements[0]);
|
|
2306
|
+
};
|
|
2307
|
+
const isSingleSelectTable = (board) => {
|
|
2308
|
+
const selectedElements = getSelectedElements(board);
|
|
2309
|
+
return selectedElements && selectedElements.length === 1 && PlaitTableElement.isTable(selectedElements[0]);
|
|
2310
|
+
};
|
|
2311
|
+
const getSelectedTableElements = (board, elements) => {
|
|
2312
|
+
const selectedElements = elements?.length ? elements : getSelectedElements(board);
|
|
2313
|
+
return selectedElements.filter(value => PlaitTableElement.isTable(value));
|
|
2133
2314
|
};
|
|
2134
2315
|
|
|
2135
2316
|
const resizeLine = (board, options, path) => {
|
|
@@ -2365,9 +2546,7 @@ const addSwimlaneRow = (board, swimlane, index) => {
|
|
|
2365
2546
|
const newRows = [...swimlane.rows];
|
|
2366
2547
|
const newRowId = idCreator();
|
|
2367
2548
|
newRows.splice(index, 0, { id: newRowId });
|
|
2368
|
-
|
|
2369
|
-
newCells.shift();
|
|
2370
|
-
newCells = [...swimlane.cells, ...newCells];
|
|
2549
|
+
const newCells = [...swimlane.cells, ...createNewSwimlaneCells(swimlane, newRowId, 'column')];
|
|
2371
2550
|
const lastCellPoints = getCellWithPoints(board, swimlane, swimlane.cells[swimlane.cells.length - 1].id).points;
|
|
2372
2551
|
const lastRowHeight = RectangleClient.getRectangleByPoints(lastCellPoints).height;
|
|
2373
2552
|
const newPoints = [swimlane.points[0], [swimlane.points[1][0], swimlane.points[1][1] + lastRowHeight]];
|
|
@@ -2379,9 +2558,7 @@ const addSwimlaneColumn = (board, swimlane, index) => {
|
|
|
2379
2558
|
const newColumns = [...swimlane.columns];
|
|
2380
2559
|
const newColumnId = idCreator();
|
|
2381
2560
|
newColumns.splice(index, 0, { id: newColumnId });
|
|
2382
|
-
|
|
2383
|
-
newCells.shift();
|
|
2384
|
-
newCells = [...swimlane.cells, ...newCells];
|
|
2561
|
+
const newCells = [...swimlane.cells, ...createNewSwimlaneCells(swimlane, newColumnId, 'row')];
|
|
2385
2562
|
const lastCellPoints = getCellWithPoints(board, swimlane, swimlane.cells[swimlane.cells.length - 1].id).points;
|
|
2386
2563
|
const lastColumnWidth = RectangleClient.getRectangleByPoints(lastCellPoints).width;
|
|
2387
2564
|
const newPoints = [swimlane.points[0], [swimlane.points[1][0] + lastColumnWidth, swimlane.points[1][1]]];
|
|
@@ -2401,7 +2578,8 @@ const removeSwimlaneRow = (board, swimlane, index) => {
|
|
|
2401
2578
|
const newCells = swimlane.cells.filter(item => item.rowId !== removeRow.id);
|
|
2402
2579
|
let removeRowHeight = removeRow.height;
|
|
2403
2580
|
if (!removeRowHeight) {
|
|
2404
|
-
const
|
|
2581
|
+
const rowCell = swimlane.cells.find(item => item.rowId === removeRow.id);
|
|
2582
|
+
const cellPoints = getCellWithPoints(board, swimlane, rowCell.id).points;
|
|
2405
2583
|
removeRowHeight = RectangleClient.getRectangleByPoints(cellPoints).height;
|
|
2406
2584
|
}
|
|
2407
2585
|
const newPoints = [swimlane.points[0], [swimlane.points[1][0], swimlane.points[1][1] - removeRowHeight]];
|
|
@@ -2422,7 +2600,8 @@ const removeSwimlaneColumn = (board, swimlane, index) => {
|
|
|
2422
2600
|
const newCells = swimlane.cells.filter(item => item.columnId !== removeColumn.id);
|
|
2423
2601
|
let removeColumnWidth = removeColumn.width;
|
|
2424
2602
|
if (!removeColumnWidth) {
|
|
2425
|
-
const
|
|
2603
|
+
const columnCell = swimlane.cells.find(item => item.columnId === removeColumn.id);
|
|
2604
|
+
const cellPoints = getCellWithPoints(board, swimlane, columnCell.id).points;
|
|
2426
2605
|
removeColumnWidth = RectangleClient.getRectangleByPoints(cellPoints).width;
|
|
2427
2606
|
}
|
|
2428
2607
|
const newPoints = [swimlane.points[0], [swimlane.points[1][0] - removeColumnWidth, swimlane.points[1][1]]];
|
|
@@ -2430,19 +2609,23 @@ const removeSwimlaneColumn = (board, swimlane, index) => {
|
|
|
2430
2609
|
}
|
|
2431
2610
|
}
|
|
2432
2611
|
};
|
|
2433
|
-
const
|
|
2434
|
-
|
|
2435
|
-
id: idCreator(),
|
|
2436
|
-
rowId: row.id,
|
|
2437
|
-
columnId: newColumnId
|
|
2438
|
-
}));
|
|
2439
|
-
};
|
|
2440
|
-
const createNewRowCells = (swimlane, newRowId) => {
|
|
2441
|
-
return swimlane.columns.map(column => ({
|
|
2612
|
+
const createNewSwimlaneCells = (swimlane, newId, type) => {
|
|
2613
|
+
const cells = swimlane[`${type}s`].map(item => ({
|
|
2442
2614
|
id: idCreator(),
|
|
2443
|
-
rowId:
|
|
2444
|
-
columnId:
|
|
2615
|
+
rowId: type === 'row' ? item.id : newId,
|
|
2616
|
+
columnId: type === 'row' ? newId : item.id
|
|
2445
2617
|
}));
|
|
2618
|
+
cells.shift();
|
|
2619
|
+
cells[0] = {
|
|
2620
|
+
...cells[0],
|
|
2621
|
+
text: {
|
|
2622
|
+
children: [{ text: 'Lane' }],
|
|
2623
|
+
align: Alignment.center,
|
|
2624
|
+
direction: type === 'row' ? undefined : 'vertical'
|
|
2625
|
+
},
|
|
2626
|
+
textHeight: 20
|
|
2627
|
+
};
|
|
2628
|
+
return cells;
|
|
2446
2629
|
};
|
|
2447
2630
|
const updateSwimlane = (board, swimlane, newColumns, newRows, newCells, newPoints) => {
|
|
2448
2631
|
const path = PlaitBoard.findPath(board, swimlane);
|
|
@@ -4757,6 +4940,7 @@ const TableEngine = {
|
|
|
4757
4940
|
const cellBottomBorder = drawLine$1(rs, [x, y + height], [x + width, y + height], roughOptions);
|
|
4758
4941
|
g.append(cellRightBorder, cellBottomBorder);
|
|
4759
4942
|
});
|
|
4943
|
+
setStrokeLinecap(g, 'round');
|
|
4760
4944
|
return g;
|
|
4761
4945
|
},
|
|
4762
4946
|
isInsidePoint(rectangle, point) {
|
|
@@ -5074,6 +5258,130 @@ const CombinedFragmentEngine = {
|
|
|
5074
5258
|
}
|
|
5075
5259
|
};
|
|
5076
5260
|
|
|
5261
|
+
const DeletionEngine = {
|
|
5262
|
+
draw(board, rectangle, options) {
|
|
5263
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
5264
|
+
const shape = rs.path(`M${rectangle.x} ${rectangle.y} L${rectangle.x + rectangle.width} ${rectangle.y + rectangle.height}
|
|
5265
|
+
M${rectangle.x + rectangle.width} ${rectangle.y} L${rectangle.x} ${rectangle.y + rectangle.height}
|
|
5266
|
+
`, { ...options, fillStyle: 'solid', strokeWidth: 4 });
|
|
5267
|
+
return shape;
|
|
5268
|
+
},
|
|
5269
|
+
isInsidePoint(rectangle, point) {
|
|
5270
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
5271
|
+
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
5272
|
+
},
|
|
5273
|
+
getCornerPoints(rectangle) {
|
|
5274
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
5275
|
+
},
|
|
5276
|
+
getNearestPoint(rectangle, point) {
|
|
5277
|
+
return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
5278
|
+
},
|
|
5279
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
5280
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
5281
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
5282
|
+
return getPolygonEdgeByConnectionPoint(corners, point);
|
|
5283
|
+
},
|
|
5284
|
+
getConnectorPoints(rectangle) {
|
|
5285
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
5286
|
+
}
|
|
5287
|
+
};
|
|
5288
|
+
|
|
5289
|
+
const ActiveClassEngine = {
|
|
5290
|
+
draw(board, rectangle, options) {
|
|
5291
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
5292
|
+
const shape = rs.path(`M${rectangle.x} ${rectangle.y} H${rectangle.x + rectangle.width} V${rectangle.y + rectangle.height} H${rectangle.x} Z M${rectangle.x + rectangle.width * 0.125} ${rectangle.y} L${rectangle.x + rectangle.width * 0.125} ${rectangle.y +
|
|
5293
|
+
rectangle.height} M${rectangle.x + rectangle.width - rectangle.width * 0.125} ${rectangle.y} L${rectangle.x +
|
|
5294
|
+
rectangle.width -
|
|
5295
|
+
rectangle.width * 0.125} ${rectangle.y + rectangle.height}`, { ...options, fillStyle: 'solid' });
|
|
5296
|
+
setStrokeLinecap(shape, 'round');
|
|
5297
|
+
return shape;
|
|
5298
|
+
},
|
|
5299
|
+
isInsidePoint(rectangle, point) {
|
|
5300
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
5301
|
+
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
5302
|
+
},
|
|
5303
|
+
getCornerPoints(rectangle) {
|
|
5304
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
5305
|
+
},
|
|
5306
|
+
getNearestPoint(rectangle, point) {
|
|
5307
|
+
return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
5308
|
+
},
|
|
5309
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
5310
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
5311
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
5312
|
+
return getPolygonEdgeByConnectionPoint(corners, point);
|
|
5313
|
+
},
|
|
5314
|
+
getConnectorPoints(rectangle) {
|
|
5315
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
5316
|
+
},
|
|
5317
|
+
getTextRectangle: (element) => {
|
|
5318
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
5319
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
5320
|
+
const height = element.textHeight;
|
|
5321
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2 - elementRectangle.width * 0.125 * 2;
|
|
5322
|
+
return {
|
|
5323
|
+
height,
|
|
5324
|
+
width: width > 0 ? width : 0,
|
|
5325
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + elementRectangle.width * 0.125,
|
|
5326
|
+
y: elementRectangle.y + (elementRectangle.height - height) / 2
|
|
5327
|
+
};
|
|
5328
|
+
}
|
|
5329
|
+
};
|
|
5330
|
+
|
|
5331
|
+
const NoteEngine = {
|
|
5332
|
+
draw(board, rectangle, options) {
|
|
5333
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
5334
|
+
const shape = rs.path(`M${rectangle.x} ${rectangle.y}
|
|
5335
|
+
h${rectangle.width - 16}
|
|
5336
|
+
v16
|
|
5337
|
+
h16
|
|
5338
|
+
v${rectangle.height - 16}
|
|
5339
|
+
h${-rectangle.width}
|
|
5340
|
+
Z
|
|
5341
|
+
M${rectangle.x + rectangle.width - 16} ${rectangle.y}
|
|
5342
|
+
A16 16, 0,0,1, ${rectangle.x + rectangle.width} ${rectangle.y + 16}
|
|
5343
|
+
`, { ...options, fillStyle: 'solid' });
|
|
5344
|
+
setStrokeLinecap(shape, 'round');
|
|
5345
|
+
return shape;
|
|
5346
|
+
},
|
|
5347
|
+
isInsidePoint(rectangle, point) {
|
|
5348
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
5349
|
+
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
5350
|
+
},
|
|
5351
|
+
getCornerPoints(rectangle) {
|
|
5352
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
5353
|
+
},
|
|
5354
|
+
getNearestPoint(rectangle, point) {
|
|
5355
|
+
const nearestPoint = getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
5356
|
+
if (nearestPoint[0] > rectangle.x + rectangle.width - 16 && nearestPoint[1] < rectangle.y + 16) {
|
|
5357
|
+
return getNearestPointBetweenPointAndEllipse(point, [rectangle.x + rectangle.width - 16, rectangle.y + 16], 16, 16);
|
|
5358
|
+
}
|
|
5359
|
+
return nearestPoint;
|
|
5360
|
+
},
|
|
5361
|
+
getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
|
|
5362
|
+
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
5363
|
+
const centerPoint = [rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height / 2];
|
|
5364
|
+
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
|
|
5365
|
+
const slope = getEllipseTangentSlope(point[0], point[1], 16, 16);
|
|
5366
|
+
return getVectorFromPointAndSlope(point[0], point[1], slope);
|
|
5367
|
+
},
|
|
5368
|
+
getConnectorPoints(rectangle) {
|
|
5369
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
5370
|
+
},
|
|
5371
|
+
getTextRectangle: (element) => {
|
|
5372
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
5373
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
5374
|
+
const height = element.textHeight;
|
|
5375
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth - 15;
|
|
5376
|
+
return {
|
|
5377
|
+
height,
|
|
5378
|
+
width: width > 0 ? width : 0,
|
|
5379
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
5380
|
+
y: elementRectangle.y + (elementRectangle.height - height) / 2
|
|
5381
|
+
};
|
|
5382
|
+
}
|
|
5383
|
+
};
|
|
5384
|
+
|
|
5077
5385
|
const ShapeEngineMap = {
|
|
5078
5386
|
[BasicShapes.rectangle]: RectangleEngine,
|
|
5079
5387
|
[BasicShapes.diamond]: DiamondEngine,
|
|
@@ -5126,8 +5434,18 @@ const ShapeEngineMap = {
|
|
|
5126
5434
|
[UMLSymbols.actor]: ActorEngine,
|
|
5127
5435
|
[UMLSymbols.useCase]: EllipseEngine,
|
|
5128
5436
|
[UMLSymbols.container]: ContainerEngine,
|
|
5437
|
+
[UMLSymbols.note]: NoteEngine,
|
|
5129
5438
|
[UMLSymbols.package]: PackageEngine,
|
|
5130
|
-
[UMLSymbols.combinedFragment]: CombinedFragmentEngine
|
|
5439
|
+
[UMLSymbols.combinedFragment]: CombinedFragmentEngine,
|
|
5440
|
+
[UMLSymbols.class]: TableEngine,
|
|
5441
|
+
[UMLSymbols.interface]: TableEngine,
|
|
5442
|
+
[UMLSymbols.activation]: RectangleEngine,
|
|
5443
|
+
[UMLSymbols.object]: RectangleEngine,
|
|
5444
|
+
[UMLSymbols.deletion]: DeletionEngine,
|
|
5445
|
+
[UMLSymbols.activityClass]: ActiveClassEngine,
|
|
5446
|
+
[UMLSymbols.simpleClass]: RectangleEngine,
|
|
5447
|
+
[UMLSymbols.port]: RectangleEngine,
|
|
5448
|
+
[UMLSymbols.branchMerge]: DiamondEngine
|
|
5131
5449
|
};
|
|
5132
5450
|
const getEngine = (shape) => {
|
|
5133
5451
|
return ShapeEngineMap[shape];
|
|
@@ -5381,7 +5699,7 @@ const PlaitDrawElement = {
|
|
|
5381
5699
|
return Object.keys(SwimlaneSymbols).includes(value.shape) && value.shape === SwimlaneSymbols.swimlaneHorizontal;
|
|
5382
5700
|
},
|
|
5383
5701
|
isUMLClassOrInterface: (value) => {
|
|
5384
|
-
return
|
|
5702
|
+
return Object.keys(UMLSymbols).includes(value.shape) && [UMLSymbols.class, UMLSymbols.interface].includes(value.shape);
|
|
5385
5703
|
}
|
|
5386
5704
|
};
|
|
5387
5705
|
|
|
@@ -5838,7 +6156,7 @@ const withDrawHotkey = (board) => {
|
|
|
5838
6156
|
const hitElement = getHitElementByPoint(board, point);
|
|
5839
6157
|
if (hitElement && PlaitDrawElement.isGeometry(hitElement)) {
|
|
5840
6158
|
if (isMultipleTextGeometry(hitElement)) {
|
|
5841
|
-
const hitText =
|
|
6159
|
+
const hitText = getHitMultipleGeometryText(hitElement, point) ||
|
|
5842
6160
|
hitElement.texts.find(item => item.key.includes(MultipleTextGeometryCommonTextKeys.content)) ||
|
|
5843
6161
|
hitElement.texts[0];
|
|
5844
6162
|
editText(board, hitElement, hitText);
|
|
@@ -5853,6 +6171,21 @@ const withDrawHotkey = (board) => {
|
|
|
5853
6171
|
return board;
|
|
5854
6172
|
};
|
|
5855
6173
|
|
|
6174
|
+
class TableGenerator extends Generator {
|
|
6175
|
+
canDraw(element, data) {
|
|
6176
|
+
return true;
|
|
6177
|
+
}
|
|
6178
|
+
draw(element, data) {
|
|
6179
|
+
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
6180
|
+
return getEngine(TableSymbols.table).draw(this.board, rectangle, {
|
|
6181
|
+
strokeWidth: 2,
|
|
6182
|
+
stroke: getDrawDefaultStrokeColor(this.board.theme.themeColorMode),
|
|
6183
|
+
}, {
|
|
6184
|
+
element: element
|
|
6185
|
+
});
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6188
|
+
|
|
5856
6189
|
const isGeometryDndMode = (board) => {
|
|
5857
6190
|
const geometryPointers = getGeometryPointers();
|
|
5858
6191
|
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
@@ -5865,6 +6198,14 @@ const isGeometryDrawingMode = (board) => {
|
|
|
5865
6198
|
const drawingMode = isGeometryPointer && isDrawingMode(board);
|
|
5866
6199
|
return drawingMode;
|
|
5867
6200
|
};
|
|
6201
|
+
const getGeometryGeneratorByShape = (board, shape) => {
|
|
6202
|
+
if (PlaitDrawElement.isUMLClassOrInterface({ shape: shape })) {
|
|
6203
|
+
return new TableGenerator(board);
|
|
6204
|
+
}
|
|
6205
|
+
else {
|
|
6206
|
+
return new GeometryShapeGenerator(board);
|
|
6207
|
+
}
|
|
6208
|
+
};
|
|
5868
6209
|
const withGeometryCreateByDrag = (board) => {
|
|
5869
6210
|
const { pointerMove, globalPointerUp, pointerUp } = board;
|
|
5870
6211
|
let geometryShapeG = null;
|
|
@@ -5873,12 +6214,12 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
5873
6214
|
board.pointerMove = (event) => {
|
|
5874
6215
|
geometryShapeG?.remove();
|
|
5875
6216
|
geometryShapeG = createG();
|
|
5876
|
-
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
5877
6217
|
const geometryPointers = getGeometryPointers();
|
|
5878
6218
|
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
5879
6219
|
const dragMode = isGeometryPointer && isDndMode(board);
|
|
5880
6220
|
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
5881
6221
|
const pointer = PlaitBoard.getPointer(board);
|
|
6222
|
+
const geometryGenerator = getGeometryGeneratorByShape(board, pointer);
|
|
5882
6223
|
if (dragMode) {
|
|
5883
6224
|
const memorizedLatest = getMemorizedLatestByPointer(pointer);
|
|
5884
6225
|
if (pointer === BasicShapes.text) {
|
|
@@ -5973,9 +6314,9 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
5973
6314
|
board.pointerMove = (event) => {
|
|
5974
6315
|
geometryShapeG?.remove();
|
|
5975
6316
|
geometryShapeG = createG();
|
|
5976
|
-
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
5977
6317
|
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
5978
6318
|
const pointer = PlaitBoard.getPointer(board);
|
|
6319
|
+
const geometryGenerator = getGeometryGeneratorByShape(board, pointer);
|
|
5979
6320
|
snapG?.remove();
|
|
5980
6321
|
if (start && isGeometryDrawingMode(board)) {
|
|
5981
6322
|
let points = normalizeShapePoints([start, movingPoint], isShift);
|
|
@@ -6108,7 +6449,8 @@ const withDrawFragment = (baseBoard) => {
|
|
|
6108
6449
|
const tableElements = drawElements.filter(value => PlaitDrawElement.isTable(value));
|
|
6109
6450
|
const boundLineElements = [
|
|
6110
6451
|
...getBoundedLineElements(board, geometryElements),
|
|
6111
|
-
...getBoundedLineElements(board, imageElements)
|
|
6452
|
+
...getBoundedLineElements(board, imageElements),
|
|
6453
|
+
...getBoundedLineElements(board, tableElements)
|
|
6112
6454
|
].filter(line => !lineElements.includes(line));
|
|
6113
6455
|
data.push(...[
|
|
6114
6456
|
...geometryElements,
|
|
@@ -6275,7 +6617,7 @@ const withGeometryResize = (board) => {
|
|
|
6275
6617
|
snapG = resizeSnapRef.snapG;
|
|
6276
6618
|
PlaitBoard.getElementActiveHost(board).append(snapG);
|
|
6277
6619
|
let points = resizeSnapRef.activePoints;
|
|
6278
|
-
if (PlaitDrawElement.isGeometry(resizeRef.element)) {
|
|
6620
|
+
if (PlaitDrawElement.isGeometry(resizeRef.element) && isGeometryIncludeText(resizeRef.element)) {
|
|
6279
6621
|
const { height: textHeight } = getFirstTextManage(resizeRef.element).getSize();
|
|
6280
6622
|
DrawTransforms.resizeGeometry(board, points, textHeight, resizeRef.path);
|
|
6281
6623
|
}
|
|
@@ -6876,21 +7218,6 @@ const withDrawRotate = (board) => {
|
|
|
6876
7218
|
return board;
|
|
6877
7219
|
};
|
|
6878
7220
|
|
|
6879
|
-
class TableGenerator extends Generator {
|
|
6880
|
-
canDraw(element, data) {
|
|
6881
|
-
return true;
|
|
6882
|
-
}
|
|
6883
|
-
draw(element, data) {
|
|
6884
|
-
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
6885
|
-
return getEngine(TableSymbols.table).draw(this.board, rectangle, {
|
|
6886
|
-
strokeWidth: 2,
|
|
6887
|
-
stroke: getDrawDefaultStrokeColor(this.board.theme.themeColorMode),
|
|
6888
|
-
}, {
|
|
6889
|
-
element: element
|
|
6890
|
-
});
|
|
6891
|
-
}
|
|
6892
|
-
}
|
|
6893
|
-
|
|
6894
7221
|
class TableComponent extends CommonElementFlavour {
|
|
6895
7222
|
constructor() {
|
|
6896
7223
|
super();
|
|
@@ -6942,7 +7269,9 @@ class TableComponent extends CommonElementFlavour {
|
|
|
6942
7269
|
});
|
|
6943
7270
|
}
|
|
6944
7271
|
getDrawShapeTexts(cells) {
|
|
6945
|
-
return cells
|
|
7272
|
+
return cells
|
|
7273
|
+
.filter(item => isCellIncludeText(item))
|
|
7274
|
+
.map(item => {
|
|
6946
7275
|
return {
|
|
6947
7276
|
key: item.id,
|
|
6948
7277
|
text: item.text,
|
|
@@ -7202,7 +7531,13 @@ function buildSwimlaneTable(element) {
|
|
|
7202
7531
|
};
|
|
7203
7532
|
}
|
|
7204
7533
|
if (item.text && item.textHeight && !item.text.direction) {
|
|
7205
|
-
item
|
|
7534
|
+
item = {
|
|
7535
|
+
...item,
|
|
7536
|
+
text: {
|
|
7537
|
+
...item.text,
|
|
7538
|
+
direction: 'vertical'
|
|
7539
|
+
}
|
|
7540
|
+
};
|
|
7206
7541
|
}
|
|
7207
7542
|
return item;
|
|
7208
7543
|
});
|
|
@@ -7554,5 +7889,5 @@ const withDraw = (board) => {
|
|
|
7554
7889
|
* Generated bundle index. Do not edit.
|
|
7555
7890
|
*/
|
|
7556
7891
|
|
|
7557
|
-
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DEFAULT_TEXT_HEIGHT, DefaultActorProperty, DefaultArrowProperty, DefaultBasicShapeProperty, DefaultBasicShapePropertyMap, DefaultCloudProperty, DefaultCombinedFragmentProperty, DefaultConnectorProperty, DefaultContainerProperty, DefaultDataBaseProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultDocumentProperty, DefaultDrawActiveStyle, DefaultDrawStyle, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultInternalStorageProperty, DefaultManualInputProperty, DefaultMergeProperty, DefaultMultiDocumentProperty, DefaultNoteProperty, DefaultPackageProperty, DefaultPentagonArrowProperty, DefaultSwimlaneHorizontalProperty, DefaultSwimlanePropertyMap, DefaultSwimlaneVerticalProperty, DefaultTextProperty, DefaultTwoWayArrowProperty, DefaultUMLPropertyMap, DrawThemeColors, DrawTransforms, FlowchartSymbols, GEOMETRY_WITHOUT_TEXT, GeometryComponent, GeometryShapeGenerator, GeometryThreshold, KEY_TO_TEXT_MANAGE, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LineActiveGenerator, LineAutoCompleteGenerator, LineComponent, LineHandleKey, LineMarkerType, LineShape, MemorizeKey, MultipleTextGeometryCommonTextKeys, MultipleTextGeometryTextKeys, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, SingleTextGenerator, StrokeStyle, SwimlaneSymbols, TableGenerator, TableSymbols, TextGenerator, UMLSymbols, WithLineAutoCompletePluginKey, alignElbowSegment, alignPoints, buildDefaultTextsByShape, createDefaultFlowchart, createDefaultGeometry, createGeometryElement, createGeometryElementWithText, createGeometryElementWithoutText, createLineElement, createMultipleTextGeometryElement, createTextElement, debugGenerator$1 as debugGenerator, deleteTextManage, drawBoundReaction, drawGeometry, drawLine, drawLineArrow, drawShape, editText, getAutoCompletePoints, getBasicPointers, getCenterPointsOnPolygon$1 as getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultBasicShapeProperty, getDefaultFlowchartProperty, getDefaultGeometryPoints, getDefaultGeometryProperty, getDefaultTextPoints, getDefaultUMLProperty, getDrawDefaultStrokeColor, getElbowLineRouteOptions, getElbowPoints, getFillByElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryPointers, getHitConnection, getHitConnectorPoint, getHitIndexOfAutoCompletePoint,
|
|
7892
|
+
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DEFAULT_TEXT_HEIGHT, DefaultActivationProperty, DefaultActorProperty, DefaultArrowProperty, DefaultBasicShapeProperty, DefaultBasicShapePropertyMap, DefaultClassProperty, DefaultCloudProperty, DefaultCombinedFragmentProperty, DefaultConnectorProperty, DefaultContainerProperty, DefaultDataBaseProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultDeletionProperty, DefaultDocumentProperty, DefaultDrawActiveStyle, DefaultDrawStyle, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultInterfaceProperty, DefaultInternalStorageProperty, DefaultManualInputProperty, DefaultMergeProperty, DefaultMultiDocumentProperty, DefaultNoteProperty, DefaultObjectProperty, DefaultPackageProperty, DefaultPentagonArrowProperty, DefaultPortProperty, DefaultSwimlaneHorizontalProperty, DefaultSwimlanePropertyMap, DefaultSwimlaneVerticalProperty, DefaultTextProperty, DefaultTwoWayArrowProperty, DefaultUMLPropertyMap, DrawThemeColors, DrawTransforms, FlowchartSymbols, GEOMETRY_WITHOUT_TEXT, GEOMETRY_WITH_MULTIPLE_TEXT, GeometryComponent, GeometryShapeGenerator, GeometryThreshold, KEY_TO_TEXT_MANAGE, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LineActiveGenerator, LineAutoCompleteGenerator, LineComponent, LineHandleKey, LineMarkerType, LineShape, MemorizeKey, MultipleTextGeometryCommonTextKeys, MultipleTextGeometryTextKeys, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, SingleTextGenerator, StrokeStyle, SwimlaneSymbols, TableGenerator, TableSymbols, TextGenerator, UMLSymbols, WithLineAutoCompletePluginKey, alignElbowSegment, alignPoints, buildDefaultTextsByShape, createDefaultFlowchart, createDefaultGeometry, createGeometryElement, createGeometryElementWithText, createGeometryElementWithoutText, createLineElement, createMultipleTextGeometryElement, createTextElement, createUMLClassOrInterfaceGeometryElement, debugGenerator$1 as debugGenerator, deleteTextManage, drawBoundReaction, drawGeometry, drawLine, drawLineArrow, drawShape, editText, getAutoCompletePoints, getBasicPointers, getCenterPointsOnPolygon$1 as getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultBasicShapeProperty, getDefaultFlowchartProperty, getDefaultGeometryPoints, getDefaultGeometryProperty, getDefaultTextPoints, getDefaultUMLProperty, getDrawDefaultStrokeColor, getElbowLineRouteOptions, getElbowPoints, getFillByElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryAlign, getGeometryPointers, getHitConnection, getHitConnectorPoint, getHitIndexOfAutoCompletePoint, getHitMultipleGeometryText, getHitShape, getIndexAndDeleteCountByKeyPoint, getLineDashByElement, getLineHandleRefPair, getLineMemorizedLatest, getLinePointers, getLinePoints, getLineTextRectangle, getLines, getMemorizeKey, getMemorizedLatestByPointer, getMemorizedLatestShape, getMidKeyPoints, getMiddlePoints, getMirrorDataPoints, getMultipleTextGeometryTextKeys, getNearestPoint, getNextRenderPoints, getNextSourceAndTargetPoints, getResizedPreviousAndNextPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getSelectedTableElements, getSnapResizingRef, getSnapResizingRefOptions, getSnappingRef, getSnappingShape, getSourceAndTargetRectangle, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getSwimlanePointers, getTextKey, getTextManage, getTextRectangle, getTextShapeProperty, getUMLPointers, getVectorByConnection, handleLineCreating, hasIllegalElbowPoint, insertElement, isDrawElementIncludeText, isDrawElementsIncludeText, isGeometryIncludeText, isHitDrawElement, isHitEdgeOfShape, isHitElementInside, isHitElementText, isHitLine, isHitLineText, isHitPolyLine, isInsideOfShape, isMultipleTextGeometry, isMultipleTextShape, isRectangleHitDrawElement, isRectangleHitElementText, isSelfLoop, isSingleSelectSwimlane, isSingleSelectTable, isSingleTextGeometry, isSingleTextShape, isTextExceedingBounds, isUpdatedHandleIndex, isUseDefaultOrthogonalRoute, memorizeLatestShape, memorizeLatestText, rerenderGeometryActive, setTextManage, traverseDrawShapes, withDraw, withLineAutoComplete };
|
|
7558
7893
|
//# sourceMappingURL=plait-draw.mjs.map
|