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} 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); if (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 to the constructor. * * @class djs.Diagram * @memberOf djs * @constructor * * @example * * Creating a plug-in that logs whenever a shape is added to the canvas. * * // 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} [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'); };