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

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