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