123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- import {
- flatten,
- forEach,
- filter,
- find,
- groupBy,
- map,
- matchPattern,
- size
- } from 'min-dash';
- import {
- selfAndAllChildren
- } from '../../util/Elements';
- import {
- append as svgAppend,
- attr as svgAttr,
- clear as svgClear,
- create as svgCreate
- } from 'tiny-svg';
- import { translate } from '../../util/SvgTransformUtil';
- var LOW_PRIORITY = 499;
- var MARKER_DRAGGING = 'djs-dragging',
- MARKER_OK = 'drop-ok',
- MARKER_NOT_OK = 'drop-not-ok',
- MARKER_NEW_PARENT = 'new-parent',
- MARKER_ATTACH = 'attach-ok';
- /**
- * Provides previews for moving shapes when moving.
- *
- * @param {EventBus} eventBus
- * @param {ElementRegistry} elementRegistry
- * @param {Canvas} canvas
- * @param {Styles} styles
- */
- export default function MovePreview(
- eventBus, elementRegistry, canvas,
- styles, previewSupport) {
- function getVisualDragShapes(shapes) {
- var elements = getAllDraggedElements(shapes);
- var filteredElements = removeEdges(elements);
- return filteredElements;
- }
- function getAllDraggedElements(shapes) {
- var allShapes = selfAndAllChildren(shapes, true);
- var allConnections = map(allShapes, function(shape) {
- return (shape.incoming || []).concat(shape.outgoing || []);
- });
- return flatten(allShapes.concat(allConnections));
- }
- /**
- * Sets drop marker on an element.
- */
- function setMarker(element, marker) {
- [ MARKER_ATTACH, MARKER_OK, MARKER_NOT_OK, MARKER_NEW_PARENT ].forEach(function(m) {
- if (m === marker) {
- canvas.addMarker(element, m);
- } else {
- canvas.removeMarker(element, m);
- }
- });
- }
- /**
- * Make an element draggable.
- *
- * @param {Object} context
- * @param {djs.model.Base} element
- * @param {Boolean} addMarker
- */
- function makeDraggable(context, element, addMarker) {
- previewSupport.addDragger(element, context.dragGroup);
- if (addMarker) {
- canvas.addMarker(element, MARKER_DRAGGING);
- }
- if (context.allDraggedElements) {
- context.allDraggedElements.push(element);
- } else {
- context.allDraggedElements = [ element ];
- }
- }
- // assign a low priority to this handler
- // to let others modify the move context before
- // we draw things
- eventBus.on('shape.move.start', LOW_PRIORITY, function(event) {
- var context = event.context,
- dragShapes = context.shapes,
- allDraggedElements = context.allDraggedElements;
- var visuallyDraggedShapes = getVisualDragShapes(dragShapes);
- if (!context.dragGroup) {
- var dragGroup = svgCreate('g');
- svgAttr(dragGroup, styles.cls('djs-drag-group', [ 'no-events' ]));
- var defaultLayer = canvas.getDefaultLayer();
- svgAppend(defaultLayer, dragGroup);
- context.dragGroup = dragGroup;
- }
- // add previews
- visuallyDraggedShapes.forEach(function(shape) {
- previewSupport.addDragger(shape, context.dragGroup);
- });
- // cache all dragged elements / gfx
- // so that we can quickly undo their state changes later
- if (!allDraggedElements) {
- allDraggedElements = getAllDraggedElements(dragShapes);
- } else {
- allDraggedElements = flatten([
- allDraggedElements,
- getAllDraggedElements(dragShapes)
- ]);
- }
- // add dragging marker
- forEach(allDraggedElements, function(e) {
- canvas.addMarker(e, MARKER_DRAGGING);
- });
- context.allDraggedElements = allDraggedElements;
- // determine, if any of the dragged elements have different parents
- context.differentParents = haveDifferentParents(dragShapes);
- });
- // update previews
- eventBus.on('shape.move.move', LOW_PRIORITY, function(event) {
- var context = event.context,
- dragGroup = context.dragGroup,
- target = context.target,
- parent = context.shape.parent,
- canExecute = context.canExecute;
- if (target) {
- if (canExecute === 'attach') {
- setMarker(target, MARKER_ATTACH);
- } else if (context.canExecute && target && target.id !== parent.id) {
- setMarker(target, MARKER_NEW_PARENT);
- } else {
- setMarker(target, context.canExecute ? MARKER_OK : MARKER_NOT_OK);
- }
- }
- translate(dragGroup, event.dx, event.dy);
- });
- eventBus.on([ 'shape.move.out', 'shape.move.cleanup' ], function(event) {
- var context = event.context,
- target = context.target;
- if (target) {
- setMarker(target, null);
- }
- });
- // remove previews
- eventBus.on('shape.move.cleanup', function(event) {
- var context = event.context,
- allDraggedElements = context.allDraggedElements,
- dragGroup = context.dragGroup;
- // remove dragging marker
- forEach(allDraggedElements, function(e) {
- canvas.removeMarker(e, MARKER_DRAGGING);
- });
- if (dragGroup) {
- svgClear(dragGroup);
- }
- });
- // API //////////////////////
- /**
- * Make an element draggable.
- *
- * @param {Object} context
- * @param {djs.model.Base} element
- * @param {Boolean} addMarker
- */
- this.makeDraggable = makeDraggable;
- }
- MovePreview.$inject = [
- 'eventBus',
- 'elementRegistry',
- 'canvas',
- 'styles',
- 'previewSupport'
- ];
- // helpers //////////////////////
- /**
- * returns elements minus all connections
- * where source or target is not elements
- */
- function removeEdges(elements) {
- var filteredElements = filter(elements, function(element) {
- if (!isConnection(element)) {
- return true;
- } else {
- return (
- find(elements, matchPattern({ id: element.source.id })) &&
- find(elements, matchPattern({ id: element.target.id }))
- );
- }
- });
- return filteredElements;
- }
- function haveDifferentParents(elements) {
- return size(groupBy(elements, function(e) { return e.parent && e.parent.id; })) !== 1;
- }
- /**
- * Checks if an element is a connection.
- */
- function isConnection(element) {
- return element.waypoints;
- }
|