123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- import { assign, forEach, isArray } from "min-dash";
- import { is } from "bpmn-js/lib/util/ModelUtil";
- import { isExpanded, isEventSubProcess } from "bpmn-js/lib/util/DiUtil";
- import { isAny } from "bpmn-js/lib/features/modeling/util/ModelingUtil";
- import { getChildLanes } from "bpmn-js/lib/features/modeling/util/LaneUtil";
- import { hasPrimaryModifier } from "diagram-js/lib/util/Mouse";
- /**
- * A provider for BPMN 2.0 elements context pad
- */
- export default function ContextPadProvider(
- config,
- injector,
- eventBus,
- contextPad,
- modeling,
- elementFactory,
- connect,
- create,
- popupMenu,
- canvas,
- rules,
- translate,
- elementRegistry
- ) {
- config = config || {};
- contextPad.registerProvider(this);
- this._contextPad = contextPad;
- this._modeling = modeling;
- this._elementFactory = elementFactory;
- this._connect = connect;
- this._create = create;
- this._popupMenu = popupMenu;
- this._canvas = canvas;
- this._rules = rules;
- this._translate = translate;
- if (config.autoPlace !== false) {
- this._autoPlace = injector.get("autoPlace", false);
- }
- eventBus.on("create.end", 250, function(event) {
- const context = event.context,
- shape = context.shape
- if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) {
- return;
- }
- const entries = contextPad.getEntries(shape)
- if (entries.replace) {
- entries.replace.action.click(event, shape);
- }
- });
- }
- ContextPadProvider.$inject = [
- "config.contextPad",
- "injector",
- "eventBus",
- "contextPad",
- "modeling",
- "elementFactory",
- "connect",
- "create",
- "popupMenu",
- "canvas",
- "rules",
- "translate",
- "elementRegistry"
- ];
- ContextPadProvider.prototype.getContextPadEntries = function(element) {
- const contextPad = this._contextPad,
- modeling = this._modeling,
- elementFactory = this._elementFactory,
- connect = this._connect,
- create = this._create,
- popupMenu = this._popupMenu,
- canvas = this._canvas,
- rules = this._rules,
- autoPlace = this._autoPlace,
- translate = this._translate
- const actions = {}
- if (element.type === "label") {
- return actions;
- }
- const businessObject = element.businessObject
- function startConnect(event, element) {
- connect.start(event, element);
- }
- function removeElement() {
- modeling.removeElements([element]);
- }
- function getReplaceMenuPosition(element) {
- const Y_OFFSET = 5
- const diagramContainer = canvas.getContainer(),
- pad = contextPad.getPad(element).html
- const diagramRect = diagramContainer.getBoundingClientRect(),
- padRect = pad.getBoundingClientRect()
- const top = padRect.top - diagramRect.top
- const left = padRect.left - diagramRect.left
- const pos = {
- x: left,
- y: top + padRect.height + Y_OFFSET
- }
- return pos;
- }
- /**
- * Create an append action
- *
- * @param {string} type
- * @param {string} className
- * @param {string} [title]
- * @param {Object} [options]
- *
- * @return {Object} descriptor
- */
- function appendAction(type, className, title, options) {
- if (typeof title !== "string") {
- options = title;
- title = translate("Append {type}", { type: type.replace(/^bpmn:/, "") });
- }
- function appendStart(event, element) {
- const shape = elementFactory.createShape(assign({ type: type }, options))
- create.start(event, shape, {
- source: element
- });
- }
- const append = autoPlace
- ? function(event, element) {
- const shape = elementFactory.createShape(assign({ type: type }, options))
- autoPlace.append(element, shape)
- }
- : appendStart
- return {
- group: "model",
- className: className,
- title: title,
- action: {
- dragstart: appendStart,
- click: append
- }
- };
- }
- function splitLaneHandler(count) {
- return function(event, element) {
- // actual split
- modeling.splitLane(element, count);
- // refresh context pad after split to
- // get rid of split icons
- contextPad.open(element, true);
- };
- }
- if (isAny(businessObject, ["bpmn:Lane", "bpmn:Participant"]) && isExpanded(businessObject)) {
- const childLanes = getChildLanes(element)
- assign(actions, {
- "lane-insert-above": {
- group: "lane-insert-above",
- className: "bpmn-icon-lane-insert-above",
- title: translate("Add Lane above"),
- action: {
- click: function(event, element) {
- modeling.addLane(element, "top");
- }
- }
- }
- });
- if (childLanes.length < 2) {
- if (element.height >= 120) {
- assign(actions, {
- "lane-divide-two": {
- group: "lane-divide",
- className: "bpmn-icon-lane-divide-two",
- title: translate("Divide into two Lanes"),
- action: {
- click: splitLaneHandler(2)
- }
- }
- });
- }
- if (element.height >= 180) {
- assign(actions, {
- "lane-divide-three": {
- group: "lane-divide",
- className: "bpmn-icon-lane-divide-three",
- title: translate("Divide into three Lanes"),
- action: {
- click: splitLaneHandler(3)
- }
- }
- });
- }
- }
- assign(actions, {
- "lane-insert-below": {
- group: "lane-insert-below",
- className: "bpmn-icon-lane-insert-below",
- title: translate("Add Lane below"),
- action: {
- click: function(event, element) {
- modeling.addLane(element, "bottom");
- }
- }
- }
- });
- }
- if (is(businessObject, "bpmn:FlowNode")) {
- if (is(businessObject, "bpmn:EventBasedGateway")) {
- assign(actions, {
- "append.receive-task": appendAction("bpmn:ReceiveTask", "bpmn-icon-receive-task", translate("Append ReceiveTask")),
- "append.message-intermediate-event": appendAction(
- "bpmn:IntermediateCatchEvent",
- "bpmn-icon-intermediate-event-catch-message",
- translate("Append MessageIntermediateCatchEvent"),
- { eventDefinitionType: "bpmn:MessageEventDefinition" }
- ),
- "append.timer-intermediate-event": appendAction(
- "bpmn:IntermediateCatchEvent",
- "bpmn-icon-intermediate-event-catch-timer",
- translate("Append TimerIntermediateCatchEvent"),
- { eventDefinitionType: "bpmn:TimerEventDefinition" }
- ),
- "append.condition-intermediate-event": appendAction(
- "bpmn:IntermediateCatchEvent",
- "bpmn-icon-intermediate-event-catch-condition",
- translate("Append ConditionIntermediateCatchEvent"),
- { eventDefinitionType: "bpmn:ConditionalEventDefinition" }
- ),
- "append.signal-intermediate-event": appendAction(
- "bpmn:IntermediateCatchEvent",
- "bpmn-icon-intermediate-event-catch-signal",
- translate("Append SignalIntermediateCatchEvent"),
- { eventDefinitionType: "bpmn:SignalEventDefinition" }
- )
- });
- } else if (isEventType(businessObject, "bpmn:BoundaryEvent", "bpmn:CompensateEventDefinition")) {
- assign(actions, {
- "append.compensation-activity": appendAction("bpmn:Task", "bpmn-icon-task", translate("Append compensation activity"), {
- isForCompensation: true
- })
- });
- } else if (
- !is(businessObject, "bpmn:EndEvent") &&
- !businessObject.isForCompensation &&
- !isEventType(businessObject, "bpmn:IntermediateThrowEvent", "bpmn:LinkEventDefinition") &&
- !isEventSubProcess(businessObject)
- ) {
- assign(actions, {
- "append.end-event": appendAction("bpmn:EndEvent", "bpmn-icon-end-event-none", translate("Append EndEvent")),
- "append.gateway": appendAction("bpmn:ExclusiveGateway", "bpmn-icon-gateway-none", translate("Append Gateway")),
- "append.append-task": appendAction("bpmn:UserTask", "bpmn-icon-user-task", translate("Append Task")),
- "append.intermediate-event": appendAction(
- "bpmn:IntermediateThrowEvent",
- "bpmn-icon-intermediate-event-none",
- translate("Append Intermediate/Boundary Event")
- )
- });
- }
- }
- if (!popupMenu.isEmpty(element, "bpmn-replace")) {
- // Replace menu entry
- assign(actions, {
- replace: {
- group: "edit",
- className: "bpmn-icon-screw-wrench",
- title: translate("Change type"),
- action: {
- click: function(event, element) {
- const position = assign(getReplaceMenuPosition(element), {
- cursor: { x: event.x, y: event.y }
- })
- popupMenu.open(element, "bpmn-replace", position);
- }
- }
- }
- });
- }
- if (isAny(businessObject, ["bpmn:FlowNode", "bpmn:InteractionNode", "bpmn:DataObjectReference", "bpmn:DataStoreReference"])) {
- assign(actions, {
- "append.text-annotation": appendAction("bpmn:TextAnnotation", "bpmn-icon-text-annotation"),
- connect: {
- group: "connect",
- className: "bpmn-icon-connection-multi",
- title: translate("Connect using " + (businessObject.isForCompensation ? "" : "Sequence/MessageFlow or ") + "Association"),
- action: {
- click: startConnect,
- dragstart: startConnect
- }
- }
- });
- }
- if (isAny(businessObject, ["bpmn:DataObjectReference", "bpmn:DataStoreReference"])) {
- assign(actions, {
- connect: {
- group: "connect",
- className: "bpmn-icon-connection-multi",
- title: translate("Connect using DataInputAssociation"),
- action: {
- click: startConnect,
- dragstart: startConnect
- }
- }
- });
- }
- if (is(businessObject, "bpmn:Group")) {
- assign(actions, {
- "append.text-annotation": appendAction("bpmn:TextAnnotation", "bpmn-icon-text-annotation")
- });
- }
- // delete element entry, only show if allowed by rules
- let deleteAllowed = rules.allowed('elements.delete', { elements: [element] })
- if (isArray(deleteAllowed)) {
- // was the element returned as a deletion candidate?
- deleteAllowed = deleteAllowed[0] === element;
- }
- if (deleteAllowed) {
- assign(actions, {
- delete: {
- group: "edit",
- className: "bpmn-icon-trash",
- title: translate("Remove"),
- action: {
- click: removeElement
- }
- }
- });
- }
- return actions;
- };
- // helpers /////////
- function isEventType(eventBo, type, definition) {
- const isType = eventBo.$instanceOf(type)
- let isDefinition = false
- const definitions = eventBo.eventDefinitions || []
- forEach(definitions, function(def) {
- if (def.$type === definition) {
- isDefinition = true;
- }
- });
- return isType && isDefinition;
- }
|