fix(auto-resize): do not resize on lane create / resize lanes, too

Related to #263
This commit is contained in:
Nico Rehwaldt 2015-08-31 15:35:32 +02:00
parent afa72ad5bd
commit ede384b5ac
4 changed files with 298 additions and 187 deletions

View File

@ -65,32 +65,42 @@ function AutoResize(eventBus, canvas, modeling){
* @param {Shape} target
*/
function expand(shape, target) {
if (is(target, 'bpmn:Participant') && target === shape.parent) {
var inbounds = isInbounds(shape, target, PADDING);
var newBounds = pick(target, [ 'x', 'y', 'width', 'height' ]);
if (inbounds.top) {
var topPosition = shape.y - OFFSET_TOP;
assign(newBounds, { y: topPosition, height: target.height + target.y - topPosition });
}
if (inbounds.bottom) {
assign(newBounds, { height: shape.y + shape.height + OFFSET_BOTTOM - target.y });
}
if (inbounds.left) {
var leftPosition = shape.x - OFFSET_LEFT;
assign(newBounds, { x: leftPosition, width: target.width + target.x - leftPosition });
}
if (inbounds.right) {
assign(newBounds, { width: shape.x + shape.width + OFFSET_RIGHT - target.x });
}
modeling.resizeShape(target, newBounds);
if (is(shape, 'bpmn:Lane')) {
return;
}
if (!is(target, 'bpmn:Participant') && !is(target, 'bpmn:Lane')) {
return;
}
if (target !== shape.parent) {
return;
}
var inbounds = isInbounds(shape, target, PADDING);
var newBounds = pick(target, [ 'x', 'y', 'width', 'height' ]);
if (inbounds.top) {
var topPosition = shape.y - OFFSET_TOP;
assign(newBounds, { y: topPosition, height: target.height + target.y - topPosition });
}
if (inbounds.bottom) {
assign(newBounds, { height: shape.y + shape.height + OFFSET_BOTTOM - target.y });
}
if (inbounds.left) {
var leftPosition = shape.x - OFFSET_LEFT;
assign(newBounds, { x: leftPosition, width: target.width + target.x - leftPosition });
}
if (inbounds.right) {
assign(newBounds, { width: shape.x + shape.width + OFFSET_RIGHT - target.x });
}
modeling.resizeShape(target, newBounds);
}
}

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:collaboration id="Collaboration_1">
<bpmn:participant id="Participant_1" processRef="Process_1" />
</bpmn:collaboration>
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:laneSet>
<bpmn:lane id="Lane_1brtzvq">
<bpmn:childLaneSet xsi:type="bpmn:tLaneSet">
<bpmn:lane id="Lane_Nested" name="Lane_Nested">
<bpmn:flowNodeRef>StartEvent_1</bpmn:flowNodeRef>
<bpmn:flowNodeRef>Task_1</bpmn:flowNodeRef>
</bpmn:lane>
</bpmn:childLaneSet>
</bpmn:lane>
</bpmn:laneSet>
<bpmn:task id="Task_1">
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
</bpmn:task>
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="StartEvent_1" targetRef="Task_1" />
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1</bpmn:outgoing>
</bpmn:startEvent>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
<bpmndi:BPMNShape id="Participant_1_di" bpmnElement="Participant_1">
<dc:Bounds x="247" y="160" width="371" height="178" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
<dc:Bounds x="345" y="231" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="318" y="267" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1_di" bpmnElement="Task_1">
<dc:Bounds x="472" y="209" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1_di" bpmnElement="SequenceFlow_1">
<di:waypoint xsi:type="dc:Point" x="381" y="249" />
<di:waypoint xsi:type="dc:Point" x="472" y="249" />
<bpmndi:BPMNLabel>
<dc:Bounds x="370" y="239" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Lane_1brtzvq_di" bpmnElement="Lane_1brtzvq">
<dc:Bounds x="277" y="160" width="341" height="178" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_Nested_di" bpmnElement="Lane_Nested">
<dc:Bounds x="307" y="160" width="311" height="178" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -16,202 +16,249 @@ function getBounds(shape) {
return pick(shape, ['x', 'y', 'width', 'height']);
}
describe('features/auto-resize', function() {
var testModules = [coreModule, modelingModule, autoResizeModule, createModule ];
var diagramXML = require('./AutoResize.collaboration.bpmn');
var task,
participant,
startEvent,
expectedBounds;
describe('participant', function() {
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
var diagramXML = require('./AutoResize.participant.bpmn');
beforeEach(inject(function(elementRegistry) {
var task,
participant,
startEvent,
expectedBounds;
task = elementRegistry.get('Task_1');
participant = elementRegistry.get('Participant_1');
startEvent = elementRegistry.get('StartEvent_1');
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
expectedBounds = getBounds(participant);
beforeEach(inject(function(elementRegistry) {
expect(expectedBounds).to.eql({ x: 247, y: 160, width: 371, height: 178 });
task = elementRegistry.get('Task_1');
participant = elementRegistry.get('Participant_1');
startEvent = elementRegistry.get('StartEvent_1');
}));
expectedBounds = getBounds(participant);
describe('after moving', function() {
it('should expand the right edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 100, y: 0 }, participant);
// then
assign(expectedBounds, { width: 525 });
expect(getBounds(participant)).to.eql(expectedBounds);
expect(expectedBounds).to.eql({ x: 247, y: 160, width: 371, height: 178 });
}));
it('should expand the top edge of the parent collaboration',
inject(function(modeling) {
describe('after moving', function() {
it('should expand the right edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 100, y: 0 }, participant);
// then
assign(expectedBounds, { width: 525 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the top edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 0, y: -50 }, participant);
// then
assign(expectedBounds, { y: 79, height: 259 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the bottom edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 0, y: 50 }, participant);
// then
assign(expectedBounds, { height: 259 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the left edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([startEvent], { x: -100, y: 0 }, participant);
// then
assign(expectedBounds, { x: 122, width: 496 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the bottom right edges of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 50, y: 50 }, participant);
// then
assign(expectedBounds, { width: 475, height: 259 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the top left edges of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([startEvent], { x: -100, y: -100 }, participant);
// then
expect(getBounds(participant)).to.eql({ x: 122, y: 51, width: 496, height: 287 });
}));
it('should not resize the parent collaboration if element is placed too far outside',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 300, y: 0 }, participant);
// then
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should undo resizing', inject(function(modeling, commandStack) {
// when
modeling.moveElements([startEvent], { x: -100, y: -100 }, participant);
commandStack.undo();
// then
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should redo resizing', inject(function(modeling, commandStack) {
// when
modeling.moveElements([startEvent], { x: -100, y: -100 }, participant);
commandStack.undo();
commandStack.redo();
// then
expect(getBounds(participant)).to.eql({ x: 122, y: 51, width: 496, height: 287 });
}));
});
describe('after appending', function(){
it('should expand the bottom right edges of the parent collaboration',
inject(function(modeling) {
// when
modeling.appendShape(task, { type: 'bpmn:Task' }, { x: 660, y: 350 }, participant);
// then
assign(expectedBounds, { width: 563, height: 310 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should undo resizing', inject(function(modeling, commandStack) {
// given
modeling.appendShape(task, { type: 'bpmn:Task' }, { x: 660, y: 250 }, participant);
// when
commandStack.undo();
// then
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should redo resizing and restore shapes and connections',
inject(function(modeling, commandStack) {
// given
var task2 = modeling.appendShape(task, { type: 'bpmn:Task' }, { x: 660, y: 250 }, participant);
// when
commandStack.undo();
commandStack.redo();
// then
assign(expectedBounds, { width: 563 });
expect(getBounds(participant)).to.eql(expectedBounds);
expect(task2).to.be.defined;
expect(task.outgoing).not.to.be.empty;
expect(task2.incoming).not.to.be.empty;
}));
});
it('should not auto-resize when adding lane', inject(function(modeling) {
// given
var laneAttrs = {
type: 'bpmn:Lane',
width: 341,
height: 178
};
// when
modeling.moveElements([task], { x: 0, y: -50 }, participant);
// then
assign(expectedBounds, { y: 79, height: 259 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the bottom edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 0, y: 50 }, participant);
// then
assign(expectedBounds, { height: 259 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the left edge of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([startEvent], { x: -100, y: 0 }, participant);
// then
assign(expectedBounds, { x: 122, width: 496 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the bottom right edges of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 50, y: 50 }, participant);
// then
assign(expectedBounds, { width: 475, height: 259 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should expand the top left edges of the parent collaboration',
inject(function(modeling) {
// when
modeling.moveElements([startEvent], { x: -100, y: -100 }, participant);
// then
expect(getBounds(participant)).to.eql({ x: 122, y: 51, width: 496, height: 287 });
}));
it('should not resize the parent collaboration if element is placed too far outside',
inject(function(modeling) {
// when
modeling.moveElements([task], { x: 300, y: 0 }, participant);
modeling.createShape(laneAttrs, { x: 280, y: 200 }, participant);
// then
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should undo resizing', inject(function(modeling, commandStack) {
// when
modeling.moveElements([startEvent], { x: -100, y: -100 }, participant);
commandStack.undo();
// then
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should redo resizing', inject(function(modeling, commandStack) {
// when
modeling.moveElements([startEvent], { x: -100, y: -100 }, participant);
commandStack.undo();
commandStack.redo();
// then
expect(getBounds(participant)).to.eql({ x: 122, y: 51, width: 496, height: 287 });
}));
});
describe('after appending', function(){
describe('lane', function() {
var diagramXML = require('./AutoResize.lanes.bpmn');
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
it('should expand the bottom right edges of the parent collaboration',
inject(function(modeling) {
// when
modeling.appendShape(task, { type: 'bpmn:Task' }, { x: 660, y: 350 }, participant);
// then
assign(expectedBounds, { width: 563, height: 310 });
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should undo resizing', inject(function(modeling, commandStack) {
// given
modeling.appendShape(task, { type: 'bpmn:Task' }, { x: 660, y: 250 }, participant);
// when
commandStack.undo();
// then
expect(getBounds(participant)).to.eql(expectedBounds);
}));
it('should redo resizing and restore shapes and connections',
inject(function(modeling, commandStack) {
it('should auto-resize to fit new element', inject(function(elementRegistry, modeling) {
// given
var task2 = modeling.appendShape(task, { type: 'bpmn:Task' }, { x: 660, y: 250 }, participant);
var laneShape = elementRegistry.get('Lane_Nested');
// when
commandStack.undo();
commandStack.redo();
modeling.createShape({ type: 'bpmn:Task' }, { x: 600, y: 320 }, laneShape);
// then
assign(expectedBounds, { width: 563 });
expect(getBounds(participant)).to.eql(expectedBounds);
expect(task2).to.be.defined;
expect(task.outgoing).not.to.be.empty;
expect(task2.incoming).not.to.be.empty;
expect(getBounds(laneShape)).to.eql({ x: 307, y: 160, width: 443, height: 280});
}));
});