This commit is contained in:
hanjian
2024-08-14 15:17:51 +08:00
parent 20a221c1a2
commit b610f94b2e
3483 changed files with 650965 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import {
is,
getBusinessObject
} from './ModelUtil';
import {
forEach
} from 'min-dash';
export function isExpanded(element) {
if (is(element, 'bpmn:CallActivity')) {
return false;
}
if (is(element, 'bpmn:SubProcess')) {
return !!getBusinessObject(element).di.isExpanded;
}
if (is(element, 'bpmn:Participant')) {
return !!getBusinessObject(element).processRef;
}
return true;
}
export function isInterrupting(element) {
return element && getBusinessObject(element).isInterrupting !== false;
}
export function isEventSubProcess(element) {
return element && !!getBusinessObject(element).triggeredByEvent;
}
export function hasEventDefinition(element, eventType) {
var bo = getBusinessObject(element),
hasEventDefinition = false;
if (bo.eventDefinitions) {
forEach(bo.eventDefinitions, function(event) {
if (is(event, eventType)) {
hasEventDefinition = true;
}
});
}
return hasEventDefinition;
}
export function hasErrorEventDefinition(element) {
return hasEventDefinition(element, 'bpmn:ErrorEventDefinition');
}
export function hasEscalationEventDefinition(element) {
return hasEventDefinition(element, 'bpmn:EscalationEventDefinition');
}
export function hasCompensateEventDefinition(element) {
return hasEventDefinition(element, 'bpmn:CompensateEventDefinition');
}

View File

@@ -0,0 +1,167 @@
import {
assign
} from 'min-dash';
import { is } from './ModelUtil';
export var DEFAULT_LABEL_SIZE = {
width: 90,
height: 20
};
export var FLOW_LABEL_INDENT = 15;
/**
* Returns true if the given semantic has an external label
*
* @param {BpmnElement} semantic
* @return {Boolean} true if has label
*/
export function isLabelExternal(semantic) {
return is(semantic, 'bpmn:Event') ||
is(semantic, 'bpmn:Gateway') ||
is(semantic, 'bpmn:DataStoreReference') ||
is(semantic, 'bpmn:DataObjectReference') ||
is(semantic, 'bpmn:DataInput') ||
is(semantic, 'bpmn:DataOutput') ||
is(semantic, 'bpmn:SequenceFlow') ||
is(semantic, 'bpmn:MessageFlow') ||
is(semantic, 'bpmn:Group');
}
/**
* Returns true if the given element has an external label
*
* @param {djs.model.shape} element
* @return {Boolean} true if has label
*/
export function hasExternalLabel(element) {
return isLabel(element.label);
}
/**
* Get the position for sequence flow labels
*
* @param {Array<Point>} waypoints
* @return {Point} the label position
*/
export function getFlowLabelPosition(waypoints) {
// get the waypoints mid
var mid = waypoints.length / 2 - 1;
var first = waypoints[Math.floor(mid)];
var second = waypoints[Math.ceil(mid + 0.01)];
// get position
var position = getWaypointsMid(waypoints);
// calculate angle
var angle = Math.atan((second.y - first.y) / (second.x - first.x));
var x = position.x,
y = position.y;
if (Math.abs(angle) < Math.PI / 2) {
y -= FLOW_LABEL_INDENT;
} else {
x += FLOW_LABEL_INDENT;
}
return { x: x, y: y };
}
/**
* Get the middle of a number of waypoints
*
* @param {Array<Point>} waypoints
* @return {Point} the mid point
*/
export function getWaypointsMid(waypoints) {
var mid = waypoints.length / 2 - 1;
var first = waypoints[Math.floor(mid)];
var second = waypoints[Math.ceil(mid + 0.01)];
return {
x: first.x + (second.x - first.x) / 2,
y: first.y + (second.y - first.y) / 2
};
}
export function getExternalLabelMid(element) {
if (element.waypoints) {
return getFlowLabelPosition(element.waypoints);
} else if (is(element, 'bpmn:Group')) {
return {
x: element.x + element.width / 2,
y: element.y + DEFAULT_LABEL_SIZE.height / 2
};
} else {
return {
x: element.x + element.width / 2,
y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2
};
}
}
/**
* Returns the bounds of an elements label, parsed from the elements DI or
* generated from its bounds.
*
* @param {BpmnElement} semantic
* @param {djs.model.Base} element
*/
export function getExternalLabelBounds(semantic, element) {
var mid,
size,
bounds,
di = semantic.di,
label = di.label;
if (label && label.bounds) {
bounds = label.bounds;
let obj = label.$parent.waypoint;
if(bounds.x == 0 && bounds.y == 0){
let x = 0;
let y =0;
if(obj.length>1){
x = (obj[obj.length-2].x+ obj[obj.length-1].x)/2;
y = (obj[obj.length-2].y+ obj[obj.length-1].y)/2;
}
bounds.x=x;
bounds.y=y;
}
size = {
width: Math.max(DEFAULT_LABEL_SIZE.width, bounds.width),
height: bounds.height
};
mid = {
x: bounds.x + bounds.width / 2,
y: bounds.y + bounds.height / 2
};
} else {
mid = getExternalLabelMid(element);
size = DEFAULT_LABEL_SIZE;
}
return assign({
x: mid.x - size.width / 2,
y: mid.y - size.height / 2
}, size);
}
export function isLabel(element) {
return element && !!element.labelTarget;
}

View File

@@ -0,0 +1,25 @@
/**
* Is an element of the given BPMN type?
*
* @param {djs.model.Base|ModdleElement} element
* @param {String} type
*
* @return {Boolean}
*/
export function is(element, type) {
var bo = getBusinessObject(element);
return bo && (typeof bo.$instanceOf === 'function') && bo.$instanceOf(type);
}
/**
* Return the business object for a given element.
*
* @param {djs.model.Base|ModdleElement} element
*
* @return {ModdleElement}
*/
export function getBusinessObject(element) {
return (element && element.businessObject) || element;
}

View File

@@ -0,0 +1,80 @@
/**
* This file must not be changed or exchanged.
*
* @see http://bpmn.io/license for more information.
*/
import {
domify,
delegate as domDelegate
} from 'min-dom';
// inlined ../../resources/logo.svg
var BPMNIO_LOGO_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 960"><path fill="#fff" d="M960 60v839c0 33-27 61-60 61H60c-33 0-60-27-60-60V60C0 27 27 0 60 0h839c34 0 61 27 61 60z"/><path fill="#52b415" d="M217 548a205 205 0 0 0-144 58 202 202 0 0 0-4 286 202 202 0 0 0 285 3 200 200 0 0 0 48-219 203 203 0 0 0-185-128zM752 6a206 206 0 0 0-192 285 206 206 0 0 0 269 111 207 207 0 0 0 111-260A204 204 0 0 0 752 6zM62 0A62 62 0 0 0 0 62v398l60 46a259 259 0 0 1 89-36c5-28 10-57 14-85l99 2 12 85a246 246 0 0 1 88 38l70-52 69 71-52 68c17 30 29 58 35 90l86 14-2 100-86 12a240 240 0 0 1-38 89l43 58h413c37 0 60-27 60-61V407a220 220 0 0 1-44 40l21 85-93 39-45-76a258 258 0 0 1-98 1l-45 76-94-39 22-85a298 298 0 0 1-70-69l-86 22-38-94 76-45a258 258 0 0 1-1-98l-76-45 40-94 85 22a271 271 0 0 1 41-47z"/></svg>';
var BPMNIO_LOGO_URL = 'data:image/svg+xml,' + encodeURIComponent(BPMNIO_LOGO_SVG);
export var BPMNIO_IMG = '<img width="52" height="52" src="' + BPMNIO_LOGO_URL + '" />';
function css(attrs) {
return attrs.join(';');
}
var LIGHTBOX_STYLES = css([
'z-index: 1001',
'position: fixed',
'top: 0',
'left: 0',
'right: 0',
'bottom: 0'
]);
var BACKDROP_STYLES = css([
'width: 100%',
'height: 100%',
'background: rgba(0,0,0,0.2)'
]);
var NOTICE_STYLES = css([
'position: absolute',
'left: 50%',
'top: 40%',
'margin: 0 -130px',
'width: 260px',
'padding: 10px',
'background: white',
'border: solid 1px #AAA',
'border-radius: 3px',
'font-family: Helvetica, Arial, sans-serif',
'font-size: 14px',
'line-height: 1.2em'
]);
var LIGHTBOX_MARKUP =
'<div class="bjs-powered-by-lightbox" style="' + LIGHTBOX_STYLES + '">' +
'<div class="backdrop" style="' + BACKDROP_STYLES + '"></div>' +
'<div class="notice" style="' + NOTICE_STYLES + '">' +
'<a href="http://bpmn.io" target="_blank" style="float: left; margin-right: 10px">' +
BPMNIO_IMG +
'</a>' +
'Web-based tooling for BPMN, DMN and CMMN diagrams ' +
'powered by <a href="http://bpmn.io" target="_blank">bpmn.io</a>.' +
'</div>' +
'</div>';
var lightbox;
export function open() {
if (!lightbox) {
lightbox = domify(LIGHTBOX_MARKUP);
domDelegate.bind(lightbox, '.backdrop', 'click', function(event) {
document.body.removeChild(lightbox);
});
}
document.body.appendChild(lightbox);
}

View File

@@ -0,0 +1,214 @@
import {
forEach,
filter,
some,
sortBy,
isArray
} from 'min-dash';
import {
IGNORED_PROPERTIES
} from './ModelCloneUtils';
function isAllowedIn(extProp, type) {
var allowedIn = extProp.meta.allowedIn;
// '*' is a wildcard, which means any element is allowed to use this property
if (allowedIn.length === 1 && allowedIn[0] === '*') {
return true;
}
return allowedIn.indexOf(type) !== -1;
}
function isType(element, types) {
return some(types, function(type) {
return typeof element === type;
});
}
/**
* A bpmn properties cloning interface
*
*/
export default function ModelCloneHelper(eventBus, bpmnFactory) {
this._eventBus = eventBus;
this._bpmnFactory = bpmnFactory;
}
ModelCloneHelper.prototype.clone = function(refElement, newElement, properties) {
var self = this;
// hasNestedProperty: property allows us to avoid ending up with empty (xml) tags
// f.ex: if extensionElements.values is empty, don't set it
var context = {
newElement: newElement,
hasNestedProperty: false
};
// we want the extensionElements to be cloned last
// so that they can check certain properties
properties = sortBy(properties, function(prop) {
return prop === 'bpmn:extensionElements';
});
forEach(properties, function(propName) {
var refElementProp = refElement.get(propName),
newElementProp = newElement.get(propName),
propDescriptor = newElement.$model.getPropertyDescriptor(newElement, propName),
newProperty, name;
// we're not interested in cloning:
// - same values from simple types
// - cloning id's
// - cloning reference elements
if (newElementProp === refElementProp) {
return;
}
if (propDescriptor && (propDescriptor.isId || propDescriptor.isReference)) {
return;
}
// if the property is of type 'boolean', 'string', 'number' or 'null', just set it
if (isType(refElementProp, [ 'boolean', 'string', 'number' ]) || refElementProp === null) {
newElement.set(propName, refElementProp);
return;
}
if (isArray(refElementProp)) {
forEach(refElementProp, function(extElement) {
var newProp;
context.refTopLevelProperty = extElement;
newProp = self._deepClone(extElement, context);
if (context.hasNestedProperty) {
newProp.$parent = newElement;
newElementProp.push(newProp);
}
context.hasNestedProperty = false;
});
} else {
name = propName.replace(/bpmn:/, '');
context.refTopLevelProperty = refElementProp;
newProperty = self._deepClone(refElementProp, context);
if (context.hasNestedProperty) {
newProperty.$parent = newElement;
newElement.set(name, newProperty);
}
context.hasNestedProperty = false;
}
});
return newElement;
};
ModelCloneHelper.prototype._deepClone = function _deepClone(propertyElement, context) {
var self = this;
var eventBus = this._eventBus;
var bpmnFactory = this._bpmnFactory;
var newProp = bpmnFactory.create(propertyElement.$type);
var properties = filter(Object.keys(propertyElement), function(prop) {
var descriptor = newProp.$model.getPropertyDescriptor(newProp, prop);
if (descriptor && (descriptor.isId || descriptor.isReference)) {
return false;
}
// we need to make sure we don't clone certain properties
// which we cannot easily know if they hold references or not
if (IGNORED_PROPERTIES.indexOf(prop) !== -1) {
return false;
}
// make sure we don't copy the type
return prop !== '$type';
});
if (!properties.length) {
context.hasNestedProperty = true;
}
forEach(properties, function(propName) {
// check if the propertyElement has this property defined
if (propertyElement[propName] !== undefined &&
(propertyElement[propName].$type || isArray(propertyElement[propName]))) {
if (isArray(propertyElement[propName])) {
newProp[propName] = [];
forEach(propertyElement[propName], function(property) {
var extProp = propertyElement.$model.getTypeDescriptor(property.$type),
newDeepProp;
// we're not going to copy undefined types
if (!extProp) {
return;
}
var canClone = eventBus.fire('property.clone', {
newElement: context.newElement,
refTopLevelProperty: context.refTopLevelProperty,
propertyDescriptor: extProp
});
if (!canClone) {
// if can clone is 'undefined' or 'false'
// check for the meta information if it is allowed
if (propertyElement.$type === 'bpmn:ExtensionElements' &&
extProp.meta && extProp.meta.allowedIn &&
!isAllowedIn(extProp, context.newElement.$type)) {
return false;
}
}
newDeepProp = self._deepClone(property, context);
newDeepProp.$parent = newProp;
if (!newProp[propName]) {
newProp[propName] = [];
}
context.hasNestedProperty = true;
newProp[propName].push(newDeepProp);
});
} else if (propertyElement[propName].$type) {
newProp[propName] = self._deepClone(propertyElement[propName], context);
if (newProp[propName]) {
context.hasNestedProperty = true;
newProp[propName].$parent = newProp;
}
}
} else {
context.hasNestedProperty = true;
// just assign directly if it's a value
newProp[propName] = propertyElement[propName];
}
});
return newProp;
};

View File

@@ -0,0 +1,36 @@
import {
forEach
} from 'min-dash';
/**
* These are the properties that should be ignored when cloning elements.
*
* @type {Array}
*/
export var IGNORED_PROPERTIES = [
'lanes',
'incoming',
'outgoing',
'artifacts',
'default',
'flowElements',
'dataInputAssociations',
'dataOutputAssociations'
];
export function getProperties(descriptor, keepDefault) {
var properties = [];
forEach(descriptor.properties, function(property) {
if (keepDefault && property.default) {
return;
}
properties.push(property.ns.name);
});
return properties;
}