|
@@ -25,32 +25,108 @@
|
25
|
25
|
*/
|
26
|
26
|
|
27
|
27
|
(function hand() { //Code isolation
|
28
|
|
- const selectorStates = {
|
|
28
|
+ var selectorStates = {
|
29
|
29
|
pointing: 0,
|
30
|
30
|
selecting: 1,
|
31
|
|
- moving: 2
|
|
31
|
+ transform: 2
|
32
|
32
|
}
|
33
|
33
|
var selected = null;
|
34
|
34
|
var selected_els = [];
|
35
|
35
|
var selectionRect = createSelectorRect();
|
36
|
|
- var selectionRectTranslation;
|
37
|
|
- var translation_elements = [];
|
|
36
|
+ var selectionRectTransform;
|
|
37
|
+ var currentTransform = null;
|
|
38
|
+ var transform_elements = [];
|
38
|
39
|
var selectorState = selectorStates.pointing;
|
39
|
40
|
var last_sent = 0;
|
|
41
|
+ var blockedSelectionButtons = Tools.server_config.BLOCKED_SELECTION_BUTTONS;
|
|
42
|
+ var selectionButtons = [
|
|
43
|
+ createButton("delete", "delete", 24, 24,
|
|
44
|
+ function (me, bbox, s) {
|
|
45
|
+ me.width.baseVal.value = me.origWidth / s;
|
|
46
|
+ me.height.baseVal.value = me.origHeight / s;
|
|
47
|
+ me.x.baseVal.value = bbox.r[0];
|
|
48
|
+ me.y.baseVal.value = bbox.r[1] - (me.origHeight + 3) / s;
|
|
49
|
+ me.style.display = "";
|
|
50
|
+ },
|
|
51
|
+ deleteSelection),
|
|
52
|
+
|
|
53
|
+ createButton("duplicate", "duplicate", 24, 24,
|
|
54
|
+ function (me, bbox, s) {
|
|
55
|
+ me.width.baseVal.value = me.origWidth / s;
|
|
56
|
+ me.height.baseVal.value = me.origHeight / s;
|
|
57
|
+ me.x.baseVal.value = bbox.r[0] + (me.origWidth + 2) / s;
|
|
58
|
+ me.y.baseVal.value = bbox.r[1] - (me.origHeight + 3) / s;
|
|
59
|
+ me.style.display = "";
|
|
60
|
+ },
|
|
61
|
+ duplicateSelection),
|
|
62
|
+
|
|
63
|
+ createButton("scaleHandle", "handle", 14, 14,
|
|
64
|
+ function (me, bbox, s) {
|
|
65
|
+ me.width.baseVal.value = me.origWidth / s;
|
|
66
|
+ me.height.baseVal.value = me.origHeight / s;
|
|
67
|
+ me.x.baseVal.value = bbox.r[0] + bbox.a[0] - me.origWidth / (2 * s);
|
|
68
|
+ me.y.baseVal.value = bbox.r[1] + bbox.b[1] - me.origHeight / (2 * s);
|
|
69
|
+ me.style.display = "";
|
|
70
|
+ },
|
|
71
|
+ startScalingTransform)
|
|
72
|
+ ];
|
|
73
|
+
|
|
74
|
+ for (i in blockedSelectionButtons) {
|
|
75
|
+ delete selectionButtons[blockedSelectionButtons[i]];
|
|
76
|
+ }
|
|
77
|
+
|
|
78
|
+ var getScale = Tools.getScale;
|
40
|
79
|
|
41
|
80
|
function getParentMathematics(el) {
|
42
|
|
- var target
|
43
|
|
- var a = el
|
|
81
|
+ var target;
|
|
82
|
+ var a = el;
|
44
|
83
|
var els = [];
|
45
|
84
|
while (a) {
|
46
|
85
|
els.unshift(a);
|
47
|
86
|
a = a.parentElement;
|
48
|
87
|
}
|
49
|
|
- var parentMathematics = els.find(el => el.getAttribute("class") === "MathElement");
|
|
88
|
+ var parentMathematics = els.find(function (el) {
|
|
89
|
+ return el.getAttribute("class") === "MathElement";
|
|
90
|
+ });
|
50
|
91
|
if ((parentMathematics) && parentMathematics.tagName === "svg") {
|
51
|
92
|
target = parentMathematics;
|
52
|
93
|
}
|
53
|
|
- return target ?? el;
|
|
94
|
+ return target || el;
|
|
95
|
+ }
|
|
96
|
+
|
|
97
|
+ function deleteSelection() {
|
|
98
|
+ var msgs = selected_els.map(function (el) {
|
|
99
|
+ return ({
|
|
100
|
+ "type": "delete",
|
|
101
|
+ "id": el.id
|
|
102
|
+ });
|
|
103
|
+ });
|
|
104
|
+ var data = {
|
|
105
|
+ _children: msgs
|
|
106
|
+ }
|
|
107
|
+ Tools.drawAndSend(data);
|
|
108
|
+ selected_els = [];
|
|
109
|
+ hideSelectionUI();
|
|
110
|
+ }
|
|
111
|
+
|
|
112
|
+ function duplicateSelection() {
|
|
113
|
+ if (!(selectorState == selectorStates.pointing)
|
|
114
|
+ || (selected_els.length == 0)) return;
|
|
115
|
+ var msgs = [];
|
|
116
|
+ var newids = [];
|
|
117
|
+ for (var i = 0; i < selected_els.length; i++) {
|
|
118
|
+ var id = selected_els[i].id;
|
|
119
|
+ msgs[i] = {
|
|
120
|
+ type: "copy",
|
|
121
|
+ id: id,
|
|
122
|
+ newid: Tools.generateUID(id[0])
|
|
123
|
+ };
|
|
124
|
+ newids[i] = id;
|
|
125
|
+ }
|
|
126
|
+ Tools.drawAndSend({ _children: msgs });
|
|
127
|
+ selected_els = newids.map(function (id) {
|
|
128
|
+ return Tools.svg.getElementById(id);
|
|
129
|
+ });
|
54
|
130
|
}
|
55
|
131
|
|
56
|
132
|
function createSelectorRect() {
|
|
@@ -70,22 +146,82 @@
|
70
|
146
|
return shape;
|
71
|
147
|
}
|
72
|
148
|
|
|
149
|
+ function createButton(name, icon, width, height, drawCallback, clickCallback) {
|
|
150
|
+ var shape = Tools.createSVGElement("use", {href: "tools/hand/" + icon + ".svg#root"});
|
|
151
|
+ shape.style.display = "none";
|
|
152
|
+ shape.origWidth = width;
|
|
153
|
+ shape.origHeight = height;
|
|
154
|
+ shape.drawCallback = drawCallback;
|
|
155
|
+ shape.clickCallback = clickCallback;
|
|
156
|
+ Tools.svg.appendChild(shape);
|
|
157
|
+ return shape;
|
|
158
|
+ }
|
|
159
|
+
|
|
160
|
+ function showSelectionButtons() {
|
|
161
|
+ var scale = getScale();
|
|
162
|
+ var selectionBBox = selectionRect.transformedBBox();
|
|
163
|
+ for (var i = 0; i < selectionButtons.length; i++) {
|
|
164
|
+ selectionButtons[i].drawCallback(selectionButtons[i],
|
|
165
|
+ selectionBBox,
|
|
166
|
+ scale);
|
|
167
|
+ }
|
|
168
|
+ }
|
|
169
|
+
|
|
170
|
+ function hideSelectionButtons() {
|
|
171
|
+ for (var i = 0; i < selectionButtons.length; i++) {
|
|
172
|
+ selectionButtons[i].style.display = "none";
|
|
173
|
+ }
|
|
174
|
+ }
|
|
175
|
+
|
|
176
|
+ function hideSelectionUI() {
|
|
177
|
+ hideSelectionButtons();
|
|
178
|
+ selectionRect.style.display = "none";
|
|
179
|
+ }
|
|
180
|
+
|
73
|
181
|
function startMovingElements(x, y, evt) {
|
74
|
182
|
evt.preventDefault();
|
75
|
|
- selectorState = selectorStates.moving;
|
|
183
|
+ selectorState = selectorStates.transform;
|
|
184
|
+ currentTransform = moveSelection;
|
76
|
185
|
selected = { x: x, y: y };
|
77
|
186
|
// Some of the selected elements could have been deleted
|
78
|
|
- selected_els = selected_els.filter(el => {
|
79
|
|
- return Tools.svg.getElementById(el.id) !== null
|
|
187
|
+ selected_els = selected_els.filter(function (el) {
|
|
188
|
+ return Tools.svg.getElementById(el.id) !== null;
|
80
|
189
|
});
|
81
|
|
- translation_elements = selected_els.map(el => {
|
82
|
|
- let tmatrix = get_translate_matrix(el);
|
83
|
|
- return { x: tmatrix.e, y: tmatrix.f }
|
|
190
|
+ transform_elements = selected_els.map(function (el) {
|
|
191
|
+ var tmatrix = get_transform_matrix(el);
|
|
192
|
+ return {
|
|
193
|
+ a: tmatrix.a, b: tmatrix.b, c: tmatrix.c,
|
|
194
|
+ d: tmatrix.d, e: tmatrix.e, f: tmatrix.f
|
|
195
|
+ };
|
84
|
196
|
});
|
85
|
|
- {
|
86
|
|
- let tmatrix = get_translate_matrix(selectionRect);
|
87
|
|
- selectionRectTranslation = { x: tmatrix.e, y: tmatrix.f };
|
88
|
|
- }
|
|
197
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
198
|
+ selectionRectTransform = { x: tmatrix.e, y: tmatrix.f };
|
|
199
|
+ }
|
|
200
|
+
|
|
201
|
+ function startScalingTransform(x, y, evt) {
|
|
202
|
+ evt.preventDefault();
|
|
203
|
+ hideSelectionButtons();
|
|
204
|
+ selectorState = selectorStates.transform;
|
|
205
|
+ var bbox = selectionRect.transformedBBox();
|
|
206
|
+ selected = {
|
|
207
|
+ x: bbox.r[0],
|
|
208
|
+ y: bbox.r[1],
|
|
209
|
+ w: bbox.a[0],
|
|
210
|
+ h: bbox.b[1],
|
|
211
|
+ };
|
|
212
|
+ transform_elements = selected_els.map(function (el) {
|
|
213
|
+ var tmatrix = get_transform_matrix(el);
|
|
214
|
+ return {
|
|
215
|
+ a: tmatrix.a, b: tmatrix.b, c: tmatrix.c,
|
|
216
|
+ d: tmatrix.d, e: tmatrix.e, f: tmatrix.f
|
|
217
|
+ };
|
|
218
|
+ });
|
|
219
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
220
|
+ selectionRectTransform = {
|
|
221
|
+ a: tmatrix.a, d: tmatrix.d,
|
|
222
|
+ e: tmatrix.e, f: tmatrix.f
|
|
223
|
+ };
|
|
224
|
+ currentTransform = scaleSelection;
|
89
|
225
|
}
|
90
|
226
|
|
91
|
227
|
function startSelector(x, y, evt) {
|
|
@@ -98,42 +234,93 @@
|
98
|
234
|
selectionRect.width.baseVal.value = 0;
|
99
|
235
|
selectionRect.height.baseVal.value = 0;
|
100
|
236
|
selectionRect.style.display = "";
|
101
|
|
- tmatrix = get_translate_matrix(selectionRect);
|
|
237
|
+ tmatrix = get_transform_matrix(selectionRect);
|
102
|
238
|
tmatrix.e = 0;
|
103
|
239
|
tmatrix.f = 0;
|
104
|
240
|
}
|
105
|
241
|
|
106
|
242
|
|
107
|
243
|
function calculateSelection() {
|
108
|
|
- var scale = Tools.drawingArea.getCTM().a;
|
109
|
|
- var selectionTBBox = selectionRect.transformedBBox(scale);
|
110
|
|
- return Array.from(Tools.drawingArea.children).filter(el => {
|
111
|
|
- return transformedBBoxIntersects(
|
112
|
|
- selectionTBBox,
|
113
|
|
- el.transformedBBox(scale)
|
114
|
|
- )
|
115
|
|
- });
|
|
244
|
+ var selectionTBBox = selectionRect.transformedBBox();
|
|
245
|
+ var elements = Tools.drawingArea.children;
|
|
246
|
+ var selected = [];
|
|
247
|
+ for (var i = 0; i < elements.length; i++) {
|
|
248
|
+ if (transformedBBoxIntersects(selectionTBBox, elements[i].transformedBBox()))
|
|
249
|
+ selected.push(Tools.drawingArea.children[i]);
|
|
250
|
+ }
|
|
251
|
+ return selected;
|
116
|
252
|
}
|
117
|
253
|
|
118
|
254
|
function moveSelection(x, y) {
|
119
|
255
|
var dx = x - selected.x;
|
120
|
256
|
var dy = y - selected.y;
|
121
|
|
- var msgs = selected_els.map((el, i) => {
|
|
257
|
+ var msgs = selected_els.map(function (el, i) {
|
|
258
|
+ var oldTransform = transform_elements[i];
|
122
|
259
|
return {
|
123
|
260
|
type: "update",
|
124
|
261
|
id: el.id,
|
125
|
|
- deltax: dx + translation_elements[i].x,
|
126
|
|
- deltay: dy + translation_elements[i].y
|
127
|
|
- }
|
|
262
|
+ transform: {
|
|
263
|
+ a: oldTransform.a,
|
|
264
|
+ b: oldTransform.b,
|
|
265
|
+ c: oldTransform.c,
|
|
266
|
+ d: oldTransform.d,
|
|
267
|
+ e: dx + oldTransform.e,
|
|
268
|
+ f: dy + oldTransform.f
|
|
269
|
+ }
|
|
270
|
+ };
|
128
|
271
|
})
|
129
|
272
|
var msg = {
|
130
|
273
|
_children: msgs
|
131
|
274
|
};
|
132
|
|
- {
|
133
|
|
- let tmatrix = get_translate_matrix(selectionRect);
|
134
|
|
- tmatrix.e = dx + selectionRectTranslation.x;
|
135
|
|
- tmatrix.f = dy + selectionRectTranslation.y;
|
|
275
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
276
|
+ tmatrix.e = dx + selectionRectTransform.x;
|
|
277
|
+ tmatrix.f = dy + selectionRectTransform.y;
|
|
278
|
+ var now = performance.now();
|
|
279
|
+ if (now - last_sent > 70) {
|
|
280
|
+ last_sent = now;
|
|
281
|
+ Tools.drawAndSend(msg);
|
|
282
|
+ } else {
|
|
283
|
+ draw(msg);
|
136
|
284
|
}
|
|
285
|
+ }
|
|
286
|
+
|
|
287
|
+ function scaleSelection(x, y) {
|
|
288
|
+ var rx = (x - selected.x) / (selected.w);
|
|
289
|
+ var ry = (y - selected.y) / (selected.h);
|
|
290
|
+ var msgs = selected_els.map(function (el, i) {
|
|
291
|
+ var oldTransform = transform_elements[i];
|
|
292
|
+ var x = el.transformedBBox().r[0];
|
|
293
|
+ var y = el.transformedBBox().r[1];
|
|
294
|
+ var a = oldTransform.a * rx;
|
|
295
|
+ var d = oldTransform.d * ry;
|
|
296
|
+ var e = selected.x * (1 - rx) - x * a +
|
|
297
|
+ (x * oldTransform.a + oldTransform.e) * rx
|
|
298
|
+ var f = selected.y * (1 - ry) - y * d +
|
|
299
|
+ (y * oldTransform.d + oldTransform.f) * ry
|
|
300
|
+ return {
|
|
301
|
+ type: "update",
|
|
302
|
+ id: el.id,
|
|
303
|
+ transform: {
|
|
304
|
+ a: a,
|
|
305
|
+ b: oldTransform.b,
|
|
306
|
+ c: oldTransform.c,
|
|
307
|
+ d: d,
|
|
308
|
+ e: e,
|
|
309
|
+ f: f
|
|
310
|
+ }
|
|
311
|
+ };
|
|
312
|
+ })
|
|
313
|
+ var msg = {
|
|
314
|
+ _children: msgs
|
|
315
|
+ };
|
|
316
|
+
|
|
317
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
318
|
+ tmatrix.a = rx;
|
|
319
|
+ tmatrix.d = ry;
|
|
320
|
+ tmatrix.e = selectionRectTransform.e +
|
|
321
|
+ selectionRect.x.baseVal.value * (selectionRectTransform.a - rx)
|
|
322
|
+ tmatrix.f = selectionRectTransform.f +
|
|
323
|
+ selectionRect.y.baseVal.value * (selectionRectTransform.d - ry)
|
137
|
324
|
var now = performance.now();
|
138
|
325
|
if (now - last_sent > 70) {
|
139
|
326
|
last_sent = now;
|
|
@@ -150,23 +337,34 @@
|
150
|
337
|
rect.height.baseVal.value = Math.abs(y - selected.y);
|
151
|
338
|
}
|
152
|
339
|
|
153
|
|
- function get_translate_matrix(elem) {
|
|
340
|
+ function resetSelectionRect() {
|
|
341
|
+ var bbox = selectionRect.transformedBBox();
|
|
342
|
+ var tmatrix = get_transform_matrix(selectionRect);
|
|
343
|
+ selectionRect.x.baseVal.value = bbox.r[0];
|
|
344
|
+ selectionRect.y.baseVal.value = bbox.r[1];
|
|
345
|
+ selectionRect.width.baseVal.value = bbox.a[0];
|
|
346
|
+ selectionRect.height.baseVal.value = bbox.b[1];
|
|
347
|
+ tmatrix.a = 1; tmatrix.b = 0; tmatrix.c = 0;
|
|
348
|
+ tmatrix.d = 1; tmatrix.e = 0; tmatrix.f = 0;
|
|
349
|
+ }
|
|
350
|
+
|
|
351
|
+ function get_transform_matrix(elem) {
|
154
|
352
|
// Returns the first translate or transform matrix or makes one
|
155
|
|
- var translate = null;
|
|
353
|
+ var transform = null;
|
156
|
354
|
for (var i = 0; i < elem.transform.baseVal.numberOfItems; ++i) {
|
157
|
355
|
var baseVal = elem.transform.baseVal[i];
|
158
|
356
|
// quick tests showed that even if one changes only the fields e and f or uses createSVGTransformFromMatrix
|
159
|
357
|
// the brower may add a SVG_TRANSFORM_MATRIX instead of a SVG_TRANSFORM_TRANSLATE
|
160
|
|
- if (baseVal.type === SVGTransform.SVG_TRANSFORM_TRANSLATE || baseVal.type === SVGTransform.SVG_TRANSFORM_MATRIX) {
|
161
|
|
- translate = baseVal;
|
|
358
|
+ if (baseVal.type === SVGTransform.SVG_TRANSFORM_MATRIX) {
|
|
359
|
+ transform = baseVal;
|
162
|
360
|
break;
|
163
|
361
|
}
|
164
|
362
|
}
|
165
|
|
- if (translate == null) {
|
166
|
|
- translate = elem.transform.baseVal.createSVGTransformFromMatrix(Tools.svg.createSVGMatrix());
|
167
|
|
- elem.transform.baseVal.appendItem(translate);
|
|
363
|
+ if (transform == null) {
|
|
364
|
+ transform = elem.transform.baseVal.createSVGTransformFromMatrix(Tools.svg.createSVGMatrix());
|
|
365
|
+ elem.transform.baseVal.appendItem(transform);
|
168
|
366
|
}
|
169
|
|
- return translate.matrix;
|
|
367
|
+ return transform.matrix;
|
170
|
368
|
}
|
171
|
369
|
|
172
|
370
|
function draw(data) {
|
|
@@ -178,9 +376,19 @@
|
178
|
376
|
case "update":
|
179
|
377
|
var elem = Tools.svg.getElementById(data.id);
|
180
|
378
|
if (!elem) throw new Error("Mover: Tried to move an element that does not exist.");
|
181
|
|
- var tmatrix = get_translate_matrix(elem);
|
182
|
|
- tmatrix.e = data.deltax || 0;
|
183
|
|
- tmatrix.f = data.deltay || 0;
|
|
379
|
+ var tmatrix = get_transform_matrix(elem);
|
|
380
|
+ for (i in data.transform) {
|
|
381
|
+ tmatrix[i] = data.transform[i]
|
|
382
|
+ }
|
|
383
|
+ break;
|
|
384
|
+ case "copy":
|
|
385
|
+ var newElement = Tools.svg.getElementById(data.id).cloneNode(true);
|
|
386
|
+ newElement.id = data.newid;
|
|
387
|
+ Tools.drawingArea.appendChild(newElement);
|
|
388
|
+ break;
|
|
389
|
+ case "delete":
|
|
390
|
+ data.tool = "Eraser";
|
|
391
|
+ messageForTool(data);
|
184
|
392
|
break;
|
185
|
393
|
default:
|
186
|
394
|
throw new Error("Mover: 'move' instruction with unknown type. ", data);
|
|
@@ -189,15 +397,23 @@
|
189
|
397
|
}
|
190
|
398
|
|
191
|
399
|
function clickSelector(x, y, evt) {
|
192
|
|
- var scale = Tools.drawingArea.getCTM().a
|
193
|
|
- selectionRect = selectionRect ?? createSelectorRect();
|
194
|
|
- if (pointInTransformedBBox([x, y], selectionRect.transformedBBox(scale))) {
|
|
400
|
+ selectionRect = selectionRect || createSelectorRect();
|
|
401
|
+ for (var i = 0; i < selectionButtons.length; i++) {
|
|
402
|
+ if (selectionButtons[i].contains(evt.target)) {
|
|
403
|
+ var button = selectionButtons[i];
|
|
404
|
+ }
|
|
405
|
+ }
|
|
406
|
+ if (button) {
|
|
407
|
+ button.clickCallback(x, y, evt);
|
|
408
|
+ } else if (pointInTransformedBBox([x, y], selectionRect.transformedBBox())) {
|
|
409
|
+ hideSelectionButtons();
|
195
|
410
|
startMovingElements(x, y, evt);
|
196
|
411
|
} else if (Tools.drawingArea.contains(evt.target)) {
|
197
|
|
- selectionRect.style.display = "none";
|
|
412
|
+ hideSelectionUI();
|
198
|
413
|
selected_els = [getParentMathematics(evt.target)];
|
199
|
414
|
startMovingElements(x, y, evt);
|
200
|
415
|
} else {
|
|
416
|
+ hideSelectionButtons();
|
201
|
417
|
startSelector(x, y, evt);
|
202
|
418
|
}
|
203
|
419
|
}
|
|
@@ -206,18 +422,20 @@
|
206
|
422
|
if (selectorState == selectorStates.selecting) {
|
207
|
423
|
selected_els = calculateSelection();
|
208
|
424
|
if (selected_els.length == 0) {
|
209
|
|
- selectionRect.style.display = "none";
|
|
425
|
+ hideSelectionUI();
|
210
|
426
|
}
|
211
|
|
- }
|
212
|
|
- translation_elements = [];
|
|
427
|
+ } else if (selectorState == selectorStates.transform)
|
|
428
|
+ resetSelectionRect();
|
|
429
|
+ if (selected_els.length != 0) showSelectionButtons();
|
|
430
|
+ transform_elements = [];
|
213
|
431
|
selectorState = selectorStates.pointing;
|
214
|
432
|
}
|
215
|
433
|
|
216
|
434
|
function moveSelector(x, y, evt) {
|
217
|
435
|
if (selectorState == selectorStates.selecting) {
|
218
|
436
|
updateRect(x, y, selectionRect);
|
219
|
|
- } else if (selectorState == selectorStates.moving) {
|
220
|
|
- moveSelection(x, y, selectionRect);
|
|
437
|
+ } else if (selectorState == selectorStates.transform && currentTransform) {
|
|
438
|
+ currentTransform(x, y);
|
221
|
439
|
}
|
222
|
440
|
}
|
223
|
441
|
|
|
@@ -252,8 +470,31 @@
|
252
|
470
|
selected = null;
|
253
|
471
|
}
|
254
|
472
|
|
|
473
|
+ function deleteShortcut(e) {
|
|
474
|
+ if (e.key == "Delete" &&
|
|
475
|
+ !e.target.matches("input[type=text], textarea"))
|
|
476
|
+ deleteSelection();
|
|
477
|
+ }
|
|
478
|
+
|
|
479
|
+ function duplicateShortcut(e) {
|
|
480
|
+ if (e.key == "d" &&
|
|
481
|
+ !e.target.matches("input[type=text], textarea"))
|
|
482
|
+ duplicateSelection();
|
|
483
|
+ }
|
|
484
|
+
|
255
|
485
|
function switchTool() {
|
|
486
|
+ onquit();
|
|
487
|
+ if (handTool.secondary.active) {
|
|
488
|
+ window.addEventListener("keydown", deleteShortcut);
|
|
489
|
+ window.addEventListener("keydown", duplicateShortcut);
|
|
490
|
+ }
|
|
491
|
+ }
|
|
492
|
+
|
|
493
|
+ function onquit() {
|
256
|
494
|
selected = null;
|
|
495
|
+ hideSelectionUI();
|
|
496
|
+ window.removeEventListener("keydown", deleteShortcut);
|
|
497
|
+ window.removeEventListener("keydown", duplicateShortcut);
|
257
|
498
|
}
|
258
|
499
|
|
259
|
500
|
var handTool = { //The new tool
|
|
@@ -264,6 +505,7 @@
|
264
|
505
|
"move": move,
|
265
|
506
|
"release": release,
|
266
|
507
|
},
|
|
508
|
+ "onquit": onquit,
|
267
|
509
|
"secondary": {
|
268
|
510
|
"name": "Selector",
|
269
|
511
|
"icon": "tools/hand/selector.svg",
|