import { Injector } from 'didi';
import CoreModule from './core';
/**
* Bootstrap an injector from a list of modules, instantiating a number of default components
*
* @ignore
* @param {Array<didi.Module>} bootstrapModules
*
* @return {didi.Injector} a injector to use to access the components
*/
function bootstrap(bootstrapModules) {
var modules = [],
components = [];
function hasModule(m) {
return modules.indexOf(m) >= 0;
}
function addModule(m) {
modules.push(m);
}
function visit(m) {
if (hasModule(m)) {
return;
}
(m.__depends__ || []).forEach(visit);
Iif (hasModule(m)) {
return;
}
addModule(m);
(m.__init__ || []).forEach(function(c) {
components.push(c);
});
}
bootstrapModules.forEach(visit);
var injector = new Injector(modules);
components.forEach(function(c) {
try {
// eagerly resolve component (fn or string)
injector[typeof c === 'string' ? 'get' : 'invoke'](c);
} catch (e) {
console.error('Failed to instantiate component');
console.error(e.stack);
throw e;
}
});
return injector;
}
/**
* Creates an injector from passed options.
*
* @ignore
* @param {Object} options
* @return {didi.Injector}
*/
function createInjector(options) {
options = options || {};
var configModule = {
'config': ['value', options]
};
var modules = [ configModule, CoreModule ].concat(options.modules || []);
return bootstrap(modules);
}
/**
* The main diagram-js entry point that bootstraps the diagram with the given
* configuration.
*
* To register extensions with the diagram, pass them as Array<didi.Module> to the constructor.
*
* @class djs.Diagram
* @memberOf djs
* @constructor
*
* @example
*
* <caption>Creating a plug-in that logs whenever a shape is added to the canvas.</caption>
*
* // plug-in implemenentation
* function MyLoggingPlugin(eventBus) {
* eventBus.on('shape.added', function(event) {
* console.log('shape ', event.shape, ' was added to the diagram');
* });
* }
*
* // export as module
* export default {
* __init__: [ 'myLoggingPlugin' ],
* myLoggingPlugin: [ 'type', MyLoggingPlugin ]
* };
*
*
* // instantiate the diagram with the new plug-in
*
* import MyLoggingModule from 'path-to-my-logging-plugin';
*
* var diagram = new Diagram({
* modules: [
* MyLoggingModule
* ]
* });
*
* diagram.invoke([ 'canvas', function(canvas) {
* // add shape to drawing canvas
* canvas.addShape({ x: 10, y: 10 });
* });
*
* // 'shape ... was added to the diagram' logged to console
*
* @param {Object} options
* @param {Array<didi.Module>} [options.modules] external modules to instantiate with the diagram
* @param {didi.Injector} [injector] an (optional) injector to bootstrap the diagram with
*/
export default function Diagram(options, injector) {
// create injector unless explicitly specified
this.injector = injector = injector || createInjector(options);
// API
/**
* Resolves a diagram service
*
* @method Diagram#get
*
* @param {String} name the name of the diagram service to be retrieved
* @param {Boolean} [strict=true] if false, resolve missing services to null
*/
this.get = injector.get;
/**
* Executes a function into which diagram services are injected
*
* @method Diagram#invoke
*
* @param {Function|Object[]} fn the function to resolve
* @param {Object} locals a number of locals to use to resolve certain dependencies
*/
this.invoke = injector.invoke;
// init
// indicate via event
/**
* An event indicating that all plug-ins are loaded.
*
* Use this event to fire other events to interested plug-ins
*
* @memberOf Diagram
*
* @event diagram.init
*
* @example
*
* eventBus.on('diagram.init', function() {
* eventBus.fire('my-custom-event', { foo: 'BAR' });
* });
*
* @type {Object}
*/
this.get('eventBus').fire('diagram.init');
}
/**
* Destroys the diagram
*
* @method Diagram#destroy
*/
Diagram.prototype.destroy = function() {
this.get('eventBus').fire('diagram.destroy');
};
/**
* Clear the diagram, removing all contents.
*/
Diagram.prototype.clear = function() {
this.get('eventBus').fire('diagram.clear');
};
|