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