@leafer-in/editor 1.0.0-rc.6 → 1.0.0-rc.8

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.
@@ -1,4 +1,380 @@
1
- import { MatrixHelper, Bounds, Matrix, Event, Group, Rect, Polygon, DataHelper, RotateEvent, PointHelper, MathHelper, DragEvent, PointerEvent, RenderEvent, KeyEvent } from '@leafer-ui/core';
1
+ import { Event, defineKey, MatrixHelper, UI, Paint, Group, Rect, Bounds, LeafList, PointerEvent, DragEvent, MoveEvent, ZoomEvent, PointHelper, AroundHelper, Box, Line, Matrix, DataHelper, RotateEvent, MathHelper, RenderEvent, KeyEvent, Creator } from '@leafer-ui/core';
2
+
3
+ /******************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+ /* global Reflect, Promise, SuppressedError, Symbol */
18
+
19
+
20
+ function __decorate(decorators, target, key, desc) {
21
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
22
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
23
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
24
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
25
+ }
26
+
27
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
28
+ var e = new Error(message);
29
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
30
+ };
31
+
32
+ class EditorEvent extends Event {
33
+ constructor(type, data) {
34
+ super(type);
35
+ if (data)
36
+ Object.assign(this, data);
37
+ }
38
+ }
39
+ EditorEvent.SELECT = 'editor.select';
40
+ EditorEvent.HOVER = 'editor.hover';
41
+
42
+ class EditorMoveEvent extends EditorEvent {
43
+ constructor(type, data) {
44
+ super(type, data);
45
+ }
46
+ }
47
+ EditorMoveEvent.MOVE = 'editor.move';
48
+
49
+ class EditorScaleEvent extends EditorEvent {
50
+ constructor(type, data) {
51
+ super(type, data);
52
+ }
53
+ }
54
+ EditorScaleEvent.SCALE = 'editor.scale';
55
+
56
+ class EditorRotateEvent extends EditorEvent {
57
+ constructor(type, data) {
58
+ super(type, data);
59
+ }
60
+ }
61
+ EditorRotateEvent.ROTATE = 'editor.rotate';
62
+
63
+ class EditorSkewEvent extends EditorEvent {
64
+ constructor(type, data) {
65
+ super(type, data);
66
+ }
67
+ }
68
+ EditorSkewEvent.SKEW = 'editor.skew';
69
+
70
+ function targetAttr(fn) {
71
+ return (target, key) => {
72
+ const privateKey = '_' + key;
73
+ defineKey(target, key, {
74
+ get() { return this[privateKey]; },
75
+ set(value) {
76
+ const old = this[privateKey];
77
+ if (old !== value)
78
+ this[privateKey] = value, fn(this, old);
79
+ }
80
+ });
81
+ };
82
+ }
83
+
84
+ const matrix = MatrixHelper.get();
85
+ const { abs } = Math;
86
+ const { copy, scale } = MatrixHelper;
87
+ class Stroker extends UI {
88
+ constructor() {
89
+ super();
90
+ this.list = [];
91
+ this.hittable = false;
92
+ this.strokeAlign = 'center';
93
+ }
94
+ setTarget(target, style) {
95
+ const { stroke, strokeWidth } = style;
96
+ this.set({ stroke, strokeWidth });
97
+ this.target = target;
98
+ }
99
+ __draw(canvas, options) {
100
+ const { list } = this;
101
+ if (list.length) {
102
+ let leaf;
103
+ const { stroke, strokeWidth } = this.__;
104
+ const { bounds } = options;
105
+ for (let i = 0; i < list.length; i++) {
106
+ leaf = list[i];
107
+ if (bounds && bounds.hit(leaf.__world, options.matrix)) {
108
+ let drewPath;
109
+ if (leaf.__.editSize === 'scale') {
110
+ const aScaleX = abs(leaf.__world.scaleX), aScaleY = abs(leaf.__world.scaleY);
111
+ if (aScaleX !== aScaleY) {
112
+ copy(matrix, leaf.__world);
113
+ scale(matrix, 1 / aScaleX, 1 / aScaleY);
114
+ canvas.setWorld(matrix, options.matrix);
115
+ canvas.beginPath();
116
+ this.__.strokeWidth = strokeWidth;
117
+ const { x, y, width, height } = leaf.__layout.boxBounds;
118
+ canvas.rect(x * aScaleX, y * aScaleY, width * aScaleX, height * aScaleY);
119
+ drewPath = true;
120
+ }
121
+ }
122
+ if (!drewPath) {
123
+ canvas.setWorld(leaf.__world, options.matrix);
124
+ canvas.beginPath();
125
+ leaf.__.__pathForRender ? leaf.__drawRenderPath(canvas) : leaf.__drawPathByBox(canvas);
126
+ this.__.strokeWidth = strokeWidth / abs(leaf.__world.scaleX);
127
+ }
128
+ typeof stroke === 'string' ? Paint.stroke(stroke, this, canvas, options) : Paint.strokes(stroke, this, canvas, options);
129
+ }
130
+ }
131
+ this.__.strokeWidth = strokeWidth;
132
+ }
133
+ }
134
+ destroy() {
135
+ this.target = null;
136
+ super.destroy();
137
+ }
138
+ }
139
+ __decorate([
140
+ targetAttr(onTarget$1)
141
+ ], Stroker.prototype, "target", void 0);
142
+ function onTarget$1(stroker) {
143
+ const value = stroker.target;
144
+ stroker.list = value ? (value instanceof Array ? value : [value]) : [];
145
+ stroker.forceUpdate();
146
+ }
147
+
148
+ class SelectArea extends Group {
149
+ constructor(data) {
150
+ super(data);
151
+ this.strokeArea = new Rect({ strokeAlign: 'center' });
152
+ this.fillArea = new Rect();
153
+ this.visible = this.hittable = false;
154
+ this.addMany(this.fillArea, this.strokeArea);
155
+ }
156
+ setStyle(style, userStyle) {
157
+ const { visible, stroke, strokeWidth } = style;
158
+ this.visible = visible;
159
+ this.strokeArea.reset(Object.assign({ stroke, strokeWidth }, (userStyle || {})));
160
+ this.fillArea.reset({ visible: userStyle ? false : true, fill: stroke, opacity: 0.2 });
161
+ }
162
+ setBounds(bounds) {
163
+ this.strokeArea.set(bounds);
164
+ this.fillArea.set(bounds);
165
+ }
166
+ }
167
+
168
+ var AnswerType;
169
+ (function (AnswerType) {
170
+ AnswerType[AnswerType["No"] = 0] = "No";
171
+ AnswerType[AnswerType["Yes"] = 1] = "Yes";
172
+ AnswerType[AnswerType["NoAndSkip"] = 2] = "NoAndSkip";
173
+ AnswerType[AnswerType["YesAndSkip"] = 3] = "YesAndSkip";
174
+ })(AnswerType || (AnswerType = {}));
175
+
176
+ const { No, Yes, NoAndSkip, YesAndSkip } = AnswerType;
177
+ const EditSelectHelper = {
178
+ findOne(path) {
179
+ return path.list.find((leaf) => leaf.editable);
180
+ },
181
+ findBounds(leaf, bounds) {
182
+ if (leaf.__.hittable && !leaf.__.locked && bounds.hit(leaf.__world)) {
183
+ if (leaf.__.editable) {
184
+ if (leaf.isBranch && !leaf.__.hitChildren) {
185
+ return leaf.__.hitSelf ? YesAndSkip : NoAndSkip;
186
+ }
187
+ else if (leaf.isFrame) {
188
+ return bounds.includes(leaf.__layout.boxBounds, leaf.__world) ? YesAndSkip : No;
189
+ }
190
+ else {
191
+ if (bounds.hit(leaf.__layout.boxBounds, leaf.__world) && leaf.__.hitSelf)
192
+ return Yes;
193
+ }
194
+ }
195
+ return No;
196
+ }
197
+ else {
198
+ return leaf.isBranch ? NoAndSkip : No;
199
+ }
200
+ }
201
+ };
202
+
203
+ const { findOne } = EditSelectHelper;
204
+ class EditSelect extends Group {
205
+ get dragging() { return !!this.originList; }
206
+ get running() { return this.editor.hittable && this.editor.config.selector; }
207
+ get isMoveMode() { return this.app && this.app.interaction.moveMode; }
208
+ constructor(editor) {
209
+ super();
210
+ this.hoverStroker = new Stroker();
211
+ this.targetStroker = new Stroker();
212
+ this.bounds = new Bounds();
213
+ this.selectArea = new SelectArea();
214
+ this.__eventIds = [];
215
+ this.editor = editor;
216
+ this.addMany(this.targetStroker, this.hoverStroker, this.selectArea);
217
+ this.__listenEvents();
218
+ }
219
+ onHover() {
220
+ const { editor } = this;
221
+ if (this.running && !this.dragging && !editor.dragging) {
222
+ const { stroke, strokeWidth, hover } = editor.config;
223
+ this.hoverStroker.setTarget(hover ? this.editor.hoverTarget : null, { stroke, strokeWidth });
224
+ }
225
+ else {
226
+ this.hoverStroker.target = null;
227
+ }
228
+ }
229
+ onSelect() {
230
+ if (this.running) {
231
+ const { config, list } = this.editor;
232
+ const { stroke, strokeWidth } = config;
233
+ this.targetStroker.setTarget(list, { stroke, strokeWidth: Math.max(1, strokeWidth / 2) });
234
+ this.hoverStroker.target = null;
235
+ }
236
+ }
237
+ update() {
238
+ if (this.running)
239
+ this.targetStroker.forceUpdate();
240
+ }
241
+ onPointerMove(e) {
242
+ if (this.running && !this.isMoveMode) {
243
+ const find = e.shiftKey ? this.findDeepOne(e) : findOne(e.path);
244
+ this.editor.hoverTarget = this.editor.hasItem(find) ? null : find;
245
+ }
246
+ if (this.isMoveMode) {
247
+ this.editor.hoverTarget = null;
248
+ }
249
+ }
250
+ onBeforeDown(e) {
251
+ if (this.running && !this.isMoveMode && !e.middle) {
252
+ const find = this.lastDownLeaf = findOne(e.path);
253
+ if (find) {
254
+ if (e.shiftKey) {
255
+ this.editor.shiftItem(find);
256
+ }
257
+ else {
258
+ this.editor.target = find;
259
+ }
260
+ this.editor.updateLayout();
261
+ find.leafer.interaction.updateDownData();
262
+ }
263
+ else if (this.allow(e.target)) {
264
+ if (!e.shiftKey)
265
+ this.editor.target = null;
266
+ }
267
+ }
268
+ }
269
+ onTap(e) {
270
+ if (this.running && e.shiftKey && !e.middle && !this.lastDownLeaf) {
271
+ const find = this.findDeepOne(e);
272
+ if (find)
273
+ this.editor.shiftItem(find);
274
+ }
275
+ else if (this.isMoveMode) {
276
+ this.editor.target = null;
277
+ }
278
+ this.lastDownLeaf = null;
279
+ }
280
+ onDragStart(e) {
281
+ if (this.running && this.allowDrag(e)) {
282
+ const { editor } = this;
283
+ const { stroke, strokeWidth, area } = editor.config;
284
+ const { x, y } = e.getInner(this);
285
+ this.bounds.set(x, y);
286
+ this.selectArea.setStyle({ visible: true, stroke, strokeWidth, x, y }, area);
287
+ this.selectArea.setBounds(this.bounds.get());
288
+ this.originList = editor.leafList.clone();
289
+ }
290
+ }
291
+ onDrag(e) {
292
+ if (this.editor.dragging) {
293
+ this.onDragEnd();
294
+ return;
295
+ }
296
+ if (this.dragging) {
297
+ const { editor } = this;
298
+ const total = e.getInnerTotal(this);
299
+ const dragBounds = this.bounds.clone().unsign();
300
+ const list = new LeafList(editor.app.find(EditSelectHelper.findBounds, dragBounds));
301
+ this.bounds.width = total.x;
302
+ this.bounds.height = total.y;
303
+ this.selectArea.setBounds(dragBounds.get());
304
+ if (list.length) {
305
+ const selectList = [];
306
+ this.originList.forEach(item => { if (!list.has(item))
307
+ selectList.push(item); });
308
+ list.forEach(item => { if (!this.originList.has(item))
309
+ selectList.push(item); });
310
+ if (selectList.length !== editor.list.length || editor.list.some((child, index) => child !== selectList[index])) {
311
+ editor.target = selectList;
312
+ }
313
+ }
314
+ else {
315
+ editor.target = this.originList.list;
316
+ if (editor.leafList.length)
317
+ editor.update();
318
+ }
319
+ }
320
+ }
321
+ onDragEnd() {
322
+ if (this.dragging)
323
+ this.originList = null, this.selectArea.visible = false;
324
+ }
325
+ onAutoMove(e) {
326
+ if (this.dragging) {
327
+ const { x, y } = e.getLocalMove(this);
328
+ this.bounds.x += x;
329
+ this.bounds.y += y;
330
+ }
331
+ }
332
+ allow(target) {
333
+ return target.leafer !== this.editor.leafer;
334
+ }
335
+ allowDrag(e) {
336
+ if (this.editor.config.boxSelect && !e.target.draggable) {
337
+ return (!this.editor.hasTarget && this.allow(e.target)) || (e.shiftKey && !findOne(e.path));
338
+ }
339
+ else {
340
+ return false;
341
+ }
342
+ }
343
+ findDeepOne(e) {
344
+ const options = { exclude: new LeafList(this.editor.editBox.rect) };
345
+ return findOne(e.target.leafer.interaction.findPath(e, options));
346
+ }
347
+ __listenEvents() {
348
+ const { editor } = this;
349
+ editor.waitLeafer(() => {
350
+ const { app } = editor;
351
+ app.selector.proxy = editor;
352
+ this.__eventIds = [
353
+ editor.on_(EditorEvent.HOVER, this.onHover, this),
354
+ editor.on_(EditorEvent.SELECT, this.onSelect, this),
355
+ app.on_(PointerEvent.MOVE, this.onPointerMove, this),
356
+ app.on_(PointerEvent.BEFORE_DOWN, this.onBeforeDown, this),
357
+ app.on_(PointerEvent.TAP, this.onTap, this),
358
+ app.on_(DragEvent.START, this.onDragStart, this),
359
+ app.on_(DragEvent.DRAG, this.onDrag, this),
360
+ app.on_(DragEvent.END, this.onDragEnd, this),
361
+ app.on_(MoveEvent.MOVE, this.onAutoMove, this),
362
+ app.on_([ZoomEvent.ZOOM, MoveEvent.MOVE], () => { this.editor.hoverTarget = null; }),
363
+ ];
364
+ });
365
+ }
366
+ __removeListenEvents() {
367
+ if (this.__eventIds) {
368
+ this.off_(this.__eventIds);
369
+ this.__eventIds.length = 0;
370
+ }
371
+ }
372
+ destroy() {
373
+ this.editor = this.originList = this.lastDownLeaf = null;
374
+ this.__removeListenEvents();
375
+ super.destroy();
376
+ }
377
+ }
2
378
 
3
379
  var IDirection8;
4
380
  (function (IDirection8) {
@@ -12,110 +388,154 @@ var IDirection8;
12
388
  IDirection8[IDirection8["left"] = 7] = "left";
13
389
  })(IDirection8 || (IDirection8 = {}));
14
390
 
15
- const { scaleOfOuter, reset } = MatrixHelper;
16
391
  const { topLeft: topLeft$1, top: top$1, topRight: topRight$1, right: right$2, bottomRight: bottomRight$1, bottom: bottom$1, bottomLeft: bottomLeft$1, left: left$2 } = IDirection8;
17
- const matrix = {};
18
- function getResizeData(old, direction, move, lockRatio, around) {
19
- if (around) {
20
- move.x *= 2;
21
- move.y *= 2;
22
- }
23
- let origin, scaleX = 1, scaleY = 1;
24
- const { x, y, width, height } = old;
25
- const topScale = (-move.y + height) / height;
26
- const rightScale = (move.x + width) / width;
27
- const bottomScale = (move.y + height) / height;
28
- const leftScale = (-move.x + width) / width;
29
- switch (direction) {
30
- case top$1:
31
- scaleY = topScale;
32
- if (lockRatio)
33
- scaleX = scaleY;
34
- origin = { x: x + width / 2, y: y + height };
35
- break;
36
- case right$2:
37
- scaleX = rightScale;
38
- if (lockRatio)
39
- scaleY = scaleX;
40
- origin = { x, y: y + height / 2 };
41
- break;
42
- case bottom$1:
43
- scaleY = bottomScale;
44
- if (lockRatio)
45
- scaleX = scaleY;
46
- origin = { x: x + width / 2, y };
47
- break;
48
- case left$2:
49
- scaleX = leftScale;
50
- if (lockRatio)
392
+ const { toPoint } = AroundHelper;
393
+ const EditDataHelper = {
394
+ getScaleData(bounds, direction, pointMove, lockRatio, around) {
395
+ let origin, scaleX = 1, scaleY = 1;
396
+ const { width, height } = bounds;
397
+ if (around) {
398
+ pointMove.x *= 2;
399
+ pointMove.y *= 2;
400
+ }
401
+ const topScale = (-pointMove.y + height) / height;
402
+ const rightScale = (pointMove.x + width) / width;
403
+ const bottomScale = (pointMove.y + height) / height;
404
+ const leftScale = (-pointMove.x + width) / width;
405
+ switch (direction) {
406
+ case top$1:
407
+ scaleY = topScale;
408
+ origin = { x: 0.5, y: 1 };
409
+ break;
410
+ case right$2:
411
+ scaleX = rightScale;
412
+ origin = { x: 0, y: 0.5 };
413
+ break;
414
+ case bottom$1:
415
+ scaleY = bottomScale;
416
+ origin = { x: 0.5, y: 0 };
417
+ break;
418
+ case left$2:
419
+ scaleX = leftScale;
420
+ origin = { x: 1, y: 0.5 };
421
+ break;
422
+ case topLeft$1:
423
+ scaleY = topScale;
424
+ scaleX = leftScale;
425
+ origin = { x: 1, y: 1 };
426
+ break;
427
+ case topRight$1:
428
+ scaleY = topScale;
429
+ scaleX = rightScale;
430
+ origin = { x: 0, y: 1 };
431
+ break;
432
+ case bottomRight$1:
433
+ scaleY = bottomScale;
434
+ scaleX = rightScale;
435
+ origin = { x: 0, y: 0 };
436
+ break;
437
+ case bottomLeft$1:
438
+ scaleY = bottomScale;
439
+ scaleX = leftScale;
440
+ origin = { x: 1, y: 0 };
441
+ }
442
+ if (lockRatio) {
443
+ if (scaleX !== 1)
51
444
  scaleY = scaleX;
52
- origin = { x: x + width, y: y + height / 2 };
53
- break;
54
- case topLeft$1:
55
- scaleY = topScale;
56
- scaleX = leftScale;
57
- if (lockRatio)
58
- scaleX = scaleY;
59
- origin = { x: x + width, y: y + height };
60
- break;
61
- case topRight$1:
62
- scaleY = topScale;
63
- scaleX = rightScale;
64
- if (lockRatio)
65
- scaleX = scaleY;
66
- origin = { x, y: y + height };
67
- break;
68
- case bottomRight$1:
69
- scaleY = bottomScale;
70
- scaleX = rightScale;
71
- if (lockRatio)
445
+ else
72
446
  scaleX = scaleY;
73
- origin = { x, y };
74
- break;
75
- case bottomLeft$1:
76
- scaleY = bottomScale;
77
- scaleX = leftScale;
78
- if (lockRatio)
79
- scaleX = scaleY;
80
- origin = { x: x + width, y };
81
- break;
82
- }
83
- if (around) {
84
- if (typeof around === 'object') {
85
- origin = { x: x + width / around.x, y: y + height / around.y };
86
447
  }
87
- else {
88
- origin = { x: x + width / 2, y: y + height / 2 };
448
+ toPoint(around || origin, bounds, origin);
449
+ return { origin, scaleX, scaleY, direction, lockRatio, around };
450
+ },
451
+ getRotateData(bounds, direction, current, last, around) {
452
+ let origin;
453
+ switch (direction) {
454
+ case topLeft$1:
455
+ origin = { x: 1, y: 1 };
456
+ break;
457
+ case topRight$1:
458
+ origin = { x: 0, y: 1 };
459
+ break;
460
+ case bottomRight$1:
461
+ origin = { x: 0, y: 0 };
462
+ break;
463
+ case bottomLeft$1:
464
+ origin = { x: 1, y: 0 };
465
+ break;
466
+ default:
467
+ origin = { x: 0.5, y: 0.5 };
468
+ }
469
+ toPoint(around || origin, bounds, origin);
470
+ return { origin, rotation: PointHelper.getRotation(last, origin, current) };
471
+ },
472
+ getSkewData(bounds, direction, move, around) {
473
+ let origin, skewX = 0, skewY = 0;
474
+ let last;
475
+ switch (direction) {
476
+ case top$1:
477
+ last = { x: 0.5, y: 0 };
478
+ origin = { x: 0.5, y: 1 };
479
+ skewX = 1;
480
+ break;
481
+ case bottom$1:
482
+ last = { x: 0.5, y: 1 };
483
+ origin = { x: 0.5, y: 0 };
484
+ skewX = 1;
485
+ break;
486
+ case left$2:
487
+ last = { x: 0, y: 0.5 };
488
+ origin = { x: 1, y: 0.5 };
489
+ skewY = 1;
490
+ break;
491
+ case right$2:
492
+ last = { x: 1, y: 0.5 };
493
+ origin = { x: 0, y: 0.5 };
494
+ skewY = 1;
89
495
  }
496
+ const { x, y, width, height } = bounds;
497
+ last.x = x + last.x * width;
498
+ last.y = y + last.y * height;
499
+ toPoint(around || origin, bounds, origin);
500
+ const rotation = PointHelper.getRotation(last, origin, { x: last.x + (skewX ? move.x : 0), y: last.y + (skewY ? move.y : 0) });
501
+ skewX ? skewX = -rotation : skewY = rotation;
502
+ return { origin, skewX, skewY };
503
+ },
504
+ getAround(around, altKey) {
505
+ return (altKey && !around) ? 'center' : around;
506
+ },
507
+ getRotateDirection(direction, rotation, totalDirection = 8) {
508
+ direction = (direction + Math.round(rotation / (360 / totalDirection))) % totalDirection;
509
+ if (direction < 0)
510
+ direction += totalDirection;
511
+ return direction;
90
512
  }
91
- reset(matrix);
92
- scaleOfOuter(matrix, origin, scaleX, scaleY);
93
- const bounds = { x: old.x + matrix.e, y: old.y + matrix.f, width: width * scaleX, height: height * scaleY };
94
- return { bounds, old, origin, scaleX, scaleY, direction, lockRatio, around, };
95
- }
513
+ };
96
514
 
97
515
  const { topLeft, top, topRight, right: right$1, bottomRight, bottom, bottomLeft, left: left$1 } = IDirection8;
98
516
  function updateCursor(editor, e) {
99
- const point = editor.enterPoint;
100
- if (!point || !editor.target || !editor.visible)
517
+ const { editBox } = editor, point = editBox.enterPoint;
518
+ if (!point || !editor.hasTarget || !editBox.visible)
101
519
  return;
102
- let { rotation } = editor;
103
- let { resizeCursor, rotateCursor, resizeable } = editor.config;
104
- const mirror = editor.tool.getMirrorData(editor);
105
- const { __direction, __isResizePoint } = point.__;
106
- editor.enterPoint = point;
107
- if (__isResizePoint && (e.metaKey || e.ctrlKey || !resizeable))
520
+ let { rotation } = editBox;
521
+ let { resizeCursor, rotateCursor, resizeable, rotateable } = editor.config;
522
+ const { direction, pointType } = point;
523
+ editBox.enterPoint = point;
524
+ const isResizePoint = pointType === 'resize';
525
+ if (isResizePoint && rotateable && (e.metaKey || e.ctrlKey || !resizeable))
108
526
  resizeCursor = rotateCursor;
109
- if (mirror.x || mirror.y) {
110
- mirrorCursors(resizeCursor = [...resizeCursor], mirror.x, mirror.y);
111
- mirrorCursors(rotateCursor = [...rotateCursor], mirror.y, mirror.x);
112
- if (mirror.x + mirror.y === 1)
527
+ if (editBox.flipped) {
528
+ const { flippedX, flippedY } = editBox;
529
+ mirrorCursors(resizeCursor = [...resizeCursor], flippedX, flippedY);
530
+ mirrorCursors(rotateCursor = [...rotateCursor], flippedY, flippedX);
531
+ if (editBox.flippedOne)
113
532
  rotation = -rotation;
114
533
  }
115
- let index = (__direction + Math.round(rotation / 45)) % 8;
116
- if (index < 0)
117
- index += 8;
118
- point.cursor = __isResizePoint ? resizeCursor[index] : rotateCursor[index];
534
+ const index = EditDataHelper.getRotateDirection(direction, rotation);
535
+ point.cursor = isResizePoint ? resizeCursor[index] : rotateCursor[index];
536
+ }
537
+ function updateMoveCursor(editor) {
538
+ editor.editBox.rect.cursor = editor.config.moveCursor;
119
539
  }
120
540
  function mirrorCursors(mirror, mirrorX, mirrorY) {
121
541
  if (mirrorX) {
@@ -138,133 +558,311 @@ function mirrorCursors(mirror, mirrorX, mirrorY) {
138
558
  }
139
559
  }
140
560
 
141
- const RectTool = {
142
- name: 'RectTool',
143
- getMirrorData(editor) {
144
- const { scaleX, scaleY } = editor.target;
145
- return {
146
- x: scaleX < 0 ? 1 : 0,
147
- y: scaleY < 0 ? 1 : 0
148
- };
149
- },
150
- resize(e) {
151
- const { target, bounds, resizeType, old } = e;
152
- const { x, y, width, height } = bounds;
153
- const point = { x: x - old.x, y: y - old.y };
154
- target.innerToWorld(point, null, true, target.parent);
155
- target.x += point.x;
156
- target.y += point.y;
157
- if (resizeType === 'scale') {
158
- target.scaleX *= width / old.width;
159
- target.scaleY *= height / old.height;
160
- }
161
- else {
162
- if (width < 0) {
163
- target.width = -width;
164
- target.scaleX *= -1;
165
- }
166
- else {
167
- if (target.width !== width)
168
- target.width = width;
169
- }
170
- if (height < 0) {
171
- target.height = -height;
172
- target.scaleY *= -1;
173
- }
174
- else {
175
- if (target.height !== height)
176
- target.height = height;
561
+ class EditPoint extends Box {
562
+ }
563
+
564
+ const fourDirection = ['top', 'right', 'bottom', 'left'];
565
+ class EditBox extends Group {
566
+ get flipped() { return this.flippedX || this.flippedY; }
567
+ get flippedX() { return this.scaleX < 0; }
568
+ get flippedY() { return this.scaleY < 0; }
569
+ get flippedOne() { return this.scaleX * this.scaleY < 0; }
570
+ constructor(editor) {
571
+ super();
572
+ this.rect = new Box({ name: 'rect', hitFill: 'all', hitStroke: 'none', strokeAlign: 'center', hitRadius: 5 });
573
+ this.circle = new EditPoint({ name: 'circle', strokeAlign: 'outside', around: 'center', cursor: 'crosshair', hitRadius: 5 });
574
+ this.buttons = new Group({ around: 'center', hitSelf: false });
575
+ this.resizePoints = [];
576
+ this.rotatePoints = [];
577
+ this.resizeLines = [];
578
+ this.__eventIds = [];
579
+ this.editor = editor;
580
+ this.visible = false;
581
+ this.create();
582
+ this.__listenEvents();
583
+ }
584
+ create() {
585
+ let rotatePoint, resizeLine, resizePoint;
586
+ const { resizePoints, rotatePoints, resizeLines, rect, circle, buttons } = this;
587
+ const arounds = [{ x: 1, y: 1 }, { x: 0.5, y: 1 }, { x: 0, y: 1 }, { x: 0, y: 0.5 }, { x: 0, y: 0 }, { x: 0.5, y: 0 }, { x: 1, y: 0 }, { x: 1, y: 0.5 }];
588
+ for (let i = 0; i < 8; i++) {
589
+ rotatePoint = new EditPoint({ around: arounds[i], width: 15, height: 15, hitFill: "all" });
590
+ rotatePoints.push(rotatePoint);
591
+ this.listenPointEvents(rotatePoint, 'rotate', i);
592
+ if (i % 2) {
593
+ resizeLine = new EditPoint({ name: 'resize-line', around: 'center', width: 10, height: 10, hitFill: "all" });
594
+ resizeLines.push(resizeLine);
595
+ this.listenPointEvents(resizeLine, 'resize', i);
177
596
  }
597
+ resizePoint = new EditPoint({ name: 'resize-point', around: 'center', strokeAlign: 'outside', hitRadius: 5 });
598
+ resizePoints.push(resizePoint);
599
+ this.listenPointEvents(resizePoint, 'resize', i);
178
600
  }
179
- },
180
- rotate(e) {
181
- const { target, rotation, origin } = e;
182
- target.rotateOf(origin, rotation);
183
- },
184
- update(editor) {
185
- const { target, config, rotatePoints, targetRect, rect, circle, resizeLines, resizePoints } = editor;
186
- const { type, resizeable, rotateable, stroke, pointFill, pointSize, pointRadius } = config;
187
- const defaultStyle = { fill: pointFill, stroke, width: pointSize, height: pointSize, cornerRadius: pointRadius };
188
- const pointStyles = config.point instanceof Array ? config.point : [config.point || defaultStyle];
189
- const box = new Bounds(target.boxBounds);
190
- const w = target.worldTransform, pw = editor.parent.worldTransform;
191
- const matrix = new Matrix(w);
192
- matrix.divide(pw);
193
- const worldX = matrix.e, worldY = matrix.f;
194
- let { scaleX, scaleY, rotation, skewX, skewY } = w;
195
- scaleX /= pw.scaleX, scaleY /= pw.scaleY, rotation -= pw.rotation, skewX -= pw.skewX, skewY -= pw.skewY;
196
- const { x, y, width, height } = box.scale(scaleX, scaleY);
197
- editor.set({ x: worldX, y: worldY, rotation, skewX, skewY });
198
- targetRect.set({ x, y, width: box.width / scaleX, height: box.height / scaleY, scaleX, scaleY, visible: true });
199
- const points = [
200
- { x, y },
201
- { x: x + width / 2, y },
202
- { x: x + width, y },
203
- { x: x + width, y: y + height / 2 },
204
- { x: x + width, y: y + height },
205
- { x: x + width / 2, y: y + height },
206
- { x, y: y + height },
207
- { x, y: y + height / 2 }
208
- ];
209
- const rectPoints = [];
210
- let point, style, rotateP, resizeP, resizeL;
601
+ buttons.add(circle);
602
+ this.listenPointEvents(circle, 'rotate', 2);
603
+ this.addMany(...rotatePoints, rect, buttons, ...resizeLines, ...resizePoints);
604
+ }
605
+ update(bounds) {
606
+ const { config, list } = this.editor;
607
+ const { width, height } = bounds;
608
+ const { rect, circle, resizePoints, rotatePoints, resizeLines } = this;
609
+ const { middlePoint, resizeable, rotateable, stroke, strokeWidth } = config;
610
+ const pointsStyle = this.getPointsStyle();
611
+ const middlePointsStyle = this.getMiddlePointsStyle();
612
+ this.visible = list[0] && !list[0].locked;
613
+ let point = {}, style, rotateP, resizeP, resizeL;
211
614
  for (let i = 0; i < 8; i++) {
212
- point = points[i];
213
- style = pointStyles[i % pointStyles.length];
214
- resizeP = resizePoints[i];
215
- resizeL = resizeLines[Math.floor(i / 2)];
216
- rotateP = rotatePoints[i];
615
+ AroundHelper.toPoint(AroundHelper.directionData[i], bounds, point);
616
+ style = this.getPointStyle((i % 2) ? middlePointsStyle[((i - 1) / 2) % middlePointsStyle.length] : pointsStyle[(i / 2) % pointsStyle.length]);
617
+ resizeP = resizePoints[i], rotateP = rotatePoints[i], resizeL = resizeLines[Math.floor(i / 2)];
217
618
  resizeP.set(style);
218
- resizeP.x = rotateP.x = resizeL.x = point.x;
219
- resizeP.y = rotateP.y = resizeL.y = point.y;
619
+ resizeP.set(point), rotateP.set(point), resizeL.set(point);
220
620
  resizeP.visible = resizeL.visible = resizeable || rotateable;
221
621
  rotateP.visible = rotateable && resizeable;
222
622
  if (i % 2) {
623
+ resizeP.visible = rotateP.visible = !!middlePoint;
223
624
  if (((i + 1) / 2) % 2) {
224
- resizeL.width = Math.abs(width);
225
- rotateP.width = Math.max(10, Math.abs(width) - 30);
625
+ resizeL.width = width;
626
+ if (resizeP.width > width - 30)
627
+ resizeP.visible = false;
226
628
  }
227
629
  else {
228
- resizeL.height = Math.abs(height);
229
- rotateP.height = Math.max(10, Math.abs(height) - 30);
630
+ resizeL.height = height;
631
+ resizeP.rotation = 90;
632
+ if (resizeP.width > height - 30)
633
+ resizeP.visible = false;
230
634
  }
231
- resizeP.rotation = 90;
232
- resizeP.visible = type === 'mobile';
233
- rotateP.visible = false;
234
635
  }
235
636
  else {
236
- rotateP.visible = type !== 'mobile';
237
- rectPoints.push(point.x, point.y);
637
+ resizeP.rotation = (i / 2) * 90;
638
+ }
639
+ }
640
+ circle.visible = rotateable && !!config.rotatePoint;
641
+ circle.set(this.getPointStyle(config.rotatePoint || pointsStyle[0]));
642
+ rect.set(Object.assign({ stroke, strokeWidth }, (config.rect || {})));
643
+ rect.set(Object.assign(Object.assign({}, bounds), { visible: true }));
644
+ this.layoutButtons();
645
+ }
646
+ layoutButtons() {
647
+ const { buttons, resizePoints } = this;
648
+ const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = this.editor.config;
649
+ const { flippedX, flippedY } = this;
650
+ let index = fourDirection.indexOf(buttonsDirection);
651
+ if ((index % 2 && flippedX) || ((index + 1) % 2 && flippedY)) {
652
+ if (buttonsFixed)
653
+ index = (index + 2) % 4;
654
+ }
655
+ const direction = buttonsFixed ? EditDataHelper.getRotateDirection(index, this.flippedOne ? this.rotation : -this.rotation, 4) : index;
656
+ const point = resizePoints[direction * 2 + 1];
657
+ const useX = direction % 2;
658
+ const sign = (!direction || direction === 3) ? -1 : 1;
659
+ const useWidth = index % 2;
660
+ const margin = (buttonsMargin + (useWidth ? ((middlePoint ? point.width : 0) + buttons.boxBounds.width) : ((middlePoint ? point.height : 0) + buttons.boxBounds.height)) / 2) * sign;
661
+ if (useX) {
662
+ buttons.x = point.x + margin;
663
+ buttons.y = point.y;
664
+ }
665
+ else {
666
+ buttons.x = point.x;
667
+ buttons.y = point.y + margin;
668
+ }
669
+ if (buttonsFixed) {
670
+ buttons.rotation = (direction - index) * 90;
671
+ buttons.scaleX = flippedX ? -1 : 1;
672
+ buttons.scaleY = flippedY ? -1 : 1;
673
+ }
674
+ }
675
+ getPointStyle(userStyle) {
676
+ const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.editor.config;
677
+ const defaultStyle = { fill: pointFill, stroke, strokeWidth, width: pointSize, height: pointSize, cornerRadius: pointRadius };
678
+ return userStyle ? Object.assign(defaultStyle, userStyle) : defaultStyle;
679
+ }
680
+ getPointsStyle() {
681
+ const { point } = this.editor.config;
682
+ return point instanceof Array ? point : [point];
683
+ }
684
+ getMiddlePointsStyle() {
685
+ const { middlePoint } = this.editor.config;
686
+ return middlePoint instanceof Array ? middlePoint : (middlePoint ? [middlePoint] : this.getPointsStyle());
687
+ }
688
+ onDragStart(e) {
689
+ this.dragging = true;
690
+ if (e.target.name === 'rect')
691
+ this.editor.opacity = this.editor.config.hideOnMove ? 0 : 1;
692
+ }
693
+ onDragEnd(e) {
694
+ this.dragging = false;
695
+ if (e.target.name === 'rect')
696
+ this.editor.opacity = 1;
697
+ }
698
+ onDrag(e) {
699
+ const { editor } = this;
700
+ const point = e.current;
701
+ if (point.pointType === 'rotate' || e.metaKey || e.ctrlKey || !editor.config.resizeable) {
702
+ if (editor.config.rotateable)
703
+ editor.onRotate(e);
704
+ }
705
+ else {
706
+ editor.onScale(e);
707
+ }
708
+ }
709
+ onArrow(e) {
710
+ if (this.editor.hasTarget) {
711
+ const move = { x: 0, y: 0 };
712
+ const distance = e.shiftKey ? 10 : 1;
713
+ switch (e.code) {
714
+ case 'ArrowDown':
715
+ move.y = distance;
716
+ break;
717
+ case 'ArrowUp':
718
+ move.y = -distance;
719
+ break;
720
+ case 'ArrowLeft':
721
+ move.x = -distance;
722
+ break;
723
+ case 'ArrowRight':
724
+ move.x = distance;
238
725
  }
726
+ if (move.x || move.y)
727
+ this.editor.move(move.x, move.y);
239
728
  }
240
- style = config.rotatePoint || style;
241
- circle.set(style);
242
- circle.x = x + width / 2;
243
- if (!style.y)
244
- circle.y = y - (10 + (resizeP.height + circle.height) / 2) * (this.getMirrorData(editor).y ? -1 : 1);
245
- circle.visible = rotateable && type === 'mobile';
246
- rect.set(config.rect || { stroke });
247
- rect.points = rectPoints;
248
- rect.visible = true;
249
729
  }
730
+ onDoubleClick() {
731
+ const { editor } = this;
732
+ if (editor.single && editor.element.isBranch) ;
733
+ }
734
+ listenPointEvents(point, type, direction) {
735
+ const { editor } = this;
736
+ point.direction = direction;
737
+ point.pointType = type;
738
+ point.on_(DragEvent.START, this.onDragStart, this);
739
+ point.on_(DragEvent.DRAG, this.onDrag, this);
740
+ point.on_(DragEvent.END, this.onDragEnd, this);
741
+ point.on_(PointerEvent.LEAVE, () => this.enterPoint = null);
742
+ if (point.name !== 'circle')
743
+ point.on_(PointerEvent.ENTER, (e) => { this.enterPoint = point, updateCursor(editor, e); });
744
+ }
745
+ __listenEvents() {
746
+ const { rect, editor } = this;
747
+ this.__eventIds = [
748
+ editor.on_(EditorEvent.SELECT, () => { this.visible = editor.hasTarget; }),
749
+ rect.on_(DragEvent.START, this.onDragStart, this),
750
+ rect.on_(DragEvent.DRAG, editor.onMove, editor),
751
+ rect.on_(DragEvent.END, this.onDragEnd, this),
752
+ rect.on_(PointerEvent.ENTER, () => updateMoveCursor(editor)),
753
+ rect.on_(PointerEvent.DOUBLE_CLICK, this.onDoubleClick, this)
754
+ ];
755
+ }
756
+ __removeListenEvents() {
757
+ this.off_(this.__eventIds);
758
+ this.__eventIds.length = 0;
759
+ }
760
+ destroy() {
761
+ this.editor = null;
762
+ this.__removeListenEvents();
763
+ super.destroy();
764
+ }
765
+ }
766
+
767
+ const config = {
768
+ editSize: 'auto',
769
+ stroke: '#836DFF',
770
+ strokeWidth: 2,
771
+ pointFill: '#FFFFFF',
772
+ pointSize: 8,
773
+ pointRadius: 16,
774
+ rotateGap: 45,
775
+ buttonsDirection: 'bottom',
776
+ buttonsMargin: 12,
777
+ moveCursor: 'move',
778
+ resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
779
+ rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
780
+ selector: true,
781
+ hover: true,
782
+ boxSelect: true,
783
+ resizeable: true,
784
+ rotateable: true,
785
+ skewable: true
250
786
  };
251
787
 
788
+ class EditTool {
789
+ constructor() {
790
+ this.tag = 'EditTool';
791
+ }
792
+ onMove(e) {
793
+ const { moveX, moveY, editor } = e;
794
+ const { app, list } = editor;
795
+ app.lockLayout();
796
+ list.forEach(target => {
797
+ const move = target.getLocalPoint({ x: moveX, y: moveY }, null, true);
798
+ target.move(move.x, move.y);
799
+ });
800
+ app.unlockLayout();
801
+ }
802
+ onScale(e) {
803
+ const { scaleX, scaleY, transform, worldOrigin, editor } = e;
804
+ const { app, list } = editor;
805
+ app.lockLayout();
806
+ list.forEach(target => {
807
+ const resize = editor.getEditSize(target) === 'size';
808
+ if (transform) {
809
+ target.transform(transform, resize);
810
+ }
811
+ else {
812
+ target.scaleOf(target.getInnerPoint(worldOrigin), scaleX, scaleY, resize);
813
+ }
814
+ });
815
+ app.unlockLayout();
816
+ }
817
+ onRotate(e) {
818
+ const { rotation, worldOrigin, editor } = e;
819
+ const { app, list } = editor;
820
+ app.lockLayout();
821
+ list.forEach(target => {
822
+ target.rotateOf(target.getInnerPoint(worldOrigin), rotation);
823
+ });
824
+ app.unlockLayout();
825
+ }
826
+ onSkew(e) {
827
+ const { skewX, skewY, transform, worldOrigin, editor } = e;
828
+ const { app, list } = editor;
829
+ app.lockLayout();
830
+ list.forEach(target => {
831
+ const resize = editor.getEditSize(target) === 'size';
832
+ if (transform) {
833
+ target.transform(transform, resize);
834
+ }
835
+ else {
836
+ target.skewOf(target.getInnerPoint(worldOrigin), skewX, skewY, resize);
837
+ }
838
+ });
839
+ app.unlockLayout();
840
+ }
841
+ update(editor) {
842
+ const { simulateTarget, element } = editor;
843
+ if (editor.multiple)
844
+ simulateTarget.parent.updateLayout();
845
+ const { x, y, scaleX, scaleY, rotation, skewX, skewY, width, height } = element.getLayoutBounds('box', editor, true);
846
+ editor.editBox.set({ x, y, scaleX, scaleY, rotation, skewX, skewY });
847
+ editor.editBox.update({ x: 0, y: 0, width, height });
848
+ }
849
+ }
850
+ EditTool.list = [];
851
+
252
852
  const { left, right } = IDirection8;
253
- const LineTool = {
254
- name: 'LineTool',
255
- getMirrorData(_editor) {
256
- return {
257
- x: 0,
258
- y: 0
259
- };
260
- },
261
- resize(e) {
262
- const { direction, dragEvent, lockRatio, around } = e;
853
+ class LineEditTool extends EditTool {
854
+ constructor() {
855
+ super(...arguments);
856
+ this.tag = 'LineEditTool';
857
+ this.scaleOfEvent = true;
858
+ }
859
+ onScaleWithDrag(e) {
860
+ const { drag, direction, lockRatio, around } = e;
263
861
  const target = e.target;
264
862
  const fromPoint = { x: 0, y: 0 };
265
863
  const { toPoint } = target;
266
864
  target.rotation = 0;
267
- let { x, y } = dragEvent.getInnerMove(target);
865
+ let { x, y } = drag.getInnerMove(target);
268
866
  if (lockRatio) {
269
867
  if (Math.abs(x) > Math.abs(y)) {
270
868
  y = 0;
@@ -295,219 +893,346 @@ const LineTool = {
295
893
  target.y = fromPoint.y;
296
894
  target.getInnerPointByLocal(toPoint, null, null, true);
297
895
  target.toPoint = toPoint;
298
- },
299
- rotate(e) {
300
- RectTool.rotate(e);
301
- },
896
+ }
897
+ onSkew(_e) {
898
+ }
302
899
  update(editor) {
303
- const { rotatePoints, circle, resizeLines, resizePoints } = editor;
304
- RectTool.update(editor);
900
+ const { rotatePoints, resizeLines, resizePoints } = editor.editBox;
901
+ super.update(editor);
305
902
  for (let i = 0; i < 8; i++) {
306
903
  if (i < 4)
307
904
  resizeLines[i].visible = false;
308
- resizePoints[i].visible = rotatePoints[i].visible = i === left || i === right;
905
+ resizePoints[i].visible = rotatePoints[i].visible = (i === left || i === right);
309
906
  }
310
- circle.visible = false;
311
907
  }
312
- };
908
+ }
313
909
 
314
- class EditorResizeEvent extends Event {
315
- constructor(type, data) {
316
- super(type);
317
- if (data)
318
- Object.assign(this, data);
910
+ function getEditTool(list) {
911
+ if (list.length === 1) {
912
+ const leaf = list[0];
913
+ if (leaf instanceof Line && !leaf.points) {
914
+ return new LineEditTool();
915
+ }
916
+ else {
917
+ return new EditTool();
918
+ }
919
+ }
920
+ else {
921
+ return new EditTool();
319
922
  }
320
923
  }
321
- EditorResizeEvent.RESIZE = 'editor.resize';
322
924
 
323
- class EditorRotateEvent extends Event {
324
- constructor(type, data) {
325
- super(type);
326
- if (data)
327
- Object.assign(this, data);
925
+ function simulate(editor) {
926
+ const { simulateTarget, leafList: targetList } = editor;
927
+ const { x, y, width, height } = new Bounds().setListWithFn(targetList.list, (leaf) => leaf.worldBoxBounds);
928
+ const parent = simulateTarget.parent = targetList.list[0].leafer.zoomLayer;
929
+ const { scaleX, scaleY, e: worldX, f: worldY } = parent.__world;
930
+ simulateTarget.reset({ x: (x - worldX) / scaleX, y: (y - worldY) / scaleY, width: width / scaleX, height: height / scaleY });
931
+ }
932
+
933
+ function onTarget(editor, oldValue) {
934
+ const { target } = editor;
935
+ if (target) {
936
+ editor.leafList = target instanceof LeafList ? target : new LeafList(target instanceof Array ? target : target);
937
+ }
938
+ else {
939
+ editor.leafList.reset();
940
+ }
941
+ editor.emitEvent(new EditorEvent(EditorEvent.SELECT, { editor, value: target, oldValue }));
942
+ if (editor.hasTarget) {
943
+ editor.waitLeafer(() => {
944
+ if (editor.multiple)
945
+ simulate(editor);
946
+ updateMoveCursor(editor);
947
+ editor.updateEditTool();
948
+ editor.update();
949
+ editor.listenTargetEvents();
950
+ });
951
+ }
952
+ else {
953
+ editor.removeTargetEvents();
328
954
  }
329
955
  }
330
- EditorRotateEvent.ROTATE = 'editor.rotate';
956
+ function onHover(editor, oldValue) {
957
+ editor.emitEvent(new EditorEvent(EditorEvent.HOVER, { editor, value: editor.hoverTarget, oldValue }));
958
+ }
331
959
 
332
- class Editor extends Group {
333
- get target() { return this._target; }
334
- set target(value) {
335
- this.__removeTargetEvents();
336
- this.visible = !!value;
337
- this._target = value;
338
- if (value)
339
- this.onTarget();
960
+ const order = (a, b) => a.parent.children.indexOf(a) - b.parent.children.indexOf(b);
961
+ const reverseOrder = (a, b) => b.parent.children.indexOf(b) - a.parent.children.indexOf(a);
962
+ const EditorHelper = {
963
+ group(list, element, group) {
964
+ list.sort(reverseOrder);
965
+ const { app, parent } = list[0];
966
+ if (!group)
967
+ group = new Group();
968
+ parent.addAt(group, parent.children.indexOf(list[0]));
969
+ list.sort(order);
970
+ const matrx = new Matrix(element.worldTransform);
971
+ matrx.divideParent(parent.worldTransform);
972
+ group.setTransform(matrx);
973
+ group.editable = true;
974
+ group.hitChildren = false;
975
+ app.lockLayout();
976
+ list.forEach(child => child.dropTo(group));
977
+ app.unlockLayout();
978
+ return group;
979
+ },
980
+ ungroup(list) {
981
+ const { app } = list[0];
982
+ const ungroupList = [];
983
+ app.lockLayout();
984
+ list.forEach(leaf => {
985
+ if (leaf.isBranch) {
986
+ const { parent, children } = leaf;
987
+ while (children.length) {
988
+ ungroupList.push(children[0]);
989
+ children[0].dropTo(parent, parent.children.indexOf(leaf));
990
+ }
991
+ leaf.remove();
992
+ }
993
+ else {
994
+ ungroupList.push(leaf);
995
+ }
996
+ });
997
+ app.unlockLayout();
998
+ return ungroupList;
999
+ },
1000
+ toTop(list) {
1001
+ list.sort(order);
1002
+ list.forEach(leaf => {
1003
+ if (leaf.parent)
1004
+ leaf.parent.add(leaf);
1005
+ });
1006
+ },
1007
+ toBottom(list) {
1008
+ list.sort(reverseOrder);
1009
+ list.forEach(leaf => {
1010
+ if (leaf.parent)
1011
+ leaf.parent.addAt(leaf, 0);
1012
+ });
340
1013
  }
1014
+ };
1015
+
1016
+ class Editor extends Group {
1017
+ get list() { return this.leafList.list; }
1018
+ get hasTarget() { return !!this.list.length; }
1019
+ get multiple() { return this.list.length > 1; }
1020
+ get single() { return this.list.length === 1; }
1021
+ get element() { return this.multiple ? this.simulateTarget : this.list[0]; }
1022
+ get buttons() { return this.editBox.buttons; }
1023
+ get dragging() { return this.editBox.dragging; }
341
1024
  constructor(userConfig, data) {
342
1025
  super(data);
343
- this.config = {
344
- type: 'pc',
345
- stroke: '#836DFF',
346
- pointFill: '#FFFFFF',
347
- pointSize: 10,
348
- pointRadius: 10,
349
- rotateGap: 90,
350
- hideOnMove: false,
351
- moveCursor: 'move',
352
- resizeType: 'auto',
353
- resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
354
- rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
355
- resizeable: true,
356
- rotateable: true
357
- };
358
- this.resizePoints = [];
359
- this.rotatePoints = [];
360
- this.resizeLines = [];
361
- this.targetRect = new Rect({ hitFill: 'all', hitRadius: 5 });
362
- this.rect = new Polygon({ hittable: false, strokeAlign: 'center' });
363
- this.circle = new Rect({ around: 'center', hitRadius: 10 });
364
- this.__eventIds = [];
365
- this.__targetEventIds = [];
1026
+ this.config = config;
1027
+ this.leafList = new LeafList();
1028
+ this.simulateTarget = new Rect({ visible: false });
1029
+ this.editBox = new EditBox(this);
1030
+ this.selector = new EditSelect(this);
1031
+ this.targetEventIds = [];
366
1032
  if (userConfig)
367
1033
  this.config = DataHelper.default(userConfig, this.config);
368
- this.init();
1034
+ this.addMany(this.selector, this.editBox);
369
1035
  }
370
- init() {
371
- let rotatePoint, resizeLine, resizePoint;
372
- const { resizePoints, rotatePoints, resizeLines } = this;
373
- const arounds = [{ x: 1, y: 1 }, 'center', { x: 0, y: 1 }, 'center', { x: 0, y: 0 }, 'center', { x: 1, y: 0 }, 'center'];
374
- for (let i = 0; i < 8; i++) {
375
- rotatePoint = new Rect({ around: arounds[i], width: 15, height: 15, hitFill: "all" });
376
- rotatePoints.push(rotatePoint);
377
- this.__listenPointEvents(rotatePoint, 'rotate', i);
378
- if (i % 2) {
379
- resizeLine = new Rect({ around: 'center', width: 10, height: 10, hitFill: "all" });
380
- resizeLines.push(resizeLine);
381
- this.__listenPointEvents(resizeLine, 'resize', i);
382
- }
383
- resizePoint = new Rect({ around: 'center', hitRadius: 5 });
384
- resizePoints.push(resizePoint);
385
- this.__listenPointEvents(resizePoint, 'resize', i);
386
- }
387
- this.__listenPointEvents(this.circle, 'rotate', 1);
388
- this.addMany(...rotatePoints, this.targetRect, this.rect, this.circle, ...resizeLines, ...resizePoints);
389
- this.__listenEvents();
1036
+ hasItem(item) {
1037
+ return this.leafList.has(item);
390
1038
  }
391
- onTarget() {
392
- this.tool = this.getTool(this.target);
393
- this.waitLeafer(() => {
394
- this.update();
395
- this.updateMoveCursor();
396
- this.__listenTargetEvents();
397
- });
1039
+ addItem(item) {
1040
+ if (!this.hasItem(item) && !item.locked)
1041
+ this.leafList.add(item), this.target = this.leafList.list;
398
1042
  }
399
- getTool(value) {
400
- return (value.tag === 'Line' && value.resizeable) ? LineTool : RectTool;
1043
+ removeItem(item) {
1044
+ if (this.hasItem(item))
1045
+ this.leafList.remove(item), this.target = this.leafList.list;
401
1046
  }
402
- update() {
403
- if (!this.target)
404
- return;
405
- this.tool.update(this);
1047
+ shiftItem(item) {
1048
+ this.hasItem(item) ? this.removeItem(item) : this.addItem(item);
406
1049
  }
407
- onDrag(e) {
408
- const { resizeable, rotateable } = this.config;
409
- if (e.metaKey || e.ctrlKey || !resizeable) {
410
- if (rotateable)
411
- this.onRotate(e);
412
- }
413
- else {
414
- this.onResize(e);
1050
+ update() {
1051
+ if (this.target) {
1052
+ this.editTool.update(this);
1053
+ this.selector.update();
415
1054
  }
416
1055
  }
1056
+ updateEditTool() {
1057
+ this.editTool = getEditTool(this.list);
1058
+ }
1059
+ getEditSize(ui) {
1060
+ let { editSize } = this.config;
1061
+ return editSize === 'auto' ? ui.editSize : editSize;
1062
+ }
417
1063
  onMove(e) {
418
- const { target } = this;
419
- const { x, y } = e.getLocalMove(target);
1064
+ const move = e.getLocalMove(this.element);
420
1065
  if (e.shiftKey) {
421
- if (Math.abs(x) > Math.abs(y)) {
422
- target.x += x;
423
- }
424
- else {
425
- target.y += y;
426
- }
1066
+ if (Math.abs(move.x) > Math.abs(move.y))
1067
+ move.y = 0;
1068
+ else
1069
+ move.x = 0;
1070
+ }
1071
+ this.move(move.x, move.y);
1072
+ }
1073
+ onScale(e) {
1074
+ const { element } = this;
1075
+ const { direction } = e.current;
1076
+ let { around, lockRatio } = this.config;
1077
+ if (e.shiftKey)
1078
+ lockRatio = true;
1079
+ const data = EditDataHelper.getScaleData(element.boxBounds, direction, e.getInnerMove(element), lockRatio, EditDataHelper.getAround(around, e.altKey));
1080
+ if (this.editTool.onScaleWithDrag) {
1081
+ data.drag = e;
1082
+ this.scaleWithDrag(data);
427
1083
  }
428
1084
  else {
429
- target.x += x;
430
- target.y += y;
1085
+ this.scaleOf(data.origin, data.scaleX, data.scaleY);
431
1086
  }
432
1087
  }
433
1088
  onRotate(e) {
434
- const { target } = this;
435
- const { rotateGap } = this.config;
436
- const { x, y, width, height } = target.boxBounds;
437
- const origin = { x: x + width / 2, y: y + height / 2 };
438
- let rotation;
1089
+ const { skewable, around, rotateGap } = this.config;
1090
+ const { direction, name } = e.current;
1091
+ if (skewable && name === 'resize-line')
1092
+ return this.onSkew(e);
1093
+ const { element, editBox } = this;
1094
+ let origin, rotation;
439
1095
  if (e instanceof RotateEvent) {
440
- rotation = e.rotation;
1096
+ rotation = e.rotation, origin = element.getInnerPoint(e);
441
1097
  }
442
1098
  else {
443
- const point = e;
444
- const last = { x: point.x - e.moveX, y: point.y - e.moveY };
445
- rotation = PointHelper.getChangeAngle(last, target.getWorldPoint(origin), point);
446
- }
447
- rotation = MathHelper.getGapRotation(target.rotation + rotation, rotateGap) - target.rotation;
448
- const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { editor: this, target, origin, rotation });
449
- this.tool.rotate(event);
450
- target.emitEvent(event);
451
- }
452
- onResize(e) {
453
- const { target } = this;
454
- const { __direction } = e.current.__;
455
- let { resizeType, around, lockRatio } = this.config;
456
- if (e.shiftKey)
457
- lockRatio = true;
458
- if (e.altKey && !around)
459
- around = 'center';
460
- if (resizeType === 'auto')
461
- resizeType = target.resizeable ? 'size' : 'scale';
462
- const data = getResizeData(target.boxBounds, __direction, e.getInnerMove(this.targetRect), lockRatio, around);
463
- const event = new EditorResizeEvent(EditorResizeEvent.RESIZE, Object.assign(Object.assign({}, data), { target, editor: this, dragEvent: e, resizeType }));
464
- this.tool.resize(event);
465
- target.emitEvent(event);
466
- }
467
- updateMoveCursor() {
468
- this.targetRect.cursor = this.config.moveCursor;
1099
+ const last = { x: e.x - e.moveX, y: e.y - e.moveY };
1100
+ const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (around || 'center'));
1101
+ rotation = data.rotation;
1102
+ origin = data.origin;
1103
+ }
1104
+ rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation);
1105
+ if (!rotation)
1106
+ return;
1107
+ if (editBox.flippedOne)
1108
+ rotation = -rotation;
1109
+ this.rotateOf(origin, rotation);
469
1110
  }
470
- __listenEvents() {
471
- this.__eventIds = [
472
- this.targetRect.on_(DragEvent.START, () => { this.opacity = this.config.hideOnMove ? 0 : 1; }),
473
- this.targetRect.on_(DragEvent.DRAG, this.onMove, this),
474
- this.targetRect.on_(DragEvent.END, () => { this.opacity = 1; }),
475
- this.targetRect.on_(PointerEvent.ENTER, this.updateMoveCursor, this)
476
- ];
1111
+ onSkew(e) {
1112
+ const { element } = this;
1113
+ const { around } = this.config;
1114
+ const { origin, skewX, skewY } = EditDataHelper.getSkewData(element.boxBounds, e.current.direction, e.getInnerMove(element), EditDataHelper.getAround(around, e.altKey));
1115
+ if (!skewX && !skewY)
1116
+ return;
1117
+ this.skewOf(origin, skewX, skewY);
477
1118
  }
478
- __removeListenEvents() {
479
- this.targetRect.off_(this.__eventIds);
480
- this.__eventIds.length = 0;
1119
+ move(x, y) {
1120
+ const { element } = this;
1121
+ const world = element.getWorldPointByLocal({ x, y }, null, true);
1122
+ const event = new EditorMoveEvent(EditorMoveEvent.MOVE, { target: element, editor: this, moveX: world.x, moveY: world.y });
1123
+ this.editTool.onMove(event);
1124
+ this.emitEvent(event);
1125
+ if (this.multiple)
1126
+ element.move(x, y);
481
1127
  }
482
- __listenPointEvents(point, type, direction) {
483
- point.__.__direction = direction;
484
- const resize = point.__.__isResizePoint = type === 'resize';
485
- point.on_(DragEvent.DRAG, resize ? this.onDrag : this.onRotate, this);
486
- point.on_(PointerEvent.LEAVE, () => this.enterPoint = null);
487
- point.on_(PointerEvent.ENTER, (e) => { this.enterPoint = point; updateCursor(this, e); });
1128
+ scaleWithDrag(data) {
1129
+ const { element } = this;
1130
+ const worldOrigin = element.getWorldPoint(data.origin);
1131
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, Object.assign(Object.assign({}, data), { target: element, editor: this, worldOrigin }));
1132
+ this.editTool.onScaleWithDrag(event);
1133
+ this.emitEvent(event);
488
1134
  }
489
- __listenTargetEvents() {
490
- if (this.target) {
491
- const { leafer } = this.target;
492
- this.__targetEventIds = [
1135
+ scaleOf(origin, scaleX, scaleY = scaleX, _resize) {
1136
+ const { element } = this;
1137
+ const worldOrigin = element.getWorldPoint(origin);
1138
+ let transform;
1139
+ if (this.multiple) {
1140
+ const childMatrix = Object.assign({}, element.localTransform);
1141
+ element.scaleOf(origin, scaleX, scaleY);
1142
+ transform = new Matrix(element.localTransform).divide(childMatrix);
1143
+ }
1144
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform });
1145
+ this.editTool.onScale(event);
1146
+ this.emitEvent(event);
1147
+ }
1148
+ rotateOf(origin, rotation) {
1149
+ const { element } = this;
1150
+ const worldOrigin = element.getWorldPoint(origin);
1151
+ const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation });
1152
+ this.editTool.onRotate(event);
1153
+ this.emitEvent(event);
1154
+ if (this.multiple)
1155
+ element.rotateOf(origin, rotation);
1156
+ }
1157
+ skewOf(origin, skewX, skewY = 0, _resize) {
1158
+ const { element } = this;
1159
+ const worldOrigin = element.getWorldPoint(origin);
1160
+ let transform;
1161
+ if (this.multiple) {
1162
+ const childMatrix = Object.assign({}, element.localTransform);
1163
+ element.skewOf(origin, skewX, skewY);
1164
+ transform = new Matrix(element.localTransform).divide(childMatrix);
1165
+ }
1166
+ const event = new EditorSkewEvent(EditorSkewEvent.SKEW, {
1167
+ target: element, editor: this, skewX, skewY, transform, worldOrigin
1168
+ });
1169
+ this.editTool.onSkew(event);
1170
+ this.emitEvent(event);
1171
+ }
1172
+ group(group) {
1173
+ if (this.multiple)
1174
+ this.target = EditorHelper.group(this.list, this.element, group);
1175
+ return this.target;
1176
+ }
1177
+ ungroup() {
1178
+ if (this.list.length)
1179
+ this.target = EditorHelper.ungroup(this.list);
1180
+ return this.list;
1181
+ }
1182
+ lock() {
1183
+ this.list.forEach(leaf => leaf.locked = true);
1184
+ this.update();
1185
+ }
1186
+ unlock() {
1187
+ this.list.forEach(leaf => leaf.locked = false);
1188
+ this.update();
1189
+ }
1190
+ toTop() {
1191
+ if (this.list.length) {
1192
+ EditorHelper.toTop(this.list);
1193
+ this.leafList.update();
1194
+ }
1195
+ }
1196
+ toBottom() {
1197
+ if (this.list.length) {
1198
+ EditorHelper.toBottom(this.list);
1199
+ this.leafList.update();
1200
+ }
1201
+ }
1202
+ listenTargetEvents() {
1203
+ if (!this.targetEventIds.length) {
1204
+ const { leafer } = this.list[0];
1205
+ this.targetEventIds = [
493
1206
  leafer.on_(RenderEvent.START, this.update, this),
494
- leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e) => { updateCursor(this, e); })
1207
+ leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e) => { updateCursor(this, e); }),
1208
+ leafer.on_(KeyEvent.DOWN, this.editBox.onArrow, this.editBox)
495
1209
  ];
496
1210
  }
497
1211
  }
498
- __removeTargetEvents() {
499
- if (this.__targetEventIds.length) {
500
- const { leafer } = this.target;
501
- if (leafer)
502
- leafer.off_(this.__targetEventIds);
503
- this.__targetEventIds.length = 0;
1212
+ removeTargetEvents() {
1213
+ const { targetEventIds } = this;
1214
+ if (targetEventIds.length) {
1215
+ this.off_(targetEventIds);
1216
+ targetEventIds.length = 0;
504
1217
  }
505
1218
  }
506
1219
  destroy() {
507
- this.__removeListenEvents();
508
- this._target = null;
509
- super.destroy();
1220
+ if (!this.destroyed) {
1221
+ this.simulateTarget.destroy();
1222
+ this.target = this.hoverTarget = this.simulateTarget = null;
1223
+ super.destroy();
1224
+ }
510
1225
  }
511
1226
  }
1227
+ __decorate([
1228
+ targetAttr(onHover)
1229
+ ], Editor.prototype, "hoverTarget", void 0);
1230
+ __decorate([
1231
+ targetAttr(onTarget)
1232
+ ], Editor.prototype, "target", void 0);
1233
+
1234
+ Creator.editor = function (options) {
1235
+ return new Editor(options);
1236
+ };
512
1237
 
513
- export { Editor, EditorResizeEvent, EditorRotateEvent, LineTool, RectTool };
1238
+ export { EditBox, EditDataHelper, EditPoint, EditSelect, EditSelectHelper, EditTool, Editor, EditorEvent, EditorHelper, EditorMoveEvent, EditorRotateEvent, EditorScaleEvent, EditorSkewEvent, LineEditTool, SelectArea, Stroker };