bm-core-ui 2.7.0 → 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +147 -0
- package/build/@types/index.d.ts +672 -92
- package/build/BMCodeEditor/BMCodeEditor.js +24 -27
- package/build/BMCollectionView/BMCollectionView.js +404 -55
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +423 -33
- package/build/BMCollectionView/BMCollectionViewLayout.js +158 -0
- package/build/BMCollectionView/BMCollectionViewMasonryLayout.js +145 -5
- package/build/BMCollectionView/BMCollectionViewTileLayout.js +147 -2
- package/build/BMCoreUI.css +60 -10
- package/build/BMView/BMMenu.js +155 -8
- package/build/BMView/BMTextField.js +25 -14
- package/build/BMView/BMView_v2.5.js +205 -3
- package/build/BMViewLayoutEditor/BMLayoutEditor.js +188 -168
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingCells.js +2 -2
- package/build/BMWindow/BMConfirmationPopup.js +15 -0
- package/build/BMWindow/BMKeyboardShortcut.js +122 -3
- package/build/BMWindow/BMWindow.js +25 -90
- package/build/Core/BMAnimationContext.js +0 -4
- package/build/Core/BMCoreUI.js +9 -1
- package/lib/@types/BMCoreUI.min.d.ts +672 -92
- package/lib/BMCoreUI.min.js +1 -1
- package/package.json +1 -1
|
@@ -171,172 +171,7 @@ BMLayoutEditor.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
171
171
|
window.addEventListener('resize', this.resizeListener);
|
|
172
172
|
|
|
173
173
|
view.allSubviews.forEach(subview => {
|
|
174
|
-
|
|
175
|
-
let selector = document.createElement('div');
|
|
176
|
-
selector.className = 'BMLayoutEditorViewSelector';
|
|
177
|
-
|
|
178
|
-
subview._selector = selector;
|
|
179
|
-
subview.node.classList.add('BMLayoutEditorManagedView');
|
|
180
|
-
|
|
181
|
-
// Also add a resize drag handle that can be used to resize the view's frame
|
|
182
|
-
const dragHandle = document.createElement('div');
|
|
183
|
-
dragHandle.className = 'material-icons BMWindowDragHandle BMLayoutEditorViewDragHandle';
|
|
184
|
-
dragHandle.innerText = 'dehaze';
|
|
185
|
-
dragHandle.style.cursor = 'nwse-resize';
|
|
186
|
-
|
|
187
|
-
selector.appendChild(dragHandle);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
let touchDragPoint;
|
|
191
|
-
|
|
192
|
-
// Initialize dragging touch events for the drag handler
|
|
193
|
-
dragHandle.addEventListener('mousedown', event => {
|
|
194
|
-
|
|
195
|
-
let size = BMSizeMake(subview.frame.size.width, subview.frame.size.height);
|
|
196
|
-
let lastPosition = BMPointMake(event.clientX, event.clientY);
|
|
197
|
-
|
|
198
|
-
let didRemoveConstraints = NO;
|
|
199
|
-
|
|
200
|
-
let mouseMoveEventListener = event => {
|
|
201
|
-
if (!didRemoveConstraints) {
|
|
202
|
-
this._view.node.querySelectorAll('.BMLayoutEditorConstraint, .BMLayoutEditorLeadLine').forEach(node => node.remove());
|
|
203
|
-
didRemoveConstraints = YES;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
let position = BMPointMake(event.clientX, event.clientY);
|
|
207
|
-
const frame = subview.frame.copy();
|
|
208
|
-
frame.size.width = size.width + (position.x - lastPosition.x) / this.scale;
|
|
209
|
-
frame.size.height = size.height + (position.y - lastPosition.y) / this.scale;
|
|
210
|
-
subview.frame = frame;
|
|
211
|
-
size = BMSizeMake(size.width + (position.x - lastPosition.x) / this.scale, size.height + (position.y - lastPosition.y) / this.scale);
|
|
212
|
-
lastPosition = position;
|
|
213
|
-
|
|
214
|
-
event.preventDefault();
|
|
215
|
-
event.stopPropagation();
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
let mask = document.createElement('div');
|
|
219
|
-
mask.className = 'BMLayoutGuideMask';
|
|
220
|
-
mask.style.cursor = 'nwse-resize';
|
|
221
|
-
document.body.appendChild(mask);
|
|
222
|
-
|
|
223
|
-
let mouseUpEventListener = event => {
|
|
224
|
-
window.removeEventListener('mousemove', mouseMoveEventListener, YES);
|
|
225
|
-
window.removeEventListener('mouseup', mouseUpEventListener, YES);
|
|
226
|
-
mask.remove();
|
|
227
|
-
event.preventDefault();
|
|
228
|
-
event.stopPropagation();
|
|
229
|
-
|
|
230
|
-
this.selectView(subview);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
window.addEventListener('mousemove', mouseMoveEventListener, YES);
|
|
234
|
-
window.addEventListener('mouseup', mouseUpEventListener, YES);
|
|
235
|
-
|
|
236
|
-
event.preventDefault();
|
|
237
|
-
event.stopPropagation();
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
let touchDragHandlePoint;
|
|
241
|
-
|
|
242
|
-
dragHandle.addEventListener('touchstart', /** @type {TouchEvent} */ event => {
|
|
243
|
-
// If there is already a drag in progress, don't process this new event
|
|
244
|
-
if (typeof touchDragPoint !== 'undefined') {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Only use the first touch point
|
|
249
|
-
touchDragHandlePoint = event.changedTouches[0].identifier;
|
|
250
|
-
|
|
251
|
-
let size = BMSizeMake(subview.frame.size.width, subview.frame.size.height);
|
|
252
|
-
let lastPosition = BMPointMake(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
|
|
253
|
-
|
|
254
|
-
let didRemoveConstraints = NO;
|
|
255
|
-
|
|
256
|
-
let mouseMoveEventListener = event => {
|
|
257
|
-
// Look for the actively tracked touch point
|
|
258
|
-
let touch;
|
|
259
|
-
for (let changedTouch of event.changedTouches) {
|
|
260
|
-
if (changedTouch.identifier == touchDragHandlePoint) {
|
|
261
|
-
touch = changedTouch;
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// If the actively tracked touch point did not move, do not process this event
|
|
267
|
-
if (!touch) return;
|
|
268
|
-
|
|
269
|
-
if (!didRemoveConstraints) {
|
|
270
|
-
this._view.node.querySelectorAll('.BMLayoutEditorConstraint, .BMLayoutEditorLeadLine').forEach(node => node.remove());
|
|
271
|
-
didRemoveConstraints = YES;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
let position = BMPointMake(touch.clientX, touch.clientY);
|
|
275
|
-
const frame = subview.frame.copy();
|
|
276
|
-
frame.size.width = size.width + (position.x - lastPosition.x) / this.scale;
|
|
277
|
-
frame.size.height = size.height + (position.y - lastPosition.y) / this.scale;
|
|
278
|
-
subview.frame = frame;
|
|
279
|
-
size = BMSizeMake(size.width + (position.x - lastPosition.x) / this.scale, size.height + (position.y - lastPosition.y) / this.scale);
|
|
280
|
-
lastPosition = position;
|
|
281
|
-
event.preventDefault();
|
|
282
|
-
event.stopPropagation();
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
let mouseUpEventListener = event => {
|
|
286
|
-
touchDragHandlePoint = undefined;
|
|
287
|
-
window.removeEventListener('touchmove', mouseMoveEventListener);
|
|
288
|
-
window.removeEventListener('touchend', mouseUpEventListener);
|
|
289
|
-
window.removeEventListener('touchcancel', mouseUpEventListener);
|
|
290
|
-
|
|
291
|
-
event.preventDefault();
|
|
292
|
-
event.stopPropagation();
|
|
293
|
-
|
|
294
|
-
this.selectView(subview);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
window.addEventListener('touchmove', mouseMoveEventListener);
|
|
298
|
-
window.addEventListener('touchend', mouseUpEventListener);
|
|
299
|
-
window.removeEventListener('touchcancel', mouseUpEventListener);
|
|
300
|
-
|
|
301
|
-
event.preventDefault();
|
|
302
|
-
event.stopPropagation();
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
// Enable double click to select views
|
|
306
|
-
let doubleClickTimeout;
|
|
307
|
-
|
|
308
|
-
selector.addEventListener('click', event => {
|
|
309
|
-
if (event.altKey) return;
|
|
310
|
-
|
|
311
|
-
this.selectView(subview, {withEvent: event});
|
|
312
|
-
if (!doubleClickTimeout) {
|
|
313
|
-
doubleClickTimeout = setTimeout(() => doubleClickTimeout = undefined, 250);
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
doubleClickTimeout = undefined;
|
|
317
|
-
if (!this._detailsToolWindow._visible) {
|
|
318
|
-
this._detailsToolWindow.bringToFrontAnimated(YES, {fromRect: BMRectMakeWithNodeFrame(this._inspectorButton)});
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
event.stopPropagation();
|
|
323
|
-
event.stopImmediatePropagation();
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
this.initDragEventListenerForNode(selector, {view: subview});
|
|
327
|
-
|
|
328
|
-
// Disable all other non-right mouse button interactions
|
|
329
|
-
selector.addEventListener('mousedown', event => (event.button != 2) && (event.stopPropagation(), event.stopImmediatePropagation()));
|
|
330
|
-
selector.addEventListener('mousemove', event => (event.button != 2) && (event.stopPropagation(), event.stopImmediatePropagation()));
|
|
331
|
-
selector.addEventListener('mouseup', event => (event.button != 2) && (event.stopPropagation(), event.stopImmediatePropagation()));
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (subview.node.childNodes.length) {
|
|
335
|
-
subview.node.insertBefore(selector, subview.node.childNodes[0]);
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
subview.node.appendChild(selector);
|
|
339
|
-
}
|
|
174
|
+
this._prepareView(subview);
|
|
340
175
|
});
|
|
341
176
|
|
|
342
177
|
var width = document.documentElement.clientWidth;
|
|
@@ -590,6 +425,180 @@ BMLayoutEditor.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
590
425
|
return this;
|
|
591
426
|
},
|
|
592
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Prepares the given view for being edited by setting up the appropriate event handlers and
|
|
430
|
+
* adding the required controls to the view's node.
|
|
431
|
+
* @param view <BMView> The view to prepare.
|
|
432
|
+
*/
|
|
433
|
+
_prepareView(view) {
|
|
434
|
+
// Create and add the selector, that takes over interactions for the view
|
|
435
|
+
let selector = document.createElement('div');
|
|
436
|
+
selector.className = 'BMLayoutEditorViewSelector';
|
|
437
|
+
|
|
438
|
+
view._selector = selector;
|
|
439
|
+
view.node.classList.add('BMLayoutEditorManagedView');
|
|
440
|
+
|
|
441
|
+
// Also add a resize drag handle that can be used to resize the view's frame
|
|
442
|
+
const dragHandle = document.createElement('div');
|
|
443
|
+
dragHandle.className = 'material-icons BMWindowDragHandle BMLayoutEditorViewDragHandle';
|
|
444
|
+
dragHandle.innerText = 'dehaze';
|
|
445
|
+
dragHandle.style.cursor = 'nwse-resize';
|
|
446
|
+
|
|
447
|
+
selector.appendChild(dragHandle);
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
let touchDragPoint;
|
|
451
|
+
|
|
452
|
+
// Initialize dragging touch events for the drag handler
|
|
453
|
+
dragHandle.addEventListener('mousedown', event => {
|
|
454
|
+
|
|
455
|
+
let size = BMSizeMake(view.frame.size.width, view.frame.size.height);
|
|
456
|
+
let lastPosition = BMPointMake(event.clientX, event.clientY);
|
|
457
|
+
|
|
458
|
+
let didRemoveConstraints = NO;
|
|
459
|
+
|
|
460
|
+
let mouseMoveEventListener = event => {
|
|
461
|
+
if (!didRemoveConstraints) {
|
|
462
|
+
this._view.node.querySelectorAll('.BMLayoutEditorConstraint, .BMLayoutEditorLeadLine').forEach(node => node.remove());
|
|
463
|
+
didRemoveConstraints = YES;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
let position = BMPointMake(event.clientX, event.clientY);
|
|
467
|
+
const frame = view.frame.copy();
|
|
468
|
+
frame.size.width = size.width + (position.x - lastPosition.x) / this.scale;
|
|
469
|
+
frame.size.height = size.height + (position.y - lastPosition.y) / this.scale;
|
|
470
|
+
view.frame = frame;
|
|
471
|
+
size = BMSizeMake(size.width + (position.x - lastPosition.x) / this.scale, size.height + (position.y - lastPosition.y) / this.scale);
|
|
472
|
+
lastPosition = position;
|
|
473
|
+
|
|
474
|
+
event.preventDefault();
|
|
475
|
+
event.stopPropagation();
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
let mask = document.createElement('div');
|
|
479
|
+
mask.className = 'BMLayoutGuideMask';
|
|
480
|
+
mask.style.cursor = 'nwse-resize';
|
|
481
|
+
document.body.appendChild(mask);
|
|
482
|
+
|
|
483
|
+
let mouseUpEventListener = event => {
|
|
484
|
+
window.removeEventListener('mousemove', mouseMoveEventListener, YES);
|
|
485
|
+
window.removeEventListener('mouseup', mouseUpEventListener, YES);
|
|
486
|
+
mask.remove();
|
|
487
|
+
event.preventDefault();
|
|
488
|
+
event.stopPropagation();
|
|
489
|
+
|
|
490
|
+
this.selectView(view);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
window.addEventListener('mousemove', mouseMoveEventListener, YES);
|
|
494
|
+
window.addEventListener('mouseup', mouseUpEventListener, YES);
|
|
495
|
+
|
|
496
|
+
event.preventDefault();
|
|
497
|
+
event.stopPropagation();
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
let touchDragHandlePoint;
|
|
501
|
+
|
|
502
|
+
dragHandle.addEventListener('touchstart', /** @type {TouchEvent} */ event => {
|
|
503
|
+
// If there is already a drag in progress, don't process this new event
|
|
504
|
+
if (typeof touchDragPoint !== 'undefined') {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Only use the first touch point
|
|
509
|
+
touchDragHandlePoint = event.changedTouches[0].identifier;
|
|
510
|
+
|
|
511
|
+
let size = BMSizeMake(view.frame.size.width, view.frame.size.height);
|
|
512
|
+
let lastPosition = BMPointMake(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
|
|
513
|
+
|
|
514
|
+
let didRemoveConstraints = NO;
|
|
515
|
+
|
|
516
|
+
let mouseMoveEventListener = event => {
|
|
517
|
+
// Look for the actively tracked touch point
|
|
518
|
+
let touch;
|
|
519
|
+
for (let changedTouch of event.changedTouches) {
|
|
520
|
+
if (changedTouch.identifier == touchDragHandlePoint) {
|
|
521
|
+
touch = changedTouch;
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// If the actively tracked touch point did not move, do not process this event
|
|
527
|
+
if (!touch) return;
|
|
528
|
+
|
|
529
|
+
if (!didRemoveConstraints) {
|
|
530
|
+
this._view.node.querySelectorAll('.BMLayoutEditorConstraint, .BMLayoutEditorLeadLine').forEach(node => node.remove());
|
|
531
|
+
didRemoveConstraints = YES;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
let position = BMPointMake(touch.clientX, touch.clientY);
|
|
535
|
+
const frame = view.frame.copy();
|
|
536
|
+
frame.size.width = size.width + (position.x - lastPosition.x) / this.scale;
|
|
537
|
+
frame.size.height = size.height + (position.y - lastPosition.y) / this.scale;
|
|
538
|
+
view.frame = frame;
|
|
539
|
+
size = BMSizeMake(size.width + (position.x - lastPosition.x) / this.scale, size.height + (position.y - lastPosition.y) / this.scale);
|
|
540
|
+
lastPosition = position;
|
|
541
|
+
event.preventDefault();
|
|
542
|
+
event.stopPropagation();
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
let mouseUpEventListener = event => {
|
|
546
|
+
touchDragHandlePoint = undefined;
|
|
547
|
+
window.removeEventListener('touchmove', mouseMoveEventListener);
|
|
548
|
+
window.removeEventListener('touchend', mouseUpEventListener);
|
|
549
|
+
window.removeEventListener('touchcancel', mouseUpEventListener);
|
|
550
|
+
|
|
551
|
+
event.preventDefault();
|
|
552
|
+
event.stopPropagation();
|
|
553
|
+
|
|
554
|
+
this.selectView(view);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
window.addEventListener('touchmove', mouseMoveEventListener);
|
|
558
|
+
window.addEventListener('touchend', mouseUpEventListener);
|
|
559
|
+
window.removeEventListener('touchcancel', mouseUpEventListener);
|
|
560
|
+
|
|
561
|
+
event.preventDefault();
|
|
562
|
+
event.stopPropagation();
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Enable double click to select views
|
|
566
|
+
let doubleClickTimeout;
|
|
567
|
+
|
|
568
|
+
selector.addEventListener('click', event => {
|
|
569
|
+
if (event.altKey) return;
|
|
570
|
+
|
|
571
|
+
this.selectView(view, {withEvent: event});
|
|
572
|
+
if (!doubleClickTimeout) {
|
|
573
|
+
doubleClickTimeout = setTimeout(() => doubleClickTimeout = undefined, 250);
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
doubleClickTimeout = undefined;
|
|
577
|
+
if (!this._detailsToolWindow._visible) {
|
|
578
|
+
this._detailsToolWindow.bringToFrontAnimated(YES, {fromRect: BMRectMakeWithNodeFrame(this._inspectorButton)});
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
event.stopPropagation();
|
|
583
|
+
event.stopImmediatePropagation();
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
this.initDragEventListenerForNode(selector, {view: view});
|
|
587
|
+
|
|
588
|
+
// Disable all other non-right mouse button interactions
|
|
589
|
+
selector.addEventListener('mousedown', event => (event.button != 2) && (event.stopPropagation(), event.stopImmediatePropagation()));
|
|
590
|
+
selector.addEventListener('mousemove', event => (event.button != 2) && (event.stopPropagation(), event.stopImmediatePropagation()));
|
|
591
|
+
selector.addEventListener('mouseup', event => (event.button != 2) && (event.stopPropagation(), event.stopImmediatePropagation()));
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
if (view.node.childNodes.length) {
|
|
595
|
+
view.node.insertBefore(selector, view.node.childNodes[0]);
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
view.node.appendChild(selector);
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
|
|
593
602
|
/**
|
|
594
603
|
* Is set to <code>YES</code> while this layout editor is full screen.
|
|
595
604
|
*/
|
|
@@ -859,7 +868,7 @@ BMLayoutEditor.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
859
868
|
const closeButton = document.createElement('div');
|
|
860
869
|
closeButton.className = 'BMWindowToolbarButton BMLayoutEditorToolbarButton';
|
|
861
870
|
closeButton.innerHTML = '<i class="material-icons"></i>';
|
|
862
|
-
closeButton.style.opacity = 1;
|
|
871
|
+
closeButton.style.opacity = '1';
|
|
863
872
|
|
|
864
873
|
closeButton.addEventListener('click', event => this.dismissAnimated(YES, {toNode: this._returnNode}));
|
|
865
874
|
|
|
@@ -872,7 +881,7 @@ BMLayoutEditor.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
872
881
|
fullscreenButton.innerHTML = `<i class="material-icons" style="pointer-events: none;">${this._useSettingsView ? 'layers' : ''}</i>`;
|
|
873
882
|
this._fullScreenButton = fullscreenButton;
|
|
874
883
|
|
|
875
|
-
fullscreenButton.style.opacity = 1;
|
|
884
|
+
fullscreenButton.style.opacity = '1';
|
|
876
885
|
fullscreenButton.style.pointerEvents = 'all';
|
|
877
886
|
|
|
878
887
|
fullscreenButton.addEventListener('click', this._useSettingsView ? event => this._treeWindow.toggleAnimated(YES) : event => this.toggleFullscreenWithEvent(event));
|
|
@@ -900,6 +909,9 @@ BMLayoutEditor.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
900
909
|
toolbar.appendChild(deviceSelector);
|
|
901
910
|
|
|
902
911
|
|
|
912
|
+
/**
|
|
913
|
+
* @type {HTMLInputElement}
|
|
914
|
+
*/
|
|
903
915
|
let widthInput = document.createElement('input');
|
|
904
916
|
widthInput.type = 'number';
|
|
905
917
|
widthInput.style.cssText = 'width: 64px !important; margin-left: 32px !important; text-align: center;';
|
|
@@ -1119,6 +1131,14 @@ BMLayoutEditor.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
1119
1131
|
this._showSizeClassMenuAtPoint(point);
|
|
1120
1132
|
});
|
|
1121
1133
|
|
|
1134
|
+
const addViewsButton = document.createElement('div');
|
|
1135
|
+
addViewsButton.className = 'BMWindowToolbarButton BMLayoutEditorToolbarButton';
|
|
1136
|
+
addViewsButton.innerHTML = '<i class="material-icons BMScriptFont" style="pointer-events: none;">+</i>';
|
|
1137
|
+
toolbar.appendChild(addViewsButton);
|
|
1138
|
+
this.addViewsButton = addViewsButton;
|
|
1139
|
+
|
|
1140
|
+
addViewsButton.addEventListener('click', event => this.showViewsPopupWithEvent(event));
|
|
1141
|
+
|
|
1122
1142
|
const layoutVariablesButton = document.createElement('div');
|
|
1123
1143
|
layoutVariablesButton.className = 'BMWindowToolbarButton BMLayoutEditorToolbarButton';
|
|
1124
1144
|
layoutVariablesButton.innerHTML = '<i class="material-icons BMScriptFont" style="pointer-events: none;">{X}</i>';
|
|
@@ -518,10 +518,10 @@ BMLayoutEditorSettingsDeactivateConstraintsCell.prototype = BMExtend(Object.crea
|
|
|
518
518
|
|
|
519
519
|
buttonView.node.addEventListener('click', event => {
|
|
520
520
|
if (hasOption && hasShift && hasCtrl) {
|
|
521
|
-
new Set(this.setting.target.rootView.allConstraints).forEach(constraint => constraint.remove());
|
|
521
|
+
new Set(this.setting.target._view.rootView.allConstraints).forEach(constraint => constraint.remove());
|
|
522
522
|
}
|
|
523
523
|
else if (hasOption) {
|
|
524
|
-
for (let constraint of this.setting.target.localConstraints) {
|
|
524
|
+
for (let constraint of this.setting.target._view.localConstraints) {
|
|
525
525
|
if (hasShift) {
|
|
526
526
|
constraint.remove();
|
|
527
527
|
}
|
|
@@ -179,6 +179,11 @@ BMAlertPopup.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
179
179
|
return BMLayoutAttribute.CenterY;
|
|
180
180
|
},
|
|
181
181
|
|
|
182
|
+
/**
|
|
183
|
+
* The DOM node that was focused when this alert was opened.
|
|
184
|
+
*/
|
|
185
|
+
_previouslyActiveNode: undefined, // DOMNode
|
|
186
|
+
|
|
182
187
|
/**
|
|
183
188
|
* Designated initializer. Initializes this alert popup with the given labels.
|
|
184
189
|
* @param title <String> The popup's title.
|
|
@@ -249,6 +254,8 @@ BMAlertPopup.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
249
254
|
escapeKeyboardShortcut.preventsDefault = YES;
|
|
250
255
|
this.registerKeyboardShortcut(escapeKeyboardShortcut);
|
|
251
256
|
|
|
257
|
+
this._previouslyActiveNode = document.activeElement;
|
|
258
|
+
|
|
252
259
|
return this;
|
|
253
260
|
},
|
|
254
261
|
/**
|
|
@@ -291,6 +298,10 @@ BMAlertPopup.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
291
298
|
this._resolve(BMConfirmationPopupResult.Confirmed);
|
|
292
299
|
}
|
|
293
300
|
|
|
301
|
+
if (this._previouslyActiveNode) {
|
|
302
|
+
this._previouslyActiveNode.focus();
|
|
303
|
+
}
|
|
304
|
+
|
|
294
305
|
return BMWindow.prototype.dismissAnimated.apply(this, arguments);
|
|
295
306
|
}
|
|
296
307
|
|
|
@@ -455,6 +466,10 @@ BMConfirmationPopup.prototype = BMExtend(Object.create(BMAlertPopup.prototype),
|
|
|
455
466
|
this._resolve(BMConfirmationPopupResult.Cancelled);
|
|
456
467
|
}
|
|
457
468
|
|
|
469
|
+
if (this._previouslyActiveNode) {
|
|
470
|
+
this._previouslyActiveNode.focus();
|
|
471
|
+
}
|
|
472
|
+
|
|
458
473
|
return BMWindow.prototype.dismissAnimated.apply(this, arguments);
|
|
459
474
|
}
|
|
460
475
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { NO } from "../Core/BMCoreUI";
|
|
2
|
-
|
|
3
1
|
// @ts-check
|
|
4
2
|
|
|
3
|
+
import { NO } from "../Core/BMCoreUI";
|
|
4
|
+
|
|
5
5
|
// @type BMKeyboardShortcutModifier
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -9,22 +9,27 @@ import { NO } from "../Core/BMCoreUI";
|
|
|
9
9
|
* for views and windows.
|
|
10
10
|
*/
|
|
11
11
|
export const BMKeyboardShortcutModifier = Object.freeze({ // <enum>
|
|
12
|
+
|
|
12
13
|
/**
|
|
13
14
|
* Represents the command key on macOS and iOS, windows key on Windows and meta key on Linux.
|
|
14
15
|
*/
|
|
15
16
|
Command: {key: 'metaKey', value: 1}, // <enum>
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* Represents the option key on macOS and alt on other systems.
|
|
18
20
|
*/
|
|
19
21
|
Option: {key: 'altKey', value: 2}, // <enum>
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* Represents the shit key.
|
|
22
25
|
*/
|
|
23
26
|
Shift: {key: 'shiftKey', value: 4}, // <enum>
|
|
27
|
+
|
|
24
28
|
/**
|
|
25
29
|
* Represents the control key.
|
|
26
30
|
*/
|
|
27
31
|
Control: {key: 'ctrlKey', value: 8}, // <enum>
|
|
32
|
+
|
|
28
33
|
/**
|
|
29
34
|
* Represents the command key on macOS and iOS and control key on other systems.
|
|
30
35
|
*/
|
|
@@ -96,7 +101,7 @@ BMKeyboardShortcut.prototype = {
|
|
|
96
101
|
preventsDefault: NO, // <Boolean>
|
|
97
102
|
|
|
98
103
|
/**
|
|
99
|
-
* Initializes this keyboard shortcut with the given key and optional modifiers, as well as
|
|
104
|
+
* Designated initializer. Initializes this keyboard shortcut with the given key and optional modifiers, as well as
|
|
100
105
|
* the target and action that will handle it.
|
|
101
106
|
*
|
|
102
107
|
* In order to be triggered, this keyboard shortcut must be registered with an event handler such as a window
|
|
@@ -124,6 +129,88 @@ BMKeyboardShortcut.prototype = {
|
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
return this;
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Initializes this keyboard shortcut with the given keyboard event. If the event includes the control or command keys, these may be converted
|
|
136
|
+
* into a system key modifier based on the current platform.
|
|
137
|
+
* @param event <KeyboardEvent> The keyboard event from which this keyboard shortcut should be initialized.
|
|
138
|
+
* {
|
|
139
|
+
* @param target <AnyObject> The object that will handle this keyboard shortcut action.
|
|
140
|
+
* @param action <String> The name of a method on the target object that will be invoked when this
|
|
141
|
+
* keyboard shortcut is triggered. That method will receive the keyboard event as its single parameter.
|
|
142
|
+
* @param preventsDefault <Boolean, nullable> Defaults to `NO`. When set to `YES`, the default action of the event that triggers this keyboard shortcut will be prevented.
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
*/
|
|
146
|
+
initWithKeyboardEvent(event, {target, action, preventsDefault} = {}) {
|
|
147
|
+
const modifiers = [];
|
|
148
|
+
if (event.shiftKey) {
|
|
149
|
+
modifiers.push(BMKeyboardShortcutModifier.Shift);
|
|
150
|
+
}
|
|
151
|
+
if (event.altKey) {
|
|
152
|
+
modifiers.push(BMKeyboardShortcutModifier.Option);
|
|
153
|
+
}
|
|
154
|
+
if (event.metaKey) {
|
|
155
|
+
if (BMKeyboardShortcutModifier.System.value == BMKeyboardShortcutModifier.Command.value) {
|
|
156
|
+
modifiers.push(BMKeyboardShortcutModifier.System);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
modifiers.push(BMKeyboardShortcutModifier.Command);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (event.ctrlKey) {
|
|
163
|
+
if (BMKeyboardShortcutModifier.System.value == BMKeyboardShortcutModifier.Control.value) {
|
|
164
|
+
modifiers.push(BMKeyboardShortcutModifier.System);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
modifiers.push(BMKeyboardShortcutModifier.Control);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return this.initWithKeyCode(event.code, {modifiers, target, action, preventsDefault});
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Initializes this keyboard shortcut with the given serialized object representation. A callback is used to
|
|
176
|
+
* convert from the target object ID to an actual target object.
|
|
177
|
+
* @param shortcut <Object> A serialized keyboard shortcut.
|
|
178
|
+
* {
|
|
179
|
+
* @param targetID <Object ^(String)> A callback that is invoked with the target ID and should return
|
|
180
|
+
* the target object which will handle the keyboard shortcut.
|
|
181
|
+
* }
|
|
182
|
+
* @returns <Object> This keyboard shortcut.
|
|
183
|
+
*/
|
|
184
|
+
initWithSerializedKeyboardShortcut(shortcut, {targetID: resolver}) {
|
|
185
|
+
if (shortcut._class != 'BMKeyboardShortcut') {
|
|
186
|
+
throw new Error(`Unknown keyboard shortcut class - "${shortcut._class}"`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const target = resolver(shortcut._targetID);
|
|
190
|
+
|
|
191
|
+
const modifiers = shortcut._modifiers.map(modifier => {
|
|
192
|
+
return Object.values(BMKeyboardShortcutModifier).find(m => m.key == modifier)
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return this.initWithKeyCode(shortcut._key, {modifiers, target, action: shortcut._action, preventsDefault: shortcut._preventsDefault});
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Returns an object representation of this keyboard shortcut that can be used with `JSON.stringify` to
|
|
200
|
+
* serialize this keyboard shortcut.
|
|
201
|
+
* @param ID <String> A string that identifies the target object and can be used when recreating
|
|
202
|
+
* the keyboard shortcut instance.
|
|
203
|
+
* @returns <Object> An object that can be used with `JSON.stringify`.
|
|
204
|
+
*/
|
|
205
|
+
serializedKeyboardShortcutWithTargetID(ID) {
|
|
206
|
+
return {
|
|
207
|
+
_class: `BMKeyboardShortcut`,
|
|
208
|
+
_key: this._key,
|
|
209
|
+
_modifiers: this._modifiers.map(m => m.key),
|
|
210
|
+
_targetID: ID,
|
|
211
|
+
_action: this._action,
|
|
212
|
+
_preventsDefault: this.preventsDefault,
|
|
213
|
+
};
|
|
127
214
|
}
|
|
128
215
|
|
|
129
216
|
};
|
|
@@ -141,6 +228,7 @@ BMKeyboardShortcut.prototype = {
|
|
|
141
228
|
* @param target <AnyObject> The object that will handle this keyboard shortcut action.
|
|
142
229
|
* @param action <String> The name of a method on the target object that will be invoked when this
|
|
143
230
|
* keyboard shortcut is triggered. That method will receive the keyboard event as its single parameter.
|
|
231
|
+
* @param preventsDefault <Boolean, nullable> Defaults to `NO`. When set to `YES`, the default action of the event that triggers this keyboard shortcut will be prevented.
|
|
144
232
|
* }
|
|
145
233
|
* @return <BMKeyboardShortcut> A keyboard shortcut.
|
|
146
234
|
*/
|
|
@@ -148,4 +236,35 @@ BMKeyboardShortcut.keyboardShortcutWithKeyCode = function (key, args) {
|
|
|
148
236
|
return (new BMKeyboardShortcut).initWithKeyCode(key, args);
|
|
149
237
|
};
|
|
150
238
|
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Constructs and returns a keyboard shortcut with the given keyboard event. If the event includes the control or command keys, these may be converted
|
|
242
|
+
* into a system key modifier based on the current platform.
|
|
243
|
+
* @param event <KeyboardEvent> The keyboard event from which this keyboard shortcut should be initialized.
|
|
244
|
+
* {
|
|
245
|
+
* @param target <AnyObject> The object that will handle this keyboard shortcut action.
|
|
246
|
+
* @param action <String> The name of a method on the target object that will be invoked when this
|
|
247
|
+
* keyboard shortcut is triggered. That method will receive the keyboard event as its single parameter.
|
|
248
|
+
* @param preventsDefault <Boolean, nullable> Defaults to `NO`. When set to `YES`, the default action of the event that triggers this keyboard shortcut will be prevented.
|
|
249
|
+
* }
|
|
250
|
+
*
|
|
251
|
+
*/
|
|
252
|
+
BMKeyboardShortcut.keyboardShortcutWithKeyboardEvent = function (event, args) {
|
|
253
|
+
return (new BMKeyboardShortcut).initWithKeyboardEvent(event, args);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Constructs and returns keyboard shortcut with the given serialized object representation. A callback is used to
|
|
258
|
+
* convert from the target object ID to an actual target object.
|
|
259
|
+
* @param shortcut <Object> A serialized keyboard shortcut.
|
|
260
|
+
* {
|
|
261
|
+
* @param targetID <Object ^(String)> A callback that is invoked with the target ID and should return
|
|
262
|
+
* the target object which will handle the keyboard shortcut.
|
|
263
|
+
* }
|
|
264
|
+
* @returns <Object> A keyboard shortcut.
|
|
265
|
+
*/
|
|
266
|
+
BMKeyboardShortcut.keyboardShortcutWithSerializedKeyboardShortcut = function (shortcut, args) {
|
|
267
|
+
return (new BMKeyboardShortcut).initWithSerializedKeyboardShortcut(shortcut, args);
|
|
268
|
+
};
|
|
269
|
+
|
|
151
270
|
// @endtype
|