267 lines
6.0 KiB
JavaScript
267 lines
6.0 KiB
JavaScript
|
|
import {
|
|||
|
|
forEach,
|
|||
|
|
isArray
|
|||
|
|
} from 'min-dash';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @typedef {import('didi').Injector} Injector
|
|||
|
|
*
|
|||
|
|
* @typedef {import('../../core/EventBus').default} EventBus
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
var NOT_REGISTERED_ERROR = 'is not a registered action',
|
|||
|
|
IS_REGISTERED_ERROR = 'is already registered';
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* An interface that provides access to modeling actions by decoupling
|
|||
|
|
* the one who requests the action to be triggered and the trigger itself.
|
|||
|
|
*
|
|||
|
|
* It's possible to add new actions by registering them with ´registerAction´
|
|||
|
|
* and likewise unregister existing ones with ´unregisterAction´.
|
|||
|
|
*
|
|||
|
|
*
|
|||
|
|
* ## Life-Cycle and configuration
|
|||
|
|
*
|
|||
|
|
* The editor actions will wait for diagram initialization before
|
|||
|
|
* registering default actions _and_ firing an `editorActions.init` event.
|
|||
|
|
*
|
|||
|
|
* Interested parties may listen to the `editorActions.init` event with
|
|||
|
|
* low priority to check, which actions got registered. Other components
|
|||
|
|
* may use the event to register their own actions via `registerAction`.
|
|||
|
|
*
|
|||
|
|
* @param {EventBus} eventBus
|
|||
|
|
* @param {Injector} injector
|
|||
|
|
*/
|
|||
|
|
export default function EditorActions(eventBus, injector) {
|
|||
|
|
|
|||
|
|
// initialize actions
|
|||
|
|
this._actions = {};
|
|||
|
|
|
|||
|
|
var self = this;
|
|||
|
|
|
|||
|
|
eventBus.on('diagram.init', function() {
|
|||
|
|
|
|||
|
|
// all diagram modules got loaded; check which ones
|
|||
|
|
// are available and register the respective default actions
|
|||
|
|
self._registerDefaultActions(injector);
|
|||
|
|
|
|||
|
|
// ask interested parties to register available editor
|
|||
|
|
// actions on diagram initialization
|
|||
|
|
eventBus.fire('editorActions.init', {
|
|||
|
|
editorActions: self
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EditorActions.$inject = [
|
|||
|
|
'eventBus',
|
|||
|
|
'injector'
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Register default actions.
|
|||
|
|
*
|
|||
|
|
* @param {Injector} injector
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype._registerDefaultActions = function(injector) {
|
|||
|
|
|
|||
|
|
// (1) retrieve optional components to integrate with
|
|||
|
|
|
|||
|
|
var commandStack = injector.get('commandStack', false);
|
|||
|
|
var modeling = injector.get('modeling', false);
|
|||
|
|
var selection = injector.get('selection', false);
|
|||
|
|
var zoomScroll = injector.get('zoomScroll', false);
|
|||
|
|
var copyPaste = injector.get('copyPaste', false);
|
|||
|
|
var canvas = injector.get('canvas', false);
|
|||
|
|
var rules = injector.get('rules', false);
|
|||
|
|
var keyboardMove = injector.get('keyboardMove', false);
|
|||
|
|
var keyboardMoveSelection = injector.get('keyboardMoveSelection', false);
|
|||
|
|
|
|||
|
|
// (2) check components and register actions
|
|||
|
|
|
|||
|
|
if (commandStack) {
|
|||
|
|
this.register('undo', function() {
|
|||
|
|
commandStack.undo();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
this.register('redo', function() {
|
|||
|
|
commandStack.redo();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (copyPaste && selection) {
|
|||
|
|
this.register('copy', function() {
|
|||
|
|
var selectedElements = selection.get();
|
|||
|
|
|
|||
|
|
if (selectedElements.length) {
|
|||
|
|
return copyPaste.copy(selectedElements);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (copyPaste) {
|
|||
|
|
this.register('paste', function() {
|
|||
|
|
copyPaste.paste();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (zoomScroll) {
|
|||
|
|
this.register('stepZoom', function(opts) {
|
|||
|
|
zoomScroll.stepZoom(opts.value);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (canvas) {
|
|||
|
|
this.register('zoom', function(opts) {
|
|||
|
|
canvas.zoom(opts.value);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (modeling && selection && rules) {
|
|||
|
|
this.register('removeSelection', function() {
|
|||
|
|
|
|||
|
|
var selectedElements = selection.get();
|
|||
|
|
|
|||
|
|
if (!selectedElements.length) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var allowed = rules.allowed('elements.delete', { elements: selectedElements }),
|
|||
|
|
removableElements;
|
|||
|
|
|
|||
|
|
if (allowed === false) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
else if (isArray(allowed)) {
|
|||
|
|
removableElements = allowed;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
removableElements = selectedElements;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (removableElements.length) {
|
|||
|
|
modeling.removeElements(removableElements.slice());
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (keyboardMove) {
|
|||
|
|
this.register('moveCanvas', function(opts) {
|
|||
|
|
keyboardMove.moveCanvas(opts);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (keyboardMoveSelection) {
|
|||
|
|
this.register('moveSelection', function(opts) {
|
|||
|
|
keyboardMoveSelection.moveSelection(opts.direction, opts.accelerated);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Triggers a registered action
|
|||
|
|
*
|
|||
|
|
* @param {string} action
|
|||
|
|
* @param {Object} opts
|
|||
|
|
*
|
|||
|
|
* @return {Unknown} Returns what the registered listener returns
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype.trigger = function(action, opts) {
|
|||
|
|
if (!this._actions[action]) {
|
|||
|
|
throw error(action, NOT_REGISTERED_ERROR);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return this._actions[action](opts);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Registers a collections of actions.
|
|||
|
|
* The key of the object will be the name of the action.
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
* ´´´
|
|||
|
|
* var actions = {
|
|||
|
|
* spaceTool: function() {
|
|||
|
|
* spaceTool.activateSelection();
|
|||
|
|
* },
|
|||
|
|
* lassoTool: function() {
|
|||
|
|
* lassoTool.activateSelection();
|
|||
|
|
* }
|
|||
|
|
* ];
|
|||
|
|
*
|
|||
|
|
* editorActions.register(actions);
|
|||
|
|
*
|
|||
|
|
* editorActions.isRegistered('spaceTool'); // true
|
|||
|
|
* ´´´
|
|||
|
|
*
|
|||
|
|
* @param {Object} actions
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype.register = function(actions, listener) {
|
|||
|
|
var self = this;
|
|||
|
|
|
|||
|
|
if (typeof actions === 'string') {
|
|||
|
|
return this._registerAction(actions, listener);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
forEach(actions, function(listener, action) {
|
|||
|
|
self._registerAction(action, listener);
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Registers a listener to an action key
|
|||
|
|
*
|
|||
|
|
* @param {string} action
|
|||
|
|
* @param {Function} listener
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype._registerAction = function(action, listener) {
|
|||
|
|
if (this.isRegistered(action)) {
|
|||
|
|
throw error(action, IS_REGISTERED_ERROR);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._actions[action] = listener;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Unregister an existing action
|
|||
|
|
*
|
|||
|
|
* @param {string} action
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype.unregister = function(action) {
|
|||
|
|
if (!this.isRegistered(action)) {
|
|||
|
|
throw error(action, NOT_REGISTERED_ERROR);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._actions[action] = undefined;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Returns the number of actions that are currently registered
|
|||
|
|
*
|
|||
|
|
* @return {number}
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype.getActions = function() {
|
|||
|
|
return Object.keys(this._actions);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Checks wether the given action is registered
|
|||
|
|
*
|
|||
|
|
* @param {string} action
|
|||
|
|
*
|
|||
|
|
* @return {boolean}
|
|||
|
|
*/
|
|||
|
|
EditorActions.prototype.isRegistered = function(action) {
|
|||
|
|
return !!this._actions[action];
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
function error(action, message) {
|
|||
|
|
return new Error(action + ' ' + message);
|
|||
|
|
}
|