Implement MouseEvent#delta for Item#onMouseDrag and #onMouseMove.

This commit is contained in:
Jürg Lehni 2011-11-17 00:04:30 +01:00
parent cf54b1a7c1
commit 1b484a2f7b
2 changed files with 38 additions and 14 deletions

View file

@ -75,20 +75,24 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
}; };
var downPoint, var downPoint,
lastPoint,
overPoint,
downItem, downItem,
hasDrag,
overItem, overItem,
hasDrag,
doubleClick, doubleClick,
clickTime; clickTime;
function callEvent(type, event, point, target, bubble) { function callEvent(type, event, point, target, lastPoint, bubble) {
var item = target, var item = target,
mouseEvent, mouseEvent,
called = false; called = false;
while (item) { while (item) {
if (item.responds(type)) { if (item.responds(type)) {
if (!mouseEvent) if (!mouseEvent)
mouseEvent = new MouseEvent(type, event, point, target); mouseEvent = new MouseEvent(type, event, point, target,
// Calculate delta if lastPoint was passed
lastPoint ? point.subtract(lastPoint) : null);
called = item.fire(type, mouseEvent) || called; called = item.fire(type, mouseEvent) || called;
if (called && (!bubble || mouseEvent._stopped)) if (called && (!bubble || mouseEvent._stopped))
break; break;
@ -98,15 +102,21 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
return called; return called;
} }
function handleEvent(view, type, event, point) { function handleEvent(view, type, event, point, lastPoint) {
if (view._eventCounters[type]) { if (view._eventCounters[type]) {
var hit = view._project.hitTest(point, hitOptions), var hit = view._project.hitTest(point, hitOptions),
item = hit && hit.item; item = hit && hit.item;
if (item) { if (item) {
// If this is a mousemove event and we change the over item,
// reset lastPoint to point so delta is (0, 0)
if (type == 'mousemove' && item != overItem)
lastPoint = point;
// If we have a downItem with a mousedrag event, do not send // If we have a downItem with a mousedrag event, do not send
// mousemove events to any item while we're dragging. // mousemove events to any item while we're dragging.
if (type != 'mousemove' || !downItem) // TODO: Do we also need to lock mousenter / mouseleave in the
callEvent(type, event, point, item); // same way?
if (type != 'mousemove' || !hasDrag)
callEvent(type, event, point, item, lastPoint);
return item; return item;
} }
} }
@ -119,16 +129,27 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
// double-click time. Firefox uses 300ms as the max time difference: // double-click time. Firefox uses 300ms as the max time difference:
doubleClick = downItem == item && Date.now() - clickTime < 300; doubleClick = downItem == item && Date.now() - clickTime < 300;
downItem = item; downItem = item;
downPoint = point; downPoint = lastPoint = overPoint = point;
hasDrag = downItem && downItem.responds('mousedrag'); hasDrag = downItem && downItem.responds('mousedrag');
}, },
_onMouseUp: function(event, point) { _onMouseUp: function(event, point) {
// TODO: Check
var item = handleEvent(this, 'mouseup', event, point); var item = handleEvent(this, 'mouseup', event, point);
// If we had a mousedrag event locking mousemove events and are over if (hasDrag) {
// another item, send it a mousemove event now // If the point has changed since the last mousedrag event, send
if (hasDrag && item != downItem) // another one
callEvent('mousemove', event, point, item); if (lastPoint && !lastPoint.equals(point))
callEvent('mousedrag', event, point, downItem, lastPoint);
// If we had a mousedrag event locking mousemove events and are
// over another item, send it a mousemove event now.
// Use point as overPoint, so delta is (0, 0) since this will
// be the first mousemove event for this item.
if (item != downItem) {
overPoint = point;
callEvent('mousemove', event, point, item, overPoint);
}
}
if (item == downItem) { if (item == downItem) {
clickTime = Date.now(); clickTime = Date.now();
callEvent(doubleClick ? 'doubleclick' : 'click', event, callEvent(doubleClick ? 'doubleclick' : 'click', event,
@ -142,8 +163,9 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
_onMouseMove: function(event, point) { _onMouseMove: function(event, point) {
// Call the mousedrag event first if an item was clicked earlier // Call the mousedrag event first if an item was clicked earlier
if (downItem) if (downItem)
callEvent('mousedrag', event, point, downItem); callEvent('mousedrag', event, point, downItem, lastPoint);
var item = handleEvent(this, 'mousemove', event, point); var item = handleEvent(this, 'mousemove', event, point, overPoint);
lastPoint = overPoint = point;
if (item != overItem) { if (item != overItem) {
callEvent('mouseleave', event, point, overItem); callEvent('mouseleave', event, point, overItem);
overItem = item; overItem = item;

View file

@ -20,11 +20,12 @@
* @extends Event * @extends Event
*/ */
var MouseEvent = this.MouseEvent = Event.extend(/** @lends MouseEvent# */{ var MouseEvent = this.MouseEvent = Event.extend(/** @lends MouseEvent# */{
initialize: function(type, event, point, target) { initialize: function(type, event, point, target, delta) {
this.base(event); this.base(event);
this.type = type; this.type = type;
this.point = point; this.point = point;
this.target = target; this.target = target;
this.delta = delta;
}, },
/** /**
@ -34,6 +35,7 @@ var MouseEvent = this.MouseEvent = Event.extend(/** @lends MouseEvent# */{
return '{ type: ' + this.type return '{ type: ' + this.type
+ ', point: ' + this.point + ', point: ' + this.point
+ ', target: ' + this.target + ', target: ' + this.target
+ (this.delta ? ', delta: ' + this.delta : '')
+ ', modifiers: ' + this.getModifiers() + ', modifiers: ' + this.getModifiers()
+ ' }'; + ' }';
} }