Skip to content

Commit

Permalink
feat(fabric.Canvas): fire an extra mouse up for the original control …
Browse files Browse the repository at this point in the history
…of the initial target (#7612)
  • Loading branch information
asturur authored Jan 15, 2022
1 parent ff53792 commit 91f0940
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* @fires dragover
* @fires dragenter
* @fires dragleave
* @fires drop:before before drop event. same native event. This is added to handle edge cases
* @fires drop
* @fires after:render at the end of the render process, receives the context in the callback
* @fires before:render at start the render process, receives the context in the callback
Expand Down
19 changes: 14 additions & 5 deletions src/mixins/canvas_events.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -462,25 +462,34 @@
);
}
}
var corner, pointer;
if (target) {
corner = target._findTargetCorner(
this.getPointer(e, true),
fabric.util.isTouchEvent(e)
);
if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {
this.setActiveObject(target, e);
shouldRender = true;
}
else {
var corner = target._findTargetCorner(
this.getPointer(e, true),
fabric.util.isTouchEvent(e)
);
var control = target.controls[corner],
mouseUpHandler = control && control.getMouseUpHandler(e, target, control);
if (mouseUpHandler) {
var pointer = this.getPointer(e);
pointer = this.getPointer(e);
mouseUpHandler(e, transform, pointer.x, pointer.y);
}
}
target.isMoving = false;
}
// if we are ending up a transform on a different control or a new object
// fire the original mouse up from the corner that started the transform
if (transform && (transform.target !== target || transform.corner !== corner)) {
var originalControl = transform.target && transform.target.controls[transform.corner],
originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);
pointer = pointer || this.getPointer(e);
originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);
}
this._setCursorFromEvent(e, target);
this._handleEvent(e, 'up', LEFT_CLICK, isClick);
this._groupSelector = null;
Expand Down
78 changes: 78 additions & 0 deletions test/unit/canvas_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,84 @@
assert.equal(rect.scaleY, 3, 'rect scaled Y');
});

QUnit.test('A transform will call mouseup and mousedown on the control', function(assert) {
var e = { clientX: 3, clientY: 3, which: 1 };
var e1 = { clientX: 6, clientY: 6, which: 1 };
var e2 = { clientX: 9, clientY: 9, which: 1 };
var rect = new fabric.Rect({ left: 0, top: 0, width: 3, height: 3, strokeWidth: 0 });
var mouseUpCalled = false;
var mouseDownCalled = false;
rect.controls = {
br: fabric.Object.prototype.controls.br,
};
rect.controls.br.mouseUpHandler = function() {
mouseUpCalled = true;
};
rect.controls.br.mouseDownHandler = function() {
mouseDownCalled = true;
};
canvas.add(rect);
canvas.setActiveObject(rect);
canvas.__onMouseDown(e);
canvas.__onMouseMove(e1);
canvas.__onMouseMove(e2);
canvas.__onMouseUp(e2);
assert.equal(mouseUpCalled, true, 'mouse up handler for control has been called');
assert.equal(mouseDownCalled, true, 'mouse down handler for control has been called');
});

QUnit.test('A transform than ends outside the object will call mouseup handler', function(assert) {
var e = { clientX: 3, clientY: 3, which: 1 };
var e1 = { clientX: 6, clientY: 6, which: 1 };
var e2 = { clientX: 9, clientY: 9, which: 1 };
var e3 = { clientX: 100, clientY: 100, which: 1 };
var rect = new fabric.Rect({ left: 0, top: 0, width: 3, height: 3, strokeWidth: 0 });
var mouseUpCalled = false;
rect.controls = {
br: fabric.Object.prototype.controls.br,
};
rect.controls.br.mouseUpHandler = function() {
mouseUpCalled = true;
};
canvas.add(rect);
canvas.setActiveObject(rect);
canvas.__onMouseDown(e);
canvas.__onMouseMove(e1);
canvas.__onMouseMove(e2);
canvas.__onMouseUp(e3);
assert.equal(mouseUpCalled, true, 'mouse up handler for control has been called anyway');
});

QUnit.test('A transform than ends on a new control, calls both mouseup handler', function(assert) {
var e = { clientX: 3, clientY: 3, which: 1 };
var e1 = { clientX: 6, clientY: 6, which: 1 };
var e2 = { clientX: 9, clientY: 9, which: 1 };
var e3 = { clientX: 9, clientY: 3, which: 1 };
var rect = new fabric.Rect({ left: 0, top: 0, width: 3, height: 3, strokeWidth: 0 });
var mouseUpCalled1 = false;
var mouseUpCalled2 = false;

rect.controls = {
br: fabric.Object.prototype.controls.br,
tr: fabric.Object.prototype.controls.tr,
};
rect.controls.br.mouseUpHandler = function() {
mouseUpCalled1 = true;
};
rect.controls.tr.mouseUpHandler = function() {
mouseUpCalled2 = true;
};
canvas.add(rect);
canvas.setActiveObject(rect);
canvas.__onMouseDown(e);
canvas.__onMouseMove(e1);
canvas.__onMouseMove(e2);
canvas.__onMouseUp(e3);
assert.equal(mouseUpCalled1, true, 'mouse up handler for rect has been called anyway');
assert.equal(mouseUpCalled2, true, 'mouse up handler for rect2 has been called');
});


QUnit.test('avoid multiple bindings', function(assert) {
var c = new fabric.Canvas();
var eventsArray = [
Expand Down

0 comments on commit 91f0940

Please sign in to comment.