123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- import {
- assign
- } from 'min-dash';
- import {
- getLabel
- } from './LabelUtil';
- import {
- getBusinessObject,
- is
- } from '../../util/ModelUtil';
- import {
- createCategoryValue
- } from '../modeling/behavior/util/CategoryUtil';
- import { isAny } from '../modeling/util/ModelingUtil';
- import { isExpanded } from '../../util/DiUtil';
- import {
- getExternalLabelMid,
- isLabelExternal,
- hasExternalLabel,
- isLabel
- } from '../../util/LabelUtil';
- export default function LabelEditingProvider(
- eventBus, bpmnFactory, canvas, directEditing,
- modeling, resizeHandles, textRenderer) {
- this._bpmnFactory = bpmnFactory;
- this._canvas = canvas;
- this._modeling = modeling;
- this._textRenderer = textRenderer;
- directEditing.registerProvider(this);
- // listen to dblclick on non-root elements
- eventBus.on('element.dblclick', function(event) {
- activateDirectEdit(event.element, true);
- });
- // complete on followup canvas operation
- eventBus.on([
- 'autoPlace.start',
- 'canvas.viewbox.changing',
- 'drag.init',
- 'element.mousedown',
- 'popupMenu.open'
- ], function(event) {
- if (directEditing.isActive()) {
- directEditing.complete();
- }
- });
- // cancel on command stack changes
- eventBus.on([ 'commandStack.changed' ], function(e) {
- if (directEditing.isActive()) {
- directEditing.cancel();
- }
- });
- eventBus.on('directEditing.activate', function(event) {
- resizeHandles.removeResizers();
- });
- eventBus.on('create.end', 500, function(event) {
- var context = event.context,
- element = context.shape,
- canExecute = event.context.canExecute,
- isTouch = event.isTouch;
- // TODO(nikku): we need to find a way to support the
- // direct editing on mobile devices; right now this will
- // break for desworkflowediting on mobile devices
- // as it breaks the user interaction workflow
- // TODO(nre): we should temporarily focus the edited element
- // here and release the focused viewport after the direct edit
- // operation is finished
- if (isTouch) {
- return;
- }
- if (!canExecute) {
- return;
- }
- if (context.hints && context.hints.createElementsBehavior === false) {
- return;
- }
- activateDirectEdit(element);
- });
- eventBus.on('autoPlace.end', 500, function(event) {
- activateDirectEdit(event.shape);
- });
- function activateDirectEdit(element, force) {
- if (force ||
- isAny(element, [ 'bpmn:Task', 'bpmn:TextAnnotation', 'bpmn:Group' ]) ||
- isCollapsedSubProcess(element)) {
- directEditing.activate(element);
- }
- }
- }
- LabelEditingProvider.$inject = [
- 'eventBus',
- 'bpmnFactory',
- 'canvas',
- 'directEditing',
- 'modeling',
- 'resizeHandles',
- 'textRenderer'
- ];
- /**
- * Activate direct editing for activities and text annotations.
- *
- * @param {djs.model.Base} element
- *
- * @return {Object} an object with properties bounds (position and size), text and options
- */
- LabelEditingProvider.prototype.activate = function(element) {
- // text
- var text = getLabel(element);
- if (text === undefined) {
- return;
- }
- var context = {
- text: text
- };
- // bounds
- var bounds = this.getEditingBBox(element);
- assign(context, bounds);
- var options = {};
- // tasks
- if (
- isAny(element, [
- 'bpmn:Task',
- 'bpmn:Participant',
- 'bpmn:Lane',
- 'bpmn:CallActivity'
- ]) ||
- isCollapsedSubProcess(element)
- ) {
- assign(options, {
- centerVertically: true
- });
- }
- // external labels
- if (isLabelExternal(element)) {
- assign(options, {
- autoResize: true
- });
- }
- // text annotations
- if (is(element, 'bpmn:TextAnnotation')) {
- assign(options, {
- resizable: true,
- autoResize: true
- });
- }
- assign(context, {
- options: options
- });
- return context;
- };
- /**
- * Get the editing bounding box based on the element's size and position
- *
- * @param {djs.model.Base} element
- *
- * @return {Object} an object containing information about position
- * and size (fixed or minimum and/or maximum)
- */
- LabelEditingProvider.prototype.getEditingBBox = function(element) {
- var canvas = this._canvas;
- var target = element.label || element;
- var bbox = canvas.getAbsoluteBBox(target);
- var mid = {
- x: bbox.x + bbox.width / 2,
- y: bbox.y + bbox.height / 2
- };
- // default position
- var bounds = { x: bbox.x, y: bbox.y };
- var zoom = canvas.zoom();
- var defaultStyle = this._textRenderer.getDefaultStyle(),
- externalStyle = this._textRenderer.getExternalStyle();
- // take zoom into account
- var externalFontSize = externalStyle.fontSize * zoom,
- externalLineHeight = externalStyle.lineHeight,
- defaultFontSize = defaultStyle.fontSize * zoom,
- defaultLineHeight = defaultStyle.lineHeight;
- var style = {
- fontFamily: this._textRenderer.getDefaultStyle().fontFamily,
- fontWeight: this._textRenderer.getDefaultStyle().fontWeight
- };
- // adjust for expanded pools AND lanes
- if (is(element, 'bpmn:Lane') || isExpandedPool(element)) {
- assign(bounds, {
- width: bbox.height,
- height: 30 * zoom,
- x: bbox.x - bbox.height / 2 + (15 * zoom),
- y: mid.y - (30 * zoom) / 2
- });
- assign(style, {
- fontSize: defaultFontSize + 'px',
- lineHeight: defaultLineHeight,
- paddingTop: (7 * zoom) + 'px',
- paddingBottom: (7 * zoom) + 'px',
- paddingLeft: (5 * zoom) + 'px',
- paddingRight: (5 * zoom) + 'px',
- transform: 'rotate(-90deg)'
- });
- }
- // internal labels for tasks and collapsed call activities,
- // sub processes and participants
- if (isAny(element, [ 'bpmn:Task', 'bpmn:CallActivity']) ||
- isCollapsedPool(element) ||
- isCollapsedSubProcess(element)) {
- assign(bounds, {
- width: bbox.width,
- height: bbox.height
- });
- assign(style, {
- fontSize: defaultFontSize + 'px',
- lineHeight: defaultLineHeight,
- paddingTop: (7 * zoom) + 'px',
- paddingBottom: (7 * zoom) + 'px',
- paddingLeft: (5 * zoom) + 'px',
- paddingRight: (5 * zoom) + 'px'
- });
- }
- // internal labels for expanded sub processes
- if (isExpandedSubProcess(element)) {
- assign(bounds, {
- width: bbox.width,
- x: bbox.x
- });
- assign(style, {
- fontSize: defaultFontSize + 'px',
- lineHeight: defaultLineHeight,
- paddingTop: (7 * zoom) + 'px',
- paddingBottom: (7 * zoom) + 'px',
- paddingLeft: (5 * zoom) + 'px',
- paddingRight: (5 * zoom) + 'px'
- });
- }
- var width = 90 * zoom,
- paddingTop = 7 * zoom,
- paddingBottom = 4 * zoom;
- // external labels for events, data elements, gateways, groups and connections
- if (target.labelTarget) {
- assign(bounds, {
- width: width,
- height: bbox.height + paddingTop + paddingBottom,
- x: mid.x - width / 2,
- y: bbox.y - paddingTop
- });
- assign(style, {
- fontSize: externalFontSize + 'px',
- lineHeight: externalLineHeight,
- paddingTop: paddingTop + 'px',
- paddingBottom: paddingBottom + 'px'
- });
- }
- // external label not yet created
- if (isLabelExternal(target)
- && !hasExternalLabel(target)
- && !isLabel(target)) {
- var externalLabelMid = getExternalLabelMid(element);
- var absoluteBBox = canvas.getAbsoluteBBox({
- x: externalLabelMid.x,
- y: externalLabelMid.y,
- width: 0,
- height: 0
- });
- var height = externalFontSize + paddingTop + paddingBottom;
- assign(bounds, {
- width: width,
- height: height,
- x: absoluteBBox.x - width / 2,
- y: absoluteBBox.y - height / 2
- });
- assign(style, {
- fontSize: externalFontSize + 'px',
- lineHeight: externalLineHeight,
- paddingTop: paddingTop + 'px',
- paddingBottom: paddingBottom + 'px'
- });
- }
- // text annotations
- if (is(element, 'bpmn:TextAnnotation')) {
- assign(bounds, {
- width: bbox.width,
- height: bbox.height,
- minWidth: 30 * zoom,
- minHeight: 10 * zoom
- });
- assign(style, {
- textAlign: 'left',
- paddingTop: (5 * zoom) + 'px',
- paddingBottom: (7 * zoom) + 'px',
- paddingLeft: (7 * zoom) + 'px',
- paddingRight: (5 * zoom) + 'px',
- fontSize: defaultFontSize + 'px',
- lineHeight: defaultLineHeight
- });
- }
- return { bounds: bounds, style: style };
- };
- LabelEditingProvider.prototype.update = function(
- element, newLabel,
- activeContextText, bounds) {
- var newBounds,
- bbox;
- if (is(element, 'bpmn:TextAnnotation')) {
- bbox = this._canvas.getAbsoluteBBox(element);
- newBounds = {
- x: element.x,
- y: element.y,
- width: element.width / bbox.width * bounds.width,
- height: element.height / bbox.height * bounds.height
- };
- }
- if (is(element, 'bpmn:Group')) {
- var businessObject = getBusinessObject(element);
- // initialize categoryValue if not existing
- if (!businessObject.categoryValueRef) {
- var rootElement = this._canvas.getRootElement(),
- definitions = getBusinessObject(rootElement).$parent;
- var categoryValue = createCategoryValue(definitions, this._bpmnFactory);
- getBusinessObject(element).categoryValueRef = categoryValue;
- }
- }
- if (isEmptyText(newLabel)) {
- newLabel = null;
- }
- this._modeling.updateLabel(element, newLabel, newBounds);
- };
- // helpers //////////////////////
- function isCollapsedSubProcess(element) {
- return is(element, 'bpmn:SubProcess') && !isExpanded(element);
- }
- function isExpandedSubProcess(element) {
- return is(element, 'bpmn:SubProcess') && isExpanded(element);
- }
- function isCollapsedPool(element) {
- return is(element, 'bpmn:Participant') && !isExpanded(element);
- }
- function isExpandedPool(element) {
- return is(element, 'bpmn:Participant') && isExpanded(element);
- }
- function isEmptyText(label) {
- return !label || !label.trim();
- }
|