@easy-editor/plugin-dashboard 1.0.1 → 1.0.3

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/dist/index.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  var core = require('@easy-editor/core');
4
6
  var mobx = require('mobx');
5
7
 
@@ -55,12 +57,12 @@ function _applyDecs2311(e, t, n, r, o, i) {
55
57
  t[4](this, e);
56
58
  }
57
59
  } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) {
58
- if ((c = y[+s][r]) && 7 != (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet");
60
+ if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet");
59
61
  y[+s][r] = o < 3 ? 1 : o;
60
62
  }
61
63
  }
62
64
  for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) {
63
- var T = b(h[O], "A decorator", "be", !0),
65
+ var T = b(h[O], "A decorator", "be", true),
64
66
  z = n ? h[O - 1] : void 0,
65
67
  A = {},
66
68
  H = {
@@ -69,7 +71,7 @@ function _applyDecs2311(e, t, n, r, o, i) {
69
71
  metadata: a,
70
72
  addInitializer: function (e, t) {
71
73
  if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished");
72
- b(t, "An initializer", "be", !0), i.push(t);
74
+ b(t, "An initializer", "be", true), i.push(t);
73
75
  }.bind(null, A)
74
76
  };
75
77
  if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = {
@@ -93,8 +95,8 @@ function _applyDecs2311(e, t, n, r, o, i) {
93
95
  }
94
96
  function w(e) {
95
97
  return m(e, d, {
96
- configurable: !0,
97
- enumerable: !0,
98
+ configurable: true,
99
+ enumerable: true,
98
100
  value: a
99
101
  });
100
102
  }
@@ -140,7 +142,7 @@ function _toPrimitive(t, r) {
140
142
  if ("object" != typeof t || !t) return t;
141
143
  var e = t[Symbol.toPrimitive];
142
144
  if (void 0 !== e) {
143
- var i = e.call(t, r || "default");
145
+ var i = e.call(t, r);
144
146
  if ("object" != typeof i) return i;
145
147
  throw new TypeError("@@toPrimitive must return a primitive value.");
146
148
  }
@@ -151,10 +153,144 @@ function _toPropertyKey(t) {
151
153
  return "symbol" == typeof i ? i : i + "";
152
154
  }
153
155
 
154
- let _initProto, _init_enabled, _init_extra_enabled, _init_guideLines, _init_extra_guideLines, _init_nodeLineMap, _init_extra_nodeLineMap, _init_adsorptionLines, _init_extra_adsorptionLines;
156
+ let _initProto$1;
157
+ let AlignType = /*#__PURE__*/function (AlignType) {
158
+ AlignType["LEFT"] = "left";
159
+ AlignType["RIGHT"] = "right";
160
+ AlignType["TOP"] = "top";
161
+ AlignType["BOTTOM"] = "bottom";
162
+ AlignType["HORIZONTAL_CENTER"] = "horizontalCenter";
163
+ AlignType["VERTICAL_CENTER"] = "verticalCenter";
164
+ return AlignType;
165
+ }({});
166
+ let DistributeType = /*#__PURE__*/function (DistributeType) {
167
+ DistributeType["HORIZONTAL"] = "horizontal";
168
+ DistributeType["VERTICAL"] = "vertical";
169
+ return DistributeType;
170
+ }({});
171
+ class Alignment {
172
+ static {
173
+ [_initProto$1] = _applyDecs2311(this, [], [[mobx.action, 2, "align"], [mobx.action, 2, "distribute"]]).e;
174
+ }
175
+ constructor(designer) {
176
+ this.designer = designer;
177
+ }
178
+ get selection() {
179
+ return this.designer.selection;
180
+ }
181
+ getSelectedNodes() {
182
+ return this.selection.getTopNodes(false).filter(node => node && !node.isRoot);
183
+ }
184
+ calculateBoundingBox(nodes) {
185
+ let [minX, minY, maxX, maxY] = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];
186
+ for (const node of nodes) {
187
+ const rect = node.getDashboardRect();
188
+ minX = Math.min(minX, rect.x);
189
+ minY = Math.min(minY, rect.y);
190
+ maxX = Math.max(maxX, rect.x + rect.width);
191
+ maxY = Math.max(maxY, rect.y + rect.height);
192
+ }
193
+ return {
194
+ minX,
195
+ minY,
196
+ maxX,
197
+ maxY,
198
+ width: maxX - minX,
199
+ height: maxY - minY
200
+ };
201
+ }
202
+ updateNodePosition(node, x, y) {
203
+ if (node.isGroup) {
204
+ const nodeRect = node.getDashboardRect();
205
+ const deltaX = x - nodeRect.x;
206
+ const deltaY = y - nodeRect.y;
207
+ for (const child of node.getAllNodesInGroup()) {
208
+ const childRect = child.getDashboardRect();
209
+ child.updateDashboardRect({
210
+ x: childRect.x + deltaX,
211
+ y: childRect.y + deltaY
212
+ });
213
+ }
214
+ } else {
215
+ node.updateDashboardRect({
216
+ x,
217
+ y
218
+ });
219
+ }
220
+ }
221
+ align(type) {
222
+ const nodes = this.getSelectedNodes();
223
+ if (nodes.length < 2) return false;
224
+ const box = this.calculateBoundingBox(nodes);
225
+ for (const node of nodes) {
226
+ const rect = node.getDashboardRect();
227
+ let newX = rect.x;
228
+ let newY = rect.y;
229
+ switch (type) {
230
+ case AlignType.LEFT:
231
+ newX = box.minX;
232
+ break;
233
+ case AlignType.RIGHT:
234
+ newX = box.maxX - rect.width;
235
+ break;
236
+ case AlignType.TOP:
237
+ newY = box.minY;
238
+ break;
239
+ case AlignType.BOTTOM:
240
+ newY = box.maxY - rect.height;
241
+ break;
242
+ case AlignType.HORIZONTAL_CENTER:
243
+ newX = box.minX + (box.width - rect.width) / 2;
244
+ break;
245
+ case AlignType.VERTICAL_CENTER:
246
+ newY = box.minY + (box.height - rect.height) / 2;
247
+ break;
248
+ }
249
+ this.updateNodePosition(node, newX, newY);
250
+ }
251
+ return true;
252
+ }
253
+ distribute(type) {
254
+ const nodes = this.getSelectedNodes();
255
+ if (nodes.length < 3) return false;
256
+ const box = this.calculateBoundingBox(nodes);
257
+ if (type === DistributeType.HORIZONTAL) {
258
+ const sorted = [...nodes].sort((a, b) => a.getDashboardRect().x - b.getDashboardRect().x);
259
+ const totalWidth = sorted.reduce((sum, n) => sum + n.getDashboardRect().width, 0);
260
+ const gap = (box.width - totalWidth) / (nodes.length - 1);
261
+ let currentX = box.minX;
262
+ for (const node of sorted) {
263
+ const rect = node.getDashboardRect();
264
+ this.updateNodePosition(node, currentX, rect.y);
265
+ currentX += rect.width + gap;
266
+ }
267
+ } else {
268
+ const sorted = [...nodes].sort((a, b) => a.getDashboardRect().y - b.getDashboardRect().y);
269
+ const totalHeight = sorted.reduce((sum, n) => sum + n.getDashboardRect().height, 0);
270
+ const gap = (box.height - totalHeight) / (nodes.length - 1);
271
+ let currentY = box.minY;
272
+ for (const node of sorted) {
273
+ const rect = node.getDashboardRect();
274
+ this.updateNodePosition(node, rect.x, currentY);
275
+ currentY += rect.height + gap;
276
+ }
277
+ }
278
+ return true;
279
+ }
280
+ alignLeft = (_initProto$1(this), () => this.align(AlignType.LEFT));
281
+ alignRight = () => this.align(AlignType.RIGHT);
282
+ alignTop = () => this.align(AlignType.TOP);
283
+ alignBottom = () => this.align(AlignType.BOTTOM);
284
+ alignHorizontalCenter = () => this.align(AlignType.HORIZONTAL_CENTER);
285
+ alignVerticalCenter = () => this.align(AlignType.VERTICAL_CENTER);
286
+ distributeHorizontal = () => this.distribute(DistributeType.HORIZONTAL);
287
+ distributeVertical = () => this.distribute(DistributeType.VERTICAL);
288
+ }
289
+
290
+ let _initProto, _init_enabled, _init_extra_enabled, _init_guideLines, _init_extra_guideLines, _init_nodeLineMap, _init_extra_nodeLineMap, _init_adsorptionLines, _init_extra_adsorptionLines, _init_adsorptionLinesWithDistance, _init_extra_adsorptionLinesWithDistance, _init_userGuideLines, _init_extra_userGuideLines;
155
291
  class GuideLine {
156
292
  static {
157
- [_init_enabled, _init_extra_enabled, _init_guideLines, _init_extra_guideLines, _init_nodeLineMap, _init_extra_nodeLineMap, _init_adsorptionLines, _init_extra_adsorptionLines, _initProto] = _applyDecs2311(this, [], [[mobx.observable, 1, "enabled"], [[mobx.observable, mobx.observable.shallow], 17, "guideLines"], [mobx.computed, 3, "guideLinesMap"], [[mobx.observable, mobx.observable.shallow], 17, "nodeLineMap"], [mobx.observable, 1, "adsorptionLines"], [mobx.action, 2, "addGuideLine"], [mobx.action, 2, "removeGuideLine"], [mobx.action, 2, "updateGuideLine"], [mobx.action, 2, "calculateGuideLineInfo"], [mobx.action, 2, "getAdsorptionPosition"], [mobx.action, 2, "resetAdsorptionLines"]]).e;
293
+ [_init_enabled, _init_extra_enabled, _init_guideLines, _init_extra_guideLines, _init_nodeLineMap, _init_extra_nodeLineMap, _init_adsorptionLines, _init_extra_adsorptionLines, _init_adsorptionLinesWithDistance, _init_extra_adsorptionLinesWithDistance, _init_userGuideLines, _init_extra_userGuideLines, _initProto] = _applyDecs2311(this, [], [[mobx.observable, 1, "enabled"], [[mobx.observable, mobx.observable.shallow], 17, "guideLines"], [mobx.computed, 3, "guideLinesMap"], [[mobx.observable, mobx.observable.shallow], 17, "nodeLineMap"], [mobx.observable, 1, "adsorptionLines"], [[mobx.observable, mobx.observable.shallow], 17, "adsorptionLinesWithDistance"], [[mobx.observable, mobx.observable.shallow], 17, "userGuideLines"], [mobx.action, 2, "addGuideLine"], [mobx.action, 2, "removeGuideLine"], [mobx.action, 2, "updateGuideLine"], [mobx.computed, 3, "userGuideLinesMap"], [mobx.action, 2, "addUserGuideLine"], [mobx.action, 2, "updateUserGuideLine"], [mobx.action, 2, "removeUserGuideLine"], [mobx.action, 2, "clearUserGuideLines"], [mobx.action, 2, "calculateGuideLineInfo"], [mobx.action, 2, "getAdsorptionPosition"], [mobx.action, 2, "resetAdsorptionLines"]]).e;
158
294
  }
159
295
  #A = (_initProto(this), _init_enabled(this, true));
160
296
  get enabled() {
@@ -197,6 +333,21 @@ class GuideLine {
197
333
  set adsorptionLines(v) {
198
334
  this.#D = v;
199
335
  }
336
+ #E = (_init_extra_adsorptionLines(this), _init_adsorptionLinesWithDistance(this, []));
337
+ get adsorptionLinesWithDistance() {
338
+ return this.#E;
339
+ }
340
+ set adsorptionLinesWithDistance(v) {
341
+ this.#E = v;
342
+ }
343
+ #F = (_init_extra_adsorptionLinesWithDistance(this), _init_userGuideLines(this, []));
344
+ get userGuideLines() {
345
+ return this.#F;
346
+ }
347
+ set userGuideLines(v) {
348
+ this.#F = v;
349
+ }
350
+ userGuideLineIdCounter = (_init_extra_userGuideLines(this), 0);
200
351
  get currentDocument() {
201
352
  return this.designer.currentDocument;
202
353
  }
@@ -252,6 +403,41 @@ class GuideLine {
252
403
  this.guideLines[index] = guideLine;
253
404
  }
254
405
  }
406
+ get userGuideLinesMap() {
407
+ const result = Object.groupBy(this.userGuideLines, item => item.type);
408
+ return {
409
+ verticalLinesMap: new Map(result.vertical?.map(item => [item.position, item])),
410
+ horizontalLinesMap: new Map(result.horizontal?.map(item => [item.position, item]))
411
+ };
412
+ }
413
+ addUserGuideLine(type, position) {
414
+ const id = `user-guideline-${++this.userGuideLineIdCounter}`;
415
+ const guideLine = {
416
+ id,
417
+ type,
418
+ position: Math.round(position)
419
+ };
420
+ this.userGuideLines.push(guideLine);
421
+ return guideLine;
422
+ }
423
+ updateUserGuideLine(id, position) {
424
+ const index = this.userGuideLines.findIndex(item => item.id === id);
425
+ if (index !== -1) {
426
+ this.userGuideLines[index] = {
427
+ ...this.userGuideLines[index],
428
+ position: Math.round(position)
429
+ };
430
+ }
431
+ }
432
+ removeUserGuideLine(id) {
433
+ const index = this.userGuideLines.findIndex(item => item.id === id);
434
+ if (index !== -1) {
435
+ this.userGuideLines.splice(index, 1);
436
+ }
437
+ }
438
+ clearUserGuideLines() {
439
+ this.userGuideLines = [];
440
+ }
255
441
  calculateGuideLineInfo() {
256
442
  if (!this.enabled) return;
257
443
  const verticalLinesMap = new Map();
@@ -288,7 +474,8 @@ class GuideLine {
288
474
  this.nodeLineMap.verticalLinesMap = verticalLinesMap;
289
475
  this.nodeLineMap.horizontalLinesMap = horizontalLinesMap;
290
476
  }
291
- adsorptionSize = (_init_extra_adsorptionLines(this), 10);
477
+ adsorptionSize = 10;
478
+ maxDistanceDisplay = 300;
292
479
  getAdsorptionPosition(rect, adsorption) {
293
480
  if (typeof adsorption === 'number') {
294
481
  adsorption = [adsorption];
@@ -300,42 +487,63 @@ class GuideLine {
300
487
  const currentHorizontalLine = [rect.top, rect.top + rect.height / 2, rect.bottom];
301
488
  currentVerticalLine.forEach((item, index) => {
302
489
  let minDistance = Number.POSITIVE_INFINITY;
490
+ let closestPosition = null;
303
491
  this.nodeLineMap.verticalLinesMap.forEach((_, pos) => {
304
492
  const distance = Math.abs(item - pos);
305
493
  if (distance !== 0 && distance < this.adsorptionSize && distance < minDistance) {
306
- minDistance = pos;
494
+ minDistance = distance;
495
+ closestPosition = pos;
307
496
  }
308
497
  });
309
498
  this.guideLinesMap.verticalLinesMap.forEach((_, pos) => {
310
499
  const distance = Math.abs(item - pos);
311
500
  if (distance !== 0 && distance < this.adsorptionSize && distance < minDistance) {
312
- minDistance = pos;
501
+ minDistance = distance;
502
+ closestPosition = pos;
503
+ }
504
+ });
505
+ this.userGuideLinesMap.verticalLinesMap.forEach((_, pos) => {
506
+ const distance = Math.abs(item - pos);
507
+ if (distance !== 0 && distance < this.adsorptionSize && distance < minDistance) {
508
+ minDistance = distance;
509
+ closestPosition = pos;
313
510
  }
314
511
  });
315
- if (minDistance !== Number.POSITIVE_INFINITY && adsorptionVerticalLines.findIndex(item => item.position === minDistance) === -1) {
512
+ if (closestPosition !== null && adsorptionVerticalLines.findIndex(item => item.position === closestPosition) === -1) {
316
513
  adsorptionVerticalLines.push({
317
514
  adsorption: index,
318
- position: minDistance
515
+ position: closestPosition
319
516
  });
320
517
  }
321
518
  });
322
519
  currentHorizontalLine.forEach((item, index) => {
323
- let minDistance = -1;
520
+ let minDistance = Number.POSITIVE_INFINITY;
521
+ let closestPosition = null;
324
522
  this.nodeLineMap.horizontalLinesMap.forEach((_, pos) => {
325
- if (Math.abs(item - pos) < this.adsorptionSize) {
326
- minDistance = pos;
523
+ const distance = Math.abs(item - pos);
524
+ if (distance !== 0 && distance < this.adsorptionSize && distance < minDistance) {
525
+ minDistance = distance;
526
+ closestPosition = pos;
327
527
  }
328
528
  });
329
529
  this.guideLinesMap.horizontalLinesMap.forEach((_, pos) => {
330
530
  const distance = Math.abs(item - pos);
331
- if (distance < this.adsorptionSize && distance < minDistance) {
332
- minDistance = pos;
531
+ if (distance !== 0 && distance < this.adsorptionSize && distance < minDistance) {
532
+ minDistance = distance;
533
+ closestPosition = pos;
333
534
  }
334
535
  });
335
- if (minDistance !== -1 && adsorptionHorizontalLines.findIndex(item => item.position === minDistance) === -1) {
536
+ this.userGuideLinesMap.horizontalLinesMap.forEach((_, pos) => {
537
+ const distance = Math.abs(item - pos);
538
+ if (distance !== 0 && distance < this.adsorptionSize && distance < minDistance) {
539
+ minDistance = distance;
540
+ closestPosition = pos;
541
+ }
542
+ });
543
+ if (closestPosition !== null && adsorptionHorizontalLines.findIndex(item => item.position === closestPosition) === -1) {
336
544
  adsorptionHorizontalLines.push({
337
545
  adsorption: index,
338
- position: minDistance
546
+ position: closestPosition
339
547
  });
340
548
  }
341
549
  });
@@ -344,9 +552,32 @@ class GuideLine {
344
552
  x: undefined,
345
553
  y: undefined
346
554
  };
555
+ const linesWithDistance = [];
347
556
  if (isAdsorption) {
348
557
  adsorptionVerticalLines.forEach(item => this.adsorptionLines.verticalLines.add(item.position));
349
558
  adsorptionHorizontalLines.forEach(item => this.adsorptionLines.horizontalLines.add(item.position));
559
+ for (const line of adsorptionVerticalLines) {
560
+ const lineInfo = {
561
+ position: line.position,
562
+ type: 'vertical'
563
+ };
564
+ const segments = this.calculateVerticalLineSegments(rect, line.position);
565
+ if (segments.length > 0) {
566
+ lineInfo.distanceSegments = segments;
567
+ }
568
+ linesWithDistance.push(lineInfo);
569
+ }
570
+ for (const line of adsorptionHorizontalLines) {
571
+ const lineInfo = {
572
+ position: line.position,
573
+ type: 'horizontal'
574
+ };
575
+ const segments = this.calculateHorizontalLineSegments(rect, line.position);
576
+ if (segments.length > 0) {
577
+ lineInfo.distanceSegments = segments;
578
+ }
579
+ linesWithDistance.push(lineInfo);
580
+ }
350
581
  if (adsorptionVerticalLines.length > 0) {
351
582
  if (adsorption) {
352
583
  adsorb.x = adsorptionVerticalLines.find(item => adsorption.includes(item.adsorption));
@@ -364,6 +595,7 @@ class GuideLine {
364
595
  }
365
596
  }
366
597
  }
598
+ this.adsorptionLinesWithDistance = linesWithDistance;
367
599
  return {
368
600
  isAdsorption,
369
601
  adsorb
@@ -372,6 +604,250 @@ class GuideLine {
372
604
  resetAdsorptionLines() {
373
605
  this.adsorptionLines.verticalLines.clear();
374
606
  this.adsorptionLines.horizontalLines.clear();
607
+ this.adsorptionLinesWithDistance = [];
608
+ }
609
+ calculateVerticalLineSegments(rect, linePosition) {
610
+ const segments = [];
611
+ const selected = this.getSelectedNodeIds();
612
+ const nodes = [...this.currentDocument.nodesMap.values()].filter(node => !node.hidden && !selected.includes(node.id) && !node.isRoot && !node.isGroup);
613
+ let nearestAbove = null;
614
+ let nearestBelow = null;
615
+ for (const node of nodes) {
616
+ const nodeRect = node.getDashboardRect();
617
+ if (!nodeRect) continue;
618
+ const nodeLines = [nodeRect.left, nodeRect.left + nodeRect.width / 2, nodeRect.right];
619
+ const isOnLine = nodeLines.some(pos => Math.abs(pos - linePosition) < 1);
620
+ if (!isOnLine) continue;
621
+ if (nodeRect.bottom <= rect.top) {
622
+ const distance = rect.top - nodeRect.bottom;
623
+ if (!nearestAbove || distance < nearestAbove.distance) {
624
+ nearestAbove = {
625
+ distance,
626
+ nodeRect
627
+ };
628
+ }
629
+ } else if (nodeRect.top >= rect.bottom) {
630
+ const distance = nodeRect.top - rect.bottom;
631
+ if (!nearestBelow || distance < nearestBelow.distance) {
632
+ nearestBelow = {
633
+ distance,
634
+ nodeRect
635
+ };
636
+ }
637
+ }
638
+ }
639
+ if (nearestAbove && this.isDistanceInDisplayRange(nearestAbove.distance)) {
640
+ segments.push({
641
+ distance: Math.round(nearestAbove.distance),
642
+ start: nearestAbove.nodeRect.bottom,
643
+ end: rect.top,
644
+ fixedPos: linePosition,
645
+ labelPos: nearestAbove.nodeRect.bottom + nearestAbove.distance / 2
646
+ });
647
+ }
648
+ if (nearestBelow && this.isDistanceInDisplayRange(nearestBelow.distance)) {
649
+ segments.push({
650
+ distance: Math.round(nearestBelow.distance),
651
+ start: rect.bottom,
652
+ end: nearestBelow.nodeRect.top,
653
+ fixedPos: linePosition,
654
+ labelPos: rect.bottom + nearestBelow.distance / 2
655
+ });
656
+ }
657
+ return segments;
658
+ }
659
+ calculateHorizontalLineSegments(rect, linePosition) {
660
+ const segments = [];
661
+ const selected = this.getSelectedNodeIds();
662
+ const nodes = [...this.currentDocument.nodesMap.values()].filter(node => !node.hidden && !selected.includes(node.id) && !node.isRoot && !node.isGroup);
663
+ let nearestLeft = null;
664
+ let nearestRight = null;
665
+ for (const node of nodes) {
666
+ const nodeRect = node.getDashboardRect();
667
+ if (!nodeRect) continue;
668
+ const nodeLines = [nodeRect.top, nodeRect.top + nodeRect.height / 2, nodeRect.bottom];
669
+ const isOnLine = nodeLines.some(pos => Math.abs(pos - linePosition) < 1);
670
+ if (!isOnLine) continue;
671
+ if (nodeRect.right <= rect.left) {
672
+ const distance = rect.left - nodeRect.right;
673
+ if (!nearestLeft || distance < nearestLeft.distance) {
674
+ nearestLeft = {
675
+ distance,
676
+ nodeRect
677
+ };
678
+ }
679
+ } else if (nodeRect.left >= rect.right) {
680
+ const distance = nodeRect.left - rect.right;
681
+ if (!nearestRight || distance < nearestRight.distance) {
682
+ nearestRight = {
683
+ distance,
684
+ nodeRect
685
+ };
686
+ }
687
+ }
688
+ }
689
+ if (nearestLeft && this.isDistanceInDisplayRange(nearestLeft.distance)) {
690
+ segments.push({
691
+ distance: Math.round(nearestLeft.distance),
692
+ start: nearestLeft.nodeRect.right,
693
+ end: rect.left,
694
+ fixedPos: linePosition,
695
+ labelPos: nearestLeft.nodeRect.right + nearestLeft.distance / 2
696
+ });
697
+ }
698
+ if (nearestRight && this.isDistanceInDisplayRange(nearestRight.distance)) {
699
+ segments.push({
700
+ distance: Math.round(nearestRight.distance),
701
+ start: rect.right,
702
+ end: nearestRight.nodeRect.left,
703
+ fixedPos: linePosition,
704
+ labelPos: rect.right + nearestRight.distance / 2
705
+ });
706
+ }
707
+ return segments;
708
+ }
709
+ getSelectedNodeIds() {
710
+ const selected = [];
711
+ for (const node of this.designer.selection.getNodes()) {
712
+ if (node.isGroup) {
713
+ selected.push(...node.getAllNodesInGroup().map(n => n.id));
714
+ } else {
715
+ selected.push(node.id);
716
+ }
717
+ }
718
+ return selected;
719
+ }
720
+ isDistanceInDisplayRange(distance) {
721
+ return distance >= this.adsorptionSize && distance <= this.maxDistanceDisplay;
722
+ }
723
+ }
724
+
725
+ class MarqueeSelection {
726
+ emitter = core.createEventBus('MarqueeEngine');
727
+ isMarqueeSelecting = false;
728
+ enabled = true;
729
+ constructor(designer) {
730
+ this.designer = designer;
731
+ }
732
+ isSelecting() {
733
+ return this.isMarqueeSelecting;
734
+ }
735
+ from(shell, viewport, isClickOnNode) {
736
+ if (!shell) {
737
+ return () => {};
738
+ }
739
+ let startX = 0;
740
+ let startY = 0;
741
+ let isCtrlPressed = false;
742
+ const masterSensors = this.getMasterSensors();
743
+ const calculateRect = (x1, y1, x2, y2) => {
744
+ return {
745
+ x: Math.min(x1, x2),
746
+ y: Math.min(y1, y2),
747
+ width: Math.abs(x2 - x1),
748
+ height: Math.abs(y2 - y1)
749
+ };
750
+ };
751
+ const move = e => {
752
+ const localPoint = viewport.toLocalPoint(e);
753
+ const currentX = localPoint.clientX;
754
+ const currentY = localPoint.clientY;
755
+ const marqueeRect = calculateRect(startX, startY, currentX, currentY);
756
+ this.emitter.emit('marquee', {
757
+ startX,
758
+ startY,
759
+ currentX,
760
+ currentY,
761
+ rect: marqueeRect,
762
+ isCtrlPressed: e.ctrlKey || e.metaKey
763
+ });
764
+ };
765
+ const over = e => {
766
+ const handleEvents = core.makeEventsHandler(e, masterSensors);
767
+ handleEvents(doc => {
768
+ doc.removeEventListener('mousemove', move, true);
769
+ doc.removeEventListener('mouseup', over, true);
770
+ });
771
+ const localPoint = viewport.toLocalPoint(e);
772
+ const currentX = localPoint.clientX;
773
+ const currentY = localPoint.clientY;
774
+ const marqueeRect = calculateRect(startX, startY, currentX, currentY);
775
+ this.isMarqueeSelecting = false;
776
+ this.designer.detecting.enable = true;
777
+ this.emitter.emit('marqueeEnd', {
778
+ startX,
779
+ startY,
780
+ currentX,
781
+ currentY,
782
+ rect: marqueeRect,
783
+ isCtrlPressed: e.ctrlKey || e.metaKey
784
+ });
785
+ };
786
+ const mousedown = e => {
787
+ if (e.button !== 0) return;
788
+ if (!this.enabled) {
789
+ return;
790
+ }
791
+ const target = e.target;
792
+ if (isClickOnNode(target)) {
793
+ return;
794
+ }
795
+ e.preventDefault();
796
+ const localPoint = viewport.toLocalPoint(e);
797
+ startX = localPoint.clientX;
798
+ startY = localPoint.clientY;
799
+ isCtrlPressed = e.ctrlKey || e.metaKey;
800
+ const handleEvents = core.makeEventsHandler(e, masterSensors);
801
+ handleEvents(doc => {
802
+ doc.addEventListener('mousemove', move, true);
803
+ doc.addEventListener('mouseup', over, true);
804
+ });
805
+ this.emitter.emit('marqueeStart', {
806
+ startX,
807
+ startY,
808
+ currentX: startX,
809
+ currentY: startY,
810
+ rect: {
811
+ x: startX,
812
+ y: startY,
813
+ width: 0,
814
+ height: 0
815
+ },
816
+ isCtrlPressed
817
+ });
818
+ this.isMarqueeSelecting = true;
819
+ this.designer.detecting.enable = false;
820
+ };
821
+ shell.addEventListener('mousedown', mousedown);
822
+ return () => {
823
+ shell.removeEventListener('mousedown', mousedown);
824
+ };
825
+ }
826
+ onMarqueeStart(func) {
827
+ this.emitter.on('marqueeStart', func);
828
+ return () => {
829
+ this.emitter.off('marqueeStart', func);
830
+ };
831
+ }
832
+ onMarquee(func) {
833
+ this.emitter.on('marquee', func);
834
+ return () => {
835
+ this.emitter.off('marquee', func);
836
+ };
837
+ }
838
+ onMarqueeEnd(func) {
839
+ this.emitter.on('marqueeEnd', func);
840
+ return () => {
841
+ this.emitter.off('marqueeEnd', func);
842
+ };
843
+ }
844
+ getMasterSensors() {
845
+ return this.designer.project.documents.map(doc => {
846
+ if (doc.opened && doc.simulator?.sensorAvailable) {
847
+ return doc.simulator;
848
+ }
849
+ return null;
850
+ }).filter(Boolean);
375
851
  }
376
852
  }
377
853
 
@@ -523,10 +999,11 @@ const DashboardPlugin = options => {
523
999
  x: boxX = 0,
524
1000
  y: boxY = 0
525
1001
  } = startOffsetNodes.box;
1002
+ const currentRect = new DOMRect(e.canvasX - boxX, e.canvasY - boxY, width, height);
526
1003
  const {
527
1004
  isAdsorption,
528
1005
  adsorb
529
- } = designer.guideline.getAdsorptionPosition(new DOMRect(e.canvasX - boxX, e.canvasY - boxY, width, height));
1006
+ } = designer.guideline.getAdsorptionPosition(currentRect);
530
1007
  let adsorbX = undefined;
531
1008
  let adsorbY = undefined;
532
1009
  if (isAdsorption) {
@@ -616,6 +1093,8 @@ const DashboardPlugin = options => {
616
1093
  Node
617
1094
  } = extendClass;
618
1095
  let guideline = null;
1096
+ let alignment = null;
1097
+ let marqueeSelection = null;
619
1098
  extend('Designer', {
620
1099
  guideline: {
621
1100
  get() {
@@ -624,6 +1103,22 @@ const DashboardPlugin = options => {
624
1103
  }
625
1104
  return guideline;
626
1105
  }
1106
+ },
1107
+ alignment: {
1108
+ get() {
1109
+ if (!alignment) {
1110
+ alignment = new Alignment(this);
1111
+ }
1112
+ return alignment;
1113
+ }
1114
+ },
1115
+ marqueeSelection: {
1116
+ get() {
1117
+ if (!marqueeSelection) {
1118
+ marqueeSelection = new MarqueeSelection(this);
1119
+ }
1120
+ return marqueeSelection;
1121
+ }
627
1122
  }
628
1123
  });
629
1124
  extend('Document', {
@@ -633,18 +1128,21 @@ const DashboardPlugin = options => {
633
1128
  let nodeList = [];
634
1129
  if (typeof nodeIdList[0] === 'string') {
635
1130
  nodeList = nodeIdList.map(id => this.getNode(id));
1131
+ } else {
1132
+ nodeList = nodeIdList;
636
1133
  }
1134
+ nodeList = nodeList.filter(node => node && !node.isRoot);
1135
+ if (nodeList.length === 0) return;
1136
+ const targetParent = nodeList[0].parent || this.rootNode;
637
1137
  const groupNode = this.createNode(groupInitSchema);
638
- let maxZIndex = Number.POSITIVE_INFINITY;
1138
+ let minIndex = Number.POSITIVE_INFINITY;
639
1139
  for (const node of nodeList) {
640
- if (node.index < maxZIndex) {
641
- maxZIndex = node.index;
642
- }
643
- if (node && !node.isRoot) {
644
- this.migrateNode(node, groupNode);
1140
+ if (node.index < minIndex) {
1141
+ minIndex = node.index;
645
1142
  }
1143
+ this.migrateNode(node, groupNode);
646
1144
  }
647
- this.rootNode?.insert(groupNode, maxZIndex);
1145
+ targetParent?.insert(groupNode, minIndex);
648
1146
  return groupNode;
649
1147
  }
650
1148
  },
@@ -657,11 +1155,12 @@ const DashboardPlugin = options => {
657
1155
  groupNode = group;
658
1156
  }
659
1157
  if (!groupNode || !groupNode.isGroup || !groupNode.children) return;
660
- const nodes = groupNode.childrenNodes;
661
- while (nodes.length > 0) {
662
- if (groupNode.parent) {
663
- this.migrateNode(nodes[0], groupNode.parent);
664
- }
1158
+ const parent = groupNode.parent;
1159
+ if (!parent) return;
1160
+ groupNode.index;
1161
+ const nodes = [...groupNode.childrenNodes];
1162
+ for (let i = 0; i < nodes.length; i++) {
1163
+ this.migrateNode(nodes[i], parent);
665
1164
  }
666
1165
  this.removeNode(groupNode);
667
1166
  }
@@ -882,4 +1381,10 @@ const calculateDashboardRectBox = nodes => {
882
1381
  return new DOMRect(minX, minY, maxX - minX, maxY - minY);
883
1382
  };
884
1383
 
885
- module.exports = DashboardPlugin;
1384
+ exports.AlignType = AlignType;
1385
+ exports.Alignment = Alignment;
1386
+ exports.DistributeType = DistributeType;
1387
+ exports.GuideLine = GuideLine;
1388
+ exports.default = DashboardPlugin;
1389
+ exports.updateNodeRect = updateNodeRect;
1390
+ exports.updateNodeRectByDOM = updateNodeRectByDOM;