Skip to content

Commit

Permalink
feat(hand-tool): activate on space
Browse files Browse the repository at this point in the history
  • Loading branch information
philippfromme authored and merge-me[bot] committed Jun 13, 2019
1 parent d130018 commit e7217b9
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 14 deletions.
49 changes: 47 additions & 2 deletions lib/features/hand-tool/HandTool.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { hasPrimaryModifier } from '../../util/Mouse';

import { isKey } from '../../features/keyboard/KeyboardUtil';

var HIGH_PRIORITY = 1500;
var HAND_CURSOR = 'grab';


export default function HandTool(eventBus, canvas, dragging, toolManager) {
export default function HandTool(eventBus, canvas, dragging, keyboard, toolManager) {
this._dragging = dragging;

var self = this;

toolManager.registerTool('hand', {
tool: 'hand',
Expand All @@ -21,6 +24,37 @@ export default function HandTool(eventBus, canvas, dragging, toolManager) {
}
}, this);

keyboard.addListener(HIGH_PRIORITY, function(e) {
if (!isSpace(e.keyEvent)) {
return;
}

if (self.isActive()) {
return;
}

function activateMove(event) {
self.activateMove(event);

window.removeEventListener('mousemove', activateMove);
}

window.addEventListener('mousemove', activateMove);

function deactivateMove(e) {
if (!isSpace(e.keyEvent)) {
return;
}

window.removeEventListener('mousemove', activateMove);

keyboard.removeListener(deactivateMove, 'keyboard.keyup');

dragging.cancel();
}

keyboard.addListener(HIGH_PRIORITY, deactivateMove, 'keyboard.keyup');
}, 'keyboard.keydown');

eventBus.on('hand.end', function(event) {
var target = event.originalEvent.target;
Expand Down Expand Up @@ -69,6 +103,7 @@ HandTool.$inject = [
'eventBus',
'canvas',
'dragging',
'keyboard',
'toolManager'
];

Expand Down Expand Up @@ -112,5 +147,15 @@ HandTool.prototype.toggle = function() {
HandTool.prototype.isActive = function() {
var context = this._dragging.context();

return context && /^hand/.test(context.prefix);
if (context) {
return /^(hand|hand\.move)$/.test(context.prefix);
}

return false;
};

// helpers //////////

function isSpace(keyEvent) {
return isKey(' ', keyEvent);
}
2 changes: 2 additions & 0 deletions lib/features/hand-tool/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import KeyboardModule from '../keyboard';
import ToolManagerModule from '../tool-manager';

import HandTool from './HandTool';

export default {
__depends__: [
KeyboardModule,
ToolManagerModule
],
__init__: [ 'handTool' ],
Expand Down
35 changes: 26 additions & 9 deletions lib/features/keyboard/Keyboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
isShift
} from './KeyboardUtil';

var KEYDOWN_EVENT = 'keyboard.keydown';
var KEYDOWN_EVENT = 'keyboard.keydown',
KEYUP_EVENT = 'keyboard.keyup';

var DEFAULT_PRIORITY = 1000;

Expand Down Expand Up @@ -49,7 +50,8 @@ export default function Keyboard(config, eventBus) {
this._config = config || {};
this._eventBus = eventBus;

this._keyHandler = this._keyHandler.bind(this);
this._keydownHandler = this._keydownHandler.bind(this);
this._keyupHandler = this._keyupHandler.bind(this);

// properly clean dom registrations
eventBus.on('diagram.destroy', function() {
Expand Down Expand Up @@ -78,8 +80,15 @@ Keyboard.$inject = [
'eventBus'
];

Keyboard.prototype._keyHandler = function(event) {
Keyboard.prototype._keydownHandler = function(event) {
this._keyHandler(event, KEYDOWN_EVENT);
};

Keyboard.prototype._keyupHandler = function(event) {
this._keyHandler(event, KEYUP_EVENT);
};

Keyboard.prototype._keyHandler = function(event, type) {
var target = event.target,
eventBusResult;

Expand All @@ -91,7 +100,7 @@ Keyboard.prototype._keyHandler = function(event) {
keyEvent: event
};

eventBusResult = this._eventBus.fire(KEYDOWN_EVENT, context);
eventBusResult = this._eventBus.fire(type || KEYDOWN_EVENT, context);

if (eventBusResult) {
event.preventDefault();
Expand All @@ -106,7 +115,8 @@ Keyboard.prototype.bind = function(node) {
this._node = node;

// bind key events
domEvent.bind(node, 'keydown', this._keyHandler, true);
domEvent.bind(node, 'keydown', this._keydownHandler, true);
domEvent.bind(node, 'keyup', this._keyupHandler, true);

this._fire('bind');
};
Expand All @@ -122,7 +132,8 @@ Keyboard.prototype.unbind = function() {
this._fire('unbind');

// unbind key events
domEvent.unbind(node, 'keydown', this._keyHandler, true);
domEvent.unbind(node, 'keydown', this._keydownHandler, true);
domEvent.unbind(node, 'keyup', this._keyupHandler, true);
}

this._node = null;
Expand All @@ -137,16 +148,22 @@ Keyboard.prototype._fire = function(event) {
* the keyboard is bound and the user presses a key. If no priority is
* provided, the default value of 1000 is used.
*
* @param {Number} priority
* @param {Number} [priority]
* @param {Function} listener
* @param {string} type
*/
Keyboard.prototype.addListener = function(priority, listener) {
Keyboard.prototype.addListener = function(priority, listener, type) {
if (isFunction(priority)) {
type = listener;
listener = priority;
priority = DEFAULT_PRIORITY;
}

this._eventBus.on(KEYDOWN_EVENT, priority, listener);
this._eventBus.on(type || KEYDOWN_EVENT, priority, listener);
};

Keyboard.prototype.removeListener = function(listener, type) {
this._eventBus.off(type || KEYDOWN_EVENT, listener);
};

Keyboard.prototype.hasModifier = hasModifier;
Expand Down
79 changes: 78 additions & 1 deletion test/spec/features/hand-tool/HandToolSpec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* global sinon */

import {
bootstrapDiagram,
inject
Expand All @@ -8,6 +10,10 @@ import { createCanvasEvent as canvasEvent } from '../../../util/MockEvents';
import handToolModule from 'lib/features/hand-tool';
import draggingModule from 'lib/features/dragging';

import { createKeyEvent } from 'test/util/KeyEvents';

var spy = sinon.spy;


describe('features/hand-tool', function() {

Expand Down Expand Up @@ -36,7 +42,7 @@ describe('features/hand-tool', function() {

describe('general', function() {

it('should not move element', inject(function(canvas, handTool, dragging) {
it('should not move element', inject(function(handTool, dragging) {
// given
var position = {
x: childShape.x,
Expand All @@ -54,6 +60,77 @@ describe('features/hand-tool', function() {
expect(childShape.x).to.equal(position.x);
expect(childShape.y).to.equal(position.y);
}));

});


describe('activate on space', function() {

var removeEventListenerSpy;

beforeEach(inject(function(eventBus) {
eventBus.fire('keyboard.keydown', {
keyEvent: createKeyEvent(' ')
});

removeEventListenerSpy = spy(window, 'removeEventListener');
}));

afterEach(function() {
removeEventListenerSpy.restore();
});


it('should activate on space key down', inject(function(handTool) {

// when
triggerMouseEvent('mousemove', window);

// then
expect(handTool.isActive()).to.be.true;
}));


it('should deactivate on space key up (mousemove)', inject(function(eventBus, handTool) {

// given
triggerMouseEvent('mousemove', window);

// when
eventBus.fire('keyboard.keyup', {
keyEvent: createKeyEvent(' ')
});

// then
expect(handTool.isActive()).to.be.false;

expect(removeEventListenerSpy).to.have.been.called;
}));


it('should deactivate on space key up (NO mousemove)', inject(function(eventBus, handTool) {

// when
eventBus.fire('keyboard.keyup', {
keyEvent: createKeyEvent(' ')
});

// then
expect(handTool.isActive()).to.be.false;

expect(removeEventListenerSpy).to.have.been.called;
}));

});

});

// helpers //////////

function triggerMouseEvent(type, node) {
var event = document.createEvent('MouseEvent');

event.initMouseEvent(type, true, true, window, 0, 0, 0, 100, 100, false, false, false, false, 0, null);

return node.dispatchEvent(event);
}
77 changes: 77 additions & 0 deletions test/spec/features/keyboard/KeyboardSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,40 @@ describe('features/keyboard', function() {

describe('add listener', function() {

it('should add keydown listener by default', inject(function(keyboard) {

// given
var keydownSpy = spy();

// when
keyboard.addListener(keydownSpy);

var event = createKeyEvent(TEST_KEY);

keyboard._keydownHandler(event);

// then
expect(keydownSpy).to.have.been.called;
}));


it('should add keyup listener', inject(function(keyboard) {

// given
var keyupSpy = spy();

// when
keyboard.addListener(keyupSpy, 'keyboard.keyup');

var event = createKeyEvent(TEST_KEY, { type: 'keyup' });

keyboard._keyupHandler(event);

// then
expect(keyupSpy).to.have.been.called;
}));


it('should handle listeners by priority', inject(function(keyboard) {

// given
Expand Down Expand Up @@ -245,6 +279,49 @@ describe('features/keyboard', function() {

});


describe('remove listener', function() {

it('should remove keydown listener by default', inject(function(keyboard) {

// given
var keydownSpy = spy();

keyboard.addListener(keydownSpy);

// when
keyboard.removeListener(keydownSpy);

// then
var event = createKeyEvent(TEST_KEY);

keyboard._keydownHandler(event);

// then
expect(keydownSpy).not.to.have.been.called;
}));


it('should remove keyup listener', inject(function(keyboard) {

// given
var keyupSpy = spy();

keyboard.addListener(keyupSpy, 'keyboard.keyup');

// when
keyboard.removeListener(keyupSpy, 'keyboard.keyup');

var event = createKeyEvent(TEST_KEY, { type: 'keyup' });

keyboard._keyupHandler(event);

// then
expect(keyupSpy).not.to.have.been.called;
}));

});

});


Expand Down
Loading

0 comments on commit e7217b9

Please sign in to comment.