Merge branch 'tap'
This commit is contained in:
commit
4fb8a04251
|
@ -4,9 +4,8 @@ var _ = require('lodash');
|
|||
|
||||
var UpdateTextHandler = require('./cmd/UpdateTextHandler');
|
||||
|
||||
var LabelUtil = require('./LabelUtil');
|
||||
|
||||
var DiUtil = require('../../util/Di');
|
||||
var LabelUtil = require('./LabelUtil'),
|
||||
DiUtil = require('../../util/Di');
|
||||
|
||||
|
||||
var minBounds = {
|
||||
|
@ -20,7 +19,6 @@ function LabelEditingProvider(eventBus, canvas, directEditing, commandStack, bpm
|
|||
directEditing.registerProvider(this);
|
||||
commandStack.registerHandler('bpmnElement.updateText', UpdateTextHandler);
|
||||
|
||||
|
||||
// per default, listen to double click events
|
||||
eventBus.on('shape.dblclick', function(event) {
|
||||
directEditing.activate(event.element);
|
||||
|
@ -31,8 +29,7 @@ function LabelEditingProvider(eventBus, canvas, directEditing, commandStack, bpm
|
|||
directEditing.activate(event.element);
|
||||
});
|
||||
|
||||
// intercept direct canvas clicks to deselect all
|
||||
// selected shapes
|
||||
// intercept direct canvas clicks to deselect all selected shapes
|
||||
eventBus.on('canvas.click', function(event) {
|
||||
directEditing.complete();
|
||||
});
|
||||
|
|
|
@ -5,7 +5,136 @@ var _ = require('lodash');
|
|||
|
||||
function TouchInteraction(eventBus, canvas) {
|
||||
|
||||
var context;
|
||||
|
||||
var RANGE = { min: 0.2, max: 4 };
|
||||
var DOUBLE_TAP_THRESHOLD = 300; // ms
|
||||
|
||||
function handleTouchStart(event) {
|
||||
|
||||
var orgEvent = event.originalEvent ? event.originalEvent : event;
|
||||
|
||||
_.forEach(orgEvent.changedTouches, function (touch) {
|
||||
context.start[touch.identifier] = touch;
|
||||
});
|
||||
|
||||
if (orgEvent.touches.length === 1) {
|
||||
initMove(orgEvent);
|
||||
}
|
||||
|
||||
if (orgEvent.touches.length === 2) {
|
||||
initScale(orgEvent);
|
||||
}
|
||||
|
||||
//Stop all interaction for more than 2 touch sources
|
||||
if (orgEvent.touches.length > 2) {
|
||||
contextInit();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function handleTouchMove(event) {
|
||||
var orgEvent = event.originalEvent;
|
||||
var cX = 0;
|
||||
var cY = 0;
|
||||
var mX = 0;
|
||||
var mY = 0;
|
||||
|
||||
if (context.move && !context.scale) {
|
||||
|
||||
_.forEach(orgEvent.changedTouches, function (touch) {
|
||||
if (touch.identifier === context.moveId) {
|
||||
cX = touch.clientX;
|
||||
cY = touch.clientY;
|
||||
}
|
||||
});
|
||||
|
||||
if (!context.lasttouch.cX) {
|
||||
context.lasttouch.cX = cX;
|
||||
}
|
||||
|
||||
if (!context.lasttouch.cY) {
|
||||
context.lasttouch.cY = cY;
|
||||
}
|
||||
|
||||
mX = cX - context.lasttouch.cX;
|
||||
mY = cY - context.lasttouch.cY;
|
||||
|
||||
canvas.scroll({
|
||||
dx: mX,
|
||||
dy: mY
|
||||
});
|
||||
|
||||
context.lasttouch.cX = cX;
|
||||
context.lasttouch.cY = cY;
|
||||
}
|
||||
|
||||
if (context.scale) {
|
||||
var dist = euclideanDistance(orgEvent.touches[0], orgEvent.touches[1]);
|
||||
var distRatio = dist / context.start.dist;
|
||||
|
||||
zoom(distRatio * context.start.zoom, context.start.mid);
|
||||
context.lastDistance = dist;
|
||||
}
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function handleTouchEnd(event) {
|
||||
|
||||
var orgEvent = event.originalEvent;
|
||||
|
||||
if (orgEvent.touches.length < 1) {
|
||||
contextInit();
|
||||
}
|
||||
if (orgEvent.touches.length === 1) {
|
||||
initMove(orgEvent);
|
||||
}
|
||||
if (orgEvent.touches.length === 2) {
|
||||
initScale(orgEvent);
|
||||
}
|
||||
|
||||
_.forEach(orgEvent.changedTouches, function (touch) {
|
||||
delete context[touch.identifier];
|
||||
});
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function init(element) {
|
||||
|
||||
contextInit();
|
||||
|
||||
//--- general handlers
|
||||
$(element).on('touchstart', handleTouchStart);
|
||||
$(element).on('touchmove', handleTouchMove);
|
||||
$(document).on('touchend', handleTouchEnd);
|
||||
|
||||
|
||||
//--- snap handler
|
||||
|
||||
eventBus.on('shape.touchstart', function(event) {
|
||||
// ---
|
||||
// TODO must forwarded to touchstart???#
|
||||
handleTouchStart(event);
|
||||
});
|
||||
|
||||
eventBus.on('shape.touchend', function(event) {
|
||||
|
||||
if(event.touches.length !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if((Date.now() - context.lastTap.time) < DOUBLE_TAP_THRESHOLD) {
|
||||
eventBus.fire('shape.dbltap', event);
|
||||
}
|
||||
|
||||
context.lastTap.time = Date.now();
|
||||
});
|
||||
}
|
||||
|
||||
function cap(scale) {
|
||||
return Math.max(RANGE.min, Math.min(RANGE.max, scale));
|
||||
|
@ -27,139 +156,36 @@ function TouchInteraction(eventBus, canvas) {
|
|||
return dist;
|
||||
}
|
||||
|
||||
function init(element) {
|
||||
|
||||
function contextInit() {
|
||||
context = {
|
||||
start: {}
|
||||
function initMove(orgEvent) {
|
||||
context.move = true;
|
||||
context.moveId = orgEvent.touches[0].identifier;
|
||||
context.scale = false;
|
||||
if (!context.lasttouch) {
|
||||
context.lasttouch = {
|
||||
cX: undefined,
|
||||
cY: undefined,
|
||||
mX: 0,
|
||||
mY: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var context;
|
||||
contextInit();
|
||||
function initScale(orgEvent) {
|
||||
context.scale = true;
|
||||
context.start.dist = euclideanDistance(orgEvent.touches[0], orgEvent.touches[1]);
|
||||
context.lastDistance = context.start.dist;
|
||||
context.start.zoom = canvas.zoom();
|
||||
context.start.mid = {
|
||||
x: (orgEvent.touches[0].clientX + orgEvent.touches[1].clientX) / 2,
|
||||
y: (orgEvent.touches[0].clientY + orgEvent.touches[1].clientY) / 2
|
||||
};
|
||||
}
|
||||
|
||||
function handleTouchMove(event) {
|
||||
var orgEvent = event.originalEvent;
|
||||
var cX = 0;
|
||||
var cY = 0;
|
||||
var mX = 0;
|
||||
var mY = 0;
|
||||
|
||||
if (context.move && !context.scale) {
|
||||
|
||||
_.forEach(orgEvent.changedTouches, function (touch) {
|
||||
if (touch.identifier === context.moveId) {
|
||||
cX = touch.clientX;
|
||||
cY = touch.clientY;
|
||||
}
|
||||
});
|
||||
|
||||
if (!context.lasttouch.cX) {
|
||||
context.lasttouch.cX = cX;
|
||||
}
|
||||
|
||||
if (!context.lasttouch.cY) {
|
||||
context.lasttouch.cY = cY;
|
||||
}
|
||||
|
||||
mX = cX - context.lasttouch.cX;
|
||||
mY = cY - context.lasttouch.cY;
|
||||
|
||||
canvas.scroll({
|
||||
dx: mX,
|
||||
dy: mY
|
||||
});
|
||||
|
||||
context.lasttouch.cX = cX;
|
||||
context.lasttouch.cY = cY;
|
||||
}
|
||||
|
||||
if (context.scale) {
|
||||
var dist = euclideanDistance(orgEvent.touches[0], orgEvent.touches[1]);
|
||||
var distRatio = dist / context.start.dist;
|
||||
|
||||
zoom(distRatio * context.start.zoom, context.start.mid);
|
||||
context.lastDistance = dist;
|
||||
}
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function handleTouchEnd(event) {
|
||||
|
||||
var orgEvent = event.originalEvent;
|
||||
|
||||
if (orgEvent.touches.length < 1) {
|
||||
contextInit();
|
||||
}
|
||||
if (orgEvent.touches.length === 1) {
|
||||
initMove(orgEvent);
|
||||
}
|
||||
if (orgEvent.touches.length === 2) {
|
||||
initScale(orgEvent);
|
||||
}
|
||||
|
||||
_.forEach(orgEvent.changedTouches, function (touch) {
|
||||
delete context[touch.identifier];
|
||||
});
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function initMove(orgEvent) {
|
||||
context.move = true;
|
||||
context.moveId = orgEvent.touches[0].identifier;
|
||||
context.scale = false;
|
||||
if (!context.lasttouch) {
|
||||
context.lasttouch = {
|
||||
cX: undefined,
|
||||
cY: undefined,
|
||||
mX: 0,
|
||||
mY: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function initScale(orgEvent) {
|
||||
context.scale = true;
|
||||
context.start.dist = euclideanDistance(orgEvent.touches[0], orgEvent.touches[1]);
|
||||
context.lastDistance = context.start.dist;
|
||||
context.start.zoom = canvas.zoom();
|
||||
context.start.mid = {
|
||||
x: (orgEvent.touches[0].clientX + orgEvent.touches[1].clientX) / 2,
|
||||
y: (orgEvent.touches[0].clientY + orgEvent.touches[1].clientY) / 2
|
||||
};
|
||||
}
|
||||
|
||||
function handleTouchStart(event) {
|
||||
|
||||
var orgEvent = event.originalEvent;
|
||||
|
||||
_.forEach(orgEvent.changedTouches, function (touch) {
|
||||
context.start[touch.identifier] = touch;
|
||||
});
|
||||
|
||||
if (orgEvent.touches.length === 1) {
|
||||
initMove(orgEvent);
|
||||
}
|
||||
|
||||
if (orgEvent.touches.length === 2) {
|
||||
initScale(orgEvent);
|
||||
}
|
||||
|
||||
//Stop all interaction for more than 2 touch sources
|
||||
if (orgEvent.touches.length > 2) {
|
||||
contextInit();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
$(element).on('touchstart', handleTouchStart);
|
||||
$(element).on('touchmove', handleTouchMove);
|
||||
$(document).on('touchend', handleTouchEnd);
|
||||
function contextInit() {
|
||||
context = {
|
||||
start: {},
|
||||
lastTap: {}
|
||||
};
|
||||
}
|
||||
|
||||
eventBus.on('canvas.init', function(e) {
|
||||
|
@ -167,6 +193,6 @@ function TouchInteraction(eventBus, canvas) {
|
|||
});
|
||||
}
|
||||
|
||||
TouchInteraction.$inject = ['eventBus', 'canvas'];
|
||||
TouchInteraction.$inject = [ 'eventBus', 'canvas', 'touchFix' ];
|
||||
|
||||
module.exports = TouchInteraction;
|
|
@ -1,4 +1,7 @@
|
|||
module.exports = {
|
||||
__depends__: [
|
||||
require('diagram-js/lib/features/touch')
|
||||
],
|
||||
__init__: [ 'touchInteraction' ],
|
||||
touchInteraction: [ 'type', require('./TouchInteraction') ]
|
||||
};
|
|
@ -44,7 +44,7 @@ describe('features - label-editing', function() {
|
|||
}));
|
||||
|
||||
|
||||
it('should cancel on ESC', inject(function(elementRegistry, bpmnRegistry, directEditing, eventBus) {
|
||||
it('should cancel on <ESC>', inject(function(elementRegistry, bpmnRegistry, directEditing, eventBus) {
|
||||
|
||||
// given
|
||||
var shape = elementRegistry.getById('task-nested-embedded');
|
||||
|
@ -68,6 +68,31 @@ describe('features - label-editing', function() {
|
|||
expect(task.name).toBe(oldName);
|
||||
}));
|
||||
|
||||
|
||||
it('should submit on <canvas.click>', inject(function(elementRegistry, bpmnRegistry, directEditing, eventBus) {
|
||||
|
||||
// given
|
||||
var shape = elementRegistry.getById('task-nested-embedded');
|
||||
var task = bpmnRegistry.getSemantic('task-nested-embedded');
|
||||
|
||||
// activate
|
||||
eventBus.fire('shape.dblclick', { element: shape });
|
||||
|
||||
var newName = 'new value';
|
||||
|
||||
// a jQuery <textarea /> element
|
||||
var textarea = directEditing._textbox.textarea;
|
||||
|
||||
// when
|
||||
// change + <canvas.click>
|
||||
textarea.val(newName);
|
||||
eventBus.fire('canvas.click', {});
|
||||
|
||||
// then
|
||||
expect(directEditing.isActive()).toBe(false);
|
||||
expect(task.name).toBe(newName);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
|
||||
var Matchers = require('../../../Matchers'),
|
||||
TestHelper = require('../../../TestHelper');
|
||||
|
||||
/* global bootstrapBpmnJS, inject */
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var Modeler = require('../../../../../lib/Modeler');
|
||||
|
||||
var labelEditingModule = require('../../../../../lib/features/label-editing'),
|
||||
touchModule = require('diagram-js/lib/features/touch');
|
||||
|
||||
|
||||
describe('direct editing - touch integration', function() {
|
||||
|
||||
beforeEach(Matchers.add);
|
||||
|
||||
|
||||
var container;
|
||||
|
||||
beforeEach(function() {
|
||||
container = jasmine.getEnv().getTestContainer();
|
||||
});
|
||||
|
||||
|
||||
function createModeler(xml, done) {
|
||||
var modeler = new Modeler({ container: container });
|
||||
|
||||
modeler.importXML(xml, function(err) {
|
||||
done(err, modeler);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
it('should work on modeler (manual test)', function(done) {
|
||||
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
|
||||
createModeler(xml, done);
|
||||
});
|
||||
|
||||
|
||||
describe('event integration', function() {
|
||||
|
||||
var diagramXML = fs.readFileSync('test/fixtures/bpmn/features/label-editing/labels.bpmn', 'utf-8');
|
||||
|
||||
var testModules = [ labelEditingModule, touchModule ];
|
||||
|
||||
beforeEach(bootstrapBpmnJS(diagramXML, { modules: testModules }));
|
||||
|
||||
it('should work via dbltap (manual test)', function() { });
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue