'use strict'; var inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'), getBusinessObject = require('../../../util/ModelUtil').getBusinessObject, is = require('../../../util/ModelUtil').is, computeChildrenBBox = require('diagram-js/lib/features/resize/ResizeUtil').computeChildrenBBox; var LOW_PRIORITY = 500; function ToggleElementCollapseBehaviour(eventBus, elementFactory, modeling, resize) { CommandInterceptor.call(this, eventBus); function hideEmptyLables(children) { if (children.length) { children.forEach(function(child) { if (child.type === 'label' && !child.businessObject.name) { child.hidden = true; } }); } } function expandedBounds(shape, defaultSize) { var children = shape.children, newBounds = defaultSize, visibleElements, visibleBBox; visibleElements = filterVisible(children).concat([ shape ]); visibleBBox = computeChildrenBBox(visibleElements); if (visibleBBox) { // center to visibleBBox with max(defaultSize, childrenBounds) newBounds.width = Math.max(visibleBBox.width, newBounds.width); newBounds.height = Math.max(visibleBBox.height, newBounds.height); newBounds.x = visibleBBox.x + (visibleBBox.width - newBounds.width) / 2; newBounds.y = visibleBBox.y + (visibleBBox.height - newBounds.height) / 2; } else { // center to collapsed shape with defaultSize newBounds.x = shape.x + (shape.width - newBounds.width) / 2; newBounds.y = shape.y + (shape.height - newBounds.height) / 2; } return newBounds; } function collapsedBounds(shape, defaultSize) { return { x: shape.x + (shape.width - defaultSize.width) / 2, y: shape.y + (shape.height - defaultSize.height) / 2, width: defaultSize.width, height: defaultSize.height }; } this.executed([ 'shape.toggleCollapse' ], LOW_PRIORITY, function(e) { var context = e.context, shape = context.shape; if (!is(shape, 'bpmn:SubProcess')) { return; } if (!shape.collapsed) { // all children got made visible through djs, hide empty labels hideEmptyLables(shape.children); // remove collapsed marker getBusinessObject(shape).di.isExpanded = true; } else { // place collapsed marker getBusinessObject(shape).di.isExpanded = false; } }); this.reverted([ 'shape.toggleCollapse' ], LOW_PRIORITY, function(e) { var context = e.context; var shape = context.shape; // revert removing/placing collapsed marker if (!shape.collapsed) { getBusinessObject(shape).di.isExpanded = true; } else { getBusinessObject(shape).di.isExpanded = false; } }); this.postExecuted([ 'shape.toggleCollapse' ], LOW_PRIORITY, function(e) { var shape = e.context.shape, defaultSize = elementFactory._getDefaultSize(shape), newBounds; if (shape.collapsed) { // resize to default size of collapsed shapes newBounds = collapsedBounds(shape, defaultSize); } else { // resize to bounds of max(visible children, defaultSize) newBounds = expandedBounds(shape, defaultSize); } modeling.resizeShape(shape, newBounds); }); } inherits(ToggleElementCollapseBehaviour, CommandInterceptor); ToggleElementCollapseBehaviour.$inject = [ 'eventBus', 'elementFactory', 'modeling' ]; module.exports = ToggleElementCollapseBehaviour; /////// helpers /////////////////////////// function filterVisible(elements) { return elements.filter(function(e) { return !e.hidden; }); }