You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
5.4 KiB
242 lines
5.4 KiB
import { |
|
reduce, |
|
keys, |
|
forEach, |
|
assign |
|
} from 'min-dash'; |
|
|
|
import { |
|
getBusinessObject, |
|
getDi |
|
} from '../../../util/ModelUtil'; |
|
|
|
var DEFAULT_FLOW = 'default', |
|
ID = 'id', |
|
DI = 'di'; |
|
|
|
var NULL_DIMENSIONS = { |
|
width: 0, |
|
height: 0 |
|
}; |
|
|
|
/** |
|
* A handler that implements a BPMN 2.0 property update. |
|
* |
|
* This should be used to set simple properties on elements with |
|
* an underlying BPMN business object. |
|
* |
|
* Use respective diagram-js provided handlers if you would |
|
* like to perform automated modeling. |
|
*/ |
|
export default function UpdatePropertiesHandler( |
|
elementRegistry, moddle, translate, |
|
modeling, textRenderer) { |
|
|
|
this._elementRegistry = elementRegistry; |
|
this._moddle = moddle; |
|
this._translate = translate; |
|
this._modeling = modeling; |
|
this._textRenderer = textRenderer; |
|
} |
|
|
|
UpdatePropertiesHandler.$inject = [ |
|
'elementRegistry', |
|
'moddle', |
|
'translate', |
|
'modeling', |
|
'textRenderer' |
|
]; |
|
|
|
|
|
// api ////////////////////// |
|
|
|
/** |
|
* Updates a BPMN element with a list of new properties |
|
* |
|
* @param {Object} context |
|
* @param {djs.model.Base} context.element the element to update |
|
* @param {Object} context.properties a list of properties to set on the element's |
|
* businessObject (the BPMN model element) |
|
* |
|
* @return {Array<djs.model.Base>} the updated element |
|
*/ |
|
UpdatePropertiesHandler.prototype.execute = function(context) { |
|
|
|
var element = context.element, |
|
changed = [ element ], |
|
translate = this._translate; |
|
|
|
if (!element) { |
|
throw new Error(translate('element required')); |
|
} |
|
|
|
var elementRegistry = this._elementRegistry, |
|
ids = this._moddle.ids; |
|
|
|
var businessObject = element.businessObject, |
|
properties = unwrapBusinessObjects(context.properties), |
|
oldProperties = context.oldProperties || getProperties(element, properties); |
|
|
|
if (isIdChange(properties, businessObject)) { |
|
ids.unclaim(businessObject[ID]); |
|
|
|
elementRegistry.updateId(element, properties[ID]); |
|
|
|
ids.claim(properties[ID], businessObject); |
|
} |
|
|
|
// correctly indicate visual changes on default flow updates |
|
if (DEFAULT_FLOW in properties) { |
|
|
|
if (properties[DEFAULT_FLOW]) { |
|
changed.push(elementRegistry.get(properties[DEFAULT_FLOW].id)); |
|
} |
|
|
|
if (businessObject[DEFAULT_FLOW]) { |
|
changed.push(elementRegistry.get(businessObject[DEFAULT_FLOW].id)); |
|
} |
|
} |
|
|
|
// update properties |
|
setProperties(element, properties); |
|
|
|
// store old values |
|
context.oldProperties = oldProperties; |
|
context.changed = changed; |
|
|
|
// indicate changed on objects affected by the update |
|
return changed; |
|
}; |
|
|
|
|
|
UpdatePropertiesHandler.prototype.postExecute = function(context) { |
|
var element = context.element, |
|
label = element.label; |
|
|
|
var text = label && getBusinessObject(label).name; |
|
|
|
if (!text) { |
|
return; |
|
} |
|
|
|
// get layouted text bounds and resize external |
|
// external label accordingly |
|
var newLabelBounds = this._textRenderer.getExternalLabelBounds(label, text); |
|
|
|
this._modeling.resizeShape(label, newLabelBounds, NULL_DIMENSIONS); |
|
}; |
|
|
|
/** |
|
* Reverts the update on a BPMN elements properties. |
|
* |
|
* @param {Object} context |
|
* |
|
* @return {djs.model.Base} the updated element |
|
*/ |
|
UpdatePropertiesHandler.prototype.revert = function(context) { |
|
|
|
var element = context.element, |
|
properties = context.properties, |
|
oldProperties = context.oldProperties, |
|
businessObject = element.businessObject, |
|
elementRegistry = this._elementRegistry, |
|
ids = this._moddle.ids; |
|
|
|
// update properties |
|
setProperties(element, oldProperties); |
|
|
|
if (isIdChange(properties, businessObject)) { |
|
ids.unclaim(properties[ID]); |
|
|
|
elementRegistry.updateId(element, oldProperties[ID]); |
|
|
|
ids.claim(oldProperties[ID], businessObject); |
|
} |
|
|
|
return context.changed; |
|
}; |
|
|
|
|
|
function isIdChange(properties, businessObject) { |
|
return ID in properties && properties[ID] !== businessObject[ID]; |
|
} |
|
|
|
|
|
function getProperties(element, properties) { |
|
var propertyNames = keys(properties), |
|
businessObject = element.businessObject, |
|
di = getDi(element); |
|
|
|
return reduce(propertyNames, function(result, key) { |
|
|
|
// handle DI separately |
|
if (key !== DI) { |
|
result[key] = businessObject.get(key); |
|
|
|
} else { |
|
result[key] = getDiProperties(di, keys(properties.di)); |
|
} |
|
|
|
return result; |
|
}, {}); |
|
} |
|
|
|
|
|
function getDiProperties(di, propertyNames) { |
|
return reduce(propertyNames, function(result, key) { |
|
result[key] = di && di.get(key); |
|
|
|
return result; |
|
}, {}); |
|
} |
|
|
|
|
|
function setProperties(element, properties) { |
|
var businessObject = element.businessObject, |
|
di = getDi(element); |
|
|
|
forEach(properties, function(value, key) { |
|
|
|
if (key !== DI) { |
|
businessObject.set(key, value); |
|
} else { |
|
|
|
// only update, if di exists |
|
if (di) { |
|
setDiProperties(di, value); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
|
|
function setDiProperties(di, properties) { |
|
forEach(properties, function(value, key) { |
|
di.set(key, value); |
|
}); |
|
} |
|
|
|
|
|
var referencePropertyNames = [ 'default' ]; |
|
|
|
/** |
|
* Make sure we unwrap the actual business object |
|
* behind diagram element that may have been |
|
* passed as arguments. |
|
* |
|
* @param {Object} properties |
|
* |
|
* @return {Object} unwrappedProps |
|
*/ |
|
function unwrapBusinessObjects(properties) { |
|
|
|
var unwrappedProps = assign({}, properties); |
|
|
|
referencePropertyNames.forEach(function(name) { |
|
if (name in properties) { |
|
unwrappedProps[name] = getBusinessObject(unwrappedProps[name]); |
|
} |
|
}); |
|
|
|
return unwrappedProps; |
|
} |