-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(bpmn-snapping): seperate snapping into create/move and connect
* move create/move snapping to BpmnCreateMoveSnapping * move connect snapping to BpmnConnectSnapping * refactor tests Related camunda/camunda-modeler#1290
- Loading branch information
1 parent
3f42925
commit 94310f7
Showing
16 changed files
with
987 additions
and
1,468 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { | ||
mid, | ||
setSnapped | ||
} from 'diagram-js/lib/features/snapping/SnapUtil'; | ||
|
||
import { isCmd } from 'diagram-js/lib/features/keyboard/KeyboardUtil'; | ||
|
||
import { is } from '../../util/ModelUtil'; | ||
|
||
import { some } from 'min-dash'; | ||
|
||
var HIGHER_PRIORITY = 1250; | ||
|
||
|
||
/** | ||
* Snap during connect. | ||
* | ||
* @param {EventBus} eventBus | ||
* @param {Rules} rules | ||
*/ | ||
export default function BpmnConnectSnapping(eventBus, rules) { | ||
eventBus.on([ | ||
'connect.hover', | ||
'connect.move', | ||
'connect.end', | ||
], HIGHER_PRIORITY, function(event) { | ||
var context = event.context, | ||
source = context.source, | ||
target = context.target; | ||
|
||
if (event.originalEvent && isCmd(event.originalEvent)) { | ||
return; | ||
} | ||
|
||
if (!context.initialSourcePosition) { | ||
context.initialSourcePosition = context.sourcePosition; | ||
} | ||
|
||
var connectionAttrs = rules.allowed('connection.create', { | ||
source: source, | ||
target: target | ||
}); | ||
|
||
if (target && isAnyType(connectionAttrs, [ | ||
'bpmn:Association', | ||
'bpmn:DataInputAssociation', | ||
'bpmn:DataOutputAssociation', | ||
'bpmn:SequenceFlow' | ||
])) { | ||
|
||
// snap source | ||
context.sourcePosition = mid(source); | ||
|
||
// snap target | ||
snapToPosition(event, mid(target)); | ||
} else if (isType(connectionAttrs, 'bpmn:MessageFlow')) { | ||
|
||
if (is(source, 'bpmn:Event')) { | ||
|
||
// snap source | ||
context.sourcePosition = mid(source); | ||
} | ||
|
||
if (is(target, 'bpmn:Event')) { | ||
|
||
// snap target | ||
snapToPosition(event, mid(target)); | ||
} | ||
|
||
} else { | ||
|
||
// un-snap source | ||
context.sourcePosition = context.initialSourcePosition; | ||
} | ||
}); | ||
} | ||
|
||
BpmnConnectSnapping.$inject = [ | ||
'eventBus', | ||
'rules' | ||
]; | ||
|
||
// helpers ////////// | ||
|
||
function snapToPosition(event, position) { | ||
setSnapped(event, 'x', position.x); | ||
setSnapped(event, 'y', position.y); | ||
} | ||
|
||
function isType(attrs, type) { | ||
return attrs && attrs.type === type; | ||
} | ||
|
||
function isAnyType(attrs, types) { | ||
return some(types, function(type) { | ||
return isType(attrs, type); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import inherits from 'inherits'; | ||
|
||
import CreateMoveSnapping from 'diagram-js/lib/features/snapping/CreateMoveSnapping'; | ||
|
||
import { | ||
isSnapped, | ||
setSnapped, | ||
} from 'diagram-js/lib/features/snapping/SnapUtil'; | ||
|
||
import { is } from '../../util/ModelUtil'; | ||
|
||
import { asTRBL } from 'diagram-js/lib/layout/LayoutUtil'; | ||
|
||
import { getBoundaryAttachment } from './BpmnSnappingUtil'; | ||
|
||
var HIGH_PRIORITY = 1500; | ||
|
||
|
||
/** | ||
* Snap during create and move. | ||
* | ||
* @param {BpmnRules} bpmnRules | ||
* @param {EventBus} eventBus | ||
* @param {Injector} injector | ||
*/ | ||
export default function BpmnCreateMoveSnapping(bpmnRules, eventBus, injector) { | ||
injector.invoke(CreateMoveSnapping, this); | ||
|
||
// creating first participant | ||
eventBus.on([ 'create.move', 'create.end' ], HIGH_PRIORITY, setSnappedIfConstrained); | ||
|
||
function canAttach(shape, target, position) { | ||
return bpmnRules.canAttach([ shape ], target, null, position) === 'attach'; | ||
} | ||
|
||
// snap boundary events | ||
eventBus.on([ | ||
'create.move', | ||
'create.end', | ||
'shape.move.move', | ||
'shape.move.end' | ||
], HIGH_PRIORITY, function(event) { | ||
var context = event.context, | ||
target = context.target, | ||
shape = context.shape; | ||
|
||
if (target && canAttach(shape, target, event) && !isSnapped(event)) { | ||
snapBoundaryEvent(event, target); | ||
} | ||
}); | ||
} | ||
|
||
inherits(BpmnCreateMoveSnapping, CreateMoveSnapping); | ||
|
||
BpmnCreateMoveSnapping.$inject = [ | ||
'bpmnRules', | ||
'eventBus', | ||
'injector' | ||
]; | ||
|
||
BpmnCreateMoveSnapping.prototype.initSnap = function(event) { | ||
var snapContext = CreateMoveSnapping.prototype.initSnap.call(this, event); | ||
|
||
var shape = event.shape; | ||
|
||
if (is(shape, 'bpmn:Participant')) { | ||
|
||
// snap to borders with higher priority | ||
snapContext.setSnapLocations([ 'top-left', 'bottom-right', 'mid' ]); | ||
} | ||
|
||
return snapContext; | ||
}; | ||
|
||
BpmnCreateMoveSnapping.prototype.addSnapTargetPoints = function(snapPoints, shape, target) { | ||
CreateMoveSnapping.prototype.addSnapTargetPoints.call(this, snapPoints, shape, target); | ||
|
||
// add sequence flow parents as snap targets | ||
if (is(target, 'bpmn:SequenceFlow')) { | ||
snapPoints = this.addSnapTargetPoints(snapPoints, shape, target.parent); | ||
} | ||
|
||
return snapPoints; | ||
}; | ||
|
||
BpmnCreateMoveSnapping.prototype.getSnapTargets = function(shape, target) { | ||
return CreateMoveSnapping.prototype.getSnapTargets.call(this, shape, target) | ||
.filter(function(snapTarget) { | ||
|
||
// do not snap to lanes | ||
return !is(snapTarget, 'bpmn:Lane'); | ||
}); | ||
}; | ||
|
||
// helpers ////////// | ||
|
||
function snapBoundaryEvent(event, target) { | ||
var targetTRBL = asTRBL(target); | ||
|
||
var direction = getBoundaryAttachment(event, target); | ||
|
||
if (/top/.test(direction)) { | ||
setSnapped(event, 'y', targetTRBL.top); | ||
} else | ||
if (/bottom/.test(direction)) { | ||
setSnapped(event, 'y', targetTRBL.bottom); | ||
} | ||
|
||
if (/left/.test(direction)) { | ||
setSnapped(event, 'x', targetTRBL.left); | ||
} else | ||
if (/right/.test(direction)) { | ||
setSnapped(event, 'x', targetTRBL.right); | ||
} | ||
} | ||
|
||
function setSnappedIfConstrained(event) { | ||
var context = event.context, | ||
createConstraints = context.createConstraints; | ||
|
||
if (!createConstraints) { | ||
return; | ||
} | ||
|
||
var top = createConstraints.top, | ||
right = createConstraints.right, | ||
bottom = createConstraints.bottom, | ||
left = createConstraints.left; | ||
|
||
if ((left && left >= event.x) || (right && right <= event.x)) { | ||
setSnapped(event, 'x', event.x); | ||
} | ||
|
||
if ((top && top >= event.y) || (bottom && bottom <= event.y)) { | ||
setSnapped(event, 'y', event.y); | ||
} | ||
} |
Oops, something went wrong.