From 6b86fd965096535ec595b361b46913a986906cc0 Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Tue, 24 Jan 2023 22:48:26 +0100 Subject: [PATCH 1/7] deps: update to `didi@9.0.2` Fixes some type declarations. --- package-lock.json | 11 +++++++---- package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 633ae5ddc..57f5d18fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@bpmn-io/diagram-js-ui": "^0.2.2", "clsx": "^1.2.1", - "didi": "^9.0.0", + "didi": "^9.0.2", "hammerjs": "^2.0.1", "inherits-browser": "^0.1.0", "min-dash": "^4.0.0", @@ -2081,8 +2081,9 @@ "license": "MIT" }, "node_modules/didi": { - "version": "9.0.0", - "license": "MIT" + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/didi/-/didi-9.0.2.tgz", + "integrity": "sha512-q2+aj+lnJcUweV7A9pdUrwFr4LHVmRPwTmQLtHPFz4aT7IBoryN6Iy+jmFku+oIzr5ebBkvtBCOb87+dJhb7bg==" }, "node_modules/diff": { "version": "5.0.0", @@ -9137,7 +9138,9 @@ "dev": true }, "didi": { - "version": "9.0.0" + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/didi/-/didi-9.0.2.tgz", + "integrity": "sha512-q2+aj+lnJcUweV7A9pdUrwFr4LHVmRPwTmQLtHPFz4aT7IBoryN6Iy+jmFku+oIzr5ebBkvtBCOb87+dJhb7bg==" }, "diff": { "version": "5.0.0", diff --git a/package.json b/package.json index 16eedd90d..0c448f03b 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "dependencies": { "@bpmn-io/diagram-js-ui": "^0.2.2", "clsx": "^1.2.1", - "didi": "^9.0.0", + "didi": "^9.0.2", "hammerjs": "^2.0.1", "inherits-browser": "^0.1.0", "min-dash": "^4.0.0", From 84d8f103e62b09aa1a6a87faccc286a357b996ee Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 24 Feb 2023 14:26:45 +0100 Subject: [PATCH 2/7] feat: add type declarations for core components --- index.d.ts | 1 + lib/Diagram.d.ts | 89 ++++++ lib/Diagram.js | 33 +- lib/Diagram.spec.ts | 31 ++ lib/command/CommandHandler.d.ts | 55 ++++ lib/command/CommandHandler.js | 33 +- lib/command/CommandHandler.spec.ts | 49 +++ lib/command/CommandInterceptor.d.ts | 305 ++++++++++++++++++ lib/command/CommandInterceptor.js | 68 ++-- lib/command/CommandInterceptor.spec.ts | 79 +++++ lib/command/CommandStack.d.ts | 168 ++++++++++ lib/command/CommandStack.js | 81 +++-- lib/command/CommandStack.spec.ts | 30 ++ lib/command/index.d.ts | 7 + lib/core/Canvas.d.ts | 378 ++++++++++++++++++++++ lib/core/Canvas.js | 258 ++++++++------- lib/core/Canvas.spec.ts | 206 ++++++++++++ lib/core/ElementFactory.d.ts | 97 ++++++ lib/core/ElementFactory.js | 56 +++- lib/core/ElementFactory.spec.ts | 59 ++++ lib/core/ElementRegistry.d.ts | 122 ++++++++ lib/core/ElementRegistry.js | 80 ++--- lib/core/ElementRegistry.spec.ts | 70 +++++ lib/core/EventBus.d.ts | 276 +++++++++++++++++ lib/core/EventBus.js | 65 ++-- lib/core/EventBus.spec.ts | 58 ++++ lib/core/GraphicsFactory.d.ts | 92 ++++++ lib/core/GraphicsFactory.js | 73 ++++- lib/core/GraphicsFactory.spec.ts | 78 +++++ lib/core/index.d.ts | 29 ++ lib/draw/BaseRenderer.d.ts | 64 ++++ lib/draw/BaseRenderer.js | 53 ++-- lib/draw/BaseRenderer.spec.ts | 64 ++++ lib/features/modeling/Modeling.d.ts | 413 +++++++++++++++++++++++++ lib/features/modeling/Modeling.js | 281 ++++++++++++++--- lib/features/modeling/Modeling.spec.ts | 205 ++++++++++++ lib/features/modeling/index.d.ts | 7 + lib/features/overlays/Overlays.d.ts | 193 ++++++++++++ lib/features/overlays/Overlays.js | 84 ++--- lib/features/overlays/Overlays.spec.ts | 56 ++++ lib/model/index.d.ts | 162 ++++++++++ lib/model/index.js | 40 ++- lib/model/index.spec.ts | 44 +++ lib/util/Types.d.ts | 20 ++ lib/util/Types.js | 31 ++ package-lock.json | 20 ++ package.json | 7 +- tsconfig.json | 8 + 48 files changed, 4397 insertions(+), 381 deletions(-) create mode 100644 index.d.ts create mode 100644 lib/Diagram.d.ts create mode 100644 lib/Diagram.spec.ts create mode 100644 lib/command/CommandHandler.d.ts create mode 100644 lib/command/CommandHandler.spec.ts create mode 100644 lib/command/CommandInterceptor.d.ts create mode 100644 lib/command/CommandInterceptor.spec.ts create mode 100644 lib/command/CommandStack.d.ts create mode 100644 lib/command/CommandStack.spec.ts create mode 100644 lib/command/index.d.ts create mode 100644 lib/core/Canvas.d.ts create mode 100644 lib/core/Canvas.spec.ts create mode 100644 lib/core/ElementFactory.d.ts create mode 100644 lib/core/ElementFactory.spec.ts create mode 100644 lib/core/ElementRegistry.d.ts create mode 100644 lib/core/ElementRegistry.spec.ts create mode 100644 lib/core/EventBus.d.ts create mode 100644 lib/core/EventBus.spec.ts create mode 100644 lib/core/GraphicsFactory.d.ts create mode 100644 lib/core/GraphicsFactory.spec.ts create mode 100644 lib/core/index.d.ts create mode 100644 lib/draw/BaseRenderer.d.ts create mode 100644 lib/draw/BaseRenderer.spec.ts create mode 100644 lib/features/modeling/Modeling.d.ts create mode 100644 lib/features/modeling/Modeling.spec.ts create mode 100644 lib/features/modeling/index.d.ts create mode 100644 lib/features/overlays/Overlays.d.ts create mode 100644 lib/features/overlays/Overlays.spec.ts create mode 100644 lib/model/index.d.ts create mode 100644 lib/model/index.spec.ts create mode 100644 lib/util/Types.d.ts create mode 100644 lib/util/Types.js create mode 100644 tsconfig.json diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 000000000..a97adabb7 --- /dev/null +++ b/index.d.ts @@ -0,0 +1 @@ +export { default } from './lib/Diagram'; \ No newline at end of file diff --git a/lib/Diagram.d.ts b/lib/Diagram.d.ts new file mode 100644 index 000000000..c4746e584 --- /dev/null +++ b/lib/Diagram.d.ts @@ -0,0 +1,89 @@ +import { + InjectionContext, + Injector, + LocalsMap, + ModuleDeclaration +} from 'didi'; + +export type DiagramOptions = { + modules: ModuleDeclaration[] +} + +/** + * 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. + * + * @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 options + * @param injector An (optional) injector to bootstrap the diagram with. + */ +export default class Diagram { + constructor(options: DiagramOptions, injector?: Injector); + + /** + * Resolves a diagram service. + * + * @method Diagram#get + * + * @param name The name of the service to get. + * @param strict If false, resolve missing services to null. + */ + get(name: string, strict?: boolean): T; + + /** + * Executes a function with its dependencies injected. + * + * @method Diagram#invoke + * + * @param fn The function to be executed. + * @param context The context. + * @param locals The locals. + */ + invoke(fn: (...args: any[]) => T, context?: InjectionContext, locals?: LocalsMap): T; + + /** + * Destroys the diagram + */ + destroy(): void; + + /** + * Clear the diagram, removing all contents. + */ + clear(): void; +} \ No newline at end of file diff --git a/lib/Diagram.js b/lib/Diagram.js index d11030e46..fe679eb46 100644 --- a/lib/Diagram.js +++ b/lib/Diagram.js @@ -3,13 +3,17 @@ import { Injector } from 'didi'; import CoreModule from './core'; /** - * @typedef { import('didi').ModuleDeclaration } Module + * @typedef {import('didi').InjectionContext} InjectionContext + * @typedef {import('didi').LocalsMap} LocalsMap + * @typedef {import('didi').ModuleDeclaration} ModuleDeclaration + * + * @typedef {import('./Diagram').DiagramOptions} DiagramOptions */ /** * Bootstrap an injector from a list of modules, instantiating a number of default components * - * @param {Array} modules + * @param {ModuleDeclaration[]} modules * * @return {Injector} a injector to use to access the components */ @@ -24,7 +28,8 @@ function bootstrap(modules) { /** * Creates an injector from passed options. * - * @param {Object} options + * @param {DiagramOptions} options + * * @return {Injector} */ function createInjector(options) { @@ -47,8 +52,7 @@ function createInjector(options) { * * To register extensions with the diagram, pass them as Array to the constructor. * - * @class djs.Diagram - * @memberOf djs + * @class * @constructor * * @example @@ -86,9 +90,9 @@ function createInjector(options) { * * // 'shape ... was added to the diagram' logged to console * - * @param {Object} options - * @param {Array} [options.modules] external modules to instantiate with the diagram - * @param {Injector} [injector] an (optional) injector to bootstrap the diagram with + * @param {DiagramOptions} options + * @param {ModuleDeclaration[]} [options.modules] External modules to instantiate with the diagram. + * @param {Injector} [injector] An (optional) injector to bootstrap the diagram with. */ export default function Diagram(options, injector) { @@ -98,22 +102,23 @@ export default function Diagram(options, injector) { // API /** - * Resolves a diagram service + * 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 + * @param {string} name The name of the service to get. + * @param {boolean} [strict=true] If false, resolve missing services to null. */ this.get = injector.get; /** - * Executes a function into which diagram services are injected + * Executes a function with its dependencies 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 + * @param {Function} fn The function to be executed. + * @param {InjectionContext} [context] The context. + * @param {LocalsMap} [locals] The locals. */ this.invoke = injector.invoke; diff --git a/lib/Diagram.spec.ts b/lib/Diagram.spec.ts new file mode 100644 index 000000000..d79f03627 --- /dev/null +++ b/lib/Diagram.spec.ts @@ -0,0 +1,31 @@ +import Diagram from './Diagram'; + +import CommandModule from './command'; + +import CoreModule from './core'; +import EventBus from './core/EventBus'; + +import ModelingModule from './features/modeling'; +import Modeling from './features/modeling/Modeling'; + +const diagram = new Diagram({ + modules: [ + CoreModule, + CommandModule, + ModelingModule + ] +}); + +diagram.clear(); + +diagram.destroy(); + +diagram.invoke((eventBus: EventBus) => eventBus.fire('foo')); + +const foo = diagram.invoke((modeling: Modeling, eventBus: EventBus) => { + return { + bar: true + }; +}); + +foo.bar = false; \ No newline at end of file diff --git a/lib/command/CommandHandler.d.ts b/lib/command/CommandHandler.d.ts new file mode 100644 index 000000000..5ac0e68e5 --- /dev/null +++ b/lib/command/CommandHandler.d.ts @@ -0,0 +1,55 @@ +import { ElementLike } from '../core'; + +import CommandStack from './CommandStack'; + +import { CommandContext } from './CommandStack'; + +/** + * A command handler that may be registered via + * {@link CommandStack#registerHandler}. + */ +export default interface CommandHandler { + + /** + * Execute changes described in the passed action context. + * + * @param context The execution context. + * + * @return The list of diagram elements that have changed. + */ + execute?(context: CommandContext): ElementLike[]; + + /** + * Revert changes described in the passed action context. + * + * @param context The execution context. + * + * @return The list of diagram elements that have changed. + */ + revert?(context: CommandContext): ElementLike[]; + + /** + * Return true if the handler may execute in the given context. + * + * @param context The execution context. + * + * @return Whether the command can be executed. + */ + canExecute?(context: CommandContext): boolean; + + /** + * Execute actions before the actual command execution but + * grouped together (for undo/redo) with the action. + * + * @param context The execution context. + */ + preExecute?(context: CommandContext): void; + + /** + * Execute actions after the actual command execution but + * grouped together (for undo/redo) with the action. + * + * @param context The execution context. + */ + postExecute?(context: CommandContext): void; +} \ No newline at end of file diff --git a/lib/command/CommandHandler.js b/lib/command/CommandHandler.js index 03aa77fe2..9e50f9456 100644 --- a/lib/command/CommandHandler.js +++ b/lib/command/CommandHandler.js @@ -1,6 +1,16 @@ /** - * A command handler that may be registered with the - * {@link CommandStack} via {@link CommandStack#registerHandler}. + * @typedef {import('../core').ElementLike} ElementLike + * + * @typedef {import('./CommandStack').default} CommandStack + * @typedef {import('./CommandStack').CommandContext} CommandContext + */ + +/** + *A command handler that may be registered via + * {@link CommandStack#registerHandler}. + * + * @class + * @constructor */ export default function CommandHandler() {} @@ -8,9 +18,9 @@ export default function CommandHandler() {} /** * Execute changes described in the passed action context. * - * @param {Object} context the execution context + * @param {CommandContext} context The execution context. * - * @return {Array} list of touched (áka dirty) diagram elements + * @return {ElementLike[]} The list of diagram elements that have changed. */ CommandHandler.prototype.execute = function(context) {}; @@ -18,9 +28,9 @@ CommandHandler.prototype.execute = function(context) {}; /** * Revert changes described in the passed action context. * - * @param {Object} context the execution context + * @param {CommandContext} context The execution context. * - * @return {Array} list of touched (áka dirty) diagram elements + * @return {ElementLike[]} The list of diagram elements that have changed. */ CommandHandler.prototype.revert = function(context) {}; @@ -28,11 +38,9 @@ CommandHandler.prototype.revert = function(context) {}; /** * Return true if the handler may execute in the given context. * - * @abstract - * - * @param {Object} context the execution context + * @param {CommandContext} context The execution context. * - * @return {boolean} true if executing in the context is possible + * @return {boolean} Whether the command can be executed. */ CommandHandler.prototype.canExecute = function(context) { return true; @@ -43,14 +51,15 @@ CommandHandler.prototype.canExecute = function(context) { * Execute actions before the actual command execution but * grouped together (for undo/redo) with the action. * - * @param {Object} context the execution context + * @param {CommandContext} context The execution context. */ CommandHandler.prototype.preExecute = function(context) {}; + /** * Execute actions after the actual command execution but * grouped together (for undo/redo) with the action. * - * @param {Object} context the execution context + * @param {CommandContext} context The execution context. */ CommandHandler.prototype.postExecute = function(context) {}; \ No newline at end of file diff --git a/lib/command/CommandHandler.spec.ts b/lib/command/CommandHandler.spec.ts new file mode 100644 index 000000000..fec1c2ee7 --- /dev/null +++ b/lib/command/CommandHandler.spec.ts @@ -0,0 +1,49 @@ +import CommandHandler from '../../lib/command/CommandHandler'; + +import Canvas from '../../lib/core/Canvas'; + +export class AddShapeHandler implements CommandHandler { + private _canvas: Canvas; + + static $inject = [ 'canvas', 'rules' ]; + + constructor(canvas: Canvas) { + this._canvas = canvas; + } + + execute(context: any) { + const { + parent, + shape + } = context; + + this._canvas.addShape(shape, parent); + + return [ + parent, + shape + ]; + } + + revert(context: any) { + const { + parent, + shape + } = context; + + this._canvas.removeShape(shape); + + return [ + parent, + shape + ]; + } + + canExecute(context: any): boolean { + return true; + } + + preExecute(context: any): void {} + + postExecute(context: any): void {} +} \ No newline at end of file diff --git a/lib/command/CommandInterceptor.d.ts b/lib/command/CommandInterceptor.d.ts new file mode 100644 index 000000000..2eed45a6b --- /dev/null +++ b/lib/command/CommandInterceptor.d.ts @@ -0,0 +1,305 @@ +import EventBus from '../core/EventBus'; + +import { ElementLike } from '../core'; + +import { CommandContext } from './CommandStack'; + +type Events = string | string[]; + +export type ComposeHandlerFunction = (context: CommandContext) => void; + +export type HandlerFunction = (context: CommandContext) => ElementLike[] | void; + +/** + * A utility that can be used to plug into the command execution for + * extension and/or validation. + * + * @param eventBus + * + * @example + * + * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; + * + * class CommandLogger extends CommandInterceptor { + * constructor(eventBus) { + * super(eventBus); + * + * this.preExecute('shape.create', (event) => { + * console.log('commandStack.shape-create.preExecute', event); + * }); + * } + */ +export default class CommandInterceptor { + constructor(eventBus: EventBus); + + /** + * Check whether one or more commands can be executed. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + canExecute(handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Check whether one or more commands can be executed. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + canExecute(events: Events, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Check whether one or more commands can be executed. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + canExecute(events: Events, priority: number, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands pre-execute. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + preExecute(handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + + /** + * Intercept one or more commands pre-execute. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + preExecute(events: Events, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands pre-execute. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + preExecute(events: Events, priority: number, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands pre-executed. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + preExecuted(handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands pre-executed. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + preExecuted(events: Events, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands pre-executed. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + preExecuted(events: Events, priority: number, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands during execution. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + execute(handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands during execution. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + execute(events: Events, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands during execution. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + execute(events: Events, priority: number, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands after execution. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + executed(handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands after execution. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + executed(events: Events, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands after execution. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + executed(events: Events, priority: number, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands post-execute. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + postExecute(handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands post-execute. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + postExecute(events: Events, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands post-execute. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + postExecute(events: Events, priority: number, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands post-executed. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + postExecuted(handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands post-executed. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + postExecuted(events: Events, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands post-executed. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + postExecuted(events: Events, priority: number, handlerFn: ComposeHandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands during revert. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + revert(handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands during revert. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + revert(events: Events, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands during revert. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + revert(events: Events, priority: number, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands after revert. + * + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + reverted(handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands after revert. + * + * @param events One or more commands to intercept. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + reverted(events: Events, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; + + /** + * Intercept one or more commands after revert. + * + * @param events One or more commands to intercept. + * @param priority Priority with which command will be intercepted. + * @param handlerFn Callback. + * @param unwrap Whether the event should be unwrapped. + * @param that `this` value the callback will be called with. + */ + reverted(events: Events, priority: number, handlerFn: HandlerFunction, unwrap?: boolean, that?: any): void; +} \ No newline at end of file diff --git a/lib/command/CommandInterceptor.js b/lib/command/CommandInterceptor.js index 31515aedd..fb2e89a64 100644 --- a/lib/command/CommandInterceptor.js +++ b/lib/command/CommandInterceptor.js @@ -6,33 +6,41 @@ import { isObject } from 'min-dash'; +/** + * @typedef {import('../core/EventBus').default} EventBus + * @typedef {import(./CommandInterceptor).HandlerFunction} HandlerFunction + * @typedef {import(./CommandInterceptor).ComposeHandlerFunction} ComposeHandlerFunction + */ var DEFAULT_PRIORITY = 1000; /** - * A utility that can be used to plug-in into the command execution for + * A utility that can be used to plug into the command execution for * extension and/or validation. * + * @class + * @constructor + * * @param {EventBus} eventBus * * @example * - * import inherits from 'inherits-browser'; - * * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; * - * function CommandLogger(eventBus) { - * CommandInterceptor.call(this, eventBus); + * class CommandLogger extends CommandInterceptor { + * constructor(eventBus) { + * super(eventBus); * - * this.preExecute(function(event) { - * console.log('command pre-execute', event); + * this.preExecute('shape.create', (event) => { + * console.log('commandStack.shape-create.preExecute', event); * }); * } - * - * inherits(CommandLogger, CommandInterceptor); - * */ export default function CommandInterceptor(eventBus) { + + /** + * @type {EventBus} + */ this._eventBus = eventBus; } @@ -45,16 +53,15 @@ function unwrapEvent(fn, that) { } /** - * Register an interceptor for a command execution - * - * @param {string|Array} [events] list of commands to register on - * @param {string} [hook] command hook, i.e. preExecute, executed to listen on - * @param {number} [priority] the priority on which to hook into the execution - * @param {Function} handlerFn interceptor to be invoked with (event) - * @param {boolean} unwrap if true, unwrap the event and pass (context, command, event) to the - * listener instead - * @param {Object} [that] Pass context (`this`) to the handler function - */ + * Intercept a command during one of the phases. + * + * @param {string|string[]} [events] One or more commands to intercept. + * @param {string} [hook] Phase during which to intercept command. + * @param {number} [priority] Priority with which command will be intercepted. + * @param {ComposeHandlerFunction|HandlerFunction} handlerFn Callback. + * @param {boolean} [unwrap] Whether the event should be unwrapped. + * @param {*} [that] `this` value the callback will be called with. + */ CommandInterceptor.prototype.on = function(events, hook, priority, handlerFn, unwrap, that) { if (isFunction(hook) || isNumber(hook)) { @@ -110,24 +117,19 @@ var hooks = [ ]; /* - * Install hook shortcuts - * - * This will generate the CommandInterceptor#(preExecute|...|reverted) methods - * which will in term forward to CommandInterceptor#on. + * Add prototype methods for each phase of command execution (e.g. execute, + * revert). */ forEach(hooks, function(hook) { /** - * {canExecute|preExecute|preExecuted|execute|executed|postExecute|postExecuted|revert|reverted} - * - * A named hook for plugging into the command execution + * Add prototype method for a specific phase of command execution. * - * @param {string|Array} [events] list of commands to register on - * @param {number} [priority] the priority on which to hook into the execution - * @param {Function} handlerFn interceptor to be invoked with (event) - * @param {boolean} [unwrap=false] if true, unwrap the event and pass (context, command, event) to the - * listener instead - * @param {Object} [that] Pass context (`this`) to the handler function + * @param {string|string[]} [events] One or more commands to intercept. + * @param {number} [priority] Priority with which command will be intercepted. + * @param {ComposeHandlerFunction|HandlerFunction} handlerFn Callback. + * @param {boolean} [unwrap] Whether the event should be unwrapped. + * @param {*} [that] `this` value the callback will be called with. */ CommandInterceptor.prototype[hook] = function(events, priority, handlerFn, unwrap, that) { diff --git a/lib/command/CommandInterceptor.spec.ts b/lib/command/CommandInterceptor.spec.ts new file mode 100644 index 000000000..e2d3b1e98 --- /dev/null +++ b/lib/command/CommandInterceptor.spec.ts @@ -0,0 +1,79 @@ +import CommandInterceptor from '../../lib/command/CommandInterceptor'; + +import EventBus from '../../lib/core/EventBus'; + +import Modeling from '../../lib/features/modeling/Modeling'; + +export class AddShapeBehavior extends CommandInterceptor { + static $inject = [ 'eventBus', 'modeling' ]; + + constructor(eventBus: EventBus, modeling: Modeling) { + super(eventBus); + + this.canExecute((context) => {}, true); + + this.canExecute([ 'shape.create' ], (context) => {}, true); + + this.canExecute([ 'shape.create' ], 2000, (context) => {}, true); + + this.preExecute((context) => {}, true); + + this.preExecute([ 'shape.create' ], (context) => {}, true); + + this.preExecute([ 'shape.create' ], 2000, (context) => {}, true); + + this.preExecuted((context) => {}, true); + + this.preExecuted([ 'shape.create' ], (context) => {}, true); + + this.preExecuted([ 'shape.create' ], 2000, (context) => {}, true); + + this.execute((context) => {}, true); + + this.execute([ 'shape.create' ], (context) => {}, true); + + this.execute([ 'shape.create' ], (context) => [], true); + + this.execute([ 'shape.create' ], 2000, (context) => {}, true); + + this.executed((context) => {}, true); + + this.executed([ 'shape.create' ], (context) => {}, true); + + this.executed([ 'shape.create' ], (context) => [], true); + + this.executed([ 'shape.create' ], 2000, (context) => {}, true); + + this.postExecute((context) => {}, true); + + this.postExecute([ 'shape.create' ], (context) => {}, true); + + this.postExecute([ 'shape.create' ], 2000, (context) => {}, true); + + this.postExecuted((context) => {}, true); + + this.postExecuted([ 'shape.create' ], (context) => { + const { shape } = context; + + modeling.moveShape(shape, { x: 100, y: 100 }); + }, true); + + this.postExecuted([ 'shape.create' ], 2000, (context) => {}, true); + + this.revert((context) => {}, true); + + this.revert([ 'shape.create' ], (context) => {}, true); + + this.revert([ 'shape.create' ], (context) => [], true); + + this.revert([ 'shape.create' ], 2000, (context) => {}, true); + + this.reverted((context) => {}, true); + + this.reverted([ 'shape.create' ], (context) => {}, true); + + this.reverted([ 'shape.create' ], (context) => [], true); + + this.reverted([ 'shape.create' ], 2000, (context) => {}, true); + } +} \ No newline at end of file diff --git a/lib/command/CommandStack.d.ts b/lib/command/CommandStack.d.ts new file mode 100644 index 000000000..eb840a264 --- /dev/null +++ b/lib/command/CommandStack.d.ts @@ -0,0 +1,168 @@ +import { Injector } from 'didi'; + +import CommandHandler from './CommandHandler'; + +import EventBus from '../core/EventBus'; + +export type CommandContext = any; + +export type CommandStackAction = { + command: string; + context: any; +}; + +export type CommandHandlerConstructor = { + new (...args: any[]) : CommandHandler +}; + +export type CommandHandlerInstance = Object; + +export type CommandHandlerMap = { + [key: string]: CommandHandler; +}; + +/** + * A service that offers un- and redoable execution of commands. + * + * The command stack is responsible for executing modeling actions + * in a un- and redoable manner. To do this it delegates the actual + * command execution to {@link CommandHandler}s. + * + * Command handlers provide {@link CommandHandler#execute(ctx)} and + * {@link CommandHandler#revert(ctx)} methods to un- and redo a command + * identified by a command context. + * + * + * ## Life-Cycle events + * + * In the process the command stack fires a number of life-cycle events + * that other components to participate in the command execution. + * + * * preExecute + * * preExecuted + * * execute + * * executed + * * postExecute + * * postExecuted + * * revert + * * reverted + * + * A special event is used for validating, whether a command can be + * performed prior to its execution. + * + * * canExecute + * + * Each of the events is fired as `commandStack.{eventName}` and + * `commandStack.{commandName}.{eventName}`, respectively. This gives + * components fine grained control on where to hook into. + * + * The event object fired transports `command`, the name of the + * command and `context`, the command context. + * + * + * ## Creating Command Handlers + * + * Command handlers should provide the {@link CommandHandler#execute(ctx)} + * and {@link CommandHandler#revert(ctx)} methods to implement + * redoing and undoing of a command. + * + * A command handler _must_ ensure undo is performed properly in order + * not to break the undo chain. It must also return the shapes that + * got changed during the `execute` and `revert` operations. + * + * Command handlers may execute other modeling operations (and thus + * commands) in their `preExecute` and `postExecute` phases. The command + * stack will properly group all commands together into a logical unit + * that may be re- and undone atomically. + * + * Command handlers must not execute other commands from within their + * core implementation (`execute`, `revert`). + * + * + * ## Change Tracking + * + * During the execution of the CommandStack it will keep track of all + * elements that have been touched during the command's execution. + * + * At the end of the CommandStack execution it will notify interested + * components via an 'elements.changed' event with all the dirty + * elements. + * + * The event can be picked up by components that are interested in the fact + * that elements have been changed. One use case for this is updating + * their graphical representation after moving / resizing or deletion. + * + * @see CommandHandler + * + * @param eventBus + * @param injector + */ +export default class CommandStack { + constructor(eventBus: EventBus, injector: Injector); + + /** + * Execute a command. + * + * @param command The command to execute. + * @param context The context with which to execute the command. + */ + execute(command: string, context: CommandContext): void; + + /** + * Check whether a command can be executed. + * + * Implementors may hook into the mechanism on two ways: + * + * * in event listeners: + * + * Users may prevent the execution via an event listener. + * It must prevent the default action for `commandStack.(.)canExecute` events. + * + * * in command handlers: + * + * If the method {@link CommandHandler#canExecute} is implemented in a handler + * it will be called to figure out whether the execution is allowed. + * + * @param {string} command The command to execute. + * @param {CommandContext} context The context with which to execute the command. + * + * @return {boolean} Whether the command can be executed with the given context. + */ + canExecute(command: string, context: CommandContext): boolean; + + /** + * Clear the command stack, erasing all undo / redo history. + * + * @param emit Whether to fire an event. Defaults to `true`. + */ + clear(emit?: boolean): void; + + /** + * Undo last command(s) + */ + undo(): void; + + /** + * Redo last command(s) + */ + redo(): void; + + /** + * Register a handler instance with the command stack. + * + * @param command Command to be executed. + * @param handler Handler to execute the command. + */ + register(command: string, handler: CommandHandler): void; + + /** + * Register a handler type with the command stack by instantiating it and + * injecting its dependencies. + * + * @param {string} command Command to be executed. + * @param {CommandHandlerConstructor} handlerCls Constructor to instantiate a {@link CommandHandler}. + */ + registerHandler(command: string, handlerCls: CommandHandlerConstructor); + canUndo(): boolean; + canRedo(): boolean; +} \ No newline at end of file diff --git a/lib/command/CommandStack.js b/lib/command/CommandStack.js index 13fc23cec..8e6ef4344 100644 --- a/lib/command/CommandStack.js +++ b/lib/command/CommandStack.js @@ -4,6 +4,29 @@ import { } from 'min-dash'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../core/EventBus').default} EventBus + * + * @typedef {import('./CommandStack').CommandContext} CommandContext + * @typedef {import('./CommandHandler').default} CommandHandler + * @typedef {import('./CommandStack').CommandHandlerConstructor} CommandHandlerConstructor + * @typedef {import('./CommandStack').CommandHandlerMap} CommandHandlerMap + * @typedef {import('./CommandStack').CommandStackAction} CommandStackAction + * + * @property {CommandStackAction[]} actions + * @property {Base[]} dirty + * @property {string|null} trigger - Either 'execute', 'undo', 'redo', 'clear' or null. + */ + +/** + * @typedef {Object} CurrentExecution + * @property {CommandStackAction[]} actions + * @property {Base[]} dirty + * @property {string} trigger + */ + /** * A service that offers un- and redoable execution of commands. * @@ -85,14 +108,14 @@ export default function CommandStack(eventBus, injector) { /** * A map of all registered command handlers. * - * @type {Object} + * @type {CommandHandlerMap} */ this._handlerMap = {}; /** * A stack containing all re/undoable actions on the diagram * - * @type {Array} + * @type {CommandStackAction[]} */ this._stack = []; @@ -106,10 +129,7 @@ export default function CommandStack(eventBus, injector) { /** * Current active commandStack execution * - * @type {Object} - * @property {Object[]} actions - * @property {Object[]} dirty - * @property { 'undo' | 'redo' | 'clear' | 'execute' | null } trigger the cause of the current excecution + * @type {CurrentExecution} */ this._currentExecution = { actions: [], @@ -117,10 +137,19 @@ export default function CommandStack(eventBus, injector) { trigger: null }; - + /** + * @type {Injector} + */ this._injector = injector; + + /** + * @type EventBus + */ this._eventBus = eventBus; + /** + * @type { number } + */ this._uid = 1; eventBus.on([ @@ -135,10 +164,10 @@ CommandStack.$inject = [ 'eventBus', 'injector' ]; /** - * Execute a command + * Execute a command. * - * @param {string} command the command to execute - * @param {Object} context the environment to execute the command in + * @param {string} command The command to execute. + * @param {CommandContext} context The context with which to execute the command. */ CommandStack.prototype.execute = function(command, context) { if (!command) { @@ -156,7 +185,7 @@ CommandStack.prototype.execute = function(command, context) { /** - * Ask whether a given command can be executed. + * Check whether a command can be executed. * * Implementors may hook into the mechanism on two ways: * @@ -170,10 +199,10 @@ CommandStack.prototype.execute = function(command, context) { * If the method {@link CommandHandler#canExecute} is implemented in a handler * it will be called to figure out whether the execution is allowed. * - * @param {string} command the command to execute - * @param {Object} context the environment to execute the command in + * @param {string} command The command to execute. + * @param {CommandContext} context The context with which to execute the command. * - * @return {boolean} true if the command can be executed + * @return {boolean} Whether the command can be executed with the given context. */ CommandStack.prototype.canExecute = function(command, context) { @@ -200,7 +229,9 @@ CommandStack.prototype.canExecute = function(command, context) { /** - * Clear the command stack, erasing all undo / redo history + * Clear the command stack, erasing all undo / redo history. + * + * @param {boolean} [emit=true] Whether to fire an event. Defaults to `true`. */ CommandStack.prototype.clear = function(emit) { this._stack.length = 0; @@ -269,10 +300,10 @@ CommandStack.prototype.redo = function() { /** - * Register a handler instance with the command stack + * Register a handler instance with the command stack. * - * @param {string} command - * @param {CommandHandler} handler + * @param {string} command Command to be executed. + * @param {CommandHandler} handler Handler to execute the command. */ CommandStack.prototype.register = function(command, handler) { this._setHandler(command, handler); @@ -280,11 +311,11 @@ CommandStack.prototype.register = function(command, handler) { /** - * Register a handler type with the command stack - * by instantiating it and injecting its dependencies. + * Register a handler type with the command stack by instantiating it and + * injecting its dependencies. * - * @param {string} command - * @param {Function} a constructor for a {@link CommandHandler} + * @param {string} command Command to be executed. + * @param {CommandHandlerConstructor} handlerCls Constructor to instantiate a {@link CommandHandler}. */ CommandStack.prototype.registerHandler = function(command, handlerCls) { @@ -296,10 +327,16 @@ CommandStack.prototype.registerHandler = function(command, handlerCls) { this.register(command, handler); }; +/** + * @return {boolean} + */ CommandStack.prototype.canUndo = function() { return !!this._getUndoAction(); }; +/** + * @return {boolean} + */ CommandStack.prototype.canRedo = function() { return !!this._getRedoAction(); }; diff --git a/lib/command/CommandStack.spec.ts b/lib/command/CommandStack.spec.ts new file mode 100644 index 000000000..c7a0cb4be --- /dev/null +++ b/lib/command/CommandStack.spec.ts @@ -0,0 +1,30 @@ +import Diagram from '../../lib/Diagram'; + +import CommandModule from '../../lib/command'; +import CommandStack from '../../lib/command/CommandStack'; + +import { AddShapeHandler } from './CommandHandler.spec'; + +const diagram = new Diagram({ + modules: [ + CommandModule + ] +}); + +const commandStack = diagram.get('commandStack'); + +commandStack.registerHandler('shape.add', AddShapeHandler); + +commandStack.canExecute('shape.add', { foo: 'bar' }); + +commandStack.canUndo(); + +commandStack.canRedo(); + +commandStack.clear(); + +commandStack.execute('shape.add', { foo: 'bar' }); + +commandStack.redo(); + +commandStack.undo(); \ No newline at end of file diff --git a/lib/command/index.d.ts b/lib/command/index.d.ts new file mode 100644 index 000000000..9cee88af9 --- /dev/null +++ b/lib/command/index.d.ts @@ -0,0 +1,7 @@ +import { + ModuleDeclaration +} from 'didi'; + +declare const m : ModuleDeclaration; + +export default m; diff --git a/lib/core/Canvas.d.ts b/lib/core/Canvas.d.ts new file mode 100644 index 000000000..8cb1f7816 --- /dev/null +++ b/lib/core/Canvas.d.ts @@ -0,0 +1,378 @@ +import ElementRegistry from './ElementRegistry'; +import EventBus from './EventBus'; +import GraphicsFactory from './GraphicsFactory'; + +import { + ConnectionLike, + RootLike, + ShapeLike +} from '.'; + +import { + Dimensions, + Point, + Rect, + RectTRBL +} from '../util/Types'; + +export type CanvasConfig = { + container?: HTMLElement; + deferUpdate?: boolean; + width?: number; + height?: number; +}; + +export interface CanvasLayer { + group: SVGElement; + index: number; + visible: boolean; +} + +export type CanvasLayers = { + [key: string]: CanvasLayer; +}; + +export type CanvasPlane = { + rootElement: ShapeLike; + layer: CanvasLayer; +}; + +export interface CanvasViewbox extends Rect { + scale: number; + inner: Rect; + outer: Dimensions; +} + +/** + * The main drawing canvas. + * + * @class + * @constructor + * + * @emits Canvas#canvas.init + * + * @param config + * @param eventBus + * @param graphicsFactory + * @param elementRegistry + */ +export default class Canvas { + constructor(config: CanvasConfig, eventBus: EventBus, graphicsFactory: GraphicsFactory, elementRegistry: ElementRegistry); + + /** + * Returns the default layer on which + * all elements are drawn. + * + * @return The SVG element of the layer. + */ + getDefaultLayer(): SVGElement; + + /** + * Returns a layer that is used to draw elements + * or annotations on it. + * + * Non-existing layers retrieved through this method + * will be created. During creation, the optional index + * may be used to create layers below or above existing layers. + * A layer with a certain index is always created above all + * existing layers with the same index. + * + * @param name The name of the layer. + * @param index The index of the layer. + * + * @return {SVGElement} The SVG element of the layer. + */ + getLayer(name: string, index?: number): SVGElement; + + /** + * Shows a given layer. + * + * @param layer The name of the layer. + * + * @return The SVG element of the layer. + */ + showLayer(name: string): SVGElement; + + /** + * Hides a given layer. + * + * @param {string} layer The name of the layer. + * + * @return {SVGElement} The SVG element of the layer. + */ + hideLayer(name: string): SVGElement; + + /** + * Returns the currently active layer. Can be null. + * + * @return The active layer of `null`. + */ + getActiveLayer(): CanvasLayer | null; + + /** + * Returns the plane which contains the given element. + * + * @param element The element or its ID. + * + * @return The root of the element. + */ + findRoot(element: ShapeLike | ConnectionLike | string): RootLike | undefined; + + /** + * Return a list of all root elements on the diagram. + * + * @return The list of root elements. + */ + getRootElements(): (RootLike)[]; + + /** + * Returns the html element that encloses the + * drawing canvas. + * + * @return The HTML element of the container. + */ + getContainer(): HTMLElement; + + /** + * Adds a marker to an element (basically a css class). + * + * Fires the element.marker.update event, making it possible to + * integrate extension into the marker life-cycle, too. + * + * @example + * + * canvas.addMarker('foo', 'some-marker'); + * + * const fooGfx = canvas.getGraphics('foo'); + * + * fooGfx; // ... + * + * @param element The element or its ID. + * @param marker The marker. + */ + addMarker(element: ShapeLike | ConnectionLike | string, marker: string): void; + + /** + * Remove a marker from an element. + * + * Fires the element.marker.update event, making it possible to + * integrate extension into the marker life-cycle, too. + * + * @param element The element or its ID. + * @param marker The marker. + */ + removeMarker(element: ShapeLike | ConnectionLike | string, marker: string): void; + + /** + * Check whether an element has a given marker. + * + * @param element The element or its ID. + * @param marker The marker. + */ + hasMarker(element: ShapeLike | ConnectionLike | string, marker: string): boolean; + + /** + * Toggles a marker on an element. + * + * Fires the element.marker.update event, making it possible to + * integrate extension into the marker life-cycle, too. + * + * @param element The element or its ID. + * @param marker The marker. + */ + toggleMarker(element: ShapeLike | ConnectionLike | string, marker: string): void; + + /** + * Returns the current root element. + * + * Supports two different modes for handling root elements: + * + * 1. if no root element has been added before, an implicit root will be added + * and returned. This is used in applications that don't require explicit + * root elements. + * + * 2. when root elements have been added before calling `getRootElement`, + * root elements can be null. This is used for applications that want to manage + * root elements themselves. + * + * @return The current root element. + */ + getRootElement(): RootLike; + + /** + * Adds a given root element and returns it. + * + * @param rootElement The root element to be added. + * + * @return The added root element or an implicit root element. + */ + addRootElement(rootElement?: ShapeLike): RootLike; + + /** + * Removes a given root element and returns it. + * + * @param rootElement The root element or its ID. + * + * @return The removed root element. + */ + removeRootElement(rootElement: ShapeLike | string): ShapeLike | undefined; + + /** + * Sets a given element as the new root element for the canvas + * and returns the new root element. + * + * @param rootElement The root element to be set. + * + * @return The set root element. + */ + setRootElement(rootElement: RootLike): RootLike; + + /** + * Adds a shape to the canvas. + * + * @param shape The shape to be added. + * @param parent The shape's parent. + * @param parentIndex The index at which to add the shape to the parent's children. + * + * @return The added shape. + */ + addShape(shape: ShapeLike, parent?: ShapeLike, parentIndex?: number): ShapeLike; + + /** + * Adds a connection to the canvas. + * + * @param connection The connection to be added. + * @param parent The connection's parent. + * @param parentIndex The index at which to add the connection to the parent's children. + * + * @return The added connection. + */ + addConnection(connection: ConnectionLike, parent?: ShapeLike, parentIndex?: number): ConnectionLike; + + /** + * Removes a shape from the canvas. + * + * @param shape The shape or its ID. + * + * @return The removed shape. + */ + removeShape(shape: ShapeLike | string): ShapeLike; + + /** + * Removes a connection from the canvas. + * + * @param connection The connection or its ID. + * + * @return The removed connection. + */ + removeConnection(connection: ConnectionLike | string): ConnectionLike; + + /** + * Returns the graphical element of an element. + * + * @param element The element or its ID. + * @param secondary Whether to return the secondary graphical element. + * + * @return The graphical element. + */ + getGraphics(element: ShapeLike | ConnectionLike | string, secondary?: boolean): SVGElement; + + /** + * Gets or sets the view box of the canvas, i.e. the + * area that is currently displayed. + * + * The getter may return a cached viewbox (if it is currently + * changing). To force a recomputation, pass `false` as the first argument. + * + * @example + * + * canvas.viewbox({ x: 100, y: 100, width: 500, height: 500 }) + * + * // sets the visible area of the diagram to (100|100) -> (600|100) + * // and and scales it according to the diagram width + * + * const viewbox = canvas.viewbox(); // pass `false` to force recomputing the box. + * + * console.log(viewbox); + * // { + * // inner: Dimensions, + * // outer: Dimensions, + * // scale, + * // x, y, + * // width, height + * // } + * + * // if the current diagram is zoomed and scrolled, you may reset it to the + * // default zoom via this method, too: + * + * const zoomedAndScrolledViewbox = canvas.viewbox(); + * + * canvas.viewbox({ + * x: 0, + * y: 0, + * width: zoomedAndScrolledViewbox.outer.width, + * height: zoomedAndScrolledViewbox.outer.height + * }); + * + * @param box The viewbox to be set. + * + * @return The set viewbox. + */ + viewbox(box?: Rect): CanvasViewbox; + + /** + * Gets or sets the scroll of the canvas. + * + * @param delta The scroll to be set. + */ + scroll(delta: Point): Point; + + /** + * Scrolls the viewbox to contain the given element. + * Optionally specify a padding to be applied to the edges. + * + * @param element The element to scroll to or its ID. + * @param padding The padding to be applied. Can also specify top, bottom, left and right. + */ + scrollToElement(element: ShapeLike | ConnectionLike | string, padding?: RectTRBL | number): void; + + /** + * Gets or sets the current zoom of the canvas, optionally zooming to the + * specified position. + * + * The getter may return a cached zoom level. Call it with `false` as the first + * argument to force recomputation of the current level. + * + * @param newScale The new zoom level, either a number, + * i.e. 0.9, or `fit-viewport` to adjust the size to fit the current viewport. + * @param center The reference point { x: ..., y: ...} to zoom to. + * + * @return The set zoom level. + */ + zoom(newScale?: number | 'fit-viewport', center?: Point): number; + + /** + * Returns the size of the canvas. + * + * @return The size of the canvas. + */ + getSize(): Dimensions; + + /** + * Returns the absolute bounding box of an element. + * + * The absolute bounding box may be used to display overlays in the callers + * (browser) coordinate system rather than the zoomed in/out canvas coordinates. + * + * @param element The element. + * + * @return The element's absolute bounding box. + */ + getAbsoluteBBox(element: ShapeLike | ConnectionLike): Rect; + + /** + * Fires an event in order other modules can react to the + * canvas resizing + */ + resized(): void; +} \ No newline at end of file diff --git a/lib/core/Canvas.js b/lib/core/Canvas.js index a40c5fecb..3f477d15b 100644 --- a/lib/core/Canvas.js +++ b/lib/core/Canvas.js @@ -37,6 +37,26 @@ import { import { createMatrix as createMatrix } from 'tiny-svg'; +/** + * @typedef {import('.').ConnectionLike} ConnectionLike + * @typedef {import('.').RootLike} RootLike + * @typedef {import('.').ShapeLike} ShapeLike + * + * @typedef {import('./Canvas').CanvasConfig} CanvasConfig + * @typedef {import('./Canvas').CanvasLayer} CanvasLayer + * @typedef {import('./Canvas').CanvasLayers} CanvasLayers + * @typedef {import('./Canvas').CanvasPlane} CanvasPlane + * @typedef {import('./Canvas').CanvasViewbox} CanvasViewbox + * + * @typedef {import('./ElementRegistry').default} ElementRegistry + * @typedef {import('./EventBus').default} EventBus + * @typedef {import('./GraphicsFactory').default} GraphicsFactory + * + * @typedef {import('../util/Types').Dimensions} Dimensions + * @typedef {import('../util/Types').Point} Point + * @typedef {import('../util/Types').Rect} Rect + * @typedef {import('../util/Types').RectTRBL} RectTRBL + */ function round(number, resolution) { return Math.round(number * resolution) / resolution; @@ -58,7 +78,8 @@ function findRoot(element) { * Creates a HTML container element for a SVG element with * the given configuration * - * @param {Object} options + * @param {CanvasConfig} options + * * @return {HTMLElement} the container element */ function createContainer(options) { @@ -118,21 +139,34 @@ const REQUIRED_MODEL_ATTRS = { * * @emits Canvas#canvas.init * - * @param {Object} config + * @param {CanvasConfig|null} config * @param {EventBus} eventBus * @param {GraphicsFactory} graphicsFactory * @param {ElementRegistry} elementRegistry */ export default function Canvas(config, eventBus, graphicsFactory, elementRegistry) { - this._eventBus = eventBus; this._elementRegistry = elementRegistry; this._graphicsFactory = graphicsFactory; + /** + * @type {number} + */ this._rootsIdx = 0; + /** + * @type {CanvasLayers} + */ this._layers = {}; + + /** + * @type {CanvasPlane[]} + */ this._planes = []; + + /** + * @type {RootLike|null} + */ this._rootElement = null; this._init(config || {}); @@ -157,6 +191,8 @@ Canvas.$inject = [ * ... * * + * + * @param {CanvasConfig} config */ Canvas.prototype._init = function(config) { @@ -178,7 +214,7 @@ Canvas.prototype._init = function(config) { this._viewboxChanged = debounce(bind(this._viewboxChanged, this), 300); } - eventBus.on('diagram.init', function() { + eventBus.on('diagram.init', () => { /** * An event indicating that the canvas is ready to be drawn on. @@ -196,7 +232,7 @@ Canvas.prototype._init = function(config) { viewport: viewport }); - }, this); + }); // reset viewbox on shape changes to // recompute the viewbox @@ -207,15 +243,15 @@ Canvas.prototype._init = function(config) { 'connection.removed', 'elements.changed', 'root.set' - ], function() { + ], () => { delete this._cachedViewbox; - }, this); + }); eventBus.on('diagram.destroy', 500, this._destroy, this); eventBus.on('diagram.clear', 500, this._clear, this); }; -Canvas.prototype._destroy = function(emit) { +Canvas.prototype._destroy = function() { this._eventBus.fire('canvas.destroy', { svg: this._svg, viewport: this._viewport @@ -262,7 +298,7 @@ Canvas.prototype._clear = function() { * Returns the default layer on which * all elements are drawn. * - * @returns {SVGElement} + * @return {SVGElement} The SVG element of the layer. */ Canvas.prototype.getDefaultLayer = function() { return this.getLayer(BASE_LAYER, PLANE_LAYER_INDEX); @@ -278,10 +314,10 @@ Canvas.prototype.getDefaultLayer = function() { * A layer with a certain index is always created above all * existing layers with the same index. * - * @param {string} name - * @param {number} index + * @param {string} name The name of the layer. + * @param {number} [index] The index of the layer. * - * @returns {SVGElement} + * @return {SVGElement} The SVG element of the layer. */ Canvas.prototype.getLayer = function(name, index) { @@ -310,8 +346,9 @@ Canvas.prototype.getLayer = function(name, index) { * * This is used to determine the node a layer should be inserted at. * - * @param {Number} index - * @returns {Number} + * @param {number} index + * + * @return {number} */ Canvas.prototype._getChildIndex = function(index) { return reduce(this._layers, function(childIndex, layer) { @@ -329,7 +366,7 @@ Canvas.prototype._getChildIndex = function(index) { * @param {string} name * @param {number} [index=0] * - * @return {Object} layer descriptor with { index, group: SVGGroup } + * @return {CanvasLayer} */ Canvas.prototype._createLayer = function(name, index) { @@ -350,8 +387,9 @@ Canvas.prototype._createLayer = function(name, index) { /** * Shows a given layer. * - * @param {String} layer - * @returns {SVGElement} + * @param {string} layer The name of the layer. + * + * @return {SVGElement} The SVG element of the layer. */ Canvas.prototype.showLayer = function(name) { @@ -385,8 +423,9 @@ Canvas.prototype.showLayer = function(name) { /** * Hides a given layer. * - * @param {String} layer - * @returns {SVGElement} + * @param {string} layer The name of the layer. + * + * @return {SVGElement} The SVG element of the layer. */ Canvas.prototype.hideLayer = function(name) { @@ -428,7 +467,7 @@ Canvas.prototype._removeLayer = function(name) { /** * Returns the currently active layer. Can be null. * - * @returns {SVGElement|null} + * @return {CanvasLayer|null} The active layer of `null`. */ Canvas.prototype.getActiveLayer = function() { const plane = this._findPlaneForRoot(this.getRootElement()); @@ -444,9 +483,9 @@ Canvas.prototype.getActiveLayer = function() { /** * Returns the plane which contains the given element. * - * @param {string|djs.model.Base} element + * @param {ShapeLike|ConnectionLike|string} element The element or its ID. * - * @return {djs.model.Base} root for element + * @return {RootLike|undefined} The root of the element. */ Canvas.prototype.findRoot = function(element) { if (typeof element === 'string') { @@ -467,7 +506,7 @@ Canvas.prototype.findRoot = function(element) { /** * Return a list of all root elements on the diagram. * - * @return {djs.model.Root[]} + * @return {(RootLike)[]} The list of root elements. */ Canvas.prototype.getRootElements = function() { return this._planes.map(function(plane) { @@ -486,7 +525,7 @@ Canvas.prototype._findPlaneForRoot = function(rootElement) { * Returns the html element that encloses the * drawing canvas. * - * @return {DOMNode} + * @return {HTMLElement} The HTML element of the container. */ Canvas.prototype.getContainer = function() { return this._container; @@ -526,8 +565,8 @@ Canvas.prototype._updateMarker = function(element, marker, add) { * * @event element.marker.update * @type {Object} - * @property {djs.model.Element} element the shape - * @property {Object} gfx the graphical representation of the shape + * @property {Base} element the shape + * @property {SVGElement} gfx the graphical representation of the shape * @property {string} marker * @property {boolean} add true if the marker was added, false if it got removed */ @@ -542,14 +581,15 @@ Canvas.prototype._updateMarker = function(element, marker, add) { * integrate extension into the marker life-cycle, too. * * @example + * * canvas.addMarker('foo', 'some-marker'); * * const fooGfx = canvas.getGraphics('foo'); * * fooGfx; // ... * - * @param {string|djs.model.Base} element - * @param {string} marker + * @param {ShapeLike|ConnectionLike|string} element The element or its ID. + * @param {string} marker The marker. */ Canvas.prototype.addMarker = function(element, marker) { this._updateMarker(element, marker, true); @@ -562,18 +602,18 @@ Canvas.prototype.addMarker = function(element, marker) { * Fires the element.marker.update event, making it possible to * integrate extension into the marker life-cycle, too. * - * @param {string|djs.model.Base} element - * @param {string} marker + * @param {ShapeLike|ConnectionLike|string} element The element or its ID. + * @param {string} marker The marker. */ Canvas.prototype.removeMarker = function(element, marker) { this._updateMarker(element, marker, false); }; /** - * Check the existence of a marker on element. + * Check whether an element has a given marker. * - * @param {string|djs.model.Base} element - * @param {string} marker + * @param {ShapeLike|ConnectionLike|string} element The element or its ID. + * @param {string} marker The marker. */ Canvas.prototype.hasMarker = function(element, marker) { if (!element.id) { @@ -591,8 +631,8 @@ Canvas.prototype.hasMarker = function(element, marker) { * Fires the element.marker.update event, making it possible to * integrate extension into the marker life-cycle, too. * - * @param {string|djs.model.Base} element - * @param {string} marker + * @param {ShapeLike|ConnectionLike|string} element The element or its ID. + * @param {string} marker The marker. */ Canvas.prototype.toggleMarker = function(element, marker) { if (this.hasMarker(element, marker)) { @@ -615,7 +655,7 @@ Canvas.prototype.toggleMarker = function(element, marker) { * root elements can be null. This is used for applications that want to manage * root elements themselves. * - * @returns {Object|djs.model.Root|null} rootElement. + * @return {RootLike} The current root element. */ Canvas.prototype.getRootElement = function() { const rootElement = this._rootElement; @@ -631,11 +671,10 @@ Canvas.prototype.getRootElement = function() { /** * Adds a given root element and returns it. * - * @param {Object|djs.model.Root} rootElement + * @param {ShapeLike} [rootElement] The root element to be added. * - * @return {Object|djs.model.Root} rootElement + * @return {RootLike} The added root element or an implicit root element. */ - Canvas.prototype.addRootElement = function(rootElement) { const idx = this._rootsIdx++; @@ -666,11 +705,11 @@ Canvas.prototype.addRootElement = function(rootElement) { }; /** - * Removes a given rootElement and returns it. + * Removes a given root element and returns it. * - * @param {djs.model.Root|String} rootElement + * @param {ShapeLike|string} rootElement The root element or its ID. * - * @return {Object|djs.model.Root} rootElement + * @return {ShapeLike|undefined} The removed root element. */ Canvas.prototype.removeRootElement = function(rootElement) { @@ -704,15 +743,13 @@ Canvas.prototype.removeRootElement = function(rootElement) { }; -// root element handling ////////////////////// - /** * Sets a given element as the new root element for the canvas * and returns the new root element. * - * @param {Object|djs.model.Root} rootElement + * @param {RootLike} rootElement The root element to be set. * - * @return {Object|djs.model.Root} new root element + * @return {RootLike} The set root element. */ Canvas.prototype.setRootElement = function(rootElement, override) { @@ -799,8 +836,6 @@ Canvas.prototype._setRoot = function(rootElement, layer) { this._eventBus.fire('root.set', { element: rootElement }); }; -// add functionality ////////////////////// - Canvas.prototype._ensureValid = function(type, element) { if (!element.id) { throw new Error('element must have an id'); @@ -841,11 +876,11 @@ Canvas.prototype._setParent = function(element, parent, parentIndex) { * Extensions may hook into these events to perform their magic. * * @param {string} type - * @param {Object|djs.model.Base} element - * @param {Object|djs.model.Base} [parent] + * @param {ConnectionLike|ShapeLike} element + * @param {ShapeLike} [parent] * @param {number} [parentIndex] * - * @return {Object|djs.model.Base} the added element + * @return {ConnectionLike|ShapeLike} The added element. */ Canvas.prototype._addElement = function(type, element, parent, parentIndex) { @@ -874,26 +909,26 @@ Canvas.prototype._addElement = function(type, element, parent, parentIndex) { }; /** - * Adds a shape to the canvas + * Adds a shape to the canvas. * - * @param {Object|djs.model.Shape} shape to add to the diagram - * @param {djs.model.Base} [parent] - * @param {number} [parentIndex] + * @param {ShapeLike} shape The shape to be added + * @param {ShapeLike} [parent] The shape's parent. + * @param {number} [parentIndex] The index at which to add the shape to the parent's children. * - * @return {djs.model.Shape} the added shape + * @return {ShapeLike} The added shape. */ Canvas.prototype.addShape = function(shape, parent, parentIndex) { return this._addElement('shape', shape, parent, parentIndex); }; /** - * Adds a connection to the canvas + * Adds a connection to the canvas. * - * @param {Object|djs.model.Connection} connection to add to the diagram - * @param {djs.model.Base} [parent] - * @param {number} [parentIndex] + * @param {ConnectionLike} connection The connection to be added. + * @param {ShapeLike} [parent] The connection's parent. + * @param {number} [parentIndex] The index at which to add the connection to the parent's children. * - * @return {djs.model.Connection} the added connection + * @return {ConnectionLike} The added connection. */ Canvas.prototype.addConnection = function(connection, parent, parentIndex) { return this._addElement('connection', connection, parent, parentIndex); @@ -934,11 +969,14 @@ Canvas.prototype._removeElement = function(element, type) { /** - * Removes a shape from the canvas + * Removes a shape from the canvas. * - * @param {string|djs.model.Shape} shape or shape id to be removed + * @fires ShapeRemoveEvent + * @fires ShapeRemovedEvent * - * @return {djs.model.Shape} the removed shape + * @param {ShapeLike|string} shape The shape or its ID. + * + * @return {ShapeLike} The removed shape. */ Canvas.prototype.removeShape = function(shape) { @@ -947,10 +985,10 @@ Canvas.prototype.removeShape = function(shape) { * * @memberOf Canvas * - * @event shape.remove + * @event ShapeRemoveEvent * @type {Object} - * @property {djs.model.Shape} element the shape descriptor - * @property {Object} gfx the graphical representation of the shape + * @property {ShapeLike} element The shape. + * @property {SVGElement} gfx The graphical element. */ /** @@ -958,21 +996,24 @@ Canvas.prototype.removeShape = function(shape) { * * @memberOf Canvas * - * @event shape.removed + * @event ShapeRemoved * @type {Object} - * @property {djs.model.Shape} element the shape descriptor - * @property {Object} gfx the graphical representation of the shape + * @property {ShapeLike} element The shape. + * @property {SVGElement} gfx The graphical element. */ return this._removeElement(shape, 'shape'); }; /** - * Removes a connection from the canvas + * Removes a connection from the canvas. + * + * @fires ConnectionRemoveEvent + * @fires ConnectionRemovedEvent * - * @param {string|djs.model.Connection} connection or connection id to be removed + * @param {ConnectionLike|string} connection The connection or its ID. * - * @return {djs.model.Connection} the removed connection + * @return {ConnectionLike} The removed connection. */ Canvas.prototype.removeConnection = function(connection) { @@ -981,10 +1022,10 @@ Canvas.prototype.removeConnection = function(connection) { * * @memberOf Canvas * - * @event connection.remove + * @event ConnectionRemoveEvent * @type {Object} - * @property {djs.model.Connection} element the connection descriptor - * @property {Object} gfx the graphical representation of the connection + * @property {ConnectionLike} element The connection. + * @property {SVGElement} gfx The graphical element. */ /** @@ -994,20 +1035,20 @@ Canvas.prototype.removeConnection = function(connection) { * * @event connection.removed * @type {Object} - * @property {djs.model.Connection} element the connection descriptor - * @property {Object} gfx the graphical representation of the connection + * @property {ConnectionLike} element The connection. + * @property {SVGElement} gfx The graphical element. */ return this._removeElement(connection, 'connection'); }; /** - * Return the graphical object underlaying a certain diagram element + * Returns the graphical element of an element. * - * @param {string|djs.model.Base} element descriptor of the element - * @param {boolean} [secondary=false] whether to return the secondary connected element + * @param {ShapeLike|ConnectionLike|string} element The element or its ID. + * @param {boolean} [secondary=false] Whether to return the secondary graphical element. * - * @return {SVGElement} + * @return {SVGElement} The graphical element. */ Canvas.prototype.getGraphics = function(element, secondary) { return this._elementRegistry.getGraphics(element, secondary); @@ -1079,13 +1120,9 @@ Canvas.prototype._viewboxChanged = function() { * height: zoomedAndScrolledViewbox.outer.height * }); * - * @param {Object} [box] the new view box to set - * @param {number} box.x the top left X coordinate of the canvas visible in view box - * @param {number} box.y the top left Y coordinate of the canvas visible in view box - * @param {number} box.width the visible width - * @param {number} box.height + * @param {Rect} [box] The viewbox to be set. * - * @return {Object} the current view box + * @return {CanvasViewbox} The set viewbox. */ Canvas.prototype.viewbox = function(box) { @@ -1154,10 +1191,9 @@ Canvas.prototype.viewbox = function(box) { /** * Gets or sets the scroll of the canvas. * - * @param {Object} [delta] the new scroll to apply. + * @param {Point} [delta] The scroll to be set. * - * @param {number} [delta.dx] - * @param {number} [delta.dy] + * @return {Point} */ Canvas.prototype.scroll = function(delta) { @@ -1181,9 +1217,8 @@ Canvas.prototype.scroll = function(delta) { * Scrolls the viewbox to contain the given element. * Optionally specify a padding to be applied to the edges. * - * @param {Object|String} [element] the element to scroll to. - * @param {Object|Number} [padding=100] the padding to be applied. Can also specify top, bottom, left and right. - * + * @param {ShapeLike|ConnectionLike|string} element The element to scroll to or its ID. + * @param {RectTRBL|number} [padding=100] The padding to be applied. Can also specify top, bottom, left and right. */ Canvas.prototype.scrollToElement = function(element, padding) { let defaultPadding = 100; @@ -1251,17 +1286,17 @@ Canvas.prototype.scrollToElement = function(element, padding) { }; /** - * Gets or sets the current zoom of the canvas, optionally zooming - * to the specified position. + * Gets or sets the current zoom of the canvas, optionally zooming to the + * specified position. * - * The getter may return a cached zoom level. Call it with `false` as - * the first argument to force recomputation of the current level. + * The getter may return a cached zoom level. Call it with `false` as the first + * argument to force recomputation of the current level. * - * @param {string|number} [newScale] the new zoom level, either a number, i.e. 0.9, - * or `fit-viewport` to adjust the size to fit the current viewport - * @param {string|Point} [center] the reference point { x: .., y: ..} to zoom to, 'auto' to zoom into mid or null + * @param {number|string} [newScale] The new zoom level, either a number, + * i.e. 0.9, or `fit-viewport` to adjust the size to fit the current viewport. + * @param {Point} [center] The reference point { x: ..., y: ...} to zoom to. * - * @return {number} the current scale + * @return {number} The set zoom level. */ Canvas.prototype.zoom = function(newScale, center) { @@ -1384,9 +1419,9 @@ Canvas.prototype._setZoom = function(scale, center) { /** - * Returns the size of the canvas + * Returns the size of the canvas. * - * @return {Dimensions} + * @return {Dimensions} The size of the canvas. */ Canvas.prototype.getSize = function() { return { @@ -1397,14 +1432,14 @@ Canvas.prototype.getSize = function() { /** - * Return the absolute bounding box for the given element + * Returns the absolute bounding box of an element. + * + * The absolute bounding box may be used to display overlays in the callers + * (browser) coordinate system rather than the zoomed in/out canvas coordinates. * - * The absolute bounding box may be used to display overlays in the - * callers (browser) coordinate system rather than the zoomed in/out - * canvas coordinates. + * @param {ShapeLike|ConnectionLike} element The element. * - * @param {ElementDescriptor} element - * @return {Bounds} the absolute bounding box + * @return {Rect} The element's absolute bounding box. */ Canvas.prototype.getAbsoluteBBox = function(element) { const vbox = this.viewbox(); @@ -1439,8 +1474,7 @@ Canvas.prototype.getAbsoluteBBox = function(element) { }; /** - * Fires an event in order other modules can react to the - * canvas resizing + * Fires an event so other modules can react to the canvas resizing. */ Canvas.prototype.resized = function() { diff --git a/lib/core/Canvas.spec.ts b/lib/core/Canvas.spec.ts new file mode 100644 index 000000000..44cf7bcdd --- /dev/null +++ b/lib/core/Canvas.spec.ts @@ -0,0 +1,206 @@ +import Diagram from '../../lib/Diagram'; + +import CoreModule from '../../lib/core'; +import Canvas from '../../lib/core/Canvas'; +import ElementFactory from '../../lib/core/ElementFactory'; + +const diagram = new Diagram({ + modules: [ + CoreModule + ] +}); + +const shapeLike = { + id: 'shapeLike', + x: 100, + y: 100, + width: 100, + height: 100 +}; + +const connectionLike = { + id: 'connectionLike', + waypoints: [ + { + x: 100, + y: 100 + }, + { + x: 200, + y: 100 + } + ] +}; + +const parentLike = { + id: 'parentLike', + x: 100, + y: 100, + width: 100, + height: 100 +}; + +const elementFactory = diagram.get('elementFactory'); + +const shape1 = elementFactory.create('shape', { + id: 'shape1', + x: 100, + y: 100, + width: 100, + height: 100 +}); + +const shape2 = elementFactory.create('shape', { + id: 'shape2', + x: 100, + y: 100, + width: 100, + height: 100 +}); + +const connection = elementFactory.create('connection', { + id: 'connection', + source: shape1, + target: shape2, + waypoints: [] +}); + +const root = elementFactory.create('root', { + id: 'root' +}); + +const canvas = diagram.get('canvas'); + +canvas.addShape(shape1, root); + +canvas.addShape(shape1); + +canvas.addShape(shape1, root, 1); + +canvas.addShape(shapeLike, parentLike); + +canvas.addConnection(connection); + +canvas.addConnection(connection, root); + +canvas.addConnection(connection, root, 1); + +canvas.addConnection(connectionLike, parentLike); + +canvas.addMarker(shape1, 'foobar'); + +canvas.addMarker(shapeLike, 'foobar'); + +canvas.addMarker(connectionLike, 'foobar'); + +canvas.addRootElement(); + +canvas.addRootElement(root); + +canvas.findRoot(shape1); + +canvas.findRoot(shapeLike); + +canvas.findRoot(connectionLike); + +canvas.getAbsoluteBBox(shape1); + +canvas.getAbsoluteBBox(shapeLike); + +canvas.getAbsoluteBBox(connectionLike); + +canvas.getActiveLayer(); + +canvas.getDefaultLayer(); + +canvas.getGraphics(shape1); + +canvas.getGraphics(shape1, true); + +canvas.getGraphics(shapeLike); + +canvas.getGraphics(connectionLike); + +canvas.getLayer('foo'); + +canvas.getLayer('foo', 1); + +canvas.getRootElement(); + +canvas.getRootElements(); + +canvas.getContainer(); + +canvas.getSize(); + +canvas.hasMarker(shape1, 'foo'); + +canvas.hasMarker(shapeLike, 'foo'); + +canvas.hasMarker(connectionLike, 'foo'); + +canvas.hideLayer('foo'); + +canvas.removeMarker(shape1, 'foo'); + +canvas.removeMarker(shapeLike, 'foo'); + +canvas.removeMarker(connectionLike, 'foo'); + +canvas.removeRootElement('root'); + +canvas.removeRootElement(root); + +canvas.removeRootElement(shapeLike); + +canvas.removeShape(shape1); + +canvas.removeShape(shapeLike); + +canvas.removeConnection(connection); + +canvas.removeConnection(connectionLike); + +canvas.resized(); + +canvas.scroll({ x: 100, y: 100 }); + +canvas.scrollToElement('shape'); + +canvas.scrollToElement(shape1); + +canvas.scrollToElement(shape1, 100); + +canvas.scrollToElement(shape1, { + top: 100, + right: 100, + bottom: 100, + left: 100 +}); + +canvas.scrollToElement(shapeLike); + +canvas.scrollToElement(connectionLike); + +canvas.setRootElement(root); + +canvas.showLayer('foo'); + +canvas.toggleMarker(shape1, 'foo'); + +canvas.toggleMarker(shapeLike, 'foo'); + +canvas.toggleMarker(connectionLike, 'foo'); + +canvas.viewbox(); + +canvas.viewbox({ x: 100, y: 100, width: 100, height: 100 }); + +canvas.zoom(); + +canvas.zoom(1); + +canvas.zoom(1, { + x: 100, + y: 100 +}); \ No newline at end of file diff --git a/lib/core/ElementFactory.d.ts b/lib/core/ElementFactory.d.ts new file mode 100644 index 000000000..139f34b83 --- /dev/null +++ b/lib/core/ElementFactory.d.ts @@ -0,0 +1,97 @@ +import { + Connection, + Label, + ModelAttrsConnection, + ModelAttrsLabel, + ModelAttrsRoot, + ModelAttrsShape, + ModelTypeConnection, + ModelTypeLabel, + ModelTypeRoot, + ModelTypeShape, + Root, + Shape +} from '../model'; + +/** + * A factory for model elements. + */ +export default class ElementFactory { + constructor(); + + /** + * Create a root element. + * + * @param attrs The attributes of the root element to be created. + * + * @return The created root element. + */ + createRoot(attrs?: ModelAttrsRoot): Root; + + /** + * Create a label. + * + * @param attrs The attributes of the label to be created. + * + * @return The created label. + */ + createLabel(attrs?: ModelAttrsLabel): Label; + + /** + * Create a shape. + * + * @param attrs The attributes of the shape to be created. + * + * @return The created shape. + */ + createShape(attrs?: ModelAttrsShape): Shape; + + /** + * Create a connection. + * + * @param attrs The attributes of the connection to be created. + * + * @return The created connection. + */ + createConnection(attrs?: ModelAttrsConnection): Connection; + + /** + * Create a connection model element with the given attributes. + * + * @param type The type of the model element which is 'connection'. + * @param attrs The attributes of the connection model element. + * + * @return The created connection model element. + */ + create(type: ModelTypeConnection, attrs?: ModelAttrsConnection): Connection; + + /** + * Create a label model element with the given attributes. + * + * @param type The type of the model element which is 'label'. + * @param attrs The attributes of the label model element. + * + * @return The created label model element. + */ + create(type: ModelTypeLabel, attrs?: ModelAttrsLabel): Label; + + /** + * Create a root model element with the given attributes. + * + * @param type The type of the model element which is 'root'. + * @param attrs The attributes of the root model element. + * + * @return The created root model element. + */ + create(type: ModelTypeRoot, attrs?: ModelAttrsRoot): Root; + + /** + * Create a shape model element with the given attributes. + * + * @param type The type of the model element which is 'shape'. + * @param attrs The attributes of the shape model element. + * + * @return The created shape model element. + */ + create(type: ModelTypeShape, attrs?: ModelAttrsShape): Shape; +} \ No newline at end of file diff --git a/lib/core/ElementFactory.js b/lib/core/ElementFactory.js index d1bde1795..887e33cd4 100644 --- a/lib/core/ElementFactory.js +++ b/lib/core/ElementFactory.js @@ -5,36 +5,78 @@ import { import { assign } from 'min-dash'; /** - * A factory for diagram-js shapes + * @typedef {import('../model/index').Base} Base + * @typedef {import('../model/index').Connection} Connection + * @typedef {import('../model/index').Label} Label + * @typedef {import('../model/index').Root} Root + * @typedef {import('../model/index').Shape} Shape + * @typedef {import('../model/index').ModelAttrsConnection} ModelAttrsConnection + * @typedef {import('../model/index').ModelAttrsLabel} ModelAttrsLabel + * @typedef {import('../model/index').ModelAttrsRoot} ModelAttrsRoot + * @typedef {import('../model/index').ModelAttrsShape} ModelAttrsShape + */ + +/** + * A factory for model elements. + * + * @class + * @constructor */ export default function ElementFactory() { this._uid = 12; } - +/** + * Create a root element. + * + * @param {ModelAttrsRoot} attrs The attributes of the root element to be created. + * + * @return {Root} The created root element. + */ ElementFactory.prototype.createRoot = function(attrs) { return this.create('root', attrs); }; +/** + * Create a label. + * + * @param {ModelAttrsLabel} attrs The attributes of the label to be created. + * + * @return {Label} The created label. + */ ElementFactory.prototype.createLabel = function(attrs) { return this.create('label', attrs); }; +/** + * Create a shape. + * + * @param {ModelAttrsShape} attrs The attributes of the shape to be created. + * + * @return {Shape} The created shape. + */ ElementFactory.prototype.createShape = function(attrs) { return this.create('shape', attrs); }; +/** + * Create a connection. + * + * @param {ModelAttrsConnection} attrs The attributes of the connection to be created. + * + * @return {Connection} The created connection. + */ ElementFactory.prototype.createConnection = function(attrs) { return this.create('connection', attrs); }; /** - * Create a model element with the given type and - * a number of pre-set attributes. + * Create a model element of the given type with the given attributes. + * + * @param {string} type The type of the model element. + * @param {Object} attrs The attributes of the model element. * - * @param {string} type - * @param {Object} attrs - * @return {djs.model.Base} the newly created model instance + * @return {Connection|Label|Root|Shape} The created model element. */ ElementFactory.prototype.create = function(type, attrs) { diff --git a/lib/core/ElementFactory.spec.ts b/lib/core/ElementFactory.spec.ts new file mode 100644 index 000000000..0655edcfb --- /dev/null +++ b/lib/core/ElementFactory.spec.ts @@ -0,0 +1,59 @@ +import Diagram from '../../lib/Diagram'; + +import CoreModule from '../../lib/core'; +import ElementFactory from '../../lib/core/ElementFactory'; + +const diagram = new Diagram({ + modules: [ + CoreModule + ] +}); + +const elementFactory = diagram.get('elementFactory'); + +const shape1 = elementFactory.create('shape', { + id: 'shape1', + x: 100, + y: 100, + width: 100, + height: 100 +}); + +const shape2 = elementFactory.create('shape', { + id: 'shape2', + x: 100, + y: 100, + width: 100, + height: 100 +}); + +elementFactory.create('connection', { + id: 'connection', + source: shape1, + target: shape2, + waypoints: [] +}); + +elementFactory.create('root', { + id: 'root' +}); + +elementFactory.create('label', { + id: 'label' +}); + +elementFactory.create('connection'); + +elementFactory.create('label'); + +elementFactory.create('root'); + +elementFactory.create('shape'); + +elementFactory.createConnection(); + +elementFactory.createLabel(); + +elementFactory.createRoot(); + +elementFactory.createShape(); \ No newline at end of file diff --git a/lib/core/ElementRegistry.d.ts b/lib/core/ElementRegistry.d.ts new file mode 100644 index 000000000..502fecba3 --- /dev/null +++ b/lib/core/ElementRegistry.d.ts @@ -0,0 +1,122 @@ +import EventBus from './EventBus'; + +import { ElementLike } from '.'; + +export type ElementRegistryElement = { + element: ElementLike; + gfx: SVGElement; + secondaryGfx: SVGElement; +}; + +export type ElementRegistryElements = { + [id: string]: ElementRegistryElement; +}; + +export type ElementRegistryCallback = (element: ElementLike, gfx: SVGElement) => boolean; + +/** + * A registry that keeps track of all shapes in the diagram. + * + * @param eventBus + */ +export default class ElementRegistry { + constructor(eventBus: EventBus); + + /** + * Add an element and its graphical representation(s) to the registry. + * + * @param element The element to be added. + * @param gfx The primary graphical representation. + * @param secondaryGfx The secondary graphical representation. + */ + add(element: ElementLike, gfx: SVGElement, secondaryGfx?: SVGElement): void; + + /** + * Remove an element from the registry. + * + * @param element + */ + remove(element: ElementLike | string): void; + + /** + * Update an elements ID. + * + * @param element The element or its ID. + * @param newId The new ID. + */ + updateId(element: ElementLike | string, newId: string): void; + + /** + * Update the graphical representation of an element. + * + * @param element The element or its ID. + * @param gfx The new graphical representation. + * @param secondary Whether to update the secondary graphical representation. + */ + updateGraphics(filter: ElementLike | string, gfx: SVGElement, secondary?: boolean): void; + + /** + * Get the element with the given ID or graphical representation. + * + * @example + * + * elementRegistry.get('SomeElementId_1'); + * + * elementRegistry.get(gfx); + * + * @param filter The elements ID or graphical representation. + * + * @return The element. + */ + get(filter: string | SVGElement): ElementLike; + + /** + * Return all elements that match a given filter function. + * + * @param fn The filter function. + * + * @return The matching elements. + */ + filter(fn: ElementRegistryCallback): ElementLike[]; + + /** + * Return the first element that matches the given filter function. + * + * @param fn The filter function. + * + * @return The matching element. + */ + find(fn: ElementRegistryCallback): ElementLike | undefined; + + /** + * Get all elements. + * + * @return All elements. + */ + getAll(): ElementLike[]; + + /** + * Execute a given function for each element. + * + * @param fn The function to execute. + */ + forEach(fn: (element: ElementLike, gfx: SVGElement) => void): void; + + /** + * Return the graphical representation of an element. + * + * @example + * + * elementRegistry.getGraphics('SomeElementId_1'); + * + * elementRegistry.getGraphics(rootElement); // + * + * elementRegistry.getGraphics(rootElement, true); // + * + * @param filter The element or its ID. + * @param secondary Whether to return the secondary graphical representation. + * + * @return The graphical representation. + */ + getGraphics(filter: ElementLike | string, secondary?: boolean): SVGElement; +} \ No newline at end of file diff --git a/lib/core/ElementRegistry.js b/lib/core/ElementRegistry.js index cf6220582..e804673a1 100644 --- a/lib/core/ElementRegistry.js +++ b/lib/core/ElementRegistry.js @@ -2,11 +2,21 @@ var ELEMENT_ID = 'data-element-id'; import { attr as svgAttr } from 'tiny-svg'; +/** + * @typedef {import('.').ElementLike} ElementLike + * + * @typedef {import('./EventBus').default} EventBus + * + * @typedef {import('./ElementRegistry').ElementRegistryCallback} ElementRegistryCallback + */ /** + * A registry that keeps track of all shapes in the diagram. + * * @class + * @constructor * - * A registry that keeps track of all shapes in the diagram. + * @param {EventBus} eventBus */ export default function ElementRegistry(eventBus) { this._elements = {}; @@ -17,11 +27,11 @@ export default function ElementRegistry(eventBus) { ElementRegistry.$inject = [ 'eventBus' ]; /** - * Register a pair of (element, gfx, (secondaryGfx)). + * Add an element and its graphical representation(s) to the registry. * - * @param {djs.model.Base} element - * @param {SVGElement} gfx - * @param {SVGElement} [secondaryGfx] optional other element to register, too + * @param {ElementLike} element The element to be added. + * @param {SVGElement} gfx The primary graphical representation. + * @param {SVGElement} [secondaryGfx] The secondary graphical representation. */ ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) { @@ -40,9 +50,9 @@ ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) { }; /** - * Removes an element from the registry. + * Remove an element from the registry. * - * @param {string|djs.model.Base} element + * @param {ElementLike|string} element */ ElementRegistry.prototype.remove = function(element) { var elements = this._elements, @@ -63,10 +73,10 @@ ElementRegistry.prototype.remove = function(element) { }; /** - * Update the id of an element + * Update an elements ID. * - * @param {string|djs.model.Base} element - * @param {string} newId + * @param {ElementLike|string} element The element or its ID. + * @param {string} newId The new ID. */ ElementRegistry.prototype.updateId = function(element, newId) { @@ -92,11 +102,11 @@ ElementRegistry.prototype.updateId = function(element, newId) { }; /** - * Update the graphics of an element + * Update the graphical representation of an element. * - * @param {string|djs.model.Base} element - * @param {SVGElement} gfx - * @param {boolean} [secondary=false] whether to update the secondary connected element + * @param {ElementLike|string} element The element or its ID. + * @param {SVGElement} gfx The new graphical representation. + * @param {boolean} [secondary=false] Whether to update the secondary graphical representation. */ ElementRegistry.prototype.updateGraphics = function(filter, gfx, secondary) { var id = filter.id || filter; @@ -117,17 +127,17 @@ ElementRegistry.prototype.updateGraphics = function(filter, gfx, secondary) { }; /** - * Return the model element for a given id or graphics. + * Get the element with the given ID or graphical representation. * * @example * * elementRegistry.get('SomeElementId_1'); - * elementRegistry.get(gfx); * + * elementRegistry.get(gfx); * - * @param {string|SVGElement} filter for selecting the element + * @param {string|SVGElement} filter The elements ID or graphical representation. * - * @return {djs.model.Base} + * @return {ElementLike|undefined} The element. */ ElementRegistry.prototype.get = function(filter) { var id; @@ -145,9 +155,9 @@ ElementRegistry.prototype.get = function(filter) { /** * Return all elements that match a given filter function. * - * @param {Function} fn + * @param {ElementRegistryCallback} fn The filter function. * - * @return {Array} + * @return {ElementLike[]} The matching elements. */ ElementRegistry.prototype.filter = function(fn) { @@ -163,11 +173,11 @@ ElementRegistry.prototype.filter = function(fn) { }; /** - * Return the first element that satisfies the provided testing function. + * Return the first element that matches the given filter function. * - * @param {Function} fn + * @param {Function} fn The filter function. * - * @return {djs.model.Base} + * @return {ElementLike|undefined} The matching element. */ ElementRegistry.prototype.find = function(fn) { var map = this._elements, @@ -186,18 +196,18 @@ ElementRegistry.prototype.find = function(fn) { }; /** - * Return all rendered model elements. + * Get all elements. * - * @return {Array} + * @return {ElementLike[]} All elements. */ ElementRegistry.prototype.getAll = function() { return this.filter(function(e) { return e; }); }; /** - * Iterate over all diagram elements. + * Execute a given function for each element. * - * @param {Function} fn + * @param {Function} fn The function to execute. */ ElementRegistry.prototype.forEach = function(fn) { @@ -213,19 +223,20 @@ ElementRegistry.prototype.forEach = function(fn) { }; /** - * Return the graphical representation of an element or its id. + * Return the graphical representation of an element. * * @example + * * elementRegistry.getGraphics('SomeElementId_1'); + * * elementRegistry.getGraphics(rootElement); // * * elementRegistry.getGraphics(rootElement, true); // * + * @param {ElementLike|string} filter The element or its ID. + * @param {boolean} [secondary=false] Whether to return the secondary graphical representation. * - * @param {string|djs.model.Base} filter - * @param {boolean} [secondary=false] whether to return the secondary connected element - * - * @return {SVGElement} + * @return {SVGElement} The graphical representation. */ ElementRegistry.prototype.getGraphics = function(filter, secondary) { var id = filter.id || filter; @@ -235,12 +246,11 @@ ElementRegistry.prototype.getGraphics = function(filter, secondary) { }; /** - * Validate the suitability of the given id and signals a problem - * with an exception. + * Validate an ID and throw an error if invalid. * * @param {string} id * - * @throws {Error} if id is empty or already assigned + * @throws {Error} Error indicating that the ID is invalid or already assigned. */ ElementRegistry.prototype._validateId = function(id) { if (!id) { diff --git a/lib/core/ElementRegistry.spec.ts b/lib/core/ElementRegistry.spec.ts new file mode 100644 index 000000000..696a09dc9 --- /dev/null +++ b/lib/core/ElementRegistry.spec.ts @@ -0,0 +1,70 @@ +import Diagram from '../../lib/Diagram'; + +import CoreModule from '.'; +import ElementFactory from './ElementFactory'; +import ElementRegistry from './ElementRegistry'; +import GraphicsFactory from './GraphicsFactory'; + +const diagram = new Diagram({ + modules: [ + CoreModule + ] +}); + +const elementFactory = diagram.get('elementFactory'), + elementRegistry = diagram.get('elementRegistry'), + graphicsFactory = diagram.get('graphicsFactory'); + +const shapeLike = { id: 'shape' }; + +const shape = elementFactory.createShape(), + shapeGfx1 = graphicsFactory.create('shape', shape), + shapeGfx2 = graphicsFactory.create('shape', shape); + +elementRegistry.add(shapeLike, shapeGfx1); + +elementRegistry.add(shape, shapeGfx1); + +elementRegistry.add(shape, shapeGfx1, shapeGfx2); + +elementRegistry.remove('shape'); + +elementRegistry.remove(shapeLike); + +elementRegistry.remove(shape); + +elementRegistry.find((element, gfx) => { + console.log(element, gfx); + + return true; +}); + +elementRegistry.filter((element, gfx) => { + console.log(element, gfx); + + return true; +}); + +elementRegistry.forEach((element, gfx) => console.log(element, gfx)); + +elementRegistry.get('shape'); + +elementRegistry.getAll(); + +elementRegistry.getGraphics('shape'); + +elementRegistry.getGraphics(shapeLike); + +elementRegistry.getGraphics(shape); + +elementRegistry.updateGraphics('shape', shapeGfx1); + +elementRegistry.updateGraphics(shapeLike, shapeGfx1); + +elementRegistry.updateGraphics(shape, shapeGfx1); + +elementRegistry.updateGraphics(shape, shapeGfx2, true); + +elementRegistry.updateId(shapeLike, 'foo'); + +elementRegistry.updateId(shape, 'foo'); \ No newline at end of file diff --git a/lib/core/EventBus.d.ts b/lib/core/EventBus.d.ts new file mode 100644 index 000000000..064dd94dd --- /dev/null +++ b/lib/core/EventBus.d.ts @@ -0,0 +1,276 @@ +export type Event = { + stopPropagation(): void; + preventDefault(): void; + + cancelBubble: boolean; + defaultPrevented: boolean; +}; + +export type EventCallback = (event: T) => any | void; + +export type EventBusListener = { + priority: number; + next: EventBusListener | null; + callback: EventCallback; +}; + +/** + * A general purpose event bus. + * + * This component is used to communicate across a diagram instance. + * Other parts of a diagram can use it to listen to and broadcast events. + * + * + * ## Registering for Events + * + * The event bus provides the {@link EventBus#on} and {@link EventBus#once} + * methods to register for events. {@link EventBus#off} can be used to + * remove event registrations. Listeners receive an instance of {@link Event} + * as the first argument. It allows them to hook into the event execution. + * + * ```javascript + * + * // listen for event + * eventBus.on('foo', function(event) { + * + * // access event type + * event.type; // 'foo' + * + * // stop propagation to other listeners + * event.stopPropagation(); + * + * // prevent event default + * event.preventDefault(); + * }); + * + * // listen for event with custom payload + * eventBus.on('bar', function(event, payload) { + * console.log(payload); + * }); + * + * // listen for event returning value + * eventBus.on('foobar', function(event) { + * + * // stop event propagation + prevent default + * return false; + * + * // stop event propagation + return custom result + * return { + * complex: 'listening result' + * }; + * }); + * + * + * // listen with custom priority (default=1000, higher is better) + * eventBus.on('priorityfoo', 1500, function(event) { + * console.log('invoked first!'); + * }); + * + * + * // listen for event and pass the context (`this`) + * eventBus.on('foobar', function(event) { + * this.foo(); + * }, this); + * ``` + * + * + * ## Emitting Events + * + * Events can be emitted via the event bus using {@link EventBus#fire}. + * + * ```javascript + * + * // false indicates that the default action + * // was prevented by listeners + * if (eventBus.fire('foo') === false) { + * console.log('default has been prevented!'); + * }; + * + * + * // custom args + return value listener + * eventBus.on('sum', function(event, a, b) { + * return a + b; + * }); + * + * // you can pass custom arguments + retrieve result values. + * var sum = eventBus.fire('sum', 1, 2); + * console.log(sum); // 3 + * ``` + */ +export default class EventBus { + constructor(); + + /** + * Register an event listener for events with the given name. + * + * The callback will be invoked with `event, ...additionalArguments` + * that have been passed to {@link EventBus#fire}. + * + * Returning false from a listener will prevent the events default action + * (if any is specified). To stop an event from being processed further in + * other listeners execute {@link Event#stopPropagation}. + * + * Returning anything but `undefined` from a listener will stop the listener propagation. + * + * @param events The event(s) to listen to. + * @param callback The callback. + * @param that Value of `this` the callback will be called with. + */ + on(events: string | string[], callback: EventCallback, that?: any): void; + + /** + * Register an event listener for events with the given name. + * + * The callback will be invoked with `event, ...additionalArguments` + * that have been passed to {@link EventBus#fire}. + * + * Returning false from a listener will prevent the events default action + * (if any is specified). To stop an event from being processed further in + * other listeners execute {@link Event#stopPropagation}. + * + * Returning anything but `undefined` from a listener will stop the listener propagation. + * + * @param events The event(s) to listen to. + * @param priority The priority with which to listen. + * @param callback The callback. + * @param that Value of `this` the callback will be called with. + */ + on(events: string | string[], priority: number, callback: EventCallback, that?: any): void; + + /** + * Register an event listener that is called only once. + * + * @param event The event to listen to. + * @param callback The callback. + * @param that Value of `this` the callback will be called with. + */ + once(event: string, callback: EventCallback, that?: any): void; + + /** + * Register an event listener that is called only once. + * + * @param event The event to listen to. + * @param priority The priority with which to listen. + * @param callback The callback. + * @param that Value of `this` the callback will be called with. + */ + once(event: string, priority: number, callback: EventCallback, that?: any): void; + + /** + * Removes event listeners by event and callback. + * + * If no callback is given, all listeners for a given event name are being removed. + * + * @param events The events. + * @param callback The callback. + */ + off(events: string | string[], callback: EventCallback): void; + + /** + * Create an event recognized be the event bus. + * + * @param data Event data. + * + * @return An event that will be recognized by the event bus. + */ + createEvent(data: Object): Event; + + /** + * Fires an event. + * + * @example + * + * // fire event by name + * events.fire('foo'); + * + * // fire event object with nested type + * var event = { type: 'foo' }; + * events.fire(event); + * + * // fire event with explicit type + * var event = { x: 10, y: 20 }; + * events.fire('element.moved', event); + * + * // pass additional arguments to the event + * events.on('foo', function(event, bar) { + * alert(bar); + * }); + * + * events.fire({ type: 'foo' }, 'I am bar!'); + * + * @param type The event type. + * + * @return The return value. Will be set to `false` if the default was prevented. + */ + fire(type: string): any; + + /** + * Fires an event. + * + * @example + * + * // fire event by name + * events.fire('foo'); + * + * // fire event object with nested type + * var event = { type: 'foo' }; + * events.fire(event); + * + * // fire event with explicit type + * var event = { x: 10, y: 20 }; + * events.fire('element.moved', event); + * + * // pass additional arguments to the event + * events.on('foo', function(event, bar) { + * alert(bar); + * }); + * + * events.fire({ type: 'foo' }, 'I am bar!'); + * + * @param data The event or event data. + * @param additional Additional arguments the callback will be called with. + * + * @return The return value. Will be set to `false` if the default was prevented. + */ + fire(data: Object, ...additional: any[]): any; + + /** + * Fires an event. + * + * @example + * + * // fire event by name + * events.fire('foo'); + * + * // fire event object with nested type + * var event = { type: 'foo' }; + * events.fire(event); + * + * // fire event with explicit type + * var event = { x: 10, y: 20 }; + * events.fire('element.moved', event); + * + * // pass additional arguments to the event + * events.on('foo', function(event, bar) { + * alert(bar); + * }); + * + * events.fire({ type: 'foo' }, 'I am bar!'); + * + * @param type The event type. + * @param data The event or event data. + * @param additional Additional arguments the callback will be called with. + * + * @return The return value. Will be set to `false` if the default was prevented. + */ + fire(type: string, data: Object | Event, ...additional: any[]): any; + + /** + * Handle an error by firing an event. + * + * @param error The error to be handled. + * + * @return Whether the error was handled. + */ + handleError(error: Error): boolean; +} \ No newline at end of file diff --git a/lib/core/EventBus.js b/lib/core/EventBus.js index c46982f81..a641265ba 100644 --- a/lib/core/EventBus.js +++ b/lib/core/EventBus.js @@ -12,6 +12,16 @@ var DEFAULT_PRIORITY = 1000; var slice = Array.prototype.slice; +/** + * @typedef {import('./EventBus').Event} Event + * @typedef {import('./EventBus').EventCallback} EventCallback + * + * @typedef {Object} EventListener + * @property {Function} callback + * @property {EventListener|null} next + * @property {number} priority + */ + /** * A general purpose event bus. * @@ -116,10 +126,10 @@ export default function EventBus() { * * Returning anything but `undefined` from a listener will stop the listener propagation. * - * @param {string|Array} events - * @param {number} [priority=1000] the priority in which this listener is called, larger is higher - * @param {Function} callback - * @param {Object} [that] Pass context (`this`) to the callback + * @param {string|string[]} events The event(s) to listen to. + * @param {number} [priority=1000] The priority with which to listen. + * @param {EventCallback} callback The callback. + * @param {*} [that] Value of `this` the callback will be called with. */ EventBus.prototype.on = function(events, priority, callback, that) { @@ -159,12 +169,12 @@ EventBus.prototype.on = function(events, priority, callback, that) { /** - * Register an event listener that is executed only once. + * Register an event listener that is called only once. * - * @param {string} event the event name to register for - * @param {number} [priority=1000] the priority in which this listener is called, larger is higher - * @param {Function} callback the callback to execute - * @param {Object} [that] Pass context (`this`) to the callback + * @param {string} event The event to listen to. + * @param {number} [priority=1000] The priority with which to listen. + * @param {EventCallback} callback The callback. + * @param {*} [that] Value of `this` the callback will be called with. */ EventBus.prototype.once = function(event, priority, callback, that) { var self = this; @@ -203,8 +213,8 @@ EventBus.prototype.once = function(event, priority, callback, that) { * * If no callback is given, all listeners for a given event name are being removed. * - * @param {string|Array} events - * @param {Function} [callback] + * @param {string|string[]} events The events. + * @param {EventCallback} [callback] The callback. */ EventBus.prototype.off = function(events, callback) { @@ -220,11 +230,11 @@ EventBus.prototype.off = function(events, callback) { /** - * Create an EventBus event. + * Create an event recognized be the event bus. * - * @param {Object} data + * @param {Object} data Event data. * - * @return {Object} event, recognized by the eventBus + * @return {Event} An event that will be recognized by the event bus. */ EventBus.prototype.createEvent = function(data) { var event = new InternalEvent(); @@ -236,7 +246,7 @@ EventBus.prototype.createEvent = function(data) { /** - * Fires a named event. + * Fires an event. * * @example * @@ -258,12 +268,11 @@ EventBus.prototype.createEvent = function(data) { * * events.fire({ type: 'foo' }, 'I am bar!'); * - * @param {string} [name] the optional event name - * @param {Object} [event] the event object - * @param {...Object} additional arguments to be passed to the callback functions + * @param {string} [type] The event type. + * @param {Object} [data] The event or event data. + * @param {...*} additional Additional arguments the callback will be called with. * - * @return {boolean} the events return value, if specified or false if the - * default action was prevented by listeners + * @return {*} The return value. Will be set to `false` if the default was prevented. */ EventBus.prototype.fire = function(type, data) { var event, @@ -328,7 +337,13 @@ EventBus.prototype.fire = function(type, data) { return returnValue; }; - +/** + * Handle an error by firing an event. + * + * @param {Error} error The error to be handled. + * + * @return {boolean} Whether the error was handled. + */ EventBus.prototype.handleError = function(error) { return this.fire('error', { error: error }) === false; }; @@ -391,7 +406,7 @@ EventBus.prototype._invokeListener = function(event, args, listener) { return returnValue; }; -/* +/** * Add new listener with a certain priority to the list * of listeners (for the given event). * @@ -405,7 +420,7 @@ EventBus.prototype._invokeListener = function(event, args, listener) { * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ] * * @param {string} event - * @param {Object} listener { priority, callback } + * @param {EventListener} listener */ EventBus.prototype._addListener = function(event, newListener) { @@ -511,9 +526,9 @@ InternalEvent.prototype.init = function(data) { * Invoke function. Be fast... * * @param {Function} fn - * @param {Array} args + * @param {*[]} args * - * @return {Any} + * @return {*} */ function invokeFunction(fn, args) { return fn.apply(null, args); diff --git a/lib/core/EventBus.spec.ts b/lib/core/EventBus.spec.ts new file mode 100644 index 000000000..131047a76 --- /dev/null +++ b/lib/core/EventBus.spec.ts @@ -0,0 +1,58 @@ +import Diagram from '../../lib/Diagram'; + +import CoreModule from '.'; +import EventBus, { Event } from './EventBus'; + +const diagram = new Diagram({ + modules: [ + CoreModule + ] +}); + +const eventBus = diagram.get('eventBus'); + +const event = eventBus.createEvent({ foo: 'bar' }); + +eventBus.fire('foo'); + +eventBus.fire(event); + +eventBus.fire(event, 'foo', 'bar'); + +eventBus.fire({ foo: 'bar'}); + +eventBus.fire({ foo: 'bar'}, 'foo', 'bar'); + +eventBus.handleError(new Error()); + +const callback = () => {}; + +eventBus.off('foo', callback); + +eventBus.off([ 'foo', 'bar' ], callback); + +eventBus.on('foo', callback); + +eventBus.on([ 'foo', 'bar' ], callback); + +eventBus.on('foo', 2000, callback); + +eventBus.on('foo', callback, this); + +type FooEvent = { + foo: string; +} & Event; + +eventBus.on('foo', (event) => { + const { foo } = event; + + console.log(foo); +}); + +eventBus.once('foo', callback); + +eventBus.once('foo', callback); + +eventBus.once('foo', 2000, callback); + +eventBus.once('foo', callback, this); \ No newline at end of file diff --git a/lib/core/GraphicsFactory.d.ts b/lib/core/GraphicsFactory.d.ts new file mode 100644 index 000000000..dc6df50c1 --- /dev/null +++ b/lib/core/GraphicsFactory.d.ts @@ -0,0 +1,92 @@ +import ElementRegistry from './ElementRegistry'; +import EventBus from './EventBus'; + +import { + ConnectionLike, + ElementLike, + ShapeLike +} from '.'; + +import { + ModelType, + ModelTypeConnection, + ModelTypeShape +} from '../model'; + +/** + * A factory that creates graphical elements. + * + * @param eventBus + * @param elementRegistry + */ +export default class GraphicsFactory { + constructor(eventBus: EventBus, elementRegistry: ElementRegistry); + + /** + * Create a graphical element. + * + * @param type The type of the element. + * @param element The element. + * @param parentIndex The index at which to add the graphical element to its parent's children. + * + * @return The created graphical element. + */ + create(type: ModelType, element: ElementLike, parentIndex?: number): SVGElement; + + /** + * Update the containments of the given elements. + * + * @param elements The elements. + */ + updateContainments(elements: ElementLike[]): void; + + /** + * Draw a shape. + * + * @param visual The graphical element. + * @param element The shape. + */ + drawShape(visual: SVGElement, element: ShapeLike): SVGElement; + + /** + * Get the path of a shape. + * + * @param element The shape. + * + * @return The path of the shape. + */ + getShapePath(element: ShapeLike): string; + + /** + * Draw a connection. + * + * @param visual The graphical element. + * @param element The connection. + */ + drawConnection(visual: SVGElement, element: ConnectionLike): SVGElement; + + /** + * Get the path of a connection. + * + * @param element The connection. + * + * @return The path of the connection. + */ + getConnectionPath(connection: ConnectionLike): string; + + /** + * Update an elements graphical representation. + * + * @param type The type of the element. + * @param element The element. + * @param gfx The graphical representation. + */ + update(type: ModelTypeShape | ModelTypeConnection, element: ElementLike, gfx: SVGElement): void; + + /** + * Remove a graphical element. + * + * @param element The element. + */ + remove(element: ElementLike): void; +} \ No newline at end of file diff --git a/lib/core/GraphicsFactory.js b/lib/core/GraphicsFactory.js index 4f178a365..ae56abdd3 100644 --- a/lib/core/GraphicsFactory.js +++ b/lib/core/GraphicsFactory.js @@ -25,7 +25,20 @@ import { } from '../util/Elements'; /** - * A factory that creates graphical elements + * @typedef {import('../model').ModelType} ModelType + * @typedef {import('../model').ModelTypeConnection} ModelTypeConnection + * @typedef {import('../model').ModelTypeShape} ModelTypeShape + * + * @typedef {import('.').ConnectionLike} ConnectionLike + * @typedef {import('.').ElementLike} ElementLike + * @typedef {import('.').ShapeLike} ShapeLike + * + * @typedef {import('./ElementRegistry').default} ElementRegistry + * @typedef {import('./EventBus').default} EventBus + */ + +/** + * A factory that creates graphical elements. * * @param {EventBus} eventBus * @param {ElementRegistry} elementRegistry @@ -93,7 +106,7 @@ GraphicsFactory.prototype._clear = function(gfx) { * * * @param {string} type the type of the element, i.e. shape | connection - * @param {SVGElement} [childrenGfx] + * @param {SVGElement} childrenGfx * @param {number} [parentIndex] position to create container in parent * @param {boolean} [isFrame] is frame element * @@ -131,11 +144,25 @@ GraphicsFactory.prototype._createContainer = function( return gfx; }; +/** + * Create a graphical element. + * + * @param {ModelType} type The type of the element. + * @param {ElementLike} element The element. + * @param {number} [parentIndex] The index at which to add the graphical element to its parent's children. + * + * @return {SVGElement} The graphical element. + */ GraphicsFactory.prototype.create = function(type, element, parentIndex) { var childrenGfx = this._getChildrenContainer(element.parent); return this._createContainer(type, childrenGfx, parentIndex, isFrameElement(element)); }; +/** + * Update the containments of the given elements. + * + * @param {ElementLike[]} elements The elements. + */ GraphicsFactory.prototype.updateContainments = function(elements) { var self = this, @@ -171,30 +198,63 @@ GraphicsFactory.prototype.updateContainments = function(elements) { }); }; +/** + * Draw a shape. + * + * @param {SVGElement} visual The graphical element. + * @param {ShapeLike} element The shape. + */ GraphicsFactory.prototype.drawShape = function(visual, element) { var eventBus = this._eventBus; return eventBus.fire('render.shape', { gfx: visual, element: element }); }; +/** + * Get the path of a shape. + * + * @param {ShapeLike} element The shape. + * + * @return {string} The path of the shape. + */ GraphicsFactory.prototype.getShapePath = function(element) { var eventBus = this._eventBus; return eventBus.fire('render.getShapePath', element); }; +/** + * Draw a connection. + * + * @param {SVGElement} visual The graphical element. + * @param {ConnectionLike} element The connection. + */ GraphicsFactory.prototype.drawConnection = function(visual, element) { var eventBus = this._eventBus; return eventBus.fire('render.connection', { gfx: visual, element: element }); }; -GraphicsFactory.prototype.getConnectionPath = function(waypoints) { +/** + * Get the path of a connection. + * + * @param {ConnectionLike} element The connection. + * + * @return {string} The path of the connection. + */ +GraphicsFactory.prototype.getConnectionPath = function(connection) { var eventBus = this._eventBus; - return eventBus.fire('render.getConnectionPath', waypoints); + return eventBus.fire('render.getConnectionPath', connection); }; +/** + * Update an elements graphical representation. + * + * @param {ModelTypeShape|ModelTypeConnection} type The type of the element. + * @param {ElementLike} element The element. + * @param {SVGElement} gfx The graphical representation. + */ GraphicsFactory.prototype.update = function(type, element, gfx) { // do NOT update root element @@ -224,6 +284,11 @@ GraphicsFactory.prototype.update = function(type, element, gfx) { } }; +/** + * Remove a graphical element. + * + * @param {ElementLike} element The element. + */ GraphicsFactory.prototype.remove = function(element) { var gfx = this._elementRegistry.getGraphics(element); diff --git a/lib/core/GraphicsFactory.spec.ts b/lib/core/GraphicsFactory.spec.ts new file mode 100644 index 000000000..a633d207f --- /dev/null +++ b/lib/core/GraphicsFactory.spec.ts @@ -0,0 +1,78 @@ +import Diagram from '../../lib/Diagram'; + +import CoreModule from '.'; +import ElementFactory from './ElementFactory'; +import GraphicsFactory from './GraphicsFactory'; + +const diagram = new Diagram({ + modules: [ + CoreModule + ] +}); + +const elementFactory = diagram.get('elementFactory'), + graphicsFactory = diagram.get('graphicsFactory'); + +const shape = elementFactory.createShape(); + +const shapeGfx = graphicsFactory.create('shape', shape); + +graphicsFactory.drawShape(shapeGfx, shape); + +graphicsFactory.getShapePath(shape); + +graphicsFactory.remove(shape); + +graphicsFactory.update('shape', shape, shapeGfx); + +graphicsFactory.updateContainments([ shape ]); + +const connection = elementFactory.createConnection(); + +const connectionGfx = graphicsFactory.create('connection', connection); + +graphicsFactory.drawConnection(connectionGfx, connection); + +graphicsFactory.getConnectionPath(connection); + +graphicsFactory.remove(connection); + +const shapeLike = { + id: 'shape', + x: 100, + y: 100, + width: 100, + height: 100 +}; + +const shapeLikeGfx = graphicsFactory.create('shape', shapeLike); + +graphicsFactory.drawShape(shapeLikeGfx, shape); + +graphicsFactory.getConnectionPath(connection); + +graphicsFactory.remove(shapeLike); + +const connectionLike = { + id: 'connection', + waypoints: [ + { + x: 100, + y: 100 + }, + { + x: 200, + y: 100 + } + ] +}; + +graphicsFactory.create('connection', connectionLike); + +const connectionLikeGfx = graphicsFactory.create('connection', connectionLike); + +graphicsFactory.drawConnection(connectionLikeGfx, connectionLike); + +graphicsFactory.getConnectionPath(connectionLike); + +graphicsFactory.remove(connectionLike); \ No newline at end of file diff --git a/lib/core/index.d.ts b/lib/core/index.d.ts new file mode 100644 index 000000000..9f6939bfe --- /dev/null +++ b/lib/core/index.d.ts @@ -0,0 +1,29 @@ +import { + ModuleDeclaration +} from 'didi'; + +import { Point } from '../util/Types'; + +declare const m : ModuleDeclaration; + +export type ElementLike = { + id: string; + [key: string]: any; +}; + +export type ConnectionLike = { + waypoints: Point[]; +} & ElementLike; + +export type RootLike = { + isImplicit?: boolean; +} & ElementLike; + +export type ShapeLike = { + x: number; + y: number; + width: number; + height: number; +} & ElementLike; + +export default m; diff --git a/lib/draw/BaseRenderer.d.ts b/lib/draw/BaseRenderer.d.ts new file mode 100644 index 000000000..73887759f --- /dev/null +++ b/lib/draw/BaseRenderer.d.ts @@ -0,0 +1,64 @@ +import EventBus from '../core/EventBus'; + +import { + Base, + Connection, + Shape +} from '../model'; + +/** + * The base implementation of shape and connection renderers. + * + * @param eventBus + * @param renderPriority + */ +export default class BaseRenderer { + constructor(eventBus: EventBus, renderPriority?: number); + + /** + * Checks whether an element can be rendered. + * + * @param element The element to be rendered. + * + * @returns Whether the element can be rendered. + */ + canRender(element: Base): boolean; + + /** + * Draws a shape. + * + * @param visuals The SVG element to draw the shape into. + * @param shape The shape to be drawn. + * + * @returns The SVG element with the shape drawn into it. + */ + drawShape(visuals: SVGElement, shape: Shape): SVGElement; + + /** + * Draws a connection. + * + * @param visuals The SVG element to draw the connection into. + * @param connection The connection to be drawn. + * + * @returns The SVG element with the connection drawn into it. + */ + drawConnection(visuals: SVGElement, connection: Connection): SVGElement; + + /** + * Gets the SVG path of the graphical representation of a shape. + * + * @param shape The shape. + * + * @return The SVG path of the shape. + */ + getShapePath(shape: Shape): string; + + /** + * Gets the SVG path of the graphical representation of a connection. + * + * @param connection The connection. + * + * @return The SVG path of the connection. + */ + getConnectionPath(connection: Connection): string; +} \ No newline at end of file diff --git a/lib/draw/BaseRenderer.js b/lib/draw/BaseRenderer.js index 551d51a81..4a6abc659 100644 --- a/lib/draw/BaseRenderer.js +++ b/lib/draw/BaseRenderer.js @@ -1,5 +1,13 @@ var DEFAULT_RENDER_PRIORITY = 1000; +/** + * @typedef {import('../model').Base} Base + * @typedef {import('../model').Connection} Connection + * @typedef {import('../model').Shape} Shape + * + * @typedef {import('../core/EventBus').default} EventBus + */ + /** * The base implementation of shape and connection renderers. * @@ -38,49 +46,48 @@ export default function BaseRenderer(eventBus, renderPriority) { } /** - * Should check whether *this* renderer can render - * the element/connection. + * Checks whether an element can be rendered. * - * @param {element} element + * @param {Base} element The element to be rendered. * - * @returns {boolean} + * @returns {boolean} Whether the element can be rendered. */ -BaseRenderer.prototype.canRender = function() {}; +BaseRenderer.prototype.canRender = function(element) {}; /** - * Provides the shape's snap svg element to be drawn on the `canvas`. + * Draws a shape. * - * @param {djs.Graphics} visuals - * @param {Shape} shape + * @param {SVGElement} visuals The SVG element to draw the shape into. + * @param {Shape} shape The shape to be drawn. * - * @returns {Snap.svg} [returns a Snap.svg paper element ] + * @returns {SVGElement} The SVG element of the shape drawn. */ -BaseRenderer.prototype.drawShape = function() {}; +BaseRenderer.prototype.drawShape = function(visuals, shape) {}; /** - * Provides the shape's snap svg element to be drawn on the `canvas`. + * Draws a connection. * - * @param {djs.Graphics} visuals - * @param {Connection} connection + * @param {SVGElement} visuals The SVG element to draw the connection into. + * @param {Connection} connection The connection to be drawn. * - * @returns {Snap.svg} [returns a Snap.svg paper element ] + * @returns {SVGElement} The SVG element of the connection drawn. */ -BaseRenderer.prototype.drawConnection = function() {}; +BaseRenderer.prototype.drawConnection = function(visuals, connection) {}; /** - * Gets the SVG path of a shape that represents it's visual bounds. + * Gets the SVG path of the graphical representation of a shape. * - * @param {Shape} shape + * @param {Shape} shape The shape. * - * @return {string} svg path + * @return {string} The SVG path of the shape. */ -BaseRenderer.prototype.getShapePath = function() {}; +BaseRenderer.prototype.getShapePath = function(shape) {}; /** - * Gets the SVG path of a connection that represents it's visual bounds. + * Gets the SVG path of the graphical representation of a connection. * - * @param {Connection} connection + * @param {Connection} connection The connection. * - * @return {string} svg path + * @return {string} The SVG path of the connection. */ -BaseRenderer.prototype.getConnectionPath = function() {}; +BaseRenderer.prototype.getConnectionPath = function(connection) {}; diff --git a/lib/draw/BaseRenderer.spec.ts b/lib/draw/BaseRenderer.spec.ts new file mode 100644 index 000000000..a2a3d7c35 --- /dev/null +++ b/lib/draw/BaseRenderer.spec.ts @@ -0,0 +1,64 @@ +import { Base, Connection, Shape } from '../model'; + +import Diagram from '../../lib/Diagram'; + +import CoreModule from '../../lib/core'; +import ElementFactory from '../../lib/core/ElementFactory'; +import GraphicsFactory from '../core/GraphicsFactory'; + +import BaseRenderer from './BaseRenderer'; + +class CustomRenderer extends BaseRenderer { + canRender(element: Base): boolean { + return true; + } + + drawShape(visuals: SVGElement, shape: Shape): SVGElement { + return document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + } + + drawConnection(visuals: SVGElement, connection: Connection): SVGElement { + return document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + } + + getShapePath(shape: Shape): string { + return 'M150 0 L75 200 L225 200 Z'; + } + + getConnectionPath(connection: Connection): string { + return 'M150 0 L75 200 L225 200 Z'; + } +} + +const diagram = new Diagram({ + modules: [ + CoreModule, + { + __init__: [ 'customRenderer' ], + customRenderer: [ 'type', CustomRenderer ] + } + ] +}); + +const elementFactory = diagram.get('elementFactory'), + graphicsFactory = diagram.get('graphicsFactory'); + +const shape = elementFactory.createShape(), + connection = elementFactory.createConnection(); + +const shapeGfx = graphicsFactory.create('shape', shape), + connectionGfx = graphicsFactory.create('connection', connection); + +const customRenderer = diagram.get('customRenderer'); + +customRenderer.canRender(shape); + +customRenderer.canRender(connection); + +customRenderer.drawShape(shapeGfx, shape); + +customRenderer.drawConnection(connectionGfx, connection); + +customRenderer.getShapePath(shape); + +customRenderer.getConnectionPath(connection); \ No newline at end of file diff --git a/lib/features/modeling/Modeling.d.ts b/lib/features/modeling/Modeling.d.ts new file mode 100644 index 000000000..85e7ab91e --- /dev/null +++ b/lib/features/modeling/Modeling.d.ts @@ -0,0 +1,413 @@ +import CommandStack, { CommandHandlerConstructor } from '../../command/CommandStack'; +import ElementFactory from '../../core/ElementFactory'; +import EventBus from '../../core/EventBus'; + +import { + Base, + Connection, + Label, + ModelAttrs, + ModelAttrsConnection, + ModelAttrsLabel, + ModelAttrsShape, + Parent, + Shape +} from '../../model'; + +import { + Dimensions, + Direction, + Point, + Rect +} from '../../util/Types'; + +export type ModelingDistributeRange = { + min: number; + max: number; +}; + +export type ModelingDistributeGroup = { + elements: Base[], + range: ModelingDistributeRange | null +}; + +export type ModelingDistributeAxis = 'x' | 'y'; + +export type ModelingDistributeDimension = 'width' | 'height'; + +export type ModelingAlignAlignment = { + bottom?: number; + center?: number; + left?: number; + middle?: number; + right?: number; + top?: number; +}; + +export type ModelingHints = { + [key: string]: any; +}; + +export type ModelingMoveElementsHints = { + + /** + * Wether to attach the elements to the parent instead of making them children. + */ + attach?: boolean; +} & ModelingHints; + +export type ModelingCreateShapeHints = { + + /** + * Whether to attach the shape to its parent instead of making it a child. + */ + attach?: boolean; +} & ModelingHints; + +/** + * The basic modeling entry point. + * + * @param eventBus + * @param elementFactory + * @param commandStack + */ +export default class Modeling { + constructor(eventBus: EventBus, elementFactory: ElementFactory, commandStack: CommandStack); + + /** + * Get a map of all command handlers. + * + * @returns Map of all command handlers. + */ + getHandlers(): Map; + + /** + * Register handlers with the command stack + */ + registerHandlers(commandStack: CommandStack): void; + + /** + * Move a shape by the given delta and optionally to a new parent. + * + * @param shape The shape to be moved. + * @param delta The delta by which to move the shape. + * @param newParent The optional new parent. + * @param hints The optional hints. + */ + moveShape(shape: Shape, delta: Point, newParent?: Parent, hints?: ModelingHints): void; + + + /** + * Move a shape by the given delta and optionally to a new parent. + * + * @param shape The shape to be moved. + * @param delta The delta by which to move the shape. + * @param newParent The optional new parent. + * @param newParentIndex The optional index at which to add the shape + * to the new parent's children. + * @param hints The optional hints. + */ + moveShape(shape: Shape, delta: Point, newParent?: Parent, newParentIndex?: number, hints?: Object): void; + + /** + * Update the attachment of a shape. + * + * @param shape The shape. + * @param newHost The new host. + */ + updateAttachment(shape: Shape, newHost?: Shape): void; + + /** + * Move elements by a given delta and optionally to a new parent. + * + * @param {Base[]} shapes + * @param {Point} delta + * @param {Parent} [target] + * @param {ModelingMoveElementsHints} [hints] + */ + moveElements(shapes: Base[], delta: Point, target?: Parent, hints?: ModelingMoveElementsHints): void; + + /** + * Move a shape by the given delta and optionally to a new parent. + * + * @param shape The connection to be moved. + * @param delta The delta by which to move the connection. + * @param newParent The optional new parent. + * @param hints The optional hints. + */ + moveConnection(connection: Connection, delta: Point, newParent?: Parent, hints?: ModelingHints): void; + + /** + * Move a shape by the given delta and optionally to a new parent. + * + * @param shape The connection to be moved. + * @param delta The delta by which to move the connection. + * @param newParent The optional new parent. + * @param newParentIndex The optional index at which to add the + * connection to the new parent's children. + * @param hints The optional hints. + */ + moveConnection(connection: Connection, delta: Point, newParent?: Parent, newParentIndex?: number, hints?: ModelingHints): void; + + /** + * Lay out a connection. + * + * @param connection The connection to be laid out. + * @param hints The optional hints. + */ + layoutConnection(connection: Connection, hints?: ModelingHints): void; + + /** + * Create a connection. + * + * @param source The source of the connection. + * @param target The target of the connection. + * @param connection The connection to be + * created or its attributes. + * @param parent The parent of the connection. + * @param hints The optional hints. + * + * @return {Connection} The created connection. + */ + createConnection(source: Base, target: Base, connection: Connection | ModelAttrsConnection, parent: Parent, hints?: ModelingHints): Connection; + + /** + * Create a connection. + * + * @param source The source of the connection. + * @param target The target of the connection. + * @param parentIndex The optional index at which to add the + * connection to its parent's children. + * @param connection The connection to be + * created or its attributes. + * @param parent The parent of the connection. + * @param hints The optional hints. + * + * @return {Connection} The created connection. + */ + createConnection(source: Base, target: Base, parentIndex: number, connection: Connection | ModelAttrsConnection, parent: Parent, hints?: ModelingHints): Connection; + + /** + * Create a shape. + * + * @param shape The shape to be created or its + * attributes. + * @param position The position at which to create the shape. + * @param target The parent of the shape. + * @param hints The optional hints. + * + * @return The created shape. + */ + createShape(shape: Shape | ModelAttrsShape, position: Point, target: Parent, hints?: ModelingCreateShapeHints): Shape; + + /** + * Create a shape. + * + * @param shape The shape to be created or its + * attributes. + * @param position The position at which to create the shape. + * @param target The parent of the shape. + * @param parentIndex The optional index at which to add the shape to + * its parent's children. + * @param hints The optional hints. + * + * @return The created shape. + */ + createShape(shape: Shape | ModelAttrsShape, position: Point, target: Parent, parentIndex?: number, hints?: ModelingCreateShapeHints): Shape; + + /** + * Create elements. + * + * @param elements The elements to be created or their + * attributes. + * @param position The position at which to create the elements. + * @param parent The parent of the elements. + * @param hints The optional hints. + * + * @return The created elements. + */ + createElements(elements: (Base | ModelAttrs)[], position: Point, parent: Parent, hints?: ModelingHints): Base[]; + + /** + * Create elements. + * + * @param elements The elements to be created or their + * attributes. + * @param position The position at which to create the elements. + * @param parent The parent of the elements. + * @param parentIndex The optional index at which to add the elements + * to their parent's children. + * @param hints The optional hints. + * + * @return The created elements. + */ + createElements(elements: (Base | ModelAttrs)[], position: Point, parent: Parent, parentIndex?: number, hints?: ModelingHints): Base[]; + + /** + * Create a label. + * + * @param labelTarget The labels target. + * @param position The position at which to create the label. + * @param label The label to be created or its + * attributes. + * @param parent The parent of the label. + * + * @return The created label. + */ + createLabel(labelTarget: Base, position: Point, label: Label | ModelAttrsLabel, parent?: Parent): Label; + + /** + * Create and append a shape to a source by connecting it. + * + * @param source The source to append the shape to. + * @param shape The shape to be created or its + * attributes. + * @param position The position at which to create the shape. + * @param target The parent of the shape. + * @param hints The optional hints. + * + * @return The created and appended shape. + */ + appendShape(source: Base, shape: Shape | ModelAttrsShape, position: Point, target: Parent, hints?: ModelingHints): Shape; + + /** + * Remove elements. + * + * @param elements The elements to be removed. + */ + removeElements(elements: Base[]): void; + + /** + * Distribute elements along a given axis. + * + * @param groups The groups of elements to be + * distributed. + * @param axis The axis to distribute the elements + * along. + * @param dimension The dimension to be used + * according to the axis. + */ + distributeElements(groups: ModelingDistributeGroup[], axis: ModelingDistributeAxis, dimension: ModelingDistributeDimension): void; + + /** + * Remove a shape. + * + * @param shape The shape to be removed. + * @param hints The optional hints. + */ + removeShape(shape: Shape, hints?: ModelingHints): void; + + /** + * Remove a connection. + * + * @param connection The connection to be removed. + * @param hints The optional hints. + */ + removeConnection(connection: Connection, hints?: ModelingHints): void; + + /** + * Replace a shape. + * + * @param oldShape The shape to be replaced. + * @param newShape The shape to replace with or its + * attributes. + * @param hints The optional hints. + * + * @return The replaced shape. + */ + replaceShape(oldShape: Shape, newShape: Shape | ModelAttrsShape, hints?: ModelingHints): Shape; + + /** + * Align elements. + * + * @param elements The elements to be aligned. + * @param alignment The alignment. + */ + alignElements(elements: Base[], alignment: ModelingAlignAlignment): void; + + /** + * Resize a shape. + * + * @param shape The shape to be resized. + * @param newBounds The bounds to resize the shape to. + * @param minBounds The minimum bounds to resize the shape to. + * @param hints The optional hints. + */ + resizeShape(shape: Shape, newBounds: Rect, minBounds?: Dimensions, hints?: ModelingHints): void; + + /** + * Create space along an horizontally or vertically. + * + * @param movingShapes The shapes to be moved. + * @param resizingShapes The shapes to be resized. + * @param delta The delta. + * @param direction The direction in which to create space. + * @param start Where to start creating space in the given direction. + */ + createSpace(movingShapes: Shape[], resizingShapes: Shape[], delta: Point, direction: Direction, start: number): void; + + /** + * Update a connetions waypoints. + * + * @param connection The connection of which to update the + * waypoints. + * @param newWaypoints The updated waypoints. + * @param hints The optional hints. + */ + updateWaypoints(connection: Connection, newWaypoints: Point[], hints?: ModelingHints): void; + + /** + * Reconnect a connections source and/or target. + * + * @param connection The connection to be reconnected. + * @param source The source to connect to. + * @param target The target to connect to. + * @param dockingOrPoints The point to connect to or the + * waypoints. + * @param hints The optional hints. + */ + reconnect(connection: Connection, source: Base, target: Base, dockingOrPoints: Point | Point[], hints?: ModelingHints): void; + + /** + * Reconnect a connections source. + * + * @param connection The connection to be reconnected. + * @param newSource The source to connect to. + * @param dockingOrPoints The point to connect to or the + * waypoints. + * @param hints The optional hints. + */ + reconnectStart(connection: Connection, newSource: Base, dockingOrPoints: Point | Point[], hints?: ModelingHints): void; + + /** + * Reconnect a connections target. + * + * @param connection The connection to be reconnected. + * @param newTarget The target to connect to. + * @param dockingOrPoints The point to connect to or the + * waypoints. + * @param hints The optional hints. + */ + reconnectEnd(connection: Connection, newTarget: Base, dockingOrPoints: Point | Point[], hints?: ModelingHints): void; + + /** + * Connect two elements. + * + * @param source The source of the connection. + * @param target The target of the connection. + * @param attrs The connection to be + * created or its attributes. + * @param hints The optional hints. + * + * @return The created connection. + */ + connect(source: Base, target: Base, attrs?: ModelAttrsConnection, hints?: ModelingHints): Connection; + + /** + * Collapse or expand a shape. + * + * @param shape The shape to be expanded or collapsed. + * @param hints The optional hints. + */ + toggleCollapse(shape: Shape, hints?: ModelingHints): void; +} \ No newline at end of file diff --git a/lib/features/modeling/Modeling.js b/lib/features/modeling/Modeling.js index 9280ca7e7..ac8cc6db5 100644 --- a/lib/features/modeling/Modeling.js +++ b/lib/features/modeling/Modeling.js @@ -30,6 +30,34 @@ import ToggleShapeCollapseHandler from './cmd/ToggleShapeCollapseHandler'; import UpdateAttachmentHandler from './cmd/UpdateAttachmentHandler'; import UpdateWaypointsHandler from './cmd/UpdateWaypointsHandler'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Connection} Connection + * @typedef {import('../../model').Parent} Parent + * @typedef {import('../../model').Shape} Shape + * @typedef {import('../../model').ModelAttrsConnection} ModelAttrsConnection + * @typedef {import('../../model').ModelAttrsLabel} ModelAttrsLabel + * @typedef {import('../../model').ModelAttrsShape} ModelAttrsShape + * + * @typedef {import('../../command/CommandStack').default} CommandStack + * @typedef {import('../../core/ElementFactory').default} ElementFactory + * @typedef {import('../../core/EventBus').default} EventBus + * + * @typedef {import('../../command/CommandStack').CommandHandlerConstructor} CommandHandlerConstructor + * + * @typedef {import('../../util/Types').Dimensions} Dimensions + * @typedef {import('../../util/Types').Direction} Direction + * @typedef {import('../../util/Types').Point} Point + * @typedef {import('../../util/Types').Rect} Rect + * + * @typedef {import('./Modeling').ModelingAlignAlignment} ModelingAlignAlignment + * @typedef {import('./Modeling').ModelingCreateShapeHints} ModelingCreateShapeHints + * @typedef {import('./Modeling').ModelingDistributeAxis} ModelingDistributeAxis + * @typedef {import('./Modeling').ModelingDistributeDimension} ModelingDistributeDimension + * @typedef {import('./Modeling').ModelingDistributeGroup} ModelingDistributeGroup + * @typedef {import('./Modeling').ModelingHints} ModelingHints + * @typedef {import('./Modeling').ModelingMoveElementsHints} ModelingMoveElementsHints + */ /** * The basic modeling entry point. @@ -54,7 +82,11 @@ export default function Modeling(eventBus, elementFactory, commandStack) { Modeling.$inject = [ 'eventBus', 'elementFactory', 'commandStack' ]; - +/** + * Get a map of all command handlers. + * + * @returns {Map} Map of all command handlers. + */ Modeling.prototype.getHandlers = function() { return { 'shape.append': AppendShapeHandler, @@ -101,8 +133,16 @@ Modeling.prototype.registerHandlers = function(commandStack) { }; -// modeling helpers ////////////////////// - +/** + * Move a shape by the given delta and optionally to a new parent. + * + * @param {Shape} shape The shape to be moved. + * @param {Point} delta The delta by which to move the shape. + * @param {Parent} [newParent] The optional new parent. + * @param {number} [newParentIndex] The optional index at which to add the shape + * to the new parent's children. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.moveShape = function(shape, delta, newParent, newParentIndex, hints) { if (typeof newParentIndex === 'object') { @@ -123,10 +163,10 @@ Modeling.prototype.moveShape = function(shape, delta, newParent, newParentIndex, /** - * Update the attachment of the given shape. + * Update the attachment of a shape. * - * @param {djs.mode.Base} shape - * @param {djs.model.Base} [newHost] + * @param {Shape} shape The shape. + * @param {Shape} [newHost=undefined] The new host. */ Modeling.prototype.updateAttachment = function(shape, newHost) { var context = { @@ -139,14 +179,12 @@ Modeling.prototype.updateAttachment = function(shape, newHost) { /** - * Move a number of shapes to a new target, either setting it as - * the new parent or attaching it. + * Move elements by a given delta and optionally to a new parent. * - * @param {Array} shapes + * @param {Base[]} shapes * @param {Point} delta - * @param {djs.model.Base} [target] - * @param {Object} [hints] - * @param {boolean} [hints.attach=false] + * @param {Parent} [target] + * @param {ModelingMoveElementsHints} [hints] */ Modeling.prototype.moveElements = function(shapes, delta, target, hints) { @@ -177,7 +215,16 @@ Modeling.prototype.moveElements = function(shapes, delta, target, hints) { this._commandStack.execute('elements.move', context); }; - +/** + * Move a shape by the given delta and optionally to a new parent. + * + * @param {Connection} shape The connection to be moved. + * @param {Point} delta The delta by which to move the connection. + * @param {Parent} [newParent] The optional new parent. + * @param {number} [newParentIndex] The optional index at which to add the + * connection to the new parent's children. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.moveConnection = function(connection, delta, newParent, newParentIndex, hints) { if (typeof newParentIndex === 'object') { @@ -196,7 +243,12 @@ Modeling.prototype.moveConnection = function(connection, delta, newParent, newPa this._commandStack.execute('connection.move', context); }; - +/** + * Lay out a connection. + * + * @param {Connection} connection The connection to be laid out. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.layoutConnection = function(connection, hints) { var context = { connection: connection, @@ -208,16 +260,18 @@ Modeling.prototype.layoutConnection = function(connection, hints) { /** - * Create connection. + * Create a connection. * - * @param {djs.model.Base} source - * @param {djs.model.Base} target - * @param {number} [parentIndex] - * @param {Object|djs.model.Connection} connection - * @param {djs.model.Base} parent - * @param {Object} hints + * @param {Base} source The source of the connection. + * @param {Base} target The target of the connection. + * @param {number} [parentIndex] The optional index at which to add the + * connection to its parent's children. + * @param {Connection|ModelAttrsConnection} connection The connection to be + * created or its attributes. + * @param {Parent} parent The parent of the connection. + * @param {ModelingHints} [hints] The optional hints. * - * @return {djs.model.Connection} the created connection. + * @return {Connection} The created connection. */ Modeling.prototype.createConnection = function(source, target, parentIndex, connection, parent, hints) { @@ -246,16 +300,17 @@ Modeling.prototype.createConnection = function(source, target, parentIndex, conn /** - * Create a shape at the specified position. + * Create a shape. * - * @param {djs.model.Shape|Object} shape - * @param {Point} position - * @param {djs.model.Shape|djs.model.Root} target - * @param {number} [parentIndex] position in parents children list - * @param {Object} [hints] - * @param {boolean} [hints.attach] whether to attach to target or become a child + * @param {Shape|ModelAttrsShape} shape The shape to be created or its + * attributes. + * @param {Point} position The position at which to create the shape. + * @param {Parent} target The parent of the shape. + * @param {number} [parentIndex] The optional index at which to add the shape to + * its parent's children. + * @param {ModelingCreateShapeHints} [hints] The optional hints. * - * @return {djs.model.Shape} the created shape + * @return {Shape} The created shape. */ Modeling.prototype.createShape = function(shape, position, target, parentIndex, hints) { @@ -293,7 +348,19 @@ Modeling.prototype.createShape = function(shape, position, target, parentIndex, return context.shape; }; - +/** + * Create elements. + * + * @param {(Base|ModelAttrs)[]} elements The elements to be created or their + * attributes. + * @param {Point} position The position at which to create the elements. + * @param {Parent} parent The parent of the elements. + * @param {number} [parentIndex] The optional index at which to add the elements + * to their parent's children. + * @param {ModelingHints} [hints] The optional hints. + * + * @return {Base[]} The created elements. + */ Modeling.prototype.createElements = function(elements, position, parent, parentIndex, hints) { if (!isArray(elements)) { elements = [ elements ]; @@ -319,7 +386,17 @@ Modeling.prototype.createElements = function(elements, position, parent, parentI return context.elements; }; - +/** + * Create a label. + * + * @param {Base} labelTarget The labels target. + * @param {Point} position The position at which to create the label. + * @param {Label|ModelAttrsLabel} label The label to be created or its + * attributes. + * @param {Parent} [parent] The parent of the label. + * + * @return {Label} The created label. + */ Modeling.prototype.createLabel = function(labelTarget, position, label, parent) { label = this._create('label', label); @@ -338,19 +415,16 @@ Modeling.prototype.createLabel = function(labelTarget, position, label, parent) /** - * Append shape to given source, drawing a connection - * between source and the newly created shape. - * - * @param {djs.model.Shape} source - * @param {djs.model.Shape|Object} shape - * @param {Point} position - * @param {djs.model.Shape} target - * @param {Object} [hints] - * @param {boolean} [hints.attach] - * @param {djs.model.Connection|Object} [hints.connection] - * @param {djs.model.Base} [hints.connectionParent] - * - * @return {djs.model.Shape} the newly created shape + * Create and append a shape to a source by connecting it. + * + * @param {Base} source The source to append the shape to. + * @param {Shape|ModelAttrsShape} shape The shape to be created or its + * attributes. + * @param {Point} position The position at which to create the shape. + * @param {Parent} target The parent of the shape. + * @param {ModelingHints} [hints] The optional hints. + * + * @return {Shape} The created and appended shape. */ Modeling.prototype.appendShape = function(source, shape, position, target, hints) { @@ -373,7 +447,11 @@ Modeling.prototype.appendShape = function(source, shape, position, target, hints return context.shape; }; - +/** + * Remove elements. + * + * @param {Base[]} elements The elements to be removed. + */ Modeling.prototype.removeElements = function(elements) { var context = { elements: elements @@ -382,7 +460,16 @@ Modeling.prototype.removeElements = function(elements) { this._commandStack.execute('elements.delete', context); }; - +/** + * Distribute elements along a given axis. + * + * @param {ModelingDistributeGroup[]} groups The groups of elements to be + * distributed. + * @param {ModelingDistributeAxis} axis The axis to distribute the elements + * along. + * @param {ModelingDistributeDimension} dimension The dimension to be used + * according to the axis. + */ Modeling.prototype.distributeElements = function(groups, axis, dimension) { var context = { groups: groups, @@ -393,7 +480,12 @@ Modeling.prototype.distributeElements = function(groups, axis, dimension) { this._commandStack.execute('elements.distribute', context); }; - +/** + * Remove a shape. + * + * @param {Shape} shape The shape to be removed. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.removeShape = function(shape, hints) { var context = { shape: shape, @@ -403,7 +495,12 @@ Modeling.prototype.removeShape = function(shape, hints) { this._commandStack.execute('shape.delete', context); }; - +/** + * Remove a connection. + * + * @param {Connection} connection The connection to be removed. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.removeConnection = function(connection, hints) { var context = { connection: connection, @@ -413,6 +510,16 @@ Modeling.prototype.removeConnection = function(connection, hints) { this._commandStack.execute('connection.delete', context); }; +/** + * Replace a shape. + * + * @param {Shape} oldShape The shape to be replaced. + * @param {Shape|ModelAttrsShape} newShape The shape to replace with or its + * attributes. + * @param {ModelingHints} [hints] The optional hints. + * + * @return {Shape} The replaced shape. + */ Modeling.prototype.replaceShape = function(oldShape, newShape, hints) { var context = { oldShape: oldShape, @@ -425,6 +532,12 @@ Modeling.prototype.replaceShape = function(oldShape, newShape, hints) { return context.newShape; }; +/** + * Align elements. + * + * @param {Base[]} elements The elements to be aligned. + * @param {ModelingAlignAlignment} alignment The alignment. + */ Modeling.prototype.alignElements = function(elements, alignment) { var context = { elements: elements, @@ -434,6 +547,14 @@ Modeling.prototype.alignElements = function(elements, alignment) { this._commandStack.execute('elements.align', context); }; +/** + * Resize a shape. + * + * @param {Shape} shape The shape to be resized. + * @param {Rect} newBounds The bounds to resize the shape to. + * @param {Dimensions} minBounds The minimum bounds to resize the shape to. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.resizeShape = function(shape, newBounds, minBounds, hints) { var context = { shape: shape, @@ -445,6 +566,15 @@ Modeling.prototype.resizeShape = function(shape, newBounds, minBounds, hints) { this._commandStack.execute('shape.resize', context); }; +/** + * Create space along an horizontally or vertically. + * + * @param {Shape[]} movingShapes The shapes to be moved. + * @param {Shape[]} resizingShapes The shapes to be resized. + * @param {Point} delta The delta. + * @param {Direction} direction The direction in which to create space. + * @param {number} start Where to start creating space in the given direction. + */ Modeling.prototype.createSpace = function(movingShapes, resizingShapes, delta, direction, start) { var context = { delta: delta, @@ -457,6 +587,14 @@ Modeling.prototype.createSpace = function(movingShapes, resizingShapes, delta, d this._commandStack.execute('spaceTool', context); }; +/** + * Update a connetions waypoints. + * + * @param {Connection} connection The connection of which to update the + * waypoints. + * @param {Point[]} newWaypoints The updated waypoints. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.updateWaypoints = function(connection, newWaypoints, hints) { var context = { connection: connection, @@ -467,6 +605,16 @@ Modeling.prototype.updateWaypoints = function(connection, newWaypoints, hints) { this._commandStack.execute('connection.updateWaypoints', context); }; +/** + * Reconnect a connections source and/or target. + * + * @param {Connection} connection The connection to be reconnected. + * @param {Base} source The source to connect to. + * @param {Base} target The target to connect to. + * @param {Point|Point[]} dockingOrPoints The point to connect to or the + * waypoints. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.reconnect = function(connection, source, target, dockingOrPoints, hints) { var context = { connection: connection, @@ -479,6 +627,15 @@ Modeling.prototype.reconnect = function(connection, source, target, dockingOrPoi this._commandStack.execute('connection.reconnect', context); }; +/** + * Reconnect a connections source. + * + * @param {Connection} connection The connection to be reconnected. + * @param {Base} newSource The source to connect to. + * @param {Point|Point[]} dockingOrPoints The point to connect to or the + * waypoints. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.reconnectStart = function(connection, newSource, dockingOrPoints, hints) { if (!hints) { hints = {}; @@ -489,6 +646,15 @@ Modeling.prototype.reconnectStart = function(connection, newSource, dockingOrPoi })); }; +/** + * Reconnect a connections target. + * + * @param {Connection} connection The connection to be reconnected. + * @param {Base} newTarget The target to connect to. + * @param {Point|Point[]} dockingOrPoints The point to connect to or the + * waypoints. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.reconnectEnd = function(connection, newTarget, dockingOrPoints, hints) { if (!hints) { hints = {}; @@ -499,6 +665,17 @@ Modeling.prototype.reconnectEnd = function(connection, newTarget, dockingOrPoint })); }; +/** + * Connect two elements. + * + * @param {Base} source The source of the connection. + * @param {Base} target The target of the connection. + * @param {Connection|ModelAttrsConnection} attrs The connection to be + * created or its attributes. + * @param {ModelingHints} [hints] The optional hints. + * + * @return {Connection} The created connection. + */ Modeling.prototype.connect = function(source, target, attrs, hints) { return this.createConnection(source, target, attrs || {}, source.parent, hints); }; @@ -511,6 +688,12 @@ Modeling.prototype._create = function(type, attrs) { } }; +/** + * Collapse or expand a shape. + * + * @param {Shape} shape The shape to be expanded or collapsed. + * @param {ModelingHints} [hints] The optional hints. + */ Modeling.prototype.toggleCollapse = function(shape, hints) { var context = { shape: shape, diff --git a/lib/features/modeling/Modeling.spec.ts b/lib/features/modeling/Modeling.spec.ts new file mode 100644 index 000000000..91ceb3883 --- /dev/null +++ b/lib/features/modeling/Modeling.spec.ts @@ -0,0 +1,205 @@ +import Diagram from '../../../lib/Diagram'; + +import CommandStack from '../../command/CommandStack'; + +import CoreModule from '.'; +import ElementFactory from '../../core/ElementFactory'; + +import ModelingModule from '.'; +import Modeling from './Modeling'; + +const diagram = new Diagram({ + modules: [ + CoreModule, + ModelingModule + ] +}); + +const elementFactory = diagram.get('elementFactory'); + +const connection = elementFactory.createConnection(), + label = elementFactory.createLabel(), + root = elementFactory.createRoot(), + shape = elementFactory.createShape(); + +const modeling = diagram.get('modeling'); + +modeling.moveShape(shape, { x: 100, y: 100 }); + +modeling.moveShape(shape, { x: 100, y: 100 }, root); + +modeling.moveShape(shape, { x: 100, y: 100 }, root, 1); + +modeling.moveShape(shape, { x: 100, y: 100 }, root, 1, { foo: 'bar' }); + +modeling.updateAttachment(shape); + +modeling.updateAttachment(shape, elementFactory.createShape()); + +modeling.moveElements([ shape ], { x: 100, y: 100 }); + +modeling.moveElements([ shape ], { x: 100, y: 100 }, root); + +modeling.moveElements([ shape ], { x: 100, y: 100 }, root, { attach: true }); + +modeling.moveConnection(connection, { x: 100, y: 100 }); + +modeling.moveConnection(connection, { x: 100, y: 100 }, root); + +modeling.moveConnection(connection, { x: 100, y: 100 }, root, 1); + +modeling.moveConnection(connection, { x: 100, y: 100 }, root, 1, { foo: 'bar' }); + +modeling.layoutConnection(connection); + +modeling.layoutConnection(connection, { foo: 'bar' }); + +modeling.createConnection(shape, elementFactory.createShape(), { id: 'foo' }, root); + +modeling.createConnection(shape, elementFactory.createShape(), connection, root); + +modeling.createConnection(shape, elementFactory.createShape(), connection, root, { foo: 'bar' }); + +modeling.createShape({ id: 'foo' }, { x: 100, y: 100 }, root); + +modeling.createShape(shape, { x: 100, y: 100 }, root); + +modeling.createShape(shape, { x: 100, y: 100 }, root, { + attach: true +}); + +modeling.createElements([ + shape, + elementFactory.createShape() +], { x: 100, y: 100 }, root); + +modeling.createElements([ + shape, + elementFactory.createShape() +], { x: 100, y: 100 }, root, 1); + +modeling.createElements([ + shape, + elementFactory.createShape() +], { x: 100, y: 100 }, root, 1, { foo: 'bar' }); + +modeling.createLabel(shape, { x: 100, y: 100 }, label); + +modeling.createLabel(shape, { x: 100, y: 100 }, label, root); + +modeling.appendShape( + shape, elementFactory.createShape(), { x: 100, y: 100 }, root); + +modeling.appendShape(shape, elementFactory.createShape(), { x: 100, y: 100 }, root, { foo: 'bar' }); + +modeling.removeElements([ shape ]); + +modeling.distributeElements([ + { + elements: [ shape ], + range: { + min: 100, + max: 200 + } + } +], 'x', 'width'); + +modeling.removeShape(shape); + +modeling.removeShape(shape, { foo: 'bar' }); + +modeling.removeConnection(connection); + +modeling.removeConnection(connection, { foo: 'bar' }); + +modeling.replaceShape(shape, { id: 'foo' }); + +modeling.replaceShape(shape, elementFactory.createShape()); + +modeling.replaceShape(shape, elementFactory.createShape(), { foo: 'bar' }); + +modeling.alignElements([ shape, connection ], { + top: 100, + right: 100, + left: 100, + bottom: 100, + center: 100, + middle: 100 +}); + +modeling.resizeShape(shape, { x: 100, y: 100, width: 100, height: 100 }); + +modeling.resizeShape(shape, { x: 100, y: 100, width: 100, height: 100 }, + { width: 100, height: 100 }); + +modeling.resizeShape(shape, { x: 100, y: 100, width: 100, height: 100 }, + { width: 100, height: 100 }, { foo: 'bar' }); + +modeling.createSpace([ shape ], [], { x: 100, y: 100 }, 'e', 100); + +modeling.updateWaypoints(connection, [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +]); + +modeling.updateWaypoints(connection, [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +], { foo: 'bar' }); + +modeling.reconnect( + connection, shape, elementFactory.createShape(), { x: 100, y: 100 }); + +modeling.reconnect( + connection, shape, elementFactory.createShape(), { x: 100, y: 100 }, { + foo: 'bar' + }); + +modeling.reconnect(connection, shape, elementFactory.createShape(), [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +]); + +modeling.reconnectStart(connection, shape, { x: 100, y: 100 }); + +modeling.reconnectStart(connection, shape, { x: 100, y: 100 }, { + foo: 'bar' +}); + +modeling.reconnectStart(connection, shape, [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +]); + +modeling.reconnectStart(connection, shape, [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +], { + foo: 'bar' +}); + +modeling.reconnectEnd(connection, shape, { x: 100, y: 100 }); + +modeling.reconnectEnd(connection, shape, { x: 100, y: 100 }, { + foo: 'bar' +}); + +modeling.reconnectEnd(connection, shape, [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +]); + +modeling.reconnectEnd(connection, shape, [ + { x: 100, y: 100 }, + { x: 200, y: 100 } +], { + foo: 'bar' +}); + +modeling.connect(shape, elementFactory.createShape()); + +modeling.toggleCollapse(shape); + +modeling.toggleCollapse(shape, { + layoutConnection: false +}); \ No newline at end of file diff --git a/lib/features/modeling/index.d.ts b/lib/features/modeling/index.d.ts new file mode 100644 index 000000000..9cee88af9 --- /dev/null +++ b/lib/features/modeling/index.d.ts @@ -0,0 +1,7 @@ +import { + ModuleDeclaration +} from 'didi'; + +declare const m : ModuleDeclaration; + +export default m; diff --git a/lib/features/overlays/Overlays.d.ts b/lib/features/overlays/Overlays.d.ts new file mode 100644 index 000000000..1c6a2ad96 --- /dev/null +++ b/lib/features/overlays/Overlays.d.ts @@ -0,0 +1,193 @@ +import Canvas from '../../core/Canvas'; +import ElementRegistry from '../../core/ElementRegistry'; +import EventBus from '../../core/EventBus'; + +import { Base } from '../../model'; + +export type OverlaysConfigShow = { + minZoom?: number, + maxZoom?: number +}; + +export type OverlaysConfigScale = { + min?: number, + max?: number +}; + +export type OverlaysConfigDefault = { + show?: OverlaysConfigShow, + scale?: OverlaysConfigScale | boolean +}; + +export type OverlaysPosition = { + top?: number, + right?: number, + bottom?: number, + left?: number +}; + +export type OverlaysConfig = { + defaults?: OverlaysConfigDefault +}; + +export type OverlayAttrs = { + html: HTMLElement | string, + position: OverlaysPosition +} & OverlaysConfigDefault; + +export type Overlay = { + id: string, + type: string | null, + element: Base | string +} & OverlayAttrs; + +export type OverlayContainer = { + html: HTMLElement, + element: Base, + overlays: Overlay[] +}; + +export type OverlaysFilter = { + id?: string; + element?: Base | string; + type?: string; +} | string; + +/** + * A service that allows users to attach overlays to diagram elements. + * + * The overlay service will take care of overlay positioning during updates. + * + * @example + * + * // add a pink badge on the top left of the shape + * overlays.add(someShape, { + * position: { + * top: -5, + * left: -5 + * }, + * html: '
0
' + * }); + * + * // or add via shape id + * + * overlays.add('some-element-id', { + * position: { + * top: -5, + * left: -5 + * } + * html: '
0
' + * }); + * + * // or add with optional type + * + * overlays.add(someShape, 'badge', { + * position: { + * top: -5, + * left: -5 + * } + * html: '
0
' + * }); + * + * + * // remove an overlay + * + * var id = overlays.add(...); + * overlays.remove(id); + * + * + * You may configure overlay defaults during tool by providing a `config` module + * with `overlays.defaults` as an entry: + * + * { + * overlays: { + * defaults: { + * show: { + * minZoom: 0.7, + * maxZoom: 5.0 + * }, + * scale: { + * min: 1 + * } + * } + * } + */ +export default class Overlays { + constructor(config: OverlaysConfig, eventBus: EventBus, canvas: Canvas, elementRegistry: ElementRegistry) + + /** + * Returns the overlay with the specified ID or a list of overlays + * for an element with a given type. + * + * @example + * + * // return the single overlay with the given ID + * overlays.get('some-id'); + * + * // return all overlays for the shape + * overlays.get({ element: someShape }); + * + * // return all overlays on shape with type 'badge' + * overlays.get({ element: someShape, type: 'badge' }); + * + * // shape can also be specified as ID + * overlays.get({ element: 'element-id', type: 'badge' }); + * + * @param search The filter to be used to find the overlay(s). + * + * @return The overlay(s). + */ + get(search: OverlaysFilter): Overlay | Overlay[]; + + /** + * Adds an HTML overlay to an element. + * + * @param element The element to add the overlay to. + * @param overlay The overlay. + * + * @return The overlay's ID that can be used to get or remove it. + */ + add(element: Base | string, overlay: OverlayAttrs): string; + + /** + * Adds an HTML overlay to an element. + * + * @param element The element to add the overlay to. + * @param type An optional type that can be used to filter. + * @param overlay The overlay. + * + * @return The overlay's ID that can be used to get or remove it. + */ + add(element: Base | string, type: string, overlay: OverlayAttrs): string; + + /** + * Remove an overlay with the given ID or all overlays matching the given filter. + * + * @see Overlays#get for filter options. + * + * @param filter The filter to be used to find the overlay. + */ + remove(filter: OverlaysFilter): void; + + /** + * Checks whether overlays are shown. + * + * @returns Whether overlays are shown. + */ + isShown(): boolean; + + /** + * Show all overlays. + */ + show(): void; + + /** + * Hide all overlays. + */ + hide(): void; + + /** + * Remove all overlays and their container. + */ + clear(): void; +} \ No newline at end of file diff --git a/lib/features/overlays/Overlays.js b/lib/features/overlays/Overlays.js index c15202007..c89687195 100644 --- a/lib/features/overlays/Overlays.js +++ b/lib/features/overlays/Overlays.js @@ -30,6 +30,18 @@ var ids = new Ids('ov'); var LOW_PRIORITY = 500; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * + * @typedef {import('./Overlays').Overlay} Overlay + * @typedef {import('./Overlays').OverlayAttrs} OverlayAttrs + * @typedef {import('./Overlays').OverlayContainer} OverlayContainer + * @typedef {import('./Overlays').OverlaysConfig} OverlaysConfig + * @typedef {import('./Overlays').OverlaysConfigDefault} OverlaysConfigDefault + * @typedef {import('./Overlays').OverlaysFilter} OverlaysFilter + */ /** * A service that allows users to attach overlays to diagram elements. @@ -39,6 +51,7 @@ var LOW_PRIORITY = 500; * @example * * // add a pink badge on the top left of the shape + * * overlays.add(someShape, { * position: { * top: -5, @@ -90,19 +103,21 @@ var LOW_PRIORITY = 500; * } * } * - * @param {Object} config + * @param {OverlaysConfig} config * @param {EventBus} eventBus * @param {Canvas} canvas * @param {ElementRegistry} elementRegistry */ export default function Overlays(config, eventBus, canvas, elementRegistry) { - this._eventBus = eventBus; this._canvas = canvas; this._elementRegistry = elementRegistry; this._ids = ids; + /** + * @type {OverlaysConfigDefault} + */ this._overlayDefaults = assign({ // no show constraints @@ -113,16 +128,18 @@ export default function Overlays(config, eventBus, canvas, elementRegistry) { }, config && config.defaults); /** - * Mapping overlayId -> overlay + * @type {Map} */ this._overlays = {}; /** - * Mapping elementId -> overlay container + * @type {OverlayContainer[]} */ this._overlayContainers = []; - // root html element for all overlays + /** + * @type {HTMLElement} + */ this._overlayRoot = createRoot(canvas.getContainer()); this._init(); @@ -138,12 +155,12 @@ Overlays.$inject = [ /** - * Returns the overlay with the specified id or a list of overlays + * Returns the overlay with the specified ID or a list of overlays * for an element with a given type. * * @example * - * // return the single overlay with the given id + * // return the single overlay with the given ID * overlays.get('some-id'); * * // return all overlays for the shape @@ -152,16 +169,12 @@ Overlays.$inject = [ * // return all overlays on shape with type 'badge' * overlays.get({ element: someShape, type: 'badge' }); * - * // shape can also be specified as id + * // shape can also be specified as ID * overlays.get({ element: 'element-id', type: 'badge' }); * + * @param {OverlaysFilter} search The filter to be used to find the overlay(s). * - * @param {Object} search - * @param {string} [search.id] - * @param {string|djs.model.Base} [search.element] - * @param {string} [search.type] - * - * @return {Object|Array} the overlay(s) + * @return {Overlay|Overlay[]} The overlay(s). */ Overlays.prototype.get = function(search) { @@ -193,27 +206,13 @@ Overlays.prototype.get = function(search) { }; /** - * Adds a HTML overlay to an element. - * - * @param {string|djs.model.Base} element attach overlay to this shape - * @param {string} [type] optional type to assign to the overlay - * @param {Object} overlay the overlay configuration + * Adds an HTML overlay to an element. * - * @param {string|DOMElement} overlay.html html element to use as an overlay - * @param {Object} [overlay.show] show configuration - * @param {number} [overlay.show.minZoom] minimal zoom level to show the overlay - * @param {number} [overlay.show.maxZoom] maximum zoom level to show the overlay - * @param {Object} overlay.position where to attach the overlay - * @param {number} [overlay.position.left] relative to element bbox left attachment - * @param {number} [overlay.position.top] relative to element bbox top attachment - * @param {number} [overlay.position.bottom] relative to element bbox bottom attachment - * @param {number} [overlay.position.right] relative to element bbox right attachment - * @param {boolean|Object} [overlay.scale=true] false to preserve the same size regardless of - * diagram zoom - * @param {number} [overlay.scale.min] - * @param {number} [overlay.scale.max] + * @param {Base|string} element The element to add the overlay to. + * @param {string} [type] An optional type that can be used to filter. + * @param {OverlayAttrs} overlay The overlay. * - * @return {string} id that may be used to reference the overlay for update or removal + * @return {string} The overlay's ID that can be used to get or remove it. */ Overlays.prototype.add = function(element, type, overlay) { @@ -254,11 +253,11 @@ Overlays.prototype.add = function(element, type, overlay) { /** - * Remove an overlay with the given id or all overlays matching the given filter. + * Remove an overlay with the given ID or all overlays matching the given filter. * * @see Overlays#get for filter options. * - * @param {string|object} [filter] + * @param {OverlaysFilter} filter The filter to be used to find the overlay. */ Overlays.prototype.remove = function(filter) { @@ -294,19 +293,32 @@ Overlays.prototype.remove = function(filter) { }; +/** + * Checks whether overlays are shown. + * + * @returns {boolean} Whether overlays are shown. + */ Overlays.prototype.isShown = function() { return this._overlayRoot.style.display !== 'none'; }; +/** + * Show all overlays. + */ Overlays.prototype.show = function() { setVisible(this._overlayRoot); }; - +/** + * Hide all overlays. + */ Overlays.prototype.hide = function() { setVisible(this._overlayRoot, false); }; +/** + * Remove all overlays and their container. + */ Overlays.prototype.clear = function() { this._overlays = {}; diff --git a/lib/features/overlays/Overlays.spec.ts b/lib/features/overlays/Overlays.spec.ts new file mode 100644 index 000000000..022ceb3bf --- /dev/null +++ b/lib/features/overlays/Overlays.spec.ts @@ -0,0 +1,56 @@ +import Diagram from '../../../lib/Diagram'; + +import CoreModule from '.'; +import ElementFactory from '../../core/ElementFactory'; + +import Overlays, { OverlayAttrs } from './Overlays'; + +const diagram = new Diagram({ + modules: [ + CoreModule + ] +}); + +const elementFactory = diagram.get('elementFactory'); + +const shape = elementFactory.createShape(); + +const overlays = diagram.get('overlays'); + +const overlay: OverlayAttrs = { + html: '

Foo

', + position: { + top: 0, + right: 0 + }, + show: { + minZoom: 1 + }, + scale: true +}; + +overlays.add('shape', overlay); + +overlays.add('shape', 'foo', overlay); + +overlays.get({ id: 'shape' }); + +overlays.get({ element: shape }); + +overlays.get({ type: 'foo' }); + +overlays.get('foo'); + +overlays.remove({ id: 'shape' }); + +overlays.remove({ element: shape }); + +overlays.remove({ type: 'foo' }); + +overlays.remove('foo'); + +overlays.hide(); + +overlays.show(); + +overlays.isShown(); \ No newline at end of file diff --git a/lib/model/index.d.ts b/lib/model/index.d.ts new file mode 100644 index 000000000..0394b2fce --- /dev/null +++ b/lib/model/index.d.ts @@ -0,0 +1,162 @@ +import { Point } from '../util/Types'; + +export type ModelTypeBase = 'base'; +export type ModelTypeConnection = 'connection'; +export type ModelTypeLabel = 'label'; +export type ModelTypeRoot = 'root'; +export type ModelTypeShape = 'shape'; + +export type ModelType = ModelTypeConnection | ModelTypeLabel | ModelTypeRoot | ModelTypeShape; + +export type ModelBaseAttrs = { + businessObject?: any; + id?: string; + label?: Label; + parent?: Base; + incoming?: Connection[]; + outgoing?: Connection[]; +}; + +export type ModelAttrsShape = { + isFrame?: boolean; + children?: Base[]; + host?: Shape; + attachers?: Shape[]; + x?: number; + y?: number; + width?: number; + height?: number; +} & ModelBaseAttrs; + +export type ModelAttrsRoot = {} & ModelAttrsShape; + +export type ModelAttrsLabel = { + labelTarget?: Base; +} & ModelAttrsShape; + +export type ModelAttrsConnection = { + source?: Base; + target?: Base; + waypoints?: Point[]; +} & ModelBaseAttrs; + +export type ModelAttrs = ModelAttrsConnection | ModelAttrsLabel | ModelAttrsRoot | ModelAttrsShape; + +export type Base = { + businessObject: any; + id: string; + label: Label; + parent: Base; + incoming: Connection[]; + outgoing: Connection[]; +}; + +export type Shape = { + isFrame: boolean; + children: Base[]; + host: Shape; + attachers: Shape[]; + x: number; + y: number; + width: number; + height: number; +} & Base; + +export type Root = {} & Shape; + +export type Label = { + labelTarget: Base; +} & Shape; + +export type Connection = { + source: Base; + target: Base; + waypoints: Point[]; +} & Base; + +export type Parent = Shape | Root; + +/** + * Creates a connection model element. + * + * @example + * + * import * as Model from 'diagram-js/lib/model'; + * + * const connection = Model.create('connection', { + * waypoints: [ + * { x: 100, y: 100 }, + * { x: 200, y: 100 } + * ] + * }); + * + * @param type The type of model element to be created which is 'connection'. + * @param attrs Attributes to create the connection model element with. + * + * @return The created connection model element. + */ +export function create(type: ModelTypeConnection, attrs: ModelAttrsConnection): Connection; + +/** + * Creates a label model element. + * + * @example + * + * import * as Model from 'diagram-js/lib/model'; + * + * const label = Model.create('label', { + * x: 100, + * y: 100, + * width: 100, + * height: 100, + * labelTarget: shape + * }); + * + * @param type The type of model element to be created which is 'label'. + * @param attrs Attributes to create the label model element with. + * + * @return The created label model element. + */ +export function create(type: ModelTypeLabel, attrs: ModelAttrsLabel): Label; + +/** + * Creates a root model element. + * + * @example + * + * import * as Model from 'diagram-js/lib/model'; + * + * const root = Model.create('root', { + * x: 100, + * y: 100, + * width: 100, + * height: 100 + * }); + * + * @param type The type of model element to be created which is 'root'. + * @param attrs Attributes to create the root model element with. + * + * @return The created root model element. + */ +export function create(type: ModelTypeRoot, attrs: ModelAttrsRoot): Root; + +/** + * Creates a shape model element. + * + * @example + * + * import * as Model from 'diagram-js/lib/model'; + * + * const shape = Model.create('shape', { + * x: 100, + * y: 100, + * width: 100, + * height: 100 + * }); + * + * @param type The type of model element to be created which is 'shape'. + * @param attrs Attributes to create the shape model element with. + * + * @return The created shape model element. + */ +export function create(type: ModelTypeShape, attrs: ModelAttrsShape): Shape; \ No newline at end of file diff --git a/lib/model/index.js b/lib/model/index.js index a4409bc58..807f871dc 100644 --- a/lib/model/index.js +++ b/lib/model/index.js @@ -213,21 +213,47 @@ var types = { }; /** - * Creates a new model element of the specified type + * Creates a model element of the given type. * * @method create * * @example * - * var shape1 = Model.create('shape', { x: 10, y: 10, width: 100, height: 100 }); - * var shape2 = Model.create('shape', { x: 210, y: 210, width: 100, height: 100 }); + * import * as Model from 'diagram-js/lib/model'; * - * var connection = Model.create('connection', { waypoints: [ { x: 110, y: 55 }, {x: 210, y: 55 } ] }); + * const connection = Model.create('connection', { + * waypoints: [ + * { x: 100, y: 100 }, + * { x: 200, y: 100 } + * ] + * }); * - * @param {string} type lower-cased model name - * @param {Object} attrs attributes to initialize the new model instance with + * const label = Model.create('label', { + * x: 100, + * y: 100, + * width: 100, + * height: 100, + * labelTarget: shape + * }); * - * @return {Base} the new model instance + * const root = Model.create('root', { + * x: 100, + * y: 100, + * width: 100, + * height: 100 + * }); + * + * const shape = Model.create('shape', { + * x: 100, + * y: 100, + * width: 100, + * height: 100 + * }); + * + * @param {string} type The type of model element to be created. + * @param {Object} attrs Attributes to create the model element with. + * + * @return {Connection|Label|Root|Shape} The created model element. */ export function create(type, attrs) { var Type = types[type]; diff --git a/lib/model/index.spec.ts b/lib/model/index.spec.ts new file mode 100644 index 000000000..395dd8572 --- /dev/null +++ b/lib/model/index.spec.ts @@ -0,0 +1,44 @@ +import { create } from './index'; + +const connection = create('connection', { + id: 'foo', + waypoints: [ + { x: 100, y: 100 }, + { x: 200, y: 100 } + ], + source: create('shape', {}), + target: create('shape', {}) +}); + +connection.businessObject = {}; + +const label = create('label', { + id: 'foo', + x: 100, + y: 100, + width: 100, + height: 100, + labelTarget: create('shape', {}) +}); + +label.businessObject = {}; + +const root = create('root', { + id: 'foo', + x: 100, + y: 100, + width: 100, + height: 100 +}); + +root.businessObject = {}; + +const shape = create('shape', { + id: 'foo', + x: 100, + y: 100, + width: 100, + height: 100 +}); + +shape.businessObject = {}; \ No newline at end of file diff --git a/lib/util/Types.d.ts b/lib/util/Types.d.ts new file mode 100644 index 000000000..f6f260ce2 --- /dev/null +++ b/lib/util/Types.d.ts @@ -0,0 +1,20 @@ +export type Point = { + x: number; + y: number; +}; + +export type Dimensions = { + width: number; + height: number; +}; + +export type Rect = Point & Dimensions; + +export type RectTRBL = { + top: number; + right: number; + bottom: number; + left: number; +}; + +export type Direction = 'n' | 'w' | 's' | 'e'; \ No newline at end of file diff --git a/lib/util/Types.js b/lib/util/Types.js new file mode 100644 index 000000000..9d9875cb4 --- /dev/null +++ b/lib/util/Types.js @@ -0,0 +1,31 @@ +/** + * @typedef Point + * @property {number} x + * @property {number} y +*/ + +/** + * @typedef Dimensions + * @property {number} width + * @property {number} height +*/ + +/** + * @typedef Rect + * @property {number} x + * @property {number} y + * @property {number} width + * @property {number} height + */ + +/** + * @typedef RectTRBL + * @property {number} top + * @property {number} right + * @property {number} bottom + * @property {number} left + */ + +/** + * @typedef {string} Directions - Either 'n', 'w', 's' or 'e'. + */ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 57f5d18fb..9db97455b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "puppeteer": "^19.4.1", "sinon": "^15.0.0", "sinon-chai": "^3.7.0", + "typescript": "^4.9.4", "webpack": "^5.74.0" } }, @@ -7165,6 +7166,19 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/ua-parser-js": { "version": "0.7.33", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", @@ -12420,6 +12434,12 @@ } } }, + "typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true + }, "ua-parser-js": { "version": "0.7.33", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz", diff --git a/package.json b/package.json index 0c448f03b..3fd51f402 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "11.9.1", "description": "A toolbox for displaying and modifying diagrams on the web", "main": "index.js", + "types": "index.d.ts", "files": [ "lib", "assets", @@ -12,10 +13,11 @@ "!.eslintrc" ], "scripts": { - "all": "run-s lint test", + "all": "run-s lint test test:types", "lint": "eslint .", "dev": "npm test -- --auto-watch --no-single-run", - "test": "karma start" + "test": "karma start", + "test:types": "tsc" }, "repository": { "type": "git", @@ -64,6 +66,7 @@ "puppeteer": "^19.4.1", "sinon": "^15.0.0", "sinon-chai": "^3.7.0", + "typescript": "^4.9.4", "webpack": "^5.74.0" }, "dependencies": { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..e86579711 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "include": [ + "./lib/**/*.spec.ts" + ], + "compilerOptions": { + "noEmit": true + } +} \ No newline at end of file From 9a9fc755f415abda9b34d7bacbf3a416a956ac9a Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 23 Feb 2023 18:18:15 +0100 Subject: [PATCH 3/7] chore: fix JSDoc comments * fix @param types * fix formatting --- lib/core/Canvas.js | 2 +- lib/core/Canvas.spec.ts | 4 +- lib/draw/DefaultRenderer.js | 5 ++ lib/draw/Styles.js | 10 +-- lib/features/align-elements/AlignElements.js | 20 +++-- lib/features/attach-support/AttachSupport.js | 25 +++++-- lib/features/auto-place/AutoPlace.js | 25 +++++-- .../auto-place/AutoPlaceSelectionBehavior.js | 5 ++ lib/features/auto-place/AutoPlaceUtil.js | 16 ++-- lib/features/auto-resize/AutoResize.js | 39 ++++++---- .../auto-resize/AutoResizeProvider.js | 12 ++- lib/features/auto-scroll/AutoScroll.js | 16 +++- lib/features/bendpoints/BendpointMove.js | 17 +++++ .../bendpoints/BendpointMovePreview.js | 13 ++++ lib/features/bendpoints/BendpointSnapping.js | 7 +- lib/features/bendpoints/BendpointUtil.js | 8 +- lib/features/bendpoints/Bendpoints.js | 13 ++++ .../bendpoints/ConnectionSegmentMove.js | 29 ++++++- lib/features/bendpoints/GeometricUtil.js | 53 +++++++------ lib/features/change-support/ChangeSupport.js | 7 ++ lib/features/connect/Connect.js | 22 +++++- lib/features/connect/ConnectPreview.js | 9 ++- .../connection-preview/ConnectionPreview.js | 34 ++++++--- lib/features/context-pad/ContextPad.js | 29 ++++--- lib/features/copy-paste/CopyPaste.js | 46 ++++++++---- lib/features/create/Create.js | 19 ++++- lib/features/create/CreateConnectPreview.js | 7 +- lib/features/create/CreatePreview.js | 16 +++- .../distribute-elements/DistributeElements.js | 42 ++++++++--- lib/features/dragging/Dragging.js | 16 +++- lib/features/editor-actions/EditorActions.js | 16 ++-- lib/features/global-connect/GlobalConnect.js | 12 ++- lib/features/grid-snapping/GridSnapping.js | 9 +++ .../grid-snapping/behavior/ResizeBehavior.js | 29 ++++--- .../behavior/SpaceToolBehavior.js | 8 ++ lib/features/grid-snapping/visuals/Grid.js | 10 ++- lib/features/hand-tool/HandTool.js | 19 ++++- lib/features/hover-fix/HoverFix.js | 7 ++ .../interaction-events/InteractionEvents.js | 38 ++++++---- .../KeyboardMoveSelection.js | 7 ++ lib/features/keyboard/Keyboard.js | 6 +- lib/features/keyboard/KeyboardBindings.js | 5 ++ lib/features/label-support/LabelSupport.js | 14 +++- lib/features/lasso-tool/LassoTool.js | 20 ++++- lib/features/modeling/Modeling.spec.ts | 2 - .../modeling/cmd/AlignElementsHandler.js | 7 ++ .../modeling/cmd/AppendShapeHandler.js | 24 ++++-- .../modeling/cmd/CreateConnectionHandler.js | 26 ++++++- .../modeling/cmd/CreateElementsHandler.js | 7 ++ .../modeling/cmd/CreateLabelHandler.js | 3 + .../modeling/cmd/CreateShapeHandler.js | 14 +++- .../modeling/cmd/DeleteConnectionHandler.js | 5 ++ .../modeling/cmd/DeleteElementsHandler.js | 10 ++- .../modeling/cmd/DeleteShapeHandler.js | 6 ++ .../modeling/cmd/DistributeElementsHandler.js | 5 ++ .../modeling/cmd/LayoutConnectionHandler.js | 7 ++ .../modeling/cmd/MoveElementsHandler.js | 5 ++ lib/features/modeling/cmd/MoveShapeHandler.js | 5 ++ .../cmd/ReconnectConnectionHandler.js | 7 +- .../modeling/cmd/ReplaceShapeHandler.js | 9 ++- .../modeling/cmd/ResizeShapeHandler.js | 3 + lib/features/modeling/cmd/SpaceToolHandler.js | 5 ++ .../cmd/ToggleShapeCollapseHandler.js | 8 +- .../modeling/cmd/UpdateAttachmentHandler.js | 6 ++ .../modeling/cmd/helper/AnchorsHelper.js | 10 ++- .../modeling/cmd/helper/MoveHelper.js | 25 +++++-- lib/features/mouse/Mouse.js | 7 ++ lib/features/move/Move.js | 19 ++++- lib/features/move/MovePreview.js | 15 +++- lib/features/ordering/OrderingProvider.js | 10 ++- lib/features/outline/Outline.js | 17 +++-- lib/features/palette/Palette.js | 18 +++-- lib/features/popup-menu/PopupMenu.js | 16 ++-- lib/features/popup-menu/PopupMenuComponent.js | 2 +- lib/features/popup-menu/PopupMenuProvider.js | 14 +++- .../preview-support/PreviewSupport.js | 20 ++++- lib/features/replace/Replace.js | 6 ++ lib/features/resize/Resize.js | 27 +++++-- lib/features/resize/ResizeHandles.js | 11 ++- lib/features/resize/ResizePreview.js | 5 ++ lib/features/resize/ResizeUtil.js | 34 +++++---- .../root-elements/RootElementsBehavior.js | 7 +- lib/features/rules/RuleProvider.js | 4 + lib/features/rules/Rules.js | 4 + lib/features/search-pad/SearchPad.js | 42 +++++++---- lib/features/selection/Selection.js | 9 ++- lib/features/selection/SelectionBehavior.js | 14 +++- lib/features/selection/SelectionVisuals.js | 7 ++ lib/features/snapping/CreateMoveSnapping.js | 6 ++ lib/features/snapping/ResizeSnapping.js | 5 ++ lib/features/snapping/SnapContext.js | 2 +- lib/features/snapping/SnapUtil.js | 19 +++-- lib/features/snapping/Snapping.js | 5 +- lib/features/space-tool/SpaceTool.js | 36 ++++++--- lib/features/space-tool/SpaceToolPreview.js | 7 ++ lib/features/space-tool/SpaceUtil.js | 11 ++- lib/features/tool-manager/ToolManager.js | 9 ++- lib/features/tooltips/Tooltips.js | 5 ++ lib/features/touch/TouchFix.js | 10 ++- lib/features/touch/TouchInteractionEvents.js | 12 +++ lib/i18n/I18N.js | 4 + lib/layout/BaseLayouter.js | 15 +++- lib/layout/ConnectionDocking.js | 38 ++++------ lib/layout/CroppingConnectionDocking.js | 7 +- lib/layout/LayoutUtil.js | 34 +++++---- lib/layout/ManhattanLayout.js | 75 ++++++++++--------- lib/model/index.js | 8 -- lib/navigation/keyboard-move/KeyboardMove.js | 4 + lib/navigation/movecanvas/MoveCanvas.js | 4 + lib/navigation/zoomscroll/ZoomScroll.js | 7 +- lib/util/AttachUtil.js | 26 ++++--- lib/util/Collections.js | 4 +- lib/util/Elements.js | 49 ++++++------ lib/util/Geometry.js | 42 ++++++----- lib/util/GraphicsUtil.js | 10 +-- lib/util/IdGenerator.js | 5 +- lib/util/LineIntersection.js | 8 +- lib/util/Math.js | 5 +- lib/util/Removal.js | 4 +- lib/util/RenderUtil.js | 19 +++-- lib/util/SvgTransformUtil.js | 2 +- lib/util/Text.js | 12 ++- lib/util/Types.d.ts | 10 ++- lib/util/Types.js | 22 +++++- test/helper/index.js | 6 +- test/matchers/BoundsMatchers.js | 9 ++- test/matchers/ConnectionMatchers.js | 4 + .../attach-support/rules/AttachRules.js | 4 +- .../features/context-pad/ContextPadSpec.js | 2 +- .../spec/features/copy-paste/CopyPasteSpec.js | 12 ++- .../modeling/custom/CustomLayouter.js | 5 +- .../features/move/renderer/MarkerRenderer.js | 6 +- test/util/MockEvents.js | 3 + 133 files changed, 1383 insertions(+), 482 deletions(-) diff --git a/lib/core/Canvas.js b/lib/core/Canvas.js index 3f477d15b..aeeba0b89 100644 --- a/lib/core/Canvas.js +++ b/lib/core/Canvas.js @@ -78,7 +78,7 @@ function findRoot(element) { * Creates a HTML container element for a SVG element with * the given configuration * - * @param {CanvasConfig} options + * @param {CanvasConfig} options * * @return {HTMLElement} the container element */ diff --git a/lib/core/Canvas.spec.ts b/lib/core/Canvas.spec.ts index 44cf7bcdd..46408d5d1 100644 --- a/lib/core/Canvas.spec.ts +++ b/lib/core/Canvas.spec.ts @@ -1,8 +1,8 @@ import Diagram from '../../lib/Diagram'; import CoreModule from '../../lib/core'; -import Canvas from '../../lib/core/Canvas'; -import ElementFactory from '../../lib/core/ElementFactory'; +import Canvas from './Canvas'; +import ElementFactory from './ElementFactory'; const diagram = new Diagram({ modules: [ diff --git a/lib/draw/DefaultRenderer.js b/lib/draw/DefaultRenderer.js index 4bce1b357..57c2d49bd 100644 --- a/lib/draw/DefaultRenderer.js +++ b/lib/draw/DefaultRenderer.js @@ -19,6 +19,11 @@ import { isFrameElement } from '../util/Elements'; +/** + * @typedef {import('../core/EventBus').default} EventBus + * @typedef {import('./Styles').default} Styles + */ + // apply default renderer with lowest possible priority // so that it only kicks in if noone else could render var DEFAULT_RENDER_PRIORITY = 1; diff --git a/lib/draw/Styles.js b/lib/draw/Styles.js index c4f2ccfa2..b3f2132ac 100644 --- a/lib/draw/Styles.js +++ b/lib/draw/Styles.js @@ -28,9 +28,9 @@ export default function Styles() { /** * Builds a style definition from a className, a list of traits and an object of additional attributes. * - * @param {string} className - * @param {Array} traits - * @param {Object} additionalAttrs + * @param {string} className + * @param {Array} traits + * @param {Object} additionalAttrs * * @return {Object} the style defintion */ @@ -43,8 +43,8 @@ export default function Styles() { /** * Builds a style definition from a list of traits and an object of additional attributes. * - * @param {Array} traits - * @param {Object} additionalAttrs + * @param {Array} traits + * @param {Object} additionalAttrs * * @return {Object} the style defintion */ diff --git a/lib/features/align-elements/AlignElements.js b/lib/features/align-elements/AlignElements.js index b9da9640b..6bd189b3a 100644 --- a/lib/features/align-elements/AlignElements.js +++ b/lib/features/align-elements/AlignElements.js @@ -5,6 +5,11 @@ import { sortBy } from 'min-dash'; +/** + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ + function last(arr) { return arr && arr[arr.length - 1]; } @@ -37,7 +42,10 @@ var ALIGNMENT_SORTING = { } }; - +/** + * @param {Modeling} modeling + * @param {Rules} rules + */ export default function AlignElements(modeling, rules) { this._modeling = modeling; this._rules = rules; @@ -49,7 +57,7 @@ AlignElements.$inject = [ 'modeling', 'rules' ]; /** * Get the relevant "axis" and "dimension" related to the current type of alignment * - * @param {string} type left|right|center|top|bottom|middle + * @param {string} type left|right|center|top|bottom|middle * * @return {Object} { axis, dimension } */ @@ -76,8 +84,8 @@ AlignElements.prototype._isType = function(type, types) { /** * Get a point on the relevant axis where elements should align to * - * @param {string} type left|right|center|top|bottom|middle - * @param {Array} sortedElements + * @param {string} type left|right|center|top|bottom|middle + * @param {Array} sortedElements * * @return {Object} */ @@ -152,8 +160,8 @@ AlignElements.prototype._alignmentPosition = function(type, sortedElements) { /** * Executes the alignment of a selection of elements * - * @param {Array} elements - * @param {string} type left|right|center|top|bottom|middle + * @param {Array} elements + * @param {string} type left|right|center|top|bottom|middle */ AlignElements.prototype.trigger = function(elements, type) { var modeling = this._modeling, diff --git a/lib/features/attach-support/AttachSupport.js b/lib/features/attach-support/AttachSupport.js index bbf30eb64..0b83ed1f2 100644 --- a/lib/features/attach-support/AttachSupport.js +++ b/lib/features/attach-support/AttachSupport.js @@ -15,6 +15,17 @@ import inherits from 'inherits-browser'; import CommandInterceptor from '../../command/CommandInterceptor'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../rules/Rules').default} Rules + * @typedef {import('../modeling/Modeling').default} Modeling + */ + var LOW_PRIORITY = 251, HIGH_PRIORITY = 1401; @@ -30,7 +41,7 @@ var MARKER_ATTACH = 'attach-ok'; * Optionally depends on `diagram-js/lib/features/label-support` * to render attached labels during move preview. * - * @param {didi.Injector} injector + * @param {Injector} injector * @param {EventBus} eventBus * @param {Canvas} canvas * @param {Rules} rules @@ -273,8 +284,8 @@ AttachSupport.$inject = [ /** * Return attachers of the given shapes * - * @param {Array} shapes - * @return {Array} + * @param {Array} shapes + * @return {Array} */ function getAttachers(shapes) { return flatten(map(shapes, function(s) { @@ -286,8 +297,8 @@ function getAttachers(shapes) { * Return a combined list of elements and * attachers. * - * @param {Array} elements - * @return {Array} filtered + * @param {Array} elements + * @return {Array} filtered */ function addAttached(elements) { var attachers = getAttachers(elements); @@ -300,9 +311,9 @@ function addAttached(elements) { * contain attached elements with hosts being part * of the selection. * - * @param {Array} elements + * @param {Array} elements * - * @return {Array} filtered + * @return {Array} filtered */ function removeAttached(elements) { diff --git a/lib/features/auto-place/AutoPlace.js b/lib/features/auto-place/AutoPlace.js index 53c476117..bbeffa508 100644 --- a/lib/features/auto-place/AutoPlace.js +++ b/lib/features/auto-place/AutoPlace.js @@ -5,6 +5,16 @@ import { import { DEFAULT_DISTANCE } from './AutoPlaceUtil'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + */ + var LOW_PRIORITY = 100; @@ -14,6 +24,7 @@ var LOW_PRIORITY = 100; * * @param {EventBus} eventBus * @param {Modeling} modeling + * @param {Canvas} canvas */ export default function AutoPlace(eventBus, modeling, canvas) { @@ -31,10 +42,10 @@ export default function AutoPlace(eventBus, modeling, canvas) { /** * Append shape to source at appropriate position. * - * @param {djs.model.Shape} source - * @param {djs.model.Shape} shape + * @param {Shape} source + * @param {Shape} shape * - * @return {djs.model.Shape} appended shape + * @return {Shape} appended shape */ this.append = function(source, shape, hints) { @@ -73,10 +84,10 @@ AutoPlace.$inject = [ * Find the new position for the target element to * connect to source. * - * @param {djs.model.Shape} source - * @param {djs.model.Shape} element - * @param {Object} [hints] - * @param {Object} [hints.defaultDistance] + * @param {Shape} source + * @param {Shape} element + * @param {Object} [hints] + * @param {Object} [hints.defaultDistance] * * @returns {Point} */ diff --git a/lib/features/auto-place/AutoPlaceSelectionBehavior.js b/lib/features/auto-place/AutoPlaceSelectionBehavior.js index 6024694c4..930dc6ff2 100644 --- a/lib/features/auto-place/AutoPlaceSelectionBehavior.js +++ b/lib/features/auto-place/AutoPlaceSelectionBehavior.js @@ -1,3 +1,8 @@ +/** + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../selection/Selection').default} Selection + */ + /** * Select element after auto placement. * diff --git a/lib/features/auto-place/AutoPlaceUtil.js b/lib/features/auto-place/AutoPlaceUtil.js index b4a929abb..d02be771e 100644 --- a/lib/features/auto-place/AutoPlaceUtil.js +++ b/lib/features/auto-place/AutoPlaceUtil.js @@ -9,6 +9,12 @@ import { reduce } from 'min-dash'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Point} Point + */ + // padding to detect element placement var PLACEMENT_DETECTION_PAD = 10; @@ -20,8 +26,8 @@ var DEFAULT_MAX_DISTANCE = 250; /** * Get free position starting from given position. * - * @param {djs.model.Shape} source - * @param {djs.model.Shape} element + * @param {Shape} source + * @param {Shape} element * @param {Point} position * @param {Function} getNextPosition * @@ -116,7 +122,7 @@ export function getConnectedAtPosition(source, position, element) { * Compute optimal distance between source and target based on existing connections to and from source. * Assumes left-to-right and top-to-down modeling. * -* @param {djs.model.Shape} source +* @param {Shape} source * @param {Object} [hints] * @param {number} [hints.defaultDistance] * @param {string} [hints.direction] @@ -255,9 +261,9 @@ export function getConnectedDistance(source, hints) { * - host connected elements * - attachers connected elements * - * @param {djs.model.Shape} source + * @param {Shape} source * - * @return {Array} + * @return {Array} */ function getAutoPlaceClosure(source) { diff --git a/lib/features/auto-resize/AutoResize.js b/lib/features/auto-resize/AutoResize.js index f7b36e665..e36c610f1 100644 --- a/lib/features/auto-resize/AutoResize.js +++ b/lib/features/auto-resize/AutoResize.js @@ -21,6 +21,19 @@ import { import CommandInterceptor from '../../command/CommandInterceptor'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Direction} Direction + * @typedef {import('../../util/Types').Rect} Rect + * @typedef {import('../../util/Types').RectTRBL} RectTRBL + * + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ /** * An auto resize component that takes care of expanding a parent element @@ -132,8 +145,8 @@ inherits(AutoResize, CommandInterceptor); * This method considers the current size, the added elements as well as * the provided padding for the new bounds. * - * @param {Array} elements - * @param {djs.model.Shape} target + * @param {Shape[]} elements + * @param {Shape} target */ AutoResize.prototype._getOptimalBounds = function(elements, target) { @@ -168,8 +181,8 @@ AutoResize.prototype._getOptimalBounds = function(elements, target) { /** * Expand the target shape respecting rules, offset and padding * - * @param {Array} elements - * @param {djs.model.Shape|string} target|targetId + * @param {Shape[]} elements + * @param {Shape|string} target The target or its ID. */ AutoResize.prototype._expand = function(elements, target) { @@ -212,9 +225,9 @@ AutoResize.prototype._expand = function(elements, target) { /** * Get the amount to expand the given shape in each direction. * - * @param {djs.model.Shape} shape + * @param {Shape} shape * - * @return {TRBL} + * @return {RectTRBL} */ AutoResize.prototype.getOffset = function(shape) { return { top: 60, bottom: 60, left: 100, right: 100 }; @@ -225,9 +238,9 @@ AutoResize.prototype.getOffset = function(shape) { * Get the activation threshold for each side for which * resize triggers. * - * @param {djs.model.Shape} shape + * @param {Shape} shape * - * @return {TRBL} + * @return {RectTRBL} */ AutoResize.prototype.getPadding = function(shape) { return { top: 2, bottom: 2, left: 15, right: 15 }; @@ -237,8 +250,8 @@ AutoResize.prototype.getPadding = function(shape) { /** * Perform the actual resize operation. * - * @param {djs.model.Shape} shape - * @param {Bounds} newBounds + * @param {Shape} shape + * @param {Rect} newBounds * @param {Object} [hints] * @param {string} [hints.autoResize] */ @@ -259,10 +272,10 @@ function boundsChanged(newBounds, oldBounds) { /** * Get directions of resize as {n|w|s|e} e.g. "nw". * - * @param {Bounds} oldBounds - * @param {Bounds} newBounds + * @param {Rect} oldBounds + * @param {Rect} newBounds * - * @returns {string} Resize directions as {n|w|s|e}. + * @returns {Direction} Resize directions as {n|w|s|e}. */ function getResizeDirections(oldBounds, newBounds) { var directions = ''; diff --git a/lib/features/auto-resize/AutoResizeProvider.js b/lib/features/auto-resize/AutoResizeProvider.js index 67484beb4..5fa6cfb03 100644 --- a/lib/features/auto-resize/AutoResizeProvider.js +++ b/lib/features/auto-resize/AutoResizeProvider.js @@ -2,8 +2,16 @@ import RuleProvider from '../rules/RuleProvider'; import inherits from 'inherits-browser'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../core/EventBus').default} EventBus + */ + /** * This is a base rule provider for the element.autoResize rule. + * + * @param {EventBus} eventBus */ export default function AutoResizeProvider(eventBus) { @@ -23,8 +31,8 @@ inherits(AutoResizeProvider, RuleProvider); /** * Needs to be implemented by sub classes to allow actual auto resize * - * @param {Array} elements - * @param {djs.model.Shape} target + * @param {Shape[]} elements + * @param {Shape} target * * @return {boolean} */ diff --git a/lib/features/auto-scroll/AutoScroll.js b/lib/features/auto-scroll/AutoScroll.js index e8f64919a..852dd199e 100644 --- a/lib/features/auto-scroll/AutoScroll.js +++ b/lib/features/auto-scroll/AutoScroll.js @@ -4,6 +4,12 @@ import { toPoint } from '../../util/Event'; +/** + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../core/Canvas').default} Canvas + */ /** * Initiates canvas scrolling if current cursor point is close to a border. @@ -18,6 +24,10 @@ import { * * Threshold order: * [ left, top, right, bottom ] + * + * @param {Object} config + * @param {EventBus} eventBus + * @param {Canvas} canvas */ export default function AutoScroll(config, eventBus, canvas) { @@ -54,7 +64,7 @@ AutoScroll.$inject = [ * Starts scrolling loop. * Point is given in global scale in canvas container box plane. * - * @param {Object} point { x: X, y: Y } + * @param {Point} */ AutoScroll.prototype.startScroll = function(point) { @@ -119,7 +129,7 @@ AutoScroll.prototype.stopScroll = function() { /** * Overrides defaults options. * - * @param {Object} options + * @param {Object} options */ AutoScroll.prototype.setOptions = function(options) { this._opts = assign({}, this._opts, options); @@ -129,7 +139,7 @@ AutoScroll.prototype.setOptions = function(options) { /** * Converts event to a point in canvas container plane in global scale. * - * @param {Event} event + * @param {Event} event * @return {Point} */ AutoScroll.prototype._toBorderPoint = function(event) { diff --git a/lib/features/bendpoints/BendpointMove.js b/lib/features/bendpoints/BendpointMove.js index a9066d3fd..9d5700a7b 100644 --- a/lib/features/bendpoints/BendpointMove.js +++ b/lib/features/bendpoints/BendpointMove.js @@ -1,5 +1,15 @@ import { filterRedundantWaypoints } from '../../layout/LayoutUtil'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ + var round = Math.round; var RECONNECT_START = 'reconnectStart', @@ -9,6 +19,13 @@ var RECONNECT_START = 'reconnectStart', /** * Move bendpoints through drag and drop to add/remove bendpoints or reconnect connection. + * + * @param {Injector} injector + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {Dragging} dragging + * @param {Rules} rules + * @param {Modeling} modeling */ export default function BendpointMove(injector, eventBus, canvas, dragging, rules, modeling) { this._injector = injector; diff --git a/lib/features/bendpoints/BendpointMovePreview.js b/lib/features/bendpoints/BendpointMovePreview.js index c502d169a..35b0f319a 100644 --- a/lib/features/bendpoints/BendpointMovePreview.js +++ b/lib/features/bendpoints/BendpointMovePreview.js @@ -9,6 +9,14 @@ import { translate } from '../../util/SvgTransformUtil'; import { isReverse } from './BendpointMove'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../bendpoints/BendpointMove').default} BendpointMove + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ + var RECONNECT_START = 'reconnectStart', RECONNECT_END = 'reconnectEnd', UPDATE_WAYPOINTS = 'updateWaypoints'; @@ -23,6 +31,11 @@ var HIGH_PRIORITY = 1100; /** * Preview connection while moving bendpoints. + * + * @param {BendpointMove} bendpointMove + * @param {Injector} injector + * @param {EventBus} eventBus + * @param {Canvas} canvas */ export default function BendpointMovePreview(bendpointMove, injector, eventBus, canvas) { this._injector = injector; diff --git a/lib/features/bendpoints/BendpointSnapping.js b/lib/features/bendpoints/BendpointSnapping.js index 1142359a5..30b53d31d 100644 --- a/lib/features/bendpoints/BendpointSnapping.js +++ b/lib/features/bendpoints/BendpointSnapping.js @@ -8,12 +8,17 @@ import { setSnapped } from '../snapping/SnapUtil'; import { getClosestPointOnConnection } from './BendpointUtil'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + */ var abs = Math.abs, round = Math.round; var TOLERANCE = 10; - +/** + * @param {EventBus} eventBus + */ export default function BendpointSnapping(eventBus) { function snapTo(values, value) { diff --git a/lib/features/bendpoints/BendpointUtil.js b/lib/features/bendpoints/BendpointUtil.js index cce6083c4..83d0ebd97 100644 --- a/lib/features/bendpoints/BendpointUtil.js +++ b/lib/features/bendpoints/BendpointUtil.js @@ -25,6 +25,12 @@ import { import { getDistancePointLine, perpendicularFoot } from './GeometricUtil'; +/** + * @typedef {import('../../model').Connection} Connection + * + * @typedef {import('../../util/Types').Point} Point + */ + export var BENDPOINT_CLS = 'djs-bendpoint'; export var SEGMENT_DRAGGER_CLS = 'djs-segment-dragger'; @@ -162,7 +168,7 @@ export function calculateSegmentMoveRegion(segmentLength) { * Returns the point with the closest distance that is on the connection path. * * @param {Point} position - * @param {djs.Base.Connection} connection + * @param {Connection} connection * @returns {Point} */ export function getClosestPointOnConnection(position, connection) { diff --git a/lib/features/bendpoints/Bendpoints.js b/lib/features/bendpoints/Bendpoints.js index 80b9269e3..0e9b94cc8 100644 --- a/lib/features/bendpoints/Bendpoints.js +++ b/lib/features/bendpoints/Bendpoints.js @@ -40,9 +40,22 @@ import { translate } from '../../util/SvgTransformUtil'; +/** + * @typedef {import('../bendpoints/BendpointMove').default} BendpointMove + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../bendpoints/ConnectionSegmentMove').default} ConnectionSegmentMove + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../interaction-events/InteractionEvents').default} InteractionEvents + */ /** * A service that adds editable bendpoints to connections. + * + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {InteractionEvents} interactionEvents + * @param {BendpointMove} bendpointMove + * @param {ConnectionSegmentMove} connectionSegmentMove */ export default function Bendpoints( eventBus, canvas, interactionEvents, diff --git a/lib/features/bendpoints/ConnectionSegmentMove.js b/lib/features/bendpoints/ConnectionSegmentMove.js index c0bf0c86c..9c224e599 100644 --- a/lib/features/bendpoints/ConnectionSegmentMove.js +++ b/lib/features/bendpoints/ConnectionSegmentMove.js @@ -25,6 +25,20 @@ import { translate } from '../../util/SvgTransformUtil'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Axis} Axis + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../core/GraphicsFactory').default} GraphicsFactory + * @typedef {import('../modeling/Modeling').default} Modeling + */ function axisAdd(point, axis, delta) { return axisSet(point, axis, point[axis] + delta); @@ -58,9 +72,9 @@ function flipAxis(axis) { * * Compute a reasonable docking, if non exists. * - * @param {Point} point - * @param {djs.model.Shape} referenceElement - * @param {string} moveAxis (x|y) + * @param {Point} point + * @param {Shape} referenceElement + * @param {Axis} moveAxis * * @return {Point} */ @@ -80,7 +94,14 @@ function getDocking(point, referenceElement, moveAxis) { } /** - * A component that implements moving of bendpoints + * A component that implements moving of bendpoints. + * + * @param {Injector} injector + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {Canvas} dragging + * @param {GraphicsFactory} graphicsFactory + * @param {Modeling} modeling */ export default function ConnectionSegmentMove( injector, eventBus, canvas, diff --git a/lib/features/bendpoints/GeometricUtil.js b/lib/features/bendpoints/GeometricUtil.js index 54e263acb..db2c0df9b 100644 --- a/lib/features/bendpoints/GeometricUtil.js +++ b/lib/features/bendpoints/GeometricUtil.js @@ -1,19 +1,25 @@ +/** + * @typedef {import('../../util/Types').Point} Point + * @typedef {import('../../util/Types').Vector} Vector + */ /** - * Returns the length of a vector + * Returns the length of a vector. + * + * @param {Vector} vector * - * @param {Vector} * @return {number} */ -export function vectorLength(v) { - return Math.sqrt(Math.pow(v.x, 2) + Math.pow(v.y, 2)); +export function vectorLength(vector) { + return Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2)); } /** - * Calculates the angle between a line a the yAxis + * Calculates the angle between a line a the Y axis. + * + * @param {Point[]} line * - * @param {Array} * @return {number} */ export function getAngle(line) { @@ -25,10 +31,11 @@ export function getAngle(line) { /** - * Rotates a vector by a given angle + * Rotates a vector by a given angle. + * + * @param {Vector} vector + * @param {number} angle The angle in radians. * - * @param {Vector} - * @param {number} Angle in radians * @return {Vector} */ export function rotateVector(vector, angle) { @@ -43,9 +50,10 @@ export function rotateVector(vector, angle) { * Solves a 2D equation system * a + r*b = c, where a,b,c are 2D vectors * - * @param {Vector} - * @param {Vector} - * @param {Vector} + * @param {Vector} a + * @param {Vector} b + * @param {Vector} c + * * @return {number} */ function solveLambaSystem(a, b, c) { @@ -65,11 +73,12 @@ function solveLambaSystem(a, b, c) { /** - * Position of perpendicular foot + * Calculates the position of the perpendicular foot. * - * @param {Point} - * @param {[ Point, Point ]} line defined through two points - * @return {Point} the perpendicular foot position + * @param {Point} point + * @param {Point[]} line + * + * @return {Point} */ export function perpendicularFoot(point, line) { @@ -86,12 +95,12 @@ export function perpendicularFoot(point, line) { /** - * Calculates the distance between a point and a line + * Calculates the distance between a point and a line. * - * @param { Point } - * @param { [ Point, Point ] } line defined through two points + * @param {Point} + * @param {Point[]} line * - * @return { number } distance + * @return {number} */ export function getDistancePointLine(point, line) { @@ -108,12 +117,12 @@ export function getDistancePointLine(point, line) { /** - * Calculates the distance between two points + * Calculates the distance between two points. * * @param {Point} * @param {Point} * - * @return {number} distance + * @return {number} */ export function getDistancePointPoint(point1, point2) { diff --git a/lib/features/change-support/ChangeSupport.js b/lib/features/change-support/ChangeSupport.js index b828b8a6f..206c44347 100644 --- a/lib/features/change-support/ChangeSupport.js +++ b/lib/features/change-support/ChangeSupport.js @@ -2,6 +2,13 @@ import { getType as getElementType } from '../../util/Elements'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../core/GraphicsFactory').default} GraphicsFactory + */ + /** * Adds change support to the diagram, including * diff --git a/lib/features/connect/Connect.js b/lib/features/connect/Connect.js index 515d50b71..ee9fa55ab 100644 --- a/lib/features/connect/Connect.js +++ b/lib/features/connect/Connect.js @@ -7,7 +7,23 @@ import { isObject } from 'min-dash'; - +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ + +/** + * @param {EventBus} eventBus + * @param {Dragging} dragging + * @param {Modeling} modeling + * @param {Rules} rules + */ export default function Connect(eventBus, dragging, modeling, rules) { // rules @@ -106,8 +122,8 @@ export default function Connect(eventBus, dragging, modeling, rules) { /** * Start connect operation. * - * @param {DOMEvent} event - * @param {djs.model.Base} start + * @param {MouseEvent|TouchEvent} event + * @param {Base} start * @param {Point} [connectionStart] * @param {boolean} [autoActivate=false] */ diff --git a/lib/features/connect/ConnectPreview.js b/lib/features/connect/ConnectPreview.js index 39b69b980..90cb4f906 100644 --- a/lib/features/connect/ConnectPreview.js +++ b/lib/features/connect/ConnectPreview.js @@ -1,5 +1,12 @@ import { isReverse } from './Connect'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ + var HIGH_PRIORITY = 1100, LOW_PRIORITY = 900; @@ -9,7 +16,7 @@ var MARKER_OK = 'connect-ok', /** * Shows connection preview during connect. * - * @param {didi.Injector} injector + * @param {Injector} injector * @param {EventBus} eventBus * @param {Canvas} canvas */ diff --git a/lib/features/connection-preview/ConnectionPreview.js b/lib/features/connection-preview/ConnectionPreview.js index abab85f9a..4a0bc9199 100644 --- a/lib/features/connection-preview/ConnectionPreview.js +++ b/lib/features/connection-preview/ConnectionPreview.js @@ -20,13 +20,27 @@ import { createLine } from '../../util/RenderUtil'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Connection} Connection + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementFactory').default} ElementFactory + * @typedef {import('../../core/GraphicsFactory').default} GraphicsFactory + */ + var MARKER_CONNECTION_PREVIEW = 'djs-connection-preview'; /** * Draws connection preview. Optionally, this can use layouter and connection docking to draw * better looking previews. * - * @param {didi.Injector} injector + * @param {Injector} injector * @param {Canvas} canvas * @param {GraphicsFactory} graphicsFactory * @param {ElementFactory} elementFactory @@ -62,11 +76,11 @@ ConnectionPreview.$inject = [ * @param {Object} context * @param {Object|boolean} canConnect * @param {Object} hints - * @param {djs.model.shape} [hints.source] source element - * @param {djs.model.shape} [hints.target] target element + * @param {Base} [hints.source] source element + * @param {Base} [hints.target] target element * @param {Point} [hints.connectionStart] connection preview start * @param {Point} [hints.connectionEnd] connection preview end - * @param {Array} [hints.waypoints] provided waypoints for preview + * @param {Point[]} [hints.waypoints] provided waypoints for preview * @param {boolean} [hints.noLayout] true if preview should not be laid out * @param {boolean} [hints.noCropping] true if preview should not be cropped * @param {boolean} [hints.noNoop] true if simple connection should not be drawn @@ -144,8 +158,8 @@ ConnectionPreview.prototype.drawPreview = function(context, canConnect, hints) { * * @param {SVGElement} connectionPreviewGfx container for the connection * @param {Object} hints - * @param {djs.model.shape} [hints.source] source element - * @param {djs.model.shape} [hints.target] target element + * @param {Base} [hints.source] source element + * @param {Base} [hints.target] target element * @param {Point} [hints.connectionStart] required if source is not provided * @param {Point} [hints.connectionEnd] required if target is not provided */ @@ -167,10 +181,10 @@ ConnectionPreview.prototype.drawNoopPreview = function(connectionPreviewGfx, hin * * @param {Point} start * @param {Point} end - * @param {djs.model.shape} source - * @param {djs.model.shape} target + * @param {Base} source + * @param {Base} target * - * @returns {Array} + * @returns {Point[]} */ ConnectionPreview.prototype.cropWaypoints = function(start, end, source, target) { var graphicsFactory = this._graphicsFactory, @@ -201,7 +215,7 @@ ConnectionPreview.prototype.cleanUp = function(context) { * * @param {Object|boolean} canConnect * - * @returns {djs.model.connection} + * @returns {Connection} */ ConnectionPreview.prototype.getConnection = function(canConnect) { var attrs = ensureConnectionAttrs(canConnect); diff --git a/lib/features/context-pad/ContextPad.js b/lib/features/context-pad/ContextPad.js index b9f3ecf54..373768eda 100644 --- a/lib/features/context-pad/ContextPad.js +++ b/lib/features/context-pad/ContextPad.js @@ -23,6 +23,12 @@ import { escapeCSS } from '../../util/EscapeUtil'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../util/Types').Rect} Rect + */ + var entrySelector = '.entry'; var DEFAULT_PRIORITY = 1000; @@ -30,7 +36,11 @@ var CONTEXT_PAD_PADDING = 12; /** - * @typedef {djs.model.Base|djs.model.Base[]} ContextPadTarget + * @typedef {Base|Base[]} ContextPadTarget + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../overlays/Overlays').default} Overlays */ /** @@ -124,8 +134,8 @@ ContextPad.prototype._init = function() { /** * Register context pad provider. * - * @param {number} [priority=1000] - * @param {ContextPadProvider} provider + * @param {number} [priority=1000] + * @param {ContextPadProvider} provider * * @example * const contextPadProvider = { @@ -204,9 +214,9 @@ ContextPad.prototype.getEntries = function(target) { * * The entry to trigger is determined by the target element. * - * @param {string} action - * @param {Event} event - * @param {boolean} [autoActivate=false] + * @param {string} action + * @param {Event} event + * @param {boolean} [autoActivate=false] */ ContextPad.prototype.trigger = function(action, event, autoActivate) { @@ -471,7 +481,8 @@ ContextPad.prototype.isShown = function() { * Get contex pad position. * * @param {ContextPadTarget} target - * @return {Bounds} + * + * @return {Rect} */ ContextPad.prototype._getPosition = function(target) { @@ -500,8 +511,8 @@ function addClasses(element, classNames) { } /** - * @param {any[]} array - * @param {any} item + * @param {*[]} array + * @param {*} item * * @return {boolean} */ diff --git a/lib/features/copy-paste/CopyPaste.js b/lib/features/copy-paste/CopyPaste.js index bf33efa28..63fa8c894 100644 --- a/lib/features/copy-paste/CopyPaste.js +++ b/lib/features/copy-paste/CopyPaste.js @@ -17,13 +17,29 @@ import { import { eachElement } from '../../util/Elements'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../clipboard/Clipboard').default} Clipboard + * @typedef {import('../create/Create').default} Create + * @typedef {import('../../core/ElementFactory').default} ElementFactory + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../mouse/Mouse').default} Mouse + * @typedef {import('../rules/Rules').default} Rules + */ + /** * @typedef {Function} listener * * @param {Object} context - * @param {Array} context.elements + * @param {Array} context.elements * - * @returns {Array|boolean} - Return elements to be copied or false to disallow + * @returns {Array|boolean} - Return elements to be copied or false to disallow * copying. */ @@ -32,16 +48,16 @@ import { eachElement } from '../../util/Elements'; * * @param {Object} context * @param {Object} context.descriptor - * @param {djs.model.Base} context.element - * @param {Array} context.elements + * @param {Base} context.element + * @param {Array} context.elements */ /** * @typedef {Function} listener * * @param {Object} context - * @param {djs.model.Base} context.element - * @param {Array} context.children - Add children to be added to tree. + * @param {Base} context.element + * @param {Array} context.children - Add children to be added to tree. */ /** @@ -177,7 +193,7 @@ CopyPaste.$inject = [ /** * Copy elements. * - * @param {Array} elements + * @param {Base[]} elements * * @returns {Object} */ @@ -215,9 +231,9 @@ CopyPaste.prototype.copy = function(elements) { * Paste elements. * * @param {Object} [context] - * @param {djs.model.base} [context.element] - Parent. - * @param {Point} [context.point] - Position. - * @param {Object} [context.hints] - Hints. + * @param {Shape} [context.element] The optional parent. + * @param {Point} [context.point] The optional osition. + * @param {Object} [context.hints] The optional hints. */ CopyPaste.prototype.paste = function(context) { var tree = this._clipboard.get(); @@ -247,8 +263,8 @@ CopyPaste.prototype.paste = function(context) { /** * Paste elements directly. * - * @param {Array} elements - * @param {djs.model.base} target + * @param {Base[]} elements + * @param {Shape} target * @param {Point} position * @param {Object} [hints] */ @@ -380,8 +396,8 @@ CopyPaste.prototype.createShape = function(attrs) { /** * Check wether element has relations to other elements e.g. attachers, labels and connections. * - * @param {Object} element - * @param {Array} elements + * @param {Object} element + * @param {Base[]} elements * * @returns {boolean} */ @@ -427,7 +443,7 @@ CopyPaste.prototype.hasRelations = function(element, elements) { * ] * }; * - * @param {Array} elements + * @param {Base[]} elements * * @return {Object} */ diff --git a/lib/features/create/Create.js b/lib/features/create/Create.js index 6993fe5b8..0b992dac5 100644 --- a/lib/features/create/Create.js +++ b/lib/features/create/Create.js @@ -15,6 +15,19 @@ import { import { getBBox } from '../../util/Elements'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ + var PREFIX = 'create'; var HIGH_PRIORITY = 2000; @@ -42,10 +55,10 @@ export default function Create( /** * Check wether elements can be created. * - * @param {Array} elements - * @param {djs.model.Base} target + * @param {Base[]} elements + * @param {Shape} target * @param {Point} position - * @param {djs.model.Base} [source] + * @param {Base} [source] * * @returns {boolean|null|Object} */ diff --git a/lib/features/create/CreateConnectPreview.js b/lib/features/create/CreateConnectPreview.js index b9e92efb9..348959966 100644 --- a/lib/features/create/CreateConnectPreview.js +++ b/lib/features/create/CreateConnectPreview.js @@ -1,11 +1,16 @@ var LOW_PRIORITY = 740; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/EventBus').default} EventBus + */ /** * Shows connection preview during create. * + * @param {Injector} injector * @param {EventBus} eventBus - * @param {ConnectionPreview} connectionPreview */ export default function CreateConnectPreview(injector, eventBus) { var connectionPreview = injector.get('connectionPreview', false); diff --git a/lib/features/create/CreatePreview.js b/lib/features/create/CreatePreview.js index fbf0128bf..7d5b5972d 100644 --- a/lib/features/create/CreatePreview.js +++ b/lib/features/create/CreatePreview.js @@ -11,9 +11,23 @@ import { remove as svgRemove } from 'tiny-svg'; -var LOW_PRIORITY = 750; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../core/GraphicsFactory').default} GraphicsFactory + * @typedef {import('../preview-support/PreviewSupport').default} PreviewSupport + * @typedef {import('../../draw/Styles').default} Styles + */ +var LOW_PRIORITY = 750; +/** + * @param {Canvas} canvas + * @param {EventBus} eventBus + * @param {GraphicsFactory} graphicsFactory + * @param {PreviewSupport} previewSupport + * @param {Styles} styles + */ export default function CreatePreview( canvas, eventBus, diff --git a/lib/features/distribute-elements/DistributeElements.js b/lib/features/distribute-elements/DistributeElements.js index 05c1d4e3e..592d2da92 100644 --- a/lib/features/distribute-elements/DistributeElements.js +++ b/lib/features/distribute-elements/DistributeElements.js @@ -4,6 +4,21 @@ import { isArray } from 'min-dash'; +/** + * @typedef {Object} Range + * @property {number} min + * @property {number} max + */ + +/** + * @typedef {import('../../util/Types').Axis} Axis + * @typedef {import('../../util/Types').Dimension} Dimension + * @typedef {import('../../util/Types').Rect} Rect + * + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ + var AXIS_DIMENSIONS = { horizontal: [ 'x', 'width' ], vertical: [ 'y', 'height' ] @@ -14,6 +29,9 @@ var THRESHOLD = 5; /** * Groups and filters elements and then trigger even distribution. + * + * @param {Modeling} modeling + * @param {Rules} rules */ export default function DistributeElements(modeling, rules) { this._modeling = modeling; @@ -38,7 +56,7 @@ DistributeElements.$inject = [ 'modeling', 'rules' ]; * Registers filter functions that allow external parties to filter * out certain elements. * - * @param {Function} filterFn + * @param {Function} filterFn */ DistributeElements.prototype.registerFilter = function(filterFn) { if (typeof filterFn !== 'function') { @@ -51,8 +69,8 @@ DistributeElements.prototype.registerFilter = function(filterFn) { /** * Distributes the elements with a given orientation * - * @param {Array} elements - * @param {string} orientation + * @param {Array} elements + * @param {string} orientation */ DistributeElements.prototype.trigger = function(elements, orientation) { var modeling = this._modeling; @@ -83,7 +101,7 @@ DistributeElements.prototype.trigger = function(elements, orientation) { /** * Filters the elements with provided filters by external parties * - * @param {Array[Elements]} elements + * @param {Array[Elements]} elements * * @return {Array[Elements]} */ @@ -120,7 +138,7 @@ DistributeElements.prototype._filterElements = function(elements) { * } * ] * - * @param {Array} elements + * @param {Array} elements * * @return {Array[Objects]} */ @@ -159,7 +177,7 @@ DistributeElements.prototype._createGroups = function(elements) { /** * Maps a direction to the according axis and dimension * - * @param {string} direction 'horizontal' or 'vertical' + * @param {string} direction 'horizontal' or 'vertical' */ DistributeElements.prototype._setOrientation = function(direction) { var orientation = AXIS_DIMENSIONS[direction]; @@ -172,8 +190,8 @@ DistributeElements.prototype._setOrientation = function(direction) { /** * Checks if the two ranges intercept each other * - * @param {Object} rangeA {min, max} - * @param {Object} rangeB {min, max} + * @param {Object} rangeA {min, max} + * @param {Object} rangeB {min, max} * * @return {boolean} */ @@ -186,11 +204,11 @@ DistributeElements.prototype._hasIntersection = function(rangeA, rangeB) { /** * Returns the min and max values for an element * - * @param {Bounds} element - * @param {string} axis - * @param {string} dimension + * @param {Rect} element + * @param {Axis} axis + * @param {Dimension} dimension * - * @return {{ min: number, max: number }} + * @return {Range} */ DistributeElements.prototype._findRange = function(element) { var axis = element[this._axis], diff --git a/lib/features/dragging/Dragging.js b/lib/features/dragging/Dragging.js index 7154b9583..495422215 100644 --- a/lib/features/dragging/Dragging.js +++ b/lib/features/dragging/Dragging.js @@ -27,6 +27,15 @@ import { import { isKey } from '../keyboard/KeyboardUtil'; +/** + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../selection/Selection').default} Selection + */ + var DRAG_ACTIVE_CLS = 'djs-drag-active'; @@ -122,6 +131,11 @@ function getLength(point) { * }); * }); * } + * + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {Selection} selection + * @param {ElementRegistry} elementRegistry */ export default function Dragging(eventBus, canvas, selection, elementRegistry) { @@ -320,7 +334,7 @@ export default function Dragging(eventBus, canvas, selection, elementRegistry) { move(event); } - // update the drag events hover (djs.model.Base) and hoverGfx (Snap) + // update the drag events model element (`hover`) and graphical element (`hoverGfx`) // properties during hover and out and fire {prefix}.hover and {prefix}.out properties // respectively diff --git a/lib/features/editor-actions/EditorActions.js b/lib/features/editor-actions/EditorActions.js index 100ed5f8c..af7bc17db 100644 --- a/lib/features/editor-actions/EditorActions.js +++ b/lib/features/editor-actions/EditorActions.js @@ -3,6 +3,12 @@ import { 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'; @@ -159,8 +165,8 @@ EditorActions.prototype._registerDefaultActions = function(injector) { /** * Triggers a registered action * - * @param {string} action - * @param {Object} opts + * @param {string} action + * @param {Object} opts * * @return {Unknown} Returns what the registered listener returns */ @@ -193,7 +199,7 @@ EditorActions.prototype.trigger = function(action, opts) { * editorActions.isRegistered('spaceTool'); // true * ´´´ * - * @param {Object} actions + * @param {Object} actions */ EditorActions.prototype.register = function(actions, listener) { var self = this; @@ -210,8 +216,8 @@ EditorActions.prototype.register = function(actions, listener) { /** * Registers a listener to an action key * - * @param {string} action - * @param {Function} listener + * @param {string} action + * @param {Function} listener */ EditorActions.prototype._registerAction = function(action, listener) { if (this.isRegistered(action)) { diff --git a/lib/features/global-connect/GlobalConnect.js b/lib/features/global-connect/GlobalConnect.js index f7b1f8efe..dd76ccef2 100644 --- a/lib/features/global-connect/GlobalConnect.js +++ b/lib/features/global-connect/GlobalConnect.js @@ -1,6 +1,16 @@ var MARKER_OK = 'connect-ok', MARKER_NOT_OK = 'connect-not-ok'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../connect/Connect').default} Connect + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../mouse/Mouse').default} Mouse + * @typedef {import('../rules/Rules').default} Rules + * @typedef {import('../tool-manager/ToolManager').default} ToolManager + */ + /** * @class * @constructor @@ -125,7 +135,7 @@ GlobalConnect.prototype.isActive = function() { /** * Check if source shape can initiate connection. * - * @param {Shape} startTarget + * @param {Shape} startTarget * @return {boolean} */ GlobalConnect.prototype.canStartConnect = function(startTarget) { diff --git a/lib/features/grid-snapping/GridSnapping.js b/lib/features/grid-snapping/GridSnapping.js index 529e31d8f..1f839c318 100644 --- a/lib/features/grid-snapping/GridSnapping.js +++ b/lib/features/grid-snapping/GridSnapping.js @@ -15,12 +15,21 @@ import { quantize } from './GridUtil'; +/** + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + */ + var LOWER_PRIORITY = 1200; var LOW_PRIORITY = 800; /** * Basic grid snapping that covers connecting, creating, moving, resizing shapes, moving bendpoints * and connection segments. + * + * @param {ElementRegistry} elementRegistry + * @param {EventBus} eventBus + * @param {Object} config */ export default function GridSnapping(elementRegistry, eventBus, config) { diff --git a/lib/features/grid-snapping/behavior/ResizeBehavior.js b/lib/features/grid-snapping/behavior/ResizeBehavior.js index 5ac1a3b17..2b9c5b9ca 100644 --- a/lib/features/grid-snapping/behavior/ResizeBehavior.js +++ b/lib/features/grid-snapping/behavior/ResizeBehavior.js @@ -7,9 +7,20 @@ import { isString } from 'min-dash'; +/** + * @typedef {import('../../../model').Shape} Shape + * + * @typedef {import('../../../util/Types').Rect} Rect + * + * @typedef {import('../../../core/EventBus').default} EventBus + * @typedef {import('../../grid-snapping/GridSnapping').default} GridSnapping + */ /** * Integrates resizing with grid snapping. + * + * @param {EventBus} eventBus + * @param {GridSnapping} gridSnapping */ export default function ResizeBehavior(eventBus, gridSnapping) { CommandInterceptor.call(this, eventBus); @@ -49,10 +60,10 @@ inherits(ResizeBehavior, CommandInterceptor); /** * Snap width and height in relation to center. * - * @param {djs.model.shape} shape - * @param {Bounds} newBounds + * @param {Shape} shape + * @param {Rect} newBounds * - * @returns {Bounds} Snapped bounds. + * @returns {Rect} Snapped bounds. */ ResizeBehavior.prototype.snapSimple = function(shape, newBounds) { var gridSnapping = this._gridSnapping; @@ -74,10 +85,10 @@ ResizeBehavior.prototype.snapSimple = function(shape, newBounds) { /** * Snap x, y, width and height according to given directions. * - * @param {Bounds} newBounds + * @param {Rect} newBounds * @param {string} directions - Directions as {n|w|s|e}. * - * @returns {Bounds} Snapped bounds. + * @returns {Rect} Snapped bounds. */ ResizeBehavior.prototype.snapComplex = function(newBounds, directions) { if (/w|e/.test(directions)) { @@ -94,10 +105,10 @@ ResizeBehavior.prototype.snapComplex = function(newBounds, directions) { /** * Snap in one or both directions horizontally. * - * @param {Bounds} newBounds + * @param {Rect} newBounds * @param {string} directions - Directions as {n|w|s|e}. * - * @returns {Bounds} Snapped bounds. + * @returns {Rect} Snapped bounds. */ ResizeBehavior.prototype.snapHorizontally = function(newBounds, directions) { var gridSnapping = this._gridSnapping, @@ -138,10 +149,10 @@ ResizeBehavior.prototype.snapHorizontally = function(newBounds, directions) { /** * Snap in one or both directions vertically. * - * @param {Bounds} newBounds + * @param {Rect} newBounds * @param {string} directions - Directions as {n|w|s|e}. * - * @returns {Bounds} Snapped bounds. + * @returns {Rect} Snapped bounds. */ ResizeBehavior.prototype.snapVertically = function(newBounds, directions) { var gridSnapping = this._gridSnapping, diff --git a/lib/features/grid-snapping/behavior/SpaceToolBehavior.js b/lib/features/grid-snapping/behavior/SpaceToolBehavior.js index 3463886b8..4cd8118ed 100644 --- a/lib/features/grid-snapping/behavior/SpaceToolBehavior.js +++ b/lib/features/grid-snapping/behavior/SpaceToolBehavior.js @@ -1,7 +1,15 @@ +/** + * @typedef {import('../../../core/EventBus').default} EventBus + * @typedef {import('../../grid-snapping/GridSnapping').default} GridSnapping + */ + var HIGH_PRIORITY = 2000; /** * Integrates space tool with grid snapping. + * + * @param {EventBus} eventBus + * @param {GridSnapping} gridSnapping */ export default function SpaceToolBehavior(eventBus, gridSnapping) { eventBus.on([ diff --git a/lib/features/grid-snapping/visuals/Grid.js b/lib/features/grid-snapping/visuals/Grid.js index 2d4d6e783..a5d757cc4 100644 --- a/lib/features/grid-snapping/visuals/Grid.js +++ b/lib/features/grid-snapping/visuals/Grid.js @@ -11,6 +11,11 @@ import { SPACING, quantize } from '../GridUtil'; import { getMid } from '../../../layout/LayoutUtil'; +/** + * @typedef {import('../../../core/Canvas').default} Canvas + * @typedef {import('../../../core/EventBus').default} EventBus + */ + var GRID_COLOR = '#ccc', LAYER_NAME = 'djs-grid'; @@ -19,7 +24,10 @@ export var GRID_DIMENSIONS = { height: 100000 }; - +/** + * @param {Canvas} canvas + * @param {EventBus} eventBus + */ export default function Grid(canvas, eventBus) { this._canvas = canvas; diff --git a/lib/features/hand-tool/HandTool.js b/lib/features/hand-tool/HandTool.js index fa28355e1..fdd79da59 100644 --- a/lib/features/hand-tool/HandTool.js +++ b/lib/features/hand-tool/HandTool.js @@ -4,10 +4,27 @@ import { import { isKey } from '../../features/keyboard/KeyboardUtil'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../mouse/Mouse').default} Mouse + * @typedef {import('../tool-manager/ToolManager').default} ToolManager + */ + var HIGH_PRIORITY = 1500; var HAND_CURSOR = 'grab'; - +/** + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {Dragging} dragging + * @param {Injector} injector + * @param {ToolManager} toolManager + * @param {Mouse} mouse + */ export default function HandTool( eventBus, canvas, dragging, injector, toolManager, mouse) { diff --git a/lib/features/hover-fix/HoverFix.js b/lib/features/hover-fix/HoverFix.js index 41e3dafe0..c51c2e963 100644 --- a/lib/features/hover-fix/HoverFix.js +++ b/lib/features/hover-fix/HoverFix.js @@ -6,6 +6,13 @@ import { toPoint } from '../../util/Event'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + */ + var HIGH_PRIORITY = 1500; diff --git a/lib/features/interaction-events/InteractionEvents.js b/lib/features/interaction-events/InteractionEvents.js index af2ff8cdf..47e7b6c83 100644 --- a/lib/features/interaction-events/InteractionEvents.js +++ b/lib/features/interaction-events/InteractionEvents.js @@ -26,6 +26,14 @@ import { updateLine } from '../../util/RenderUtil'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../draw/Styles').default} Styles + */ + function allowAll(event) { return true; } function allowPrimaryAndAuxiliary(event) { @@ -55,6 +63,8 @@ var LOW_PRIORITY = 500; * prevents the original DOM operation. * * @param {EventBus} eventBus + * @param {ElementRegistry} elementRegistry + * @param {Styles} styles */ export default function InteractionEvents(eventBus, elementRegistry, styles) { @@ -64,8 +74,8 @@ export default function InteractionEvents(eventBus, elementRegistry, styles) { * Fire an interaction event. * * @param {string} type local event name, e.g. element.click. - * @param {DOMEvent} event native event - * @param {djs.model.Base} [element] the diagram element to emit the event on; + * @param {MouseEvent|TouchEvent} event native event + * @param {Base} [element] the diagram element to emit the event on; * defaults to the event target */ function fire(type, event, element) { @@ -147,8 +157,8 @@ export default function InteractionEvents(eventBus, elementRegistry, styles) { * on the target shape or connection. * * @param {string} eventName the name of the triggered DOM event - * @param {MouseEvent} event - * @param {djs.model.Base} targetElement + * @param {MouseEvent|TouchEvent} event + * @param {Base} targetElement */ function triggerMouseEvent(eventName, event, targetElement) { @@ -314,7 +324,7 @@ export default function InteractionEvents(eventBus, elementRegistry, styles) { /** * Create default hit for the given element. * - * @param {djs.model.Base} element + * @param {Base} element * @param {SVGElement} gfx * * @return {SVGElement} created hit @@ -386,8 +396,8 @@ export default function InteractionEvents(eventBus, elementRegistry, styles) { /** * Update default hit of the element. * - * @param {djs.model.Base} element - * @param {SVGElement} gfx + * @param {Base} element + * @param {SVGElement} gfx * * @return {SVGElement} updated hit */ @@ -435,7 +445,7 @@ InteractionEvents.$inject = [ * @event element.hover * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ @@ -446,7 +456,7 @@ InteractionEvents.$inject = [ * @event element.out * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ @@ -457,7 +467,7 @@ InteractionEvents.$inject = [ * @event element.click * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ @@ -468,7 +478,7 @@ InteractionEvents.$inject = [ * @event element.dblclick * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ @@ -479,7 +489,7 @@ InteractionEvents.$inject = [ * @event element.mousedown * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ @@ -490,7 +500,7 @@ InteractionEvents.$inject = [ * @event element.mouseup * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ @@ -502,7 +512,7 @@ InteractionEvents.$inject = [ * @event element.contextmenu * * @type {Object} - * @property {djs.model.Base} element + * @property {Base} element * @property {SVGElement} gfx * @property {Event} originalEvent */ \ No newline at end of file diff --git a/lib/features/keyboard-move-selection/KeyboardMoveSelection.js b/lib/features/keyboard-move-selection/KeyboardMoveSelection.js index 435e3b077..64dffe122 100644 --- a/lib/features/keyboard-move-selection/KeyboardMoveSelection.js +++ b/lib/features/keyboard-move-selection/KeyboardMoveSelection.js @@ -2,6 +2,12 @@ import { assign } from 'min-dash'; +/** + * @typedef {import('../keyboard/Keyboard').default} Keyboard + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + * @typedef {import('../selection/Selection').default} Selection + */ var DEFAULT_CONFIG = { moveSpeed: 1, @@ -64,6 +70,7 @@ var DIRECTIONS_DELTA = { * @param {number} [config.moveSpeedAccelerated=10] * @param {Keyboard} keyboard * @param {Modeling} modeling + * @param {Rules} rules * @param {Selection} selection */ export default function KeyboardMoveSelection( diff --git a/lib/features/keyboard/Keyboard.js b/lib/features/keyboard/Keyboard.js index 2f92067b6..f91b5c71f 100644 --- a/lib/features/keyboard/Keyboard.js +++ b/lib/features/keyboard/Keyboard.js @@ -15,6 +15,10 @@ import { isShift } from './KeyboardUtil'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + */ + var KEYDOWN_EVENT = 'keyboard.keydown', KEYUP_EVENT = 'keyboard.keyup'; @@ -43,7 +47,7 @@ var DEFAULT_PRIORITY = 1000; * A default binding for the keyboard may be specified via the * `keyboard.bindTo` configuration option. * - * @param {Config} config + * @param {Object} config * @param {EventBus} eventBus */ export default function Keyboard(config, eventBus) { diff --git a/lib/features/keyboard/KeyboardBindings.js b/lib/features/keyboard/KeyboardBindings.js index 58442c3cc..c1d41f01a 100644 --- a/lib/features/keyboard/KeyboardBindings.js +++ b/lib/features/keyboard/KeyboardBindings.js @@ -11,6 +11,11 @@ import { KEYS_REDO } from './KeyboardUtil'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('./Keyboard').default} Keyboard + */ + export { KEYS_COPY, KEYS_PASTE, diff --git a/lib/features/label-support/LabelSupport.js b/lib/features/label-support/LabelSupport.js index bcdfc3f8d..0d73999ea 100644 --- a/lib/features/label-support/LabelSupport.js +++ b/lib/features/label-support/LabelSupport.js @@ -17,12 +17,20 @@ import { saveClear } from '../../util/Removal'; import CommandInterceptor from '../../command/CommandInterceptor'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + */ /** * A handler that makes sure labels are properly moved with * their label targets. * - * @param {didi.Injector} injector + * @param {Injector} injector * @param {EventBus} eventBus * @param {Modeling} modeling */ @@ -155,9 +163,9 @@ LabelSupport.$inject = [ * contain attached elements with hosts being part * of the selection. * - * @param {Array} elements + * @param {Array} elements * - * @return {Array} filtered + * @return {Array} filtered */ function removeLabels(elements) { diff --git a/lib/features/lasso-tool/LassoTool.js b/lib/features/lasso-tool/LassoTool.js index 48a0aa39c..9776d8086 100644 --- a/lib/features/lasso-tool/LassoTool.js +++ b/lib/features/lasso-tool/LassoTool.js @@ -13,9 +13,27 @@ import { remove as svgRemove } from 'tiny-svg'; -var LASSO_TOOL_CURSOR = 'crosshair'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../mouse/Mouse').default} Mouse + * @typedef {import('../selection/Selection').default} Selection + * @typedef {import('../tool-manager/ToolManager').default} ToolManager + */ +var LASSO_TOOL_CURSOR = 'crosshair'; +/** + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {Dragging} dragging + * @param {ElementRegistry} elementRegistry + * @param {Selection} selection + * @param {ToolManager} toolManager + * @param {Mouse} mouse + */ export default function LassoTool( eventBus, canvas, dragging, elementRegistry, selection, toolManager, diff --git a/lib/features/modeling/Modeling.spec.ts b/lib/features/modeling/Modeling.spec.ts index 91ceb3883..50d407947 100644 --- a/lib/features/modeling/Modeling.spec.ts +++ b/lib/features/modeling/Modeling.spec.ts @@ -1,7 +1,5 @@ import Diagram from '../../../lib/Diagram'; -import CommandStack from '../../command/CommandStack'; - import CoreModule from '.'; import ElementFactory from '../../core/ElementFactory'; diff --git a/lib/features/modeling/cmd/AlignElementsHandler.js b/lib/features/modeling/cmd/AlignElementsHandler.js index 29c866031..f4e707333 100644 --- a/lib/features/modeling/cmd/AlignElementsHandler.js +++ b/lib/features/modeling/cmd/AlignElementsHandler.js @@ -1,8 +1,15 @@ import { forEach, isDefined } from 'min-dash'; +/** + * @typedef {import('../../../core/Canvas').default} Canvas + * @typedef {import('../Modeling').default} Modeling + */ + /** * A handler that align elements in a certain way. * + * @param {Modeling} modeling + * @param {Canvas} canvas */ export default function AlignElements(modeling, canvas) { this._modeling = modeling; diff --git a/lib/features/modeling/cmd/AppendShapeHandler.js b/lib/features/modeling/cmd/AppendShapeHandler.js index 00a575d52..cc1122f47 100644 --- a/lib/features/modeling/cmd/AppendShapeHandler.js +++ b/lib/features/modeling/cmd/AppendShapeHandler.js @@ -1,13 +1,21 @@ import { some } from 'min-dash'; +/** + * @typedef {import('../../../model').Base} Base + * @typedef {import('../../../model').ModelAttrsShape} ModelAttrsShape + * @typedef {import('../../../model').Parent} Parent + * @typedef {import('../../../model').Shape} Shape + * + * @typedef {import('../../../util/Types').Point} Point + * + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that implements reversible appending of shapes * to a source shape. * - * @param {canvas} Canvas - * @param {elementFactory} ElementFactory - * @param {modeling} Modeling + * @param {Modeling} Modeling */ export default function AppendShapeHandler(modeling) { this._modeling = modeling; @@ -20,13 +28,13 @@ AppendShapeHandler.$inject = [ 'modeling' ]; /** - * Creates a new shape + * Creates a new shape. * * @param {Object} context - * @param {ElementDescriptor} context.shape the new shape - * @param {ElementDescriptor} context.source the source object - * @param {ElementDescriptor} context.parent the parent object - * @param {Point} context.position position of the new element + * @param {ModelAttrsShape|Shape} context.shape The new shape. + * @param {Base} context.source The element to which to append the new shape to. + * @param {Parent} context.parent The parent. + * @param {Point} context.position The position at which to create the new shape. */ AppendShapeHandler.prototype.preExecute = function(context) { diff --git a/lib/features/modeling/cmd/CreateConnectionHandler.js b/lib/features/modeling/cmd/CreateConnectionHandler.js index 448d6e990..a0c98f093 100644 --- a/lib/features/modeling/cmd/CreateConnectionHandler.js +++ b/lib/features/modeling/cmd/CreateConnectionHandler.js @@ -1,3 +1,18 @@ +/** + * @typedef {import('../../../model').Base} Base + * + * @typedef {import('../../../util/Types').Point} Point + * + * @typedef {import('../Modeling').ModelingCreateConnectionHints} ModelingCreateConnectionHints + * + * @typedef {import('../../../core/Canvas').default} Canvas + * @typedef {import('../../../layout/BaseLayouter').default} Layouter + */ + +/** + * @param {Canvas} canvas + * @param {Layouter} layouter + */ export default function CreateConnectionHandler(canvas, layouter) { this._canvas = canvas; this._layouter = layouter; @@ -10,12 +25,15 @@ CreateConnectionHandler.$inject = [ 'canvas', 'layouter' ]; /** - * Appends a shape to a target shape + * Creates a new connection between two elements. * * @param {Object} context - * @param {djs.element.Base} context.source the source object - * @param {djs.element.Base} context.target the parent object - * @param {Point} context.position position of the new element + * @param {Base} context.source The source. + * @param {Base} context.target The target. + * @param {Shape} context.parent The parent. + * @param {number} [context.parentIndex] The optional index at which to add the + * connection to the parent's children. + * @param {ModelingCreateConnectionHints} [context.hints] The optional hints. */ CreateConnectionHandler.prototype.execute = function(context) { diff --git a/lib/features/modeling/cmd/CreateElementsHandler.js b/lib/features/modeling/cmd/CreateElementsHandler.js index 227a385e9..127e08259 100644 --- a/lib/features/modeling/cmd/CreateElementsHandler.js +++ b/lib/features/modeling/cmd/CreateElementsHandler.js @@ -13,8 +13,15 @@ import { getParents } from '../../../util/Elements'; +/** + * @typedef {import('../Modeling').default} Modeling + */ + var round = Math.round; +/** + * @param {Modeling} modeling + */ export default function CreateElementsHandler(modeling) { this._modeling = modeling; } diff --git a/lib/features/modeling/cmd/CreateLabelHandler.js b/lib/features/modeling/cmd/CreateLabelHandler.js index 458fb9932..0996c180d 100644 --- a/lib/features/modeling/cmd/CreateLabelHandler.js +++ b/lib/features/modeling/cmd/CreateLabelHandler.js @@ -2,6 +2,9 @@ import inherits from 'inherits-browser'; import CreateShapeHandler from './CreateShapeHandler'; +/** + * @typedef {import('../../../core/Canvas').default} Canvas + */ /** * A handler that attaches a label to a given target shape. diff --git a/lib/features/modeling/cmd/CreateShapeHandler.js b/lib/features/modeling/cmd/CreateShapeHandler.js index d2e578ccd..269feae6e 100644 --- a/lib/features/modeling/cmd/CreateShapeHandler.js +++ b/lib/features/modeling/cmd/CreateShapeHandler.js @@ -1,5 +1,13 @@ import { assign } from 'min-dash'; +/** + * @typedef {import('../../../model').Base} Base + * + * @typedef {import('../../../util/Types').Point} Point + * + * @typedef {import('../../../core/Canvas').default} Canvas + */ + var round = Math.round; @@ -22,8 +30,10 @@ CreateShapeHandler.$inject = [ 'canvas' ]; * Appends a shape to a target shape * * @param {Object} context - * @param {djs.model.Base} context.parent the parent object - * @param {Point} context.position position of the new element + * @param {Base} context.parent The parent. + * @param {Point} context.position The position at which to create the new shape. + * @param {number} [context.parentIndex] The optional index at which to add the + * shape to the parent's children. */ CreateShapeHandler.prototype.execute = function(context) { diff --git a/lib/features/modeling/cmd/DeleteConnectionHandler.js b/lib/features/modeling/cmd/DeleteConnectionHandler.js index 3830148c4..24c6b2ca8 100644 --- a/lib/features/modeling/cmd/DeleteConnectionHandler.js +++ b/lib/features/modeling/cmd/DeleteConnectionHandler.js @@ -2,8 +2,13 @@ import { add as collectionAdd, indexOf as collectionIdx } from '../../../util/Collections'; + import { saveClear } from '../../../util/Removal'; +/** + * @typedef {import('../../../core/Canvas').default} Canvas + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that implements reversible deletion of Connections. diff --git a/lib/features/modeling/cmd/DeleteElementsHandler.js b/lib/features/modeling/cmd/DeleteElementsHandler.js index 94ad99fe2..c9e44df20 100644 --- a/lib/features/modeling/cmd/DeleteElementsHandler.js +++ b/lib/features/modeling/cmd/DeleteElementsHandler.js @@ -1,6 +1,14 @@ import { forEach } from 'min-dash'; - +/** + * @typedef {import('../../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../Modeling').default} Modeling + */ + +/** + * @param {Modeling} modeling + * @param {ElementRegistry} elementRegistry + */ export default function DeleteElementsHandler(modeling, elementRegistry) { this._modeling = modeling; this._elementRegistry = elementRegistry; diff --git a/lib/features/modeling/cmd/DeleteShapeHandler.js b/lib/features/modeling/cmd/DeleteShapeHandler.js index 67992f17b..93cce5e77 100644 --- a/lib/features/modeling/cmd/DeleteShapeHandler.js +++ b/lib/features/modeling/cmd/DeleteShapeHandler.js @@ -5,10 +5,16 @@ import { import { saveClear } from '../../../util/Removal'; +/** + * @typedef {import('../../../core/Canvas').default} Canvas + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that implements reversible deletion of shapes. * + * @param {Canvas} canvas + * @param {Modeling} modeling */ export default function DeleteShapeHandler(canvas, modeling) { this._canvas = canvas; diff --git a/lib/features/modeling/cmd/DistributeElementsHandler.js b/lib/features/modeling/cmd/DistributeElementsHandler.js index 3048f1d0f..53be4b55a 100644 --- a/lib/features/modeling/cmd/DistributeElementsHandler.js +++ b/lib/features/modeling/cmd/DistributeElementsHandler.js @@ -3,9 +3,14 @@ import { sortBy } from 'min-dash'; +/** + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that distributes elements evenly. + * + * @param {Modeling} modeling */ export default function DistributeElements(modeling) { this._modeling = modeling; diff --git a/lib/features/modeling/cmd/LayoutConnectionHandler.js b/lib/features/modeling/cmd/LayoutConnectionHandler.js index aa1c062e0..ea507b09a 100644 --- a/lib/features/modeling/cmd/LayoutConnectionHandler.js +++ b/lib/features/modeling/cmd/LayoutConnectionHandler.js @@ -1,8 +1,15 @@ import { assign } from 'min-dash'; +/** + * @typedef {import('../../../core/Canvas').default} Canvas + * @typedef {import('../../../layout/BaseLayouter').default} Layouter + */ /** * A handler that implements reversible moving of shapes. + * + * @param {Layouter} layouter + * @param {Canvas} canvas */ export default function LayoutConnectionHandler(layouter, canvas) { this._layouter = layouter; diff --git a/lib/features/modeling/cmd/MoveElementsHandler.js b/lib/features/modeling/cmd/MoveElementsHandler.js index f5dc86944..8cf2bd25a 100644 --- a/lib/features/modeling/cmd/MoveElementsHandler.js +++ b/lib/features/modeling/cmd/MoveElementsHandler.js @@ -1,8 +1,13 @@ import MoveHelper from './helper/MoveHelper'; +/** + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that implements reversible moving of shapes. + * + * @param {Modeling} modeling */ export default function MoveElementsHandler(modeling) { this._helper = new MoveHelper(modeling); diff --git a/lib/features/modeling/cmd/MoveShapeHandler.js b/lib/features/modeling/cmd/MoveShapeHandler.js index 4adef79e0..81565a06f 100644 --- a/lib/features/modeling/cmd/MoveShapeHandler.js +++ b/lib/features/modeling/cmd/MoveShapeHandler.js @@ -16,9 +16,14 @@ import { getMovedTargetAnchor } from './helper/AnchorsHelper'; +/** + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that implements reversible moving of shapes. + * + * @param {Modeling} modeling */ export default function MoveShapeHandler(modeling) { this._modeling = modeling; diff --git a/lib/features/modeling/cmd/ReconnectConnectionHandler.js b/lib/features/modeling/cmd/ReconnectConnectionHandler.js index fa0499f85..4114d41d7 100644 --- a/lib/features/modeling/cmd/ReconnectConnectionHandler.js +++ b/lib/features/modeling/cmd/ReconnectConnectionHandler.js @@ -1,8 +1,13 @@ import { isArray } from 'min-dash'; +/** + * @typedef {import('../Modeling').default} Modeling + */ /** - * Reconnect connection handler + * Reconnect connection handler. + * + * @param {Modeling} modeling */ export default function ReconnectConnectionHandler(modeling) { this._modeling = modeling; diff --git a/lib/features/modeling/cmd/ReplaceShapeHandler.js b/lib/features/modeling/cmd/ReplaceShapeHandler.js index d34e420ff..3aa68ea07 100644 --- a/lib/features/modeling/cmd/ReplaceShapeHandler.js +++ b/lib/features/modeling/cmd/ReplaceShapeHandler.js @@ -5,6 +5,13 @@ import { getResizedTargetAnchor } from './helper/AnchorsHelper'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../Modeling').default} Modeling + * @typedef {import('../../rules/Rules').default} Rules + */ + /** * Replace shape by adding new shape and removing old shape. Incoming and outgoing connections will * be kept if possible. @@ -27,7 +34,7 @@ ReplaceShapeHandler.$inject = [ 'modeling', 'rules' ]; * Add new shape. * * @param {Object} context - * @param {djs.model.Shape} context.oldShape + * @param {Shape} context.oldShape * @param {Object} context.newData * @param {string} context.newData.type * @param {number} context.newData.x diff --git a/lib/features/modeling/cmd/ResizeShapeHandler.js b/lib/features/modeling/cmd/ResizeShapeHandler.js index dee526bf9..73f6e4a17 100644 --- a/lib/features/modeling/cmd/ResizeShapeHandler.js +++ b/lib/features/modeling/cmd/ResizeShapeHandler.js @@ -8,6 +8,9 @@ import { getResizedTargetAnchor } from './helper/AnchorsHelper'; +/** + * @typedef {import('../Modeling').default} Modeling + */ /** * A handler that implements reversible resizing of shapes. diff --git a/lib/features/modeling/cmd/SpaceToolHandler.js b/lib/features/modeling/cmd/SpaceToolHandler.js index c741b9cad..11ce6828c 100644 --- a/lib/features/modeling/cmd/SpaceToolHandler.js +++ b/lib/features/modeling/cmd/SpaceToolHandler.js @@ -16,9 +16,14 @@ import { getResizedTargetAnchor } from './helper/AnchorsHelper'; +/** + * @typedef {import('../Modeling').default} Modeling + */ /** * Add or remove space by moving and resizing shapes and updating connection waypoints. + * + * @param {Modeling} modeling */ export default function SpaceToolHandler(modeling) { this._modeling = modeling; diff --git a/lib/features/modeling/cmd/ToggleShapeCollapseHandler.js b/lib/features/modeling/cmd/ToggleShapeCollapseHandler.js index a4cf53809..99a0f04bb 100644 --- a/lib/features/modeling/cmd/ToggleShapeCollapseHandler.js +++ b/lib/features/modeling/cmd/ToggleShapeCollapseHandler.js @@ -3,6 +3,12 @@ import { forEach } from 'min-dash'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../Modeling').default} Modeling + */ + /** * A handler that toggles the collapsed state of an element * and the visibility of all its children. @@ -56,7 +62,7 @@ ToggleShapeCollapseHandler.prototype.revert = function(context) { /** * Return a map { elementId -> hiddenState}. * - * @param {Array} elements + * @param {Array} elements * * @return {Object} */ diff --git a/lib/features/modeling/cmd/UpdateAttachmentHandler.js b/lib/features/modeling/cmd/UpdateAttachmentHandler.js index 8edc91c74..2a6ecda04 100644 --- a/lib/features/modeling/cmd/UpdateAttachmentHandler.js +++ b/lib/features/modeling/cmd/UpdateAttachmentHandler.js @@ -3,8 +3,14 @@ import { remove as collectionRemove } from '../../../util/Collections'; +/** + * @typedef {import('../Modeling').default} Modeling + */ + /** * A handler that implements reversible attaching/detaching of shapes. + * + * @param {Modeling} modeling */ export default function UpdateAttachmentHandler(modeling) { this._modeling = modeling; diff --git a/lib/features/modeling/cmd/helper/AnchorsHelper.js b/lib/features/modeling/cmd/helper/AnchorsHelper.js index 2783603cb..f8c8b920a 100644 --- a/lib/features/modeling/cmd/helper/AnchorsHelper.js +++ b/lib/features/modeling/cmd/helper/AnchorsHelper.js @@ -11,6 +11,12 @@ import { map } from 'min-dash'; +/** + * @typedef {import('../../../../model').Connection} Connection + * + * @typedef {import('../../../../util/Types').Point} Point + * @typedef {import('../../../../util/Types').Rect} Rect + */ export function getResizedSourceAnchor(connection, shape, oldBounds) { @@ -79,7 +85,7 @@ function subtract(bounds, delta) { * * @param {Connection} connection * - * @return {Array} + * @return {Point[]} */ function safeGetWaypoints(connection) { @@ -104,7 +110,7 @@ function getWaypointsInsideBounds(waypoints, bounds) { * Checks if point is inside bounds, incl. edges. * * @param {Point} point - * @param {Bounds} bounds + * @param {Rect} bounds */ function isInsideBounds(point, bounds) { return getOrientation(bounds, point, 1) === 'intersect'; diff --git a/lib/features/modeling/cmd/helper/MoveHelper.js b/lib/features/modeling/cmd/helper/MoveHelper.js index 1695d8234..c275c17a5 100644 --- a/lib/features/modeling/cmd/helper/MoveHelper.js +++ b/lib/features/modeling/cmd/helper/MoveHelper.js @@ -9,6 +9,14 @@ import { import MoveClosure from './MoveClosure'; +/** + * @typedef {import('../../../../model').Base} Base + * @typedef {import('../../../../model').Shape} Shape + * + * @typedef {import('../../../../util/Types').Point} Point + * + * @typedef {import('../../Modeling').default} Modeling + */ /** * A helper that is able to carry out serialized move @@ -26,11 +34,11 @@ export default function MoveHelper(modeling) { * This moves all enclosed connections, too and layouts all affected * external connections. * - * @param {Array} elements - * @param {Point} delta - * @param {djs.model.Base} newParent applied to the first level of shapes + * @param {Base[]} elements + * @param {Point} delta + * @param {Shape} newParent The new parent of all elements that are not nested. * - * @return {Array} list of touched elements + * @return {Base[]} */ MoveHelper.prototype.moveRecursive = function(elements, delta, newParent) { if (!elements) { @@ -45,8 +53,8 @@ MoveHelper.prototype.moveRecursive = function(elements, delta, newParent) { * * @param {Object} closure * @param {Point} delta - * @param {djs.model.Base} [newParent] - * @param {djs.model.Base} [newHost] + * @param {Shape} [newParent] + * @param {Shape} [newHost] */ MoveHelper.prototype.moveClosure = function(closure, delta, newParent, newHost, primaryShape) { var modeling = this._modeling; @@ -91,8 +99,9 @@ MoveHelper.prototype.moveClosure = function(closure, delta, newParent, newHost, /** * Returns the closure for the selected elements * - * @param {Array} elements - * @return {MoveClosure} closure + * @param {Base[]} elements + * + * @return {MoveClosure} */ MoveHelper.prototype.getClosure = function(elements) { return new MoveClosure().addAll(elements, true); diff --git a/lib/features/mouse/Mouse.js b/lib/features/mouse/Mouse.js index e20432150..945bcd244 100644 --- a/lib/features/mouse/Mouse.js +++ b/lib/features/mouse/Mouse.js @@ -1,3 +1,10 @@ +/** + * @typedef {import('../../core/EventBus').default} EventBus + */ + +/** + * @param {EventBus} eventBus + */ export default function Mouse(eventBus) { var self = this; diff --git a/lib/features/move/Move.js b/lib/features/move/Move.js index 0eae520cf..92b8bfddb 100644 --- a/lib/features/move/Move.js +++ b/lib/features/move/Move.js @@ -9,6 +9,17 @@ import { classes as svgClasses } from 'tiny-svg'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + * @typedef {import('../selection/Selection').default} Selection + */ + var LOW_PRIORITY = 500, MEDIUM_PRIORITY = 1250, HIGH_PRIORITY = 1500; @@ -190,8 +201,8 @@ export default function MoveEvents( /** * Start move. * - * @param {MouseEvent} event - * @param {djs.model.Shape} shape + * @param {MouseEvent|TouchEvent} event + * @param {Shape} shape * @param {boolean} [activate] * @param {Object} [context] */ @@ -244,9 +255,9 @@ MoveEvents.$inject = [ * Return a filtered list of elements that do not contain * those nested into others. * - * @param {Array} elements + * @param {Array} elements * - * @return {Array} filtered + * @return {Array} filtered */ function removeNested(elements) { diff --git a/lib/features/move/MovePreview.js b/lib/features/move/MovePreview.js index e355e122c..5c6e0f5ae 100644 --- a/lib/features/move/MovePreview.js +++ b/lib/features/move/MovePreview.js @@ -22,6 +22,15 @@ import { import { translate } from '../../util/SvgTransformUtil'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../preview-support/PreviewSupport').default} PreviewSupport + * @typedef {import('../../draw/Styles').default} Styles + */ + var LOW_PRIORITY = 499; var MARKER_DRAGGING = 'djs-dragging', @@ -35,9 +44,9 @@ var MARKER_DRAGGING = 'djs-dragging', * Provides previews for moving shapes when moving. * * @param {EventBus} eventBus - * @param {ElementRegistry} elementRegistry * @param {Canvas} canvas * @param {Styles} styles + * @param {PreviewSupport} previewSupport */ export default function MovePreview( eventBus, canvas, styles, previewSupport) { @@ -79,7 +88,7 @@ export default function MovePreview( * Make an element draggable. * * @param {Object} context - * @param {djs.model.Base} element + * @param {Base} element * @param {boolean} addMarker */ function makeDraggable(context, element, addMarker) { @@ -202,7 +211,7 @@ export default function MovePreview( * Make an element draggable. * * @param {Object} context - * @param {djs.model.Base} element + * @param {Base} element * @param {boolean} addMarker */ this.makeDraggable = makeDraggable; diff --git a/lib/features/ordering/OrderingProvider.js b/lib/features/ordering/OrderingProvider.js index 9f1ebb614..09e2e579b 100644 --- a/lib/features/ordering/OrderingProvider.js +++ b/lib/features/ordering/OrderingProvider.js @@ -2,6 +2,12 @@ import inherits from 'inherits-browser'; import CommandInterceptor from '../../command/CommandInterceptor'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../core/EventBus').default} EventBus + */ /** * An abstract provider that allows modelers to implement a custom @@ -83,8 +89,8 @@ export default function OrderingProvider(eventBus) { * Implementors of this method must return an object with * `parent` _and_ `index` in it. * - * @param {djs.model.Base} element - * @param {djs.model.Shape} newParent + * @param {Base} element + * @param {Shape} newParent * * @return {Object} ordering descriptor */ diff --git a/lib/features/outline/Outline.js b/lib/features/outline/Outline.js index 45d2226bb..7cfbd980d 100644 --- a/lib/features/outline/Outline.js +++ b/lib/features/outline/Outline.js @@ -16,6 +16,12 @@ import { assign } from 'min-dash'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../draw/Styles').default} Styles + */ /** * @class @@ -25,9 +31,8 @@ import { * * @param {EventBus} eventBus * @param {Styles} styles - * @param {ElementRegistry} elementRegistry */ -export default function Outline(eventBus, styles, elementRegistry) { +export default function Outline(eventBus, styles) { this.offset = 6; @@ -85,8 +90,8 @@ export default function Outline(eventBus, styles, elementRegistry) { * Updates the outline of a shape respecting the dimension of the * element and an outline offset. * - * @param {SVGElement} outline - * @param {djs.model.Base} element + * @param {SVGElement} outline + * @param {Base} element */ Outline.prototype.updateShapeOutline = function(outline, element) { @@ -104,8 +109,8 @@ Outline.prototype.updateShapeOutline = function(outline, element) { * Updates the outline of a connection respecting the bounding box of * the connection and an outline offset. * - * @param {SVGElement} outline - * @param {djs.model.Base} element + * @param {SVGElement} outline + * @param {Base} element */ Outline.prototype.updateConnectionOutline = function(outline, connection) { diff --git a/lib/features/palette/Palette.js b/lib/features/palette/Palette.js index bd53d5bc6..8a3e0a50b 100644 --- a/lib/features/palette/Palette.js +++ b/lib/features/palette/Palette.js @@ -19,6 +19,11 @@ import { escapeCSS } from '../../util/EscapeUtil'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ + var TOGGLE_SELECTOR = '.djs-palette-toggle', ENTRY_SELECTOR = '.entry', ELEMENT_SELECTOR = TOGGLE_SELECTOR + ', ' + ENTRY_SELECTOR; @@ -33,6 +38,9 @@ var DEFAULT_PRIORITY = 1000; /** * A palette containing modeling elements. + * + * @param {EventBus} eventBus + * @param {Canvas} canvas */ export default function Palette(eventBus, canvas) { @@ -65,8 +73,8 @@ Palette.$inject = [ 'eventBus', 'canvas' ]; /** * Register a provider with the palette * - * @param {number} [priority=1000] - * @param {PaletteProvider} provider + * @param {number} [priority=1000] + * @param {PaletteProvider} provider * * @example * const paletteProvider = { @@ -188,7 +196,7 @@ Palette.prototype._getProviders = function(id) { /** * Update palette state. * - * @param {Object} [state] { open, twoColumn } + * @param {Object} [state] { open, twoColumn } */ Palette.prototype._toggleState = function(state) { @@ -281,8 +289,8 @@ Palette.prototype._update = function() { /** * Trigger an action available on the palette * - * @param {string} action - * @param {Event} event + * @param {string} action + * @param {Event} event */ Palette.prototype.trigger = function(action, event, autoActivate) { var entry, diff --git a/lib/features/popup-menu/PopupMenu.js b/lib/features/popup-menu/PopupMenu.js index f2cabaf95..f0677ccdd 100644 --- a/lib/features/popup-menu/PopupMenu.js +++ b/lib/features/popup-menu/PopupMenu.js @@ -19,6 +19,10 @@ import { import PopupMenuComponent from './PopupMenuComponent'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ var DATA_REF = 'data-id'; @@ -131,9 +135,9 @@ PopupMenu.prototype._render = function() { /** * Create entries and open popup menu at given position * - * @param {Object} element - * @param {string} id provider id - * @param {Object} position + * @param {Object} element + * @param {string} id provider id + * @param {Object} position * * @return {Object} popup menu instance */ @@ -353,9 +357,9 @@ PopupMenu.prototype.isEmpty = function(element, providerId) { /** * Registers a popup menu provider * - * @param {string} id + * @param {string} id * @param {number} [priority=1000] - * @param {Object} provider + * @param {Object} provider * * @example * const popupMenuProvider = { @@ -535,7 +539,7 @@ PopupMenu.prototype.trigger = function(event, entry, action = 'click') { /** * Gets an entry instance (either entry or headerEntry) by id. * - * @param {string} entryId + * @param {string} entryId * * @return {Object} entry instance */ diff --git a/lib/features/popup-menu/PopupMenuComponent.js b/lib/features/popup-menu/PopupMenuComponent.js index bfdc07179..ecdf1fdf5 100644 --- a/lib/features/popup-menu/PopupMenuComponent.js +++ b/lib/features/popup-menu/PopupMenuComponent.js @@ -246,7 +246,7 @@ export default function PopupMenuComponent(props) { /** * A component that wraps the popup menu. * - * @param {any} props + * @param {*} props */ function PopupMenuWrapper(props) { const { diff --git a/lib/features/popup-menu/PopupMenuProvider.js b/lib/features/popup-menu/PopupMenuProvider.js index 5876155c4..10574e767 100644 --- a/lib/features/popup-menu/PopupMenuProvider.js +++ b/lib/features/popup-menu/PopupMenuProvider.js @@ -1,8 +1,16 @@ +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../popup-menu/PopupMenu').default} PopupMenu + */ + /** * A basic provider that may be extended to provide entries for the popup menu. * * Extensions should implement the methods getEntries and register. Optionally * the method getHeaderEntries can be implemented. + * + * @param {PopupMenu} popupMenu */ export default function PopupMenuProvider(popupMenu) { this._popupMenu = popupMenu; @@ -16,7 +24,7 @@ PopupMenuProvider.$inject = [ 'popupMenu' ]; /** * This method should implement the creation or update of a map of entry objects. * - * @param {djs.model.Base} element + * @param {Base} element * * The following example shows how to replace any entries returned * by previous providers with one entry which alerts the id of the current selected @@ -43,7 +51,7 @@ PopupMenuProvider.getPopupMenuEntries = function(element) {}; * @deprecated * This method should implement the creation of a list of entry objects. * - * @param {djs.model.Base} element + * @param {Base} element * * The following example contains one entry which alerts the id of the current selected * element, when clicking on the entry. @@ -68,7 +76,7 @@ PopupMenuProvider.getEntries = function(element) {}; /** * This method should implement the creation of a list of header entry objects. * - * @param {djs.model.Base} element + * @param {Base} element * * The following example contains one button as header entry which alerts a string * when clicking on it. diff --git a/lib/features/preview-support/PreviewSupport.js b/lib/features/preview-support/PreviewSupport.js index d9ce94c7c..4f689df42 100644 --- a/lib/features/preview-support/PreviewSupport.js +++ b/lib/features/preview-support/PreviewSupport.js @@ -15,6 +15,15 @@ import { query as domQuery } from 'min-dom'; import { getVisual } from '../../util/GraphicsUtil'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../draw/Styles').default} Styles + */ + var MARKER_TYPES = [ 'marker-start', 'marker-mid', @@ -35,6 +44,11 @@ var NODES_CAN_HAVE_MARKER = [ /** * Adds support for previews of moving/resizing elements. + * + * @param {ElementRegistry} elementRegistry + * @param {EventBus} eventBus + * @param {Canvas} canvas + * @param {Styles} styles */ export default function PreviewSupport(elementRegistry, eventBus, canvas, styles) { this._elementRegistry = elementRegistry; @@ -65,7 +79,7 @@ PreviewSupport.$inject = [ /** * Returns graphics of an element. * - * @param {djs.model.Base} element + * @param {Base} element * * @return {SVGElement} */ @@ -76,7 +90,7 @@ PreviewSupport.prototype.getGfx = function(element) { /** * Adds a move preview of a given shape to a given svg group. * - * @param {djs.model.Base} element + * @param {Base} element * @param {SVGElement} group * @param {SVGElement} [gfx] * @@ -103,7 +117,7 @@ PreviewSupport.prototype.addDragger = function(element, group, gfx) { /** * Adds a resize preview of a given shape to a given svg group. * - * @param {djs.model.Base} element + * @param {Base} element * @param {SVGElement} group * * @return {SVGElement} frame diff --git a/lib/features/replace/Replace.js b/lib/features/replace/Replace.js index 63ae5612b..91b991e07 100644 --- a/lib/features/replace/Replace.js +++ b/lib/features/replace/Replace.js @@ -2,10 +2,16 @@ import { assign } from 'min-dash'; +/** + * @typedef {import('../modeling/Modeling').default} Modeling + */ + var round = Math.round; /** * Service that allow replacing of elements. + * + * @param {Modeling} modeling */ export default function Replace(modeling) { diff --git a/lib/features/resize/Resize.js b/lib/features/resize/Resize.js index db4a0019c..2a44d568e 100644 --- a/lib/features/resize/Resize.js +++ b/lib/features/resize/Resize.js @@ -16,6 +16,18 @@ import { roundBounds } from '../../layout/LayoutUtil'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Direction} Direction + * @typedef {import('../../util/Types').Point} Point + * + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../rules/Rules').default} Rules + */ + var DEFAULT_MIN_WIDTH = 10; @@ -55,6 +67,11 @@ var DEFAULT_MIN_WIDTH = 10; * context.childrenBoxPadding.left = 20; * }); * ``` + * + * @param {EventBus} eventBus + * @param {Rules} rules + * @param {Modeling} modeling + * @param {Dragging} dragging */ export default function Resize(eventBus, rules, modeling, dragging) { @@ -91,7 +108,7 @@ export default function Resize(eventBus, rules, modeling, dragging) { /** * Handle resize start. * - * @param {Object} context + * @param {Object} context */ function handleStart(context) { @@ -116,7 +133,7 @@ export default function Resize(eventBus, rules, modeling, dragging) { /** * Handle resize end. * - * @param {Object} context + * @param {Object} context */ function handleEnd(context) { var shape = context.shape, @@ -175,9 +192,9 @@ Resize.prototype.canResize = function(context) { * You may specify additional contextual information and must specify a * resize direction during activation of the resize event. * - * @param {MouseEvent} event - * @param {djs.model.Shape} shape - * @param {Object|string} contextOrDirection + * @param {MouseEvent|TouchEvent} event + * @param {Shape} shape + * @param {Object|Direction} contextOrDirection */ Resize.prototype.activate = function(event, shape, contextOrDirection) { var dragging = this._dragging, diff --git a/lib/features/resize/ResizeHandles.js b/lib/features/resize/ResizeHandles.js index 9aa7e367e..0b0fc3a47 100644 --- a/lib/features/resize/ResizeHandles.js +++ b/lib/features/resize/ResizeHandles.js @@ -25,6 +25,15 @@ import { import { getReferencePoint } from './Resize'; +/** + * @typedef {import('../../model').Base} Base + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../resize/Resize').default} Resize + * @typedef {import('../selection/Selection').default} Selection + */ + var HANDLE_OFFSET = -6, HANDLE_SIZE = 8, HANDLE_HIT_SIZE = 20; @@ -146,7 +155,7 @@ ResizeHandles.prototype.createResizer = function(element, direction) { /** * Add resizers for a given element. * - * @param {djs.model.Element} element + * @param {Base} element */ ResizeHandles.prototype.addResizer = function(element) { var self = this; diff --git a/lib/features/resize/ResizePreview.js b/lib/features/resize/ResizePreview.js index 1148d7d43..156590a29 100644 --- a/lib/features/resize/ResizePreview.js +++ b/lib/features/resize/ResizePreview.js @@ -9,6 +9,11 @@ import { classes as svgClasses } from 'tiny-svg'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../preview-support/PreviewSupport').default} PreviewSupport + */ /** * Provides previews for resizing shapes when resizing. diff --git a/lib/features/resize/ResizeUtil.js b/lib/features/resize/ResizeUtil.js index 13e20d45f..3059043b7 100644 --- a/lib/features/resize/ResizeUtil.js +++ b/lib/features/resize/ResizeUtil.js @@ -17,14 +17,22 @@ import { asBounds } from '../../layout/LayoutUtil'; +/** + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Direction} Direction + * @typedef {import('../../util/Types').Rect} Rect + * @typedef {import('../../util/Types').RectTRBL} RectTRBL + */ /** * Substract a TRBL from another * - * @param {TRBL} trblA - * @param {TRBL} trblB + * @param {RectTRBL} trblA + * @param {RectTRBL} trblB * - * @return {TRBL} + * @return {RectTRBL} */ export function substractTRBL(trblA, trblB) { return { @@ -38,11 +46,11 @@ export function substractTRBL(trblA, trblB) { /** * Resize the given bounds by the specified delta from a given anchor point. * - * @param {Bounds} bounds the bounding box that should be resized - * @param {string} direction in which the element is resized (nw, ne, se, sw) + * @param {Rect} bounds the bounding box that should be resized + * @param {Direction} direction in which the element is resized (nw, ne, se, sw) * @param {Point} delta of the resize operation * - * @return {Bounds} resized bounding box + * @return {Rect} resized bounding box */ export function resizeBounds(bounds, direction, delta) { var dx = delta.x, @@ -77,10 +85,10 @@ export function resizeBounds(bounds, direction, delta) { * Resize the given bounds by applying the passed * { top, right, bottom, left } delta. * - * @param {Bounds} bounds - * @param {TRBL} trblResize + * @param {Rect} bounds + * @param {RectTRBL} trblResize * - * @return {Bounds} + * @return {Rect} */ export function resizeTRBL(bounds, resize) { return { @@ -197,7 +205,7 @@ export function addPadding(bbox, padding) { * This is the default implementation which excludes * connections and labels. * - * @param {djs.model.Base} element + * @param {Base} element */ function isBBoxChild(element) { @@ -218,10 +226,10 @@ function isBBoxChild(element) { * Return children bounding computed from a shapes children * or a list of prefiltered children. * - * @param {djs.model.Shape|Array} shapeOrChildren - * @param {number|Object} padding + * @param {Shape|Shape[]} shapeOrChildren + * @param {RectTRBL|number} padding * - * @return {Bounds} + * @return {Rect} */ export function computeChildrenBBox(shapeOrChildren, padding) { diff --git a/lib/features/root-elements/RootElementsBehavior.js b/lib/features/root-elements/RootElementsBehavior.js index a2a8d221e..fb7301f55 100644 --- a/lib/features/root-elements/RootElementsBehavior.js +++ b/lib/features/root-elements/RootElementsBehavior.js @@ -2,13 +2,18 @@ import inherits from 'inherits-browser'; import CommandInterceptor from '../../command/CommandInterceptor'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + */ /** * A modeling behavior that ensures we set the correct root element * as we undo and redo commands. * * @param {Canvas} canvas - * @param {didi.Injector} injector + * @param {Injector} injector */ export default function RootElementsBehavior(canvas, injector) { diff --git a/lib/features/rules/RuleProvider.js b/lib/features/rules/RuleProvider.js index 617a002f7..f2f1475f3 100644 --- a/lib/features/rules/RuleProvider.js +++ b/lib/features/rules/RuleProvider.js @@ -2,6 +2,10 @@ import inherits from 'inherits-browser'; import CommandInterceptor from '../../command/CommandInterceptor'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + */ + /** * A basic provider that may be extended to implement modeling rules. * diff --git a/lib/features/rules/Rules.js b/lib/features/rules/Rules.js index e5c008f7d..a0ee208ff 100644 --- a/lib/features/rules/Rules.js +++ b/lib/features/rules/Rules.js @@ -1,3 +1,7 @@ +/** + * @typedef {import('didi').Injector} Injector + */ + /** * A service that provides rules for certain diagram actions. * diff --git a/lib/features/search-pad/SearchPad.js b/lib/features/search-pad/SearchPad.js index 15d978df3..088e87709 100644 --- a/lib/features/search-pad/SearchPad.js +++ b/lib/features/search-pad/SearchPad.js @@ -19,7 +19,19 @@ import { import { isKey } from '../keyboard/KeyboardUtil'; /** - * Provides searching infrastructure + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../overlays/Overlays').default} Overlays + * @typedef {import('../selection/Selection').default} Selection + */ + +/** + * Provides searching infrastructure. + * + * @param {Canvas} canvas + * @param {EventBus} eventBus + * @param {Overlays} overlays + * @param {Selection} selection */ export default function SearchPad(canvas, eventBus, overlays, selection) { this._open = false; @@ -149,7 +161,7 @@ SearchPad.prototype._unbindEvents = function() { /** * Performs a search for the given pattern. * - * @param {string} pattern + * @param {string} pattern */ SearchPad.prototype._search = function(pattern) { var self = this; @@ -186,7 +198,7 @@ SearchPad.prototype._search = function(pattern) { /** * Navigate to the previous/next result. Defaults to next result. - * @param {boolean} previous + * @param {boolean} previous */ SearchPad.prototype._scrollToDirection = function(previous) { var selected = this._getCurrentResult(); @@ -205,7 +217,7 @@ SearchPad.prototype._scrollToDirection = function(previous) { /** * Scroll to the node if it is not visible. * - * @param {Element} node + * @param {Element} node */ SearchPad.prototype._scrollToNode = function(node) { if (!node || node === this._getCurrentResult()) { @@ -257,8 +269,8 @@ SearchPad.prototype._getCurrentResult = function() { * 'id' : id attribute value to assign to the new DOM node * return : created DOM element * - * @param {SearchResult} result - * @param {string} id + * @param {SearchResult} result + * @param {string} id * @return {Element} */ SearchPad.prototype._createResultNode = function(result, id) { @@ -286,7 +298,7 @@ SearchPad.prototype._createResultNode = function(result, id) { * SearchProvider.find - provides search function over own elements * (pattern) => [{ text: , element: }, ...] * - * @param {SearchProvider} provider + * @param {SearchProvider} provider */ SearchPad.prototype.registerProvider = function(provider) { this._searchProvider = provider; @@ -361,7 +373,7 @@ SearchPad.prototype.isOpen = function() { /** * Preselect result entry. * - * @param {Element} element + * @param {Element} element */ SearchPad.prototype._preselect = function(node) { var selectedNode = this._getCurrentResult(); @@ -394,7 +406,7 @@ SearchPad.prototype._preselect = function(node) { /** * Select result node. * - * @param {Element} element + * @param {Element} element */ SearchPad.prototype._select = function(node) { var id = domAttr(node, SearchPad.RESULT_ID_ATTRIBUTE); @@ -416,7 +428,7 @@ SearchPad.prototype._select = function(node) { * Reset overlay removes and, optionally, set * overlay to a new element. * - * @param {Element} element + * @param {Element} element */ SearchPad.prototype._resetOverlay = function(element) { if (this._overlayId) { @@ -434,7 +446,7 @@ SearchPad.prototype._resetOverlay = function(element) { /** * Construct overlay object for the given bounding box. * - * @param {BoundingBox} box + * @param {BoundingBox} box * @return {Object} */ function constructOverlay(box) { @@ -466,9 +478,9 @@ function constructOverlay(box) { /** * Creates and appends child node from result tokens and HTML template. * - * @param {Element} node - * @param {Array} tokens - * @param {string} template + * @param {Element} node + * @param {Array} tokens + * @param {string} template */ function createInnerTextNode(parentNode, tokens, template) { var text = createHtmlText(tokens); @@ -481,7 +493,7 @@ function createInnerTextNode(parentNode, tokens, template) { * Create internal HTML markup from result tokens. * Caters for highlighting pattern matched tokens. * - * @param {Array} tokens + * @param {Array} tokens * @return {string} */ function createHtmlText(tokens) { diff --git a/lib/features/selection/Selection.js b/lib/features/selection/Selection.js index 3f4110238..4764eb8a3 100644 --- a/lib/features/selection/Selection.js +++ b/lib/features/selection/Selection.js @@ -3,6 +3,9 @@ import { forEach } from 'min-dash'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + */ /** * A service that offers the current selection in a diagram. @@ -10,7 +13,7 @@ import { * * @class * - * @param {EventBus} eventBus the event bus + * @param {EventBus} eventBus */ export default function Selection(eventBus, canvas) { @@ -66,8 +69,8 @@ Selection.prototype.isSelected = function(element) { * * @method Selection#select * - * @param {Object|Object[]} elements element or array of elements to be selected - * @param {boolean} [add] whether the element(s) should be appended to the current selection, defaults to false + * @param {Object|Object[]} elements element or array of elements to be selected + * @param {boolean} [add] whether the element(s) should be appended to the current selection, defaults to false */ Selection.prototype.select = function(elements, add) { var selectedElements = this._selectedElements, diff --git a/lib/features/selection/SelectionBehavior.js b/lib/features/selection/SelectionBehavior.js index afbf93972..8e2e6e81c 100644 --- a/lib/features/selection/SelectionBehavior.js +++ b/lib/features/selection/SelectionBehavior.js @@ -9,7 +9,19 @@ import { isArray } from 'min-dash'; - +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('./Selection').default} Selection + */ + +/** + * @param {EventBus} eventBus + * @param {Selection} selection + * @param {Canvas} canvas + * @param {ElementRegistry} elementRegistry + */ export default function SelectionBehavior(eventBus, selection, canvas, elementRegistry) { // Select elements on create diff --git a/lib/features/selection/SelectionVisuals.js b/lib/features/selection/SelectionVisuals.js index 6962e797b..a2183b262 100644 --- a/lib/features/selection/SelectionVisuals.js +++ b/lib/features/selection/SelectionVisuals.js @@ -13,6 +13,12 @@ import { import { getBBox } from '../../util/Elements'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('./Selection').default} Selection + */ + var MARKER_HOVER = 'hover', MARKER_SELECTED = 'selected'; @@ -29,6 +35,7 @@ var SELECTION_OUTLINE_PADDING = 6; * * @param {Canvas} canvas * @param {EventBus} eventBus + * @param {Selection} selection */ export default function SelectionVisuals(canvas, eventBus, selection) { this._canvas = canvas; diff --git a/lib/features/snapping/CreateMoveSnapping.js b/lib/features/snapping/CreateMoveSnapping.js index f08378ad2..056ebdd65 100644 --- a/lib/features/snapping/CreateMoveSnapping.js +++ b/lib/features/snapping/CreateMoveSnapping.js @@ -13,6 +13,12 @@ import { isNumber } from 'min-dash'; +/** + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('./Snapping').default} Snapping + */ + var HIGHER_PRIORITY = 1250; diff --git a/lib/features/snapping/ResizeSnapping.js b/lib/features/snapping/ResizeSnapping.js index eba0a3c32..700faf4fe 100644 --- a/lib/features/snapping/ResizeSnapping.js +++ b/lib/features/snapping/ResizeSnapping.js @@ -17,6 +17,11 @@ import { import { forEach } from 'min-dash'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('./Snapping').default} Snapping + */ + var HIGHER_PRIORITY = 1250; diff --git a/lib/features/snapping/SnapContext.js b/lib/features/snapping/SnapContext.js index 234008baa..dfc9d9079 100644 --- a/lib/features/snapping/SnapContext.js +++ b/lib/features/snapping/SnapContext.js @@ -156,7 +156,7 @@ SnapPoints.prototype.snap = function(point, snapLocation, axis, tolerance) { /** * Initialize a number of default snapping points. * - * @param {Object} defaultSnaps + * @param {Object} defaultSnaps */ SnapPoints.prototype.initDefaults = function(defaultSnaps) { diff --git a/lib/features/snapping/SnapUtil.js b/lib/features/snapping/SnapUtil.js index 7431294eb..e6ff56737 100644 --- a/lib/features/snapping/SnapUtil.js +++ b/lib/features/snapping/SnapUtil.js @@ -1,3 +1,8 @@ +/** + * @typedef {import('../../model').Connection} Connection + * @typedef {import('../../model').Shape} Shape + */ + var abs = Math.abs, round = Math.round; @@ -5,9 +10,9 @@ var abs = Math.abs, /** * Snap value to a collection of reference values. * - * @param {number} value - * @param {Array} values - * @param {number} [tolerance=10] + * @param {number} value + * @param {Array} values + * @param {number} [tolerance=10] * * @return {number} the value we snapped to or null, if none snapped */ @@ -70,8 +75,8 @@ export function mid(bounds, defaultValue) { /** * Retrieve the snap state of the given event. * - * @param {Event} event - * @param {string} axis + * @param {Event} event + * @param {string} axis * * @return {boolean} the snapped state * @@ -135,9 +140,9 @@ export function setSnapped(event, axis, value) { /** * Get children of a shape. * - * @param {djs.model.Shape} parent + * @param {Shape} parent * - * @returns {Array} + * @returns {Array} */ export function getChildren(parent) { return parent.children || []; diff --git a/lib/features/snapping/Snapping.js b/lib/features/snapping/Snapping.js index 941991a74..8b1153105 100644 --- a/lib/features/snapping/Snapping.js +++ b/lib/features/snapping/Snapping.js @@ -18,6 +18,10 @@ import { create as svgCreate } from 'tiny-svg'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + */ + var SNAP_TOLERANCE = 7; export var SNAP_LINE_HIDE_DELAY = 1000; @@ -26,7 +30,6 @@ export var SNAP_LINE_HIDE_DELAY = 1000; /** * Generic snapping feature. * - * @param {EventBus} eventBus * @param {Canvas} canvas */ export default function Snapping(canvas) { diff --git a/lib/features/space-tool/SpaceTool.js b/lib/features/space-tool/SpaceTool.js index 0b3239902..d5eaf51ac 100644 --- a/lib/features/space-tool/SpaceTool.js +++ b/lib/features/space-tool/SpaceTool.js @@ -20,6 +20,18 @@ import { set as setCursor } from '../../util/Cursor'; import { selfAndAllChildren } from '../../util/Elements'; +/** + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../modeling/Modeling').default} Modeling + * @typedef {import('../mouse/Mouse').default} Mouse + * @typedef {import('../rules/Rules').default} Rules + * @typedef {import('../tool-manager/ToolManager').default} ToolManager + */ + var abs = Math.abs, round = Math.round; @@ -162,7 +174,7 @@ SpaceTool.prototype.activateSelection = function(event, autoActivate, reactivate /** * Activate space tool make space. * - * @param {MouseEvent} event + * @param {MouseEvent|TouchEvent} event */ SpaceTool.prototype.activateMakeSpace = function(event) { this._dragging.init(event, 'spaceTool', { @@ -177,13 +189,13 @@ SpaceTool.prototype.activateMakeSpace = function(event) { /** * Make space. * - * @param {Array} movingShapes - * @param {Array} resizingShapes - * @param {Object} delta - * @param {number} delta.x - * @param {number} delta.y - * @param {string} direction - * @param {number} start + * @param {Array} movingShapes + * @param {Array} resizingShapes + * @param {Object} delta + * @param {number} delta.x + * @param {number} delta.y + * @param {string} direction + * @param {number} start */ SpaceTool.prototype.makeSpace = function(movingShapes, resizingShapes, delta, direction, start) { return this._modeling.createSpace(movingShapes, resizingShapes, delta, direction, start); @@ -252,10 +264,10 @@ SpaceTool.prototype.init = function(event, context) { /** * Get elements to be moved and resized. * - * @param {Array} elements - * @param {string} axis - * @param {number} delta - * @param {number} start + * @param {Array} elements + * @param {string} axis + * @param {number} delta + * @param {number} start * * @return {Object} */ diff --git a/lib/features/space-tool/SpaceToolPreview.js b/lib/features/space-tool/SpaceToolPreview.js index 8406b30ba..d97682610 100644 --- a/lib/features/space-tool/SpaceToolPreview.js +++ b/lib/features/space-tool/SpaceToolPreview.js @@ -19,6 +19,13 @@ import { translate } from '../../util/SvgTransformUtil'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../../draw/Styles').default} Styles + */ + var max = Math.max; diff --git a/lib/features/space-tool/SpaceUtil.js b/lib/features/space-tool/SpaceUtil.js index c293ad222..5db710f89 100644 --- a/lib/features/space-tool/SpaceUtil.js +++ b/lib/features/space-tool/SpaceUtil.js @@ -1,3 +1,8 @@ +/** + * @typedef {import('../../model').Connection} Connection + * @typedef {import('../../model').Shape} Shape + */ + import { forEach } from 'min-dash'; /** @@ -37,10 +42,10 @@ export function getDirection(axis, delta) { * Returns connections whose waypoints are to be updated. Waypoints are to be updated if start * or end is to be moved or resized. * - * @param {Array} + * @returns {Array} */ export function getWaypointsUpdatingConnections(movingShapes, resizingShapes) { var waypointsUpdatingConnections = []; diff --git a/lib/features/tool-manager/ToolManager.js b/lib/features/tool-manager/ToolManager.js index b4849a825..bfcebdd51 100644 --- a/lib/features/tool-manager/ToolManager.js +++ b/lib/features/tool-manager/ToolManager.js @@ -6,14 +6,19 @@ import { closest as domClosest } from 'min-dom'; +/** + * @typedef {import('../dragging/Dragging').default} Dragging + * @typedef {import('../../core/EventBus').default} EventBus + */ + var LOW_PRIORITY = 250; /** * The tool manager acts as middle-man between the available tool's and the Palette, * it takes care of making sure that the correct active state is set. * - * @param {Object} eventBus - * @param {Object} dragging + * @param {EventBus} eventBus + * @param {Dragging} dragging */ export default function ToolManager(eventBus, dragging) { this._eventBus = eventBus; diff --git a/lib/features/tooltips/Tooltips.js b/lib/features/tooltips/Tooltips.js index 24dcd81f7..fe36d94f1 100644 --- a/lib/features/tooltips/Tooltips.js +++ b/lib/features/tooltips/Tooltips.js @@ -15,6 +15,11 @@ import { import Ids from '../../util/IdGenerator'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ + // document wide unique tooltip ids var ids = new Ids('tt'); diff --git a/lib/features/touch/TouchFix.js b/lib/features/touch/TouchFix.js index 985c9d345..c4ba6bdff 100644 --- a/lib/features/touch/TouchFix.js +++ b/lib/features/touch/TouchFix.js @@ -4,8 +4,14 @@ import { create as svgCreate } from 'tiny-svg'; +/** + * @typedef {import('../../core/EventBus').default} EventBus + */ -export default function TouchFix(canvas, eventBus) { +/** + * @param {EventBus} eventBus + */ +export default function TouchFix(eventBus) { var self = this; @@ -14,7 +20,7 @@ export default function TouchFix(canvas, eventBus) { }); } -TouchFix.$inject = [ 'canvas', 'eventBus' ]; +TouchFix.$inject = [ 'eventBus' ]; /** diff --git a/lib/features/touch/TouchInteractionEvents.js b/lib/features/touch/TouchInteractionEvents.js index ce0ef9594..a9ba9cd79 100644 --- a/lib/features/touch/TouchInteractionEvents.js +++ b/lib/features/touch/TouchInteractionEvents.js @@ -13,6 +13,15 @@ import { toPoint } from '../../util/Event'; +/** + * @typedef {import('didi').Injector} Injector + * + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../../core/EventBus').default} EventBus + * @typedef {import('../interaction-events/InteractionEvents').default} InteractionEvents + */ + var MIN_ZOOM = 0.2, MAX_ZOOM = 4; @@ -133,7 +142,10 @@ function createTouchRecognizer(node) { /** * A plugin that provides touch events for elements. * + * @param {Injector} injector + * @param {Canvas} canvas * @param {EventBus} eventBus + * @param {ElementRegistry} elementRegistry * @param {InteractionEvents} interactionEvents */ export default function TouchInteractionEvents( diff --git a/lib/i18n/I18N.js b/lib/i18n/I18N.js index 7ba98bcd0..1fb31bb91 100644 --- a/lib/i18n/I18N.js +++ b/lib/i18n/I18N.js @@ -1,3 +1,7 @@ +/** + * @typedef {import('../core/EventBus').default} EventBus + */ + /** * A component that handles language switching in a unified way. * diff --git a/lib/layout/BaseLayouter.js b/lib/layout/BaseLayouter.js index ee476786d..1b2bcab44 100644 --- a/lib/layout/BaseLayouter.js +++ b/lib/layout/BaseLayouter.js @@ -1,3 +1,10 @@ +/** + * @typedef {import('../model').Base} Base + * @typedef {import('../model').Connection} Connection + * + * @typedef {import('../util').Point} Point + */ + import { getMid } from './LayoutUtil'; @@ -17,14 +24,14 @@ export default function BaseLayouter() {} * The connection passed is still unchanged; you may figure out about * the new connection start / end via the layout hints provided. * - * @param {djs.model.Connection} connection + * @param {Connection} connection * @param {Object} [hints] * @param {Point} [hints.connectionStart] * @param {Point} [hints.connectionEnd] - * @param {Point} [hints.source] - * @param {Point} [hints.target] + * @param {Base} [hints.source] + * @param {Base} [hints.target] * - * @return {Array} the layouted connection waypoints + * @return {Point[]} The waypoints of the laid out connection. */ BaseLayouter.prototype.layoutConnection = function(connection, hints) { diff --git a/lib/layout/ConnectionDocking.js b/lib/layout/ConnectionDocking.js index 60512a6b6..a09e9281d 100644 --- a/lib/layout/ConnectionDocking.js +++ b/lib/layout/ConnectionDocking.js @@ -1,24 +1,16 @@ /** - * @memberOf djs.layout - */ - -/** - * @class DockingPointDescriptor - */ - -/** - * @name DockingPointDescriptor#point - * @type djs.Point - */ - -/** - * @name DockingPointDescriptor#actual - * @type djs.Point + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Connection} Connection + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../util/Types').Point} Point */ /** - * @name DockingPointDescriptor#idx - * @type number + * @typedef {Object} DockingPointDescriptor + * @property {Point} point + * @property {Point} actual + * @property {number} idx */ /** @@ -33,11 +25,11 @@ export default function ConnectionDocking() {} /** * Return the actual waypoints of the connection (visually). * - * @param {djs.model.Connection} connection - * @param {djs.model.Base} [source] - * @param {djs.model.Base} [target] + * @param {Connection} connection + * @param {Base} [source] + * @param {Base} [target] * - * @return {Array} + * @return {Point[]} */ ConnectionDocking.prototype.getCroppedWaypoints = function(connection, source, target) { return connection.waypoints; @@ -46,8 +38,8 @@ ConnectionDocking.prototype.getCroppedWaypoints = function(connection, source, t /** * Return the connection docking point on the specified shape * - * @param {djs.model.Connection} connection - * @param {djs.model.Shape} shape + * @param {Connection} connection + * @param {Shape} shape * @param {boolean} [dockStart=false] * * @return {DockingPointDescriptor} diff --git a/lib/layout/CroppingConnectionDocking.js b/lib/layout/CroppingConnectionDocking.js index 1a0ad77d6..0c7b430bb 100644 --- a/lib/layout/CroppingConnectionDocking.js +++ b/lib/layout/CroppingConnectionDocking.js @@ -6,6 +6,10 @@ import { getElementLineIntersection } from './LayoutUtil'; +/** + * @typedef {import('../core/ElementRegistry').default} ElementRegistry + * @typedef {import('../core/GraphicsFactory').default} GraphicsFactory + */ function dockingToPoint(docking) { @@ -19,7 +23,8 @@ function dockingToPoint(docking) { * A {@link ConnectionDocking} that crops connection waypoints based on * the path(s) of the connection source and target. * - * @param {djs.core.ElementRegistry} elementRegistry + * @param {ElementRegistry} elementRegistry + * @param {GraphicsFactory} graphicsFactory */ export default function CroppingConnectionDocking(elementRegistry, graphicsFactory) { this._elementRegistry = elementRegistry; diff --git a/lib/layout/LayoutUtil.js b/lib/layout/LayoutUtil.js index a0f43bab5..a7385564b 100644 --- a/lib/layout/LayoutUtil.js +++ b/lib/layout/LayoutUtil.js @@ -10,6 +10,14 @@ import { import intersectPaths from 'path-intersection'; +/** + * @typedef {import('../model').Connection} Connection + * + * @typedef {import('../util/Types').DirectionTRBL} DirectionTRBL + * @typedef {import('../util/Types').Point} Point + * @typedef {import('../util/Types').Rect} Rect + * @typedef {import('../util/Types').RectTRBL} RectTRBL + */ export function roundBounds(bounds) { return { @@ -33,9 +41,9 @@ export function roundPoint(point) { /** * Convert the given bounds to a { top, left, bottom, right } descriptor. * - * @param {Bounds|Point} bounds + * @param {Point|Rect} bounds * - * @return {Object} + * @return {RectTRBL} */ export function asTRBL(bounds) { return { @@ -50,9 +58,9 @@ export function asTRBL(bounds) { /** * Convert a { top, left, bottom, right } to an objects bounds. * - * @param {Object} trbl + * @param {RectTRBL} trbl * - * @return {Bounds} + * @return {Rect} */ export function asBounds(trbl) { return { @@ -67,7 +75,7 @@ export function asBounds(trbl) { /** * Get the mid of the given bounds or point. * - * @param {Bounds|Point} bounds + * @param {Point|Rect} bounds * * @return {Point} */ @@ -82,7 +90,7 @@ export function getBoundsMid(bounds) { /** * Get the mid of the given Connection. * - * @param {djs.Base.Connection} connection + * @param {Connection} connection * * @return {Point} */ @@ -141,7 +149,7 @@ export function getConnectionMid(connection) { /** * Get the mid of the given Element. * - * @param {djs.Base.Connection} connection + * @param {Connection} connection * * @return {Point} */ @@ -162,11 +170,11 @@ export function getMid(element) { * A padding (positive or negative) may be passed to influence * horizontal / vertical orientation and intersection. * - * @param {Bounds} rect - * @param {Bounds} reference + * @param {Rect} rect + * @param {Rect} reference * @param {Point|number} padding * - * @return {string} the orientation; one of top, top-left, left, ..., bottom, right or intersect. + * @return {DirectionTRBL} the orientation; one of top, top-left, left, ..., bottom, right or intersect. */ export function getOrientation(rect, reference, padding) { @@ -203,9 +211,9 @@ export function getOrientation(rect, reference, padding) { /** * Get intersection between an element and a line path. * - * @param {PathDef} elementPath - * @param {PathDef} linePath - * @param {boolean} cropStart crop from start or end + * @param {string} elementPath + * @param {string} linePath + * @param {boolean} cropStart Whether to crop start or end. * * @return {Point} */ diff --git a/lib/layout/ManhattanLayout.js b/lib/layout/ManhattanLayout.js index b3bae53da..69b5e239a 100644 --- a/lib/layout/ManhattanLayout.js +++ b/lib/layout/ManhattanLayout.js @@ -17,6 +17,11 @@ import { pointsOnLine } from '../util/Geometry'; +/** + * @typedef {import('../util/Types').Point} Point + * @typedef {import('../util/Types').Rect} Rect + */ + var MIN_SEGMENT_LENGTH = 20, POINT_ORIENTATION_PADDING = 5; @@ -214,11 +219,11 @@ function getSimpleBendpoints(a, b, directions) { * | * [b]-[x] * - * @param {Point} a - * @param {Point} b - * @param {string} directions + * @param {Point} a + * @param {Point} b + * @param {string} directions * - * @return {Array} + * @return {Point[]} */ function getBendpoints(a, b, directions) { directions = directions || 'h:h'; @@ -255,11 +260,11 @@ function getBendpoints(a, b, directions) { * * @param {Point} a * @param {Point} b + * @param {string} [directions='h:h'] Specifies manhattan directions for each + * point as {direction}:{direction}. A direction for a point is either + * `h` (horizontal) or `v` (vertical). * - * @param {string} [directions='h:h'] specifies manhattan directions for each point as {adirection}:{bdirection}. - A directionfor a point is either `h` (horizontal) or `v` (vertical) - * - * @return {Array} + * @return {Point[]} */ export function connectPoints(a, b, directions) { @@ -275,18 +280,18 @@ export function connectPoints(a, b, directions) { /** * Connect two rectangles using a manhattan layouted connection. * - * @param {Bounds} source source rectangle - * @param {Bounds} target target rectangle + * @param {Rect} source source rectangle + * @param {Rect} target target rectangle * @param {Point} [start] source docking * @param {Point} [end] target docking * * @param {Object} [hints] * @param {string} [hints.preserveDocking=source] preserve docking on selected side - * @param {Array} [hints.preferredLayouts] + * @param {string[]} [hints.preferredLayouts] * @param {Point|boolean} [hints.connectionStart] whether the start changed * @param {Point|boolean} [hints.connectionEnd] whether the end changed * - * @return {Array} connection points + * @return {Point[]} connection points */ export function connectRectangles(source, target, start, end, hints) { @@ -318,17 +323,17 @@ export function connectRectangles(source, target, start, end, hints) { /** * Repair the connection between two rectangles, of which one has been updated. * - * @param {Bounds} source - * @param {Bounds} target + * @param {Rect} source + * @param {Rect} target * @param {Point} [start] * @param {Point} [end] - * @param {Array} [waypoints] + * @param {Point[]} [waypoints] * @param {Object} [hints] - * @param {Array} [hints.preferredLayouts] list of preferred layouts + * @param {string[]} [hints.preferredLayouts] The list of preferred layouts. * @param {boolean} [hints.connectionStart] * @param {boolean} [hints.connectionEnd] * - * @return {Array} repaired waypoints + * @return {Point[]} The waypoints of the repaired connection. */ export function repairConnection(source, target, start, end, waypoints, hints) { @@ -395,15 +400,15 @@ function isInRange(axis, a, b) { } /** - * Layout a straight connection + * Lay out a straight connection. * - * @param {Bounds} source - * @param {Bounds} target + * @param {Rect} source + * @param {Rect} target * @param {Point} start * @param {Point} end * @param {Object} [hints] * - * @return {Array|null} waypoints if straight layout worked + * @return {Point[]|null} The waypoints or null if layout isn't possible. */ export function tryLayoutStraight(source, target, start, end, hints) { var axis = {}, @@ -478,12 +483,12 @@ export function tryLayoutStraight(source, target, start, end, hints) { /** * Repair a connection from start. * - * @param {Bounds} moved - * @param {Bounds} other + * @param {Rect} moved + * @param {Rect} other * @param {Point} newDocking - * @param {Array} points originalPoints from moved to other + * @param {Point[]} points originalPoints from moved to other * - * @return {Array|null} the repaired points between the two rectangles + * @return {Point[]|null} The waypoints of the repaired connection. */ function tryRepairConnectionStart(moved, other, newDocking, points) { return _tryRepairConnectionSide(moved, other, newDocking, points); @@ -492,12 +497,12 @@ function tryRepairConnectionStart(moved, other, newDocking, points) { /** * Repair a connection from end. * - * @param {Bounds} moved - * @param {Bounds} other + * @param {Rect} moved + * @param {Rect} other * @param {Point} newDocking - * @param {Array} points originalPoints from moved to other + * @param {Point[]} points originalPoints from moved to other * - * @return {Array|null} the repaired points between the two rectangles + * @return {Point[]|null} The waypoints of the repaired connection. */ function tryRepairConnectionEnd(moved, other, newDocking, points) { var waypoints = points.slice().reverse(); @@ -510,12 +515,12 @@ function tryRepairConnectionEnd(moved, other, newDocking, points) { /** * Repair a connection from one side that moved. * - * @param {Bounds} moved - * @param {Bounds} other + * @param {Rect} moved + * @param {Rect} other * @param {Point} newDocking - * @param {Array} points originalPoints from moved to other + * @param {Point[]} points originalPoints from moved to other * - * @return {Array} the repaired points between the two rectangles + * @return {Point[]} The waypoints of the repaired connection. */ function _tryRepairConnectionSide(moved, other, newDocking, points) { @@ -728,9 +733,9 @@ function getDockingPoint(point, rectangle, dockingDirection, targetOrientation) * | * [x] ----------- [x] * - * @param {Array} waypoints + * @param {Point[]} waypoints * - * @return {Array} + * @return {Point[]} */ export function withoutRedundantPoints(waypoints) { return waypoints.reduce(function(points, p, idx) { diff --git a/lib/model/index.js b/lib/model/index.js index 807f871dc..02313925d 100644 --- a/lib/model/index.js +++ b/lib/model/index.js @@ -9,14 +9,6 @@ var parentRefs = new Refs({ name: 'children', enumerable: true, collection: true outgoingRefs = new Refs({ name: 'outgoing', collection: true }, { name: 'source' }), incomingRefs = new Refs({ name: 'incoming', collection: true }, { name: 'target' }); -/** - * @namespace djs.model - */ - -/** - * @memberOf djs.model - */ - /** * The basic graphical representation * diff --git a/lib/navigation/keyboard-move/KeyboardMove.js b/lib/navigation/keyboard-move/KeyboardMove.js index e50e1c61c..a63c18770 100644 --- a/lib/navigation/keyboard-move/KeyboardMove.js +++ b/lib/navigation/keyboard-move/KeyboardMove.js @@ -1,5 +1,9 @@ import { assign } from 'min-dash'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../features/keyboard/Keyboard').default} Keyboard + */ var DEFAULT_CONFIG = { moveSpeed: 50, diff --git a/lib/navigation/movecanvas/MoveCanvas.js b/lib/navigation/movecanvas/MoveCanvas.js index 05054271c..255ddffbe 100644 --- a/lib/navigation/movecanvas/MoveCanvas.js +++ b/lib/navigation/movecanvas/MoveCanvas.js @@ -20,6 +20,10 @@ import { toPoint } from '../../util/Event'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ var THRESHOLD = 15; diff --git a/lib/navigation/zoomscroll/ZoomScroll.js b/lib/navigation/zoomscroll/ZoomScroll.js index f531cfd77..7e9e7bef3 100644 --- a/lib/navigation/zoomscroll/ZoomScroll.js +++ b/lib/navigation/zoomscroll/ZoomScroll.js @@ -16,6 +16,11 @@ import { bind } from 'min-dash'; +/** + * @typedef {import('../../core/Canvas').default} Canvas + * @typedef {import('../../core/EventBus').default} EventBus + */ + var sign = Math.sign || function(n) { return n >= 0 ? 1 : -1; }; @@ -206,7 +211,7 @@ ZoomScroll.prototype._zoom = function(delta, position, stepSize) { /** * Toggle the zoom scroll ability via mouse wheel. * - * @param {boolean} [newEnabled] new enabled state + * @param {boolean} [newEnabled] new enabled state */ ZoomScroll.prototype.toggle = function toggle(newEnabled) { diff --git a/lib/util/AttachUtil.js b/lib/util/AttachUtil.js index fd3e1f4fd..36bb45306 100644 --- a/lib/util/AttachUtil.js +++ b/lib/util/AttachUtil.js @@ -9,15 +9,21 @@ import { delta } from './PositionUtil'; +/** + * @typedef {import('../model').Shape} Shape + * + * @typedef {import('../util/Types').Point} Point + * @typedef {import('../util/Types').Rect} Rect + */ /** - * Calculates the absolute point relative to the new element's position + * Calculates the absolute point relative to the new element's position. * - * @param {point} point [absolute] - * @param {bounds} oldBounds - * @param {bounds} newBounds + * @param {Point} point [absolute] + * @param {Rect} oldBounds + * @param {Rect} newBounds * - * @return {point} point [absolute] + * @return {Point} point [absolute] */ export function getNewAttachPoint(point, oldBounds, newBounds) { var oldCenter = center(oldBounds), @@ -38,13 +44,13 @@ export function getNewAttachPoint(point, oldBounds, newBounds) { /** * Calculates the shape's delta relative to a new position - * of a certain element's bounds + * of a certain element's bounds. * - * @param {djs.model.Shape} point [absolute] - * @param {bounds} oldBounds - * @param {bounds} newBounds + * @param {Shape} point [absolute] + * @param {Rect} oldBounds + * @param {Rect} newBounds * - * @return {delta} delta + * @return {Point} delta */ export function getNewAttachShapeDelta(shape, oldBounds, newBounds) { var shapeCenter = center(shape), diff --git a/lib/util/Collections.js b/lib/util/Collections.js index 4cbe54360..e81b0f12a 100644 --- a/lib/util/Collections.js +++ b/lib/util/Collections.js @@ -1,8 +1,8 @@ /** * Failsafe remove an element from a collection * - * @param {Array} [collection] - * @param {Object} [element] + * @param {Array} [collection] + * @param {Object} [element] * * @return {number} the previous index of the element */ diff --git a/lib/util/Elements.js b/lib/util/Elements.js index 83904c1ec..e3fead86b 100644 --- a/lib/util/Elements.js +++ b/lib/util/Elements.js @@ -11,15 +11,18 @@ import { } from 'min-dash'; /** - * @typedef { {x:number, y: number, width: number, height: number} } Bounds + * @typedef {import('../../model').Base} Base + * @typedef {import('../../model').Shape} Shape + * + * @typedef {import('../../type/Types').Rect} Rect */ /** * Get parent elements. * - * @param {Array} elements + * @param {Base[]} elements * - * @returns {Array} + * @returns {Base[]} */ export function getParents(elements) { @@ -53,7 +56,7 @@ function getParent(element, parent) { * Adds an element to a collection and returns true if the * element was added. * - * @param {Array} elements + * @param {Object[]} elements * @param {Object} e * @param {boolean} unique */ @@ -74,9 +77,9 @@ export function add(elements, e, unique) { * * Recurse into all elements that are returned by `fn`. * - * @param {Object|Array} elements - * @param {Function} fn iterator function called with (element, index, recursionDepth) - * @param {number} [depth] maximum recursion depth + * @param {Object|Object[]} elements + * @param {Function} fn iterator function called with (element, index, recursionDepth) + * @param {number} [depth] maximum recursion depth */ export function eachElement(elements, fn, depth) { @@ -99,11 +102,11 @@ export function eachElement(elements, fn, depth) { /** * Collects self + child elements up to a given depth from a list of elements. * - * @param {djs.model.Base|Array} elements the elements to select the children from - * @param {boolean} unique whether to return a unique result set (no duplicates) - * @param {number} maxDepth the depth to search through or -1 for infinite + * @param {Base|Base[]} elements the elements to select the children from + * @param {boolean} unique whether to return a unique result set (no duplicates) + * @param {number} maxDepth the depth to search through or -1 for infinite * - * @return {Array} found elements + * @return {Base[]} found elements */ export function selfAndChildren(elements, unique, maxDepth) { var result = [], @@ -130,10 +133,10 @@ export function selfAndChildren(elements, unique, maxDepth) { /** * Return self + direct children for a number of elements * - * @param {Array} elements to query - * @param {boolean} allowDuplicates to allow duplicates in the result set + * @param {Base[]} elements to query + * @param {boolean} allowDuplicates to allow duplicates in the result set * - * @return {Array} the collected elements + * @return {Base[]} the collected elements */ export function selfAndDirectChildren(elements, allowDuplicates) { return selfAndChildren(elements, !allowDuplicates, 1); @@ -143,10 +146,10 @@ export function selfAndDirectChildren(elements, allowDuplicates) { /** * Return self + ALL children for a number of elements * - * @param {Array} elements to query - * @param {boolean} allowDuplicates to allow duplicates in the result set + * @param {Base[]} elements to query + * @param {boolean} allowDuplicates to allow duplicates in the result set * - * @return {Array} the collected elements + * @return {Base[]} the collected elements */ export function selfAndAllChildren(elements, allowDuplicates) { return selfAndChildren(elements, !allowDuplicates, -1); @@ -157,7 +160,7 @@ export function selfAndAllChildren(elements, allowDuplicates) { * Gets the the closure for all selected elements, * their enclosed children and connections. * - * @param {Array} elements + * @param {Base[]} elements * @param {boolean} [isTopLevel=true] * @param {Object} [existingClosure] * @@ -240,10 +243,10 @@ export function getClosure(elements, isTopLevel, closure) { * Returns the surrounding bbox for all elements in * the array or the element primitive. * - * @param {Array|djs.model.Shape} elements + * @param {Base|Base[]} elements * @param {boolean} [stopRecursion=false] * - * @return {Bounds} + * @return {Rect} */ export function getBBox(elements, stopRecursion) { @@ -302,10 +305,10 @@ export function getBBox(elements, stopRecursion) { * * If only bbox.x or bbox.y is specified, method return all elements with * e.x > bbox.x or e.y > bbox.y * - * @param {Array} elements List of Elements to search through - * @param {djs.model.Shape} bbox the enclosing bbox. + * @param {Base[]} elements List of Elements to search through + * @param {Rect} bbox the enclosing bbox. * - * @return {Array} enclosed elements + * @return {Base[]} enclosed elements */ export function getEnclosedElements(elements, bbox) { diff --git a/lib/util/Geometry.js b/lib/util/Geometry.js index 4786634ee..1ed8496cd 100644 --- a/lib/util/Geometry.js +++ b/lib/util/Geometry.js @@ -3,12 +3,18 @@ import { } from 'min-dash'; /** - * Computes the distance between two points + * @typedef {import('../util/Types').Axis} Axis + * @typedef {import('../util/Types').Point} Point + * @typedef {import('../util/Types').Rect} Rect + */ + +/** + * Computes the distance between two points. * - * @param {Point} p - * @param {Point} q + * @param {Point} p + * @param {Point} q * - * @return {number} distance + * @return {number} The distance between the two points. */ export function pointDistance(a, b) { if (!a || !b) { @@ -23,12 +29,12 @@ export function pointDistance(a, b) { /** - * Returns true if the point r is on the line between p and q + * Returns true if the point r is on the line between p and q. * - * @param {Point} p - * @param {Point} q - * @param {Point} r - * @param {number} [accuracy=5] accuracy for points on line check (lower is better) + * @param {Point} p + * @param {Point} q + * @param {Point} r + * @param {number} [accuracy=5] The accuracy with which to check (lower is better). * * @return {boolean} */ @@ -58,7 +64,7 @@ var ALIGNED_THRESHOLD = 2; * @param {Point[]|Point} a * @param {Point} [b] * - * @return {'h'|'v'|false} axis or false + * @return {string|boolean} If and how the two points are aligned ('h', 'v' or `false`). */ export function pointsAligned(a, b) { var points = Array.from(arguments).flat(); @@ -78,8 +84,8 @@ export function pointsAligned(a, b) { } /** - * @param { 'x' | 'y' } axis - * @param { Point[] } points + * @param {Axis} axis + * @param {Point[]} points * * @return {boolean} */ @@ -94,9 +100,9 @@ export function pointsAlignedOnAxis(axis, points) { /** * Returns true if the point p is inside the rectangle rect * - * @param {Point} p - * @param {Rect} rect - * @param {number} tolerance + * @param {Point} p + * @param {Rect} rect + * @param {number} tolerance * * @return {boolean} */ @@ -112,10 +118,10 @@ export function pointInRect(p, rect, tolerance) { /** * Returns a point in the middle of points p and q * - * @param {Point} p - * @param {Point} q + * @param {Point} p + * @param {Point} q * - * @return {Point} middle point + * @return {Point} The mid point between the two points. */ export function getMidPoint(p, q) { return { diff --git a/lib/util/GraphicsUtil.js b/lib/util/GraphicsUtil.js index 722122651..866f36f0f 100644 --- a/lib/util/GraphicsUtil.js +++ b/lib/util/GraphicsUtil.js @@ -6,11 +6,11 @@ */ /** - * Returns the visual part of a diagram element + * Returns the visual part of a diagram element. * - * @param {Snap} gfx + * @param {SVGElement} gfx * - * @return {Snap} + * @return {SVGElement} */ export function getVisual(gfx) { return gfx.childNodes[0]; @@ -19,8 +19,8 @@ export function getVisual(gfx) { /** * Returns the children for a given diagram element. * - * @param {Snap} gfx - * @return {Snap} + * @param {SVGElement} gfx + * @return {SVGElement} */ export function getChildren(gfx) { return gfx.parentNode.childNodes[1]; diff --git a/lib/util/IdGenerator.js b/lib/util/IdGenerator.js index b69c9e611..1896d92d2 100644 --- a/lib/util/IdGenerator.js +++ b/lib/util/IdGenerator.js @@ -1,9 +1,8 @@ /** * Util that provides unique IDs. * - * @class djs.util.IdGenerator + * @class * @constructor - * @memberOf djs.util * * The ids can be customized via a given prefix and contain a random value to avoid collisions. * @@ -18,8 +17,6 @@ export default function IdGenerator(prefix) { /** * Returns a next unique ID. * - * @method djs.util.IdGenerator#next - * * @returns {string} the id */ IdGenerator.prototype.next = function() { diff --git a/lib/util/LineIntersection.js b/lib/util/LineIntersection.js index d8da03797..24418a709 100644 --- a/lib/util/LineIntersection.js +++ b/lib/util/LineIntersection.js @@ -4,6 +4,10 @@ import { import intersectPaths from 'path-intersection'; +/** + * @typedef {import('../util/Types').Point} Point + */ + var round = Math.round, max = Math.max; @@ -103,8 +107,8 @@ function getPathIntersection(waypoints, reference) { /** * Returns the closest point on the connection towards a given reference point. * - * @param {Array} waypoints - * @param {Point} reference + * @param {Point[]} waypoints + * @param {Point} reference * * @return {Object} intersection data (segment, point) */ diff --git a/lib/util/Math.js b/lib/util/Math.js index 13e85ce93..3e0b2b558 100644 --- a/lib/util/Math.js +++ b/lib/util/Math.js @@ -1,6 +1,7 @@ /** - * Get the logarithm of x with base 10 - * @param {Integer} value + * Get the logarithm of x with base 10. + * + * @param {number} x */ export function log10(x) { return Math.log(x) / Math.log(10); diff --git a/lib/util/Removal.js b/lib/util/Removal.js index f231b79e0..62715575d 100644 --- a/lib/util/Removal.js +++ b/lib/util/Removal.js @@ -9,10 +9,10 @@ * may touch, i.e. remove multiple elements in the collection * at a time. * - * @param {Array} [collection] + * @param {Object[]} [collection] * @param {Function} removeFn * - * @return {Array} the cleared collection + * @return {Object[]} the cleared collection */ export function saveClear(collection, removeFn) { diff --git a/lib/util/RenderUtil.js b/lib/util/RenderUtil.js index 2cc3b22f5..73b4f0f8e 100644 --- a/lib/util/RenderUtil.js +++ b/lib/util/RenderUtil.js @@ -7,11 +7,16 @@ import { create as svgCreate } from 'tiny-svg'; +/** + * @typedef {(string|number)[]} Component + * + * @typedef {import('../util/Types').Point} Point + */ /** - * @param { [ string, ...any[] ][] } elements + * @param {Component[]} elements * - * @return { string } + * @return {string} */ export function componentsToPath(elements) { return elements.flat().join(',').replace(/,?([A-z]),?/g, '$1'); @@ -101,9 +106,9 @@ function vectorLength(x, y) { } /** - * @param { { x: number, y: number }[] } points - * @param { any } [attrs] - * @param { number } [radius] + * @param {Point[]} points + * @param {*} [attrs] + * @param {number} [radius] * * @return {SVGElement} */ @@ -128,8 +133,8 @@ export function createLine(points, attrs, radius) { } /** - * @param { SVGElement } gfx - * @param { { x: number, y: number }[]} points + * @param {SVGElement} gfx + * @param {Point[]} points * * @return {SVGElement} */ diff --git a/lib/util/SvgTransformUtil.js b/lib/util/SvgTransformUtil.js index fe12755c4..939141feb 100644 --- a/lib/util/SvgTransformUtil.js +++ b/lib/util/SvgTransformUtil.js @@ -5,7 +5,7 @@ import { /** - * @param {} element + * @param {SVGElement} element * @param {number} x * @param {number} y * @param {number} angle diff --git a/lib/util/Text.js b/lib/util/Text.js index 497145c26..f39389aa4 100644 --- a/lib/util/Text.js +++ b/lib/util/Text.js @@ -16,6 +16,10 @@ import { assignStyle } from 'min-dom'; +/** + * @typedef {import('../util/Types').Dimensions} Dimensions + */ + var DEFAULT_BOX_PADDING = 0; var DEFAULT_LABEL_SIZE = { @@ -89,7 +93,8 @@ function getTextBBox(text, fakeText) { * * Alters the lines passed. * - * @param {Array} lines + * @param {string[]} lines + * * @return {Object} the line descriptor, an object { width, height, text } */ function layoutNext(lines, maxWidth, fakeText) { @@ -134,8 +139,9 @@ var SOFT_BREAK = '\u00AD'; * Shortens a line based on spacing and hyphens. * Returns the shortened result on success. * - * @param {string} line - * @param {number} maxLength the maximum characters of the string + * @param {string} line + * @param {number} maxLength the maximum characters of the string + * * @return {string} the shortened string */ function semanticShorten(line, maxLength) { diff --git a/lib/util/Types.d.ts b/lib/util/Types.d.ts index f6f260ce2..723f40ba7 100644 --- a/lib/util/Types.d.ts +++ b/lib/util/Types.d.ts @@ -3,6 +3,10 @@ export type Point = { y: number; }; +export type Vector = Point; + +export type Dimension = 'width' | 'height'; + export type Dimensions = { width: number; height: number; @@ -17,4 +21,8 @@ export type RectTRBL = { left: number; }; -export type Direction = 'n' | 'w' | 's' | 'e'; \ No newline at end of file +export type Axis = 'x' | 'y'; + +export type Direction = 'n' | 'w' | 's' | 'e' | 'nw' | 'ne' | 'sw' | 'se'; + +export type DirectionTRBL = 'top' | 'right' | 'bottom' | 'left' | 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; \ No newline at end of file diff --git a/lib/util/Types.js b/lib/util/Types.js index 9d9875cb4..2426e152a 100644 --- a/lib/util/Types.js +++ b/lib/util/Types.js @@ -2,13 +2,21 @@ * @typedef Point * @property {number} x * @property {number} y -*/ + */ + +/** + * @typedef {Point} Vector + */ + +/** + * @typedef {string} Dimension Either 'width' or 'height'. + */ /** * @typedef Dimensions * @property {number} width * @property {number} height -*/ + */ /** * @typedef Rect @@ -27,5 +35,13 @@ */ /** - * @typedef {string} Directions - Either 'n', 'w', 's' or 'e'. + * @typedef {string} Axis Either 'x' or 'y'. + */ + +/** + * @typedef {string} Directions Either 'n', 'w', 's', 'e', 'nw', 'ne', 'sw' or 'se'. + */ + +/** + * @typedef {string} DirectionTRBL Either 'top', 'right', 'bottom', 'left', 'top-right', 'top-left', 'bottom-right' or 'bottom-left'; */ \ No newline at end of file diff --git a/test/helper/index.js b/test/helper/index.js index 0a02a8ca9..459d385f2 100644 --- a/test/helper/index.js +++ b/test/helper/index.js @@ -30,8 +30,8 @@ var OPTIONS, DIAGRAM_JS; * * }); * - * @param {Object} (options) optional options to be passed to the diagram upon instantiation - * @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them + * @param {Object} (options) optional options to be passed to the diagram upon instantiation + * @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them * @return {Function} a function to be passed to beforeEach */ export function bootstrapDiagram(options, locals) { @@ -112,7 +112,7 @@ export function bootstrapDiagram(options, locals) { * * }); * - * @param {Function} fn the function to inject to + * @param {Function} fn the function to inject to * @return {Function} a function that can be passed to it to carry out the injection */ export function inject(fn) { diff --git a/test/matchers/BoundsMatchers.js b/test/matchers/BoundsMatchers.js index 40e25fb78..6e3e780b9 100644 --- a/test/matchers/BoundsMatchers.js +++ b/test/matchers/BoundsMatchers.js @@ -1,5 +1,12 @@ import { pick } from 'min-dash'; +/** + * @typedef {import('../../lib/util/Types').Dimensions} Dimensions + * @typedef {import('../../lib/util/Types').Point} Point + * @typedef {import('../../lib/util/Types').Rect} Rect + * @typedef {import('../../lib/util/Types').RectTRBL} RectTRBL + */ + var BOUNDS_ATTRS = [ 'x', 'y', 'width', 'height' ], POSITION_ATTRS = [ 'x', 'y' ], DIMENSION_ATTRS = [ 'width', 'height' ]; @@ -53,7 +60,7 @@ export default function(chai, utils) { * expect(di.label).to.have.bounds({ x: 100, y: 100, width: 10, height: 20 }); * expect(shape).to.have.bounds({ top: 100, left: 0, right: 200, bottom: 50 }); * - * @param {Bounds|TLBR} exp + * @param {Rect|RectTRBL} exp */ Assertion.addMethod('bounds', function(exp) { var obj = this._obj; diff --git a/test/matchers/ConnectionMatchers.js b/test/matchers/ConnectionMatchers.js index c54c48013..664b50db7 100644 --- a/test/matchers/ConnectionMatchers.js +++ b/test/matchers/ConnectionMatchers.js @@ -1,5 +1,9 @@ import { pick } from 'min-dash'; +/** + * @typedef {import('../../lib/util/Types').Point} Point + */ + var POSITION_ATTRS = [ 'x', 'y' ]; function extractPoints(point) { diff --git a/test/spec/features/attach-support/rules/AttachRules.js b/test/spec/features/attach-support/rules/AttachRules.js index b4fe088e3..2f52b3dfe 100644 --- a/test/spec/features/attach-support/rules/AttachRules.js +++ b/test/spec/features/attach-support/rules/AttachRules.js @@ -75,8 +75,8 @@ AttachRules.prototype.init = function() { * Returns 'attach' if all shape ids are contained in the attachmentIds array. * Returns false if at least one of the shapes is not contained. * - * @param {Array} attachmentIds - * @param {Array} shapes + * @param {Array} attachmentIds + * @param {Array} shapes */ function retainmentAllowed(attachmentIds, shapes) { var allowed = 'attach'; diff --git a/test/spec/features/context-pad/ContextPadSpec.js b/test/spec/features/context-pad/ContextPadSpec.js index f5a66b314..a0c71b39f 100755 --- a/test/spec/features/context-pad/ContextPadSpec.js +++ b/test/spec/features/context-pad/ContextPadSpec.js @@ -58,7 +58,7 @@ describe('features/context-pad', function() { /** * @constructor * - * @param {any} [entriesOrUpdater] + * @param {*} [entriesOrUpdater] */ function Provider(entriesOrUpdater) { this.getContextPadEntries = function(element) { diff --git a/test/spec/features/copy-paste/CopyPasteSpec.js b/test/spec/features/copy-paste/CopyPasteSpec.js index cd75c5125..058100ff7 100644 --- a/test/spec/features/copy-paste/CopyPasteSpec.js +++ b/test/spec/features/copy-paste/CopyPasteSpec.js @@ -18,6 +18,10 @@ import modelingModule from 'lib/features/modeling'; import rulesModule from './rules'; import selectionModule from 'lib/features/selection'; +/** + * @typedef {import('../../model').Base} Base + */ + var HIGH_PRIORITY = 2000; @@ -756,11 +760,11 @@ describe('features/copy-paste', function() { * Find elements in a tree. * Return found elements or false. * - * @param {Array} elements + * @param {Array} elements * @param {Object} tree * @param {number} [depth] * - * @returns {Array|false} + * @returns {Array|false} */ function findElementsInTree(elements, tree, depth) { var foundElements = _findElementsInTree(elements, tree, depth); @@ -776,11 +780,11 @@ function findElementsInTree(elements, tree, depth) { * Find element in a tree. * Return found element or false. * - * @param {djs.model.Base} element + * @param {Base} element * @param {Object} tree * @param {number} [depth] * - * @returns {djs.model.Base|false} + * @returns {Base|false} */ function findElementInTree(elements, tree, depth) { var foundElements = _findElementsInTree(elements, tree, depth); diff --git a/test/spec/features/modeling/custom/CustomLayouter.js b/test/spec/features/modeling/custom/CustomLayouter.js index 8c4a366fc..6db90f472 100644 --- a/test/spec/features/modeling/custom/CustomLayouter.js +++ b/test/spec/features/modeling/custom/CustomLayouter.js @@ -1,5 +1,8 @@ import { getMid } from 'lib/layout/LayoutUtil'; +/** + * @typedef {import('../../model').Connection} Connection + */ /** * A base connection layouter implementation @@ -12,7 +15,7 @@ export default function CustomLayouter() {} /** * Return the new layouted waypoints for the given connection. * - * @param {djs.model.Connection} connection + * @param {Connection} connection * @param {Object} [hints] * @param {boolean} [hints.connectionStart] * @param {boolean} [hints.connectionEnd] diff --git a/test/spec/features/move/renderer/MarkerRenderer.js b/test/spec/features/move/renderer/MarkerRenderer.js index d0ebab733..18b6872be 100644 --- a/test/spec/features/move/renderer/MarkerRenderer.js +++ b/test/spec/features/move/renderer/MarkerRenderer.js @@ -16,6 +16,10 @@ import { createLine } from 'lib//util/RenderUtil'; +/** + * @typedef {import('../../model').Connection} Connection + */ + var HIGH_PRIORITY = 3000; var CONNECTION_STYLE = { @@ -127,7 +131,7 @@ function idToReference(id) { /** * Check wether given connection has marker of given type. * - * @param {djs.model.connection} connection + * @param {Connection} connection * @param {string} markerType * * @returns {boolean} diff --git a/test/util/MockEvents.js b/test/util/MockEvents.js index 60c12a45b..d520a630d 100644 --- a/test/util/MockEvents.js +++ b/test/util/MockEvents.js @@ -4,6 +4,9 @@ import { getDiagramJS } from 'test/TestHelper'; +/** + * @typedef {import('../../lib/util/Types').Point} Point + */ /** * Create an event with global coordinates From b225443b12e01f7646df1861f4b37fd6380cb056 Mon Sep 17 00:00:00 2001 From: Martin Stamm Date: Tue, 28 Feb 2023 14:50:38 +0100 Subject: [PATCH 4/7] chore: simplify import paths --- lib/command/CommandHandler.spec.ts | 4 ++-- lib/command/CommandInterceptor.spec.ts | 6 +++--- lib/command/CommandStack.spec.ts | 6 +++--- lib/core/Canvas.spec.ts | 4 ++-- lib/core/ElementFactory.spec.ts | 6 +++--- lib/core/ElementRegistry.spec.ts | 2 +- lib/core/EventBus.spec.ts | 2 +- lib/core/GraphicsFactory.spec.ts | 2 +- lib/draw/BaseRenderer.spec.ts | 6 +++--- lib/features/modeling/Modeling.spec.ts | 2 +- lib/features/overlays/Overlays.spec.ts | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/command/CommandHandler.spec.ts b/lib/command/CommandHandler.spec.ts index fec1c2ee7..ff6f1f017 100644 --- a/lib/command/CommandHandler.spec.ts +++ b/lib/command/CommandHandler.spec.ts @@ -1,6 +1,6 @@ -import CommandHandler from '../../lib/command/CommandHandler'; +import CommandHandler from './CommandHandler'; -import Canvas from '../../lib/core/Canvas'; +import Canvas from '../core/Canvas'; export class AddShapeHandler implements CommandHandler { private _canvas: Canvas; diff --git a/lib/command/CommandInterceptor.spec.ts b/lib/command/CommandInterceptor.spec.ts index e2d3b1e98..0ace9b36b 100644 --- a/lib/command/CommandInterceptor.spec.ts +++ b/lib/command/CommandInterceptor.spec.ts @@ -1,8 +1,8 @@ -import CommandInterceptor from '../../lib/command/CommandInterceptor'; +import CommandInterceptor from './CommandInterceptor'; -import EventBus from '../../lib/core/EventBus'; +import EventBus from '../core/EventBus'; -import Modeling from '../../lib/features/modeling/Modeling'; +import Modeling from '../features/modeling/Modeling'; export class AddShapeBehavior extends CommandInterceptor { static $inject = [ 'eventBus', 'modeling' ]; diff --git a/lib/command/CommandStack.spec.ts b/lib/command/CommandStack.spec.ts index c7a0cb4be..9d1325fa0 100644 --- a/lib/command/CommandStack.spec.ts +++ b/lib/command/CommandStack.spec.ts @@ -1,7 +1,7 @@ -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; -import CommandModule from '../../lib/command'; -import CommandStack from '../../lib/command/CommandStack'; +import CommandModule from '.'; +import CommandStack from './CommandStack'; import { AddShapeHandler } from './CommandHandler.spec'; diff --git a/lib/core/Canvas.spec.ts b/lib/core/Canvas.spec.ts index 46408d5d1..e0ee39d66 100644 --- a/lib/core/Canvas.spec.ts +++ b/lib/core/Canvas.spec.ts @@ -1,6 +1,6 @@ -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; -import CoreModule from '../../lib/core'; +import CoreModule from '.'; import Canvas from './Canvas'; import ElementFactory from './ElementFactory'; diff --git a/lib/core/ElementFactory.spec.ts b/lib/core/ElementFactory.spec.ts index 0655edcfb..4a386f4b7 100644 --- a/lib/core/ElementFactory.spec.ts +++ b/lib/core/ElementFactory.spec.ts @@ -1,7 +1,7 @@ -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; -import CoreModule from '../../lib/core'; -import ElementFactory from '../../lib/core/ElementFactory'; +import CoreModule from '.'; +import ElementFactory from './ElementFactory'; const diagram = new Diagram({ modules: [ diff --git a/lib/core/ElementRegistry.spec.ts b/lib/core/ElementRegistry.spec.ts index 696a09dc9..02594f2ce 100644 --- a/lib/core/ElementRegistry.spec.ts +++ b/lib/core/ElementRegistry.spec.ts @@ -1,4 +1,4 @@ -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; import CoreModule from '.'; import ElementFactory from './ElementFactory'; diff --git a/lib/core/EventBus.spec.ts b/lib/core/EventBus.spec.ts index 131047a76..19af09e1c 100644 --- a/lib/core/EventBus.spec.ts +++ b/lib/core/EventBus.spec.ts @@ -1,4 +1,4 @@ -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; import CoreModule from '.'; import EventBus, { Event } from './EventBus'; diff --git a/lib/core/GraphicsFactory.spec.ts b/lib/core/GraphicsFactory.spec.ts index a633d207f..8869c9744 100644 --- a/lib/core/GraphicsFactory.spec.ts +++ b/lib/core/GraphicsFactory.spec.ts @@ -1,4 +1,4 @@ -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; import CoreModule from '.'; import ElementFactory from './ElementFactory'; diff --git a/lib/draw/BaseRenderer.spec.ts b/lib/draw/BaseRenderer.spec.ts index a2a3d7c35..f5a57790a 100644 --- a/lib/draw/BaseRenderer.spec.ts +++ b/lib/draw/BaseRenderer.spec.ts @@ -1,9 +1,9 @@ import { Base, Connection, Shape } from '../model'; -import Diagram from '../../lib/Diagram'; +import Diagram from '../Diagram'; -import CoreModule from '../../lib/core'; -import ElementFactory from '../../lib/core/ElementFactory'; +import CoreModule from '../core'; +import ElementFactory from '../core/ElementFactory'; import GraphicsFactory from '../core/GraphicsFactory'; import BaseRenderer from './BaseRenderer'; diff --git a/lib/features/modeling/Modeling.spec.ts b/lib/features/modeling/Modeling.spec.ts index 50d407947..251840099 100644 --- a/lib/features/modeling/Modeling.spec.ts +++ b/lib/features/modeling/Modeling.spec.ts @@ -1,4 +1,4 @@ -import Diagram from '../../../lib/Diagram'; +import Diagram from '../../Diagram'; import CoreModule from '.'; import ElementFactory from '../../core/ElementFactory'; diff --git a/lib/features/overlays/Overlays.spec.ts b/lib/features/overlays/Overlays.spec.ts index 022ceb3bf..f37340e3e 100644 --- a/lib/features/overlays/Overlays.spec.ts +++ b/lib/features/overlays/Overlays.spec.ts @@ -1,4 +1,4 @@ -import Diagram from '../../../lib/Diagram'; +import Diagram from '../../Diagram'; import CoreModule from '.'; import ElementFactory from '../../core/ElementFactory'; From 04108e9bd6e3ad3e2fd7de4d6e1263e20df55750 Mon Sep 17 00:00:00 2001 From: Martin Stamm Date: Tue, 28 Feb 2023 14:51:51 +0100 Subject: [PATCH 5/7] chore: rename CoreModule => OverlaysModule --- lib/features/overlays/Overlays.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/overlays/Overlays.spec.ts b/lib/features/overlays/Overlays.spec.ts index f37340e3e..cf228f3c7 100644 --- a/lib/features/overlays/Overlays.spec.ts +++ b/lib/features/overlays/Overlays.spec.ts @@ -1,13 +1,13 @@ import Diagram from '../../Diagram'; -import CoreModule from '.'; +import OverlaysModule from '.'; import ElementFactory from '../../core/ElementFactory'; import Overlays, { OverlayAttrs } from './Overlays'; const diagram = new Diagram({ modules: [ - CoreModule + OverlaysModule ] }); From 81d861ede95277d634a9191e85bf82f6e53aa3d1 Mon Sep 17 00:00:00 2001 From: Martin Stamm Date: Tue, 28 Feb 2023 14:53:13 +0100 Subject: [PATCH 6/7] chore: drop unnecessary `CoreModule` --- lib/features/modeling/Modeling.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/features/modeling/Modeling.spec.ts b/lib/features/modeling/Modeling.spec.ts index 251840099..3cb812d08 100644 --- a/lib/features/modeling/Modeling.spec.ts +++ b/lib/features/modeling/Modeling.spec.ts @@ -1,6 +1,5 @@ import Diagram from '../../Diagram'; -import CoreModule from '.'; import ElementFactory from '../../core/ElementFactory'; import ModelingModule from '.'; @@ -8,7 +7,6 @@ import Modeling from './Modeling'; const diagram = new Diagram({ modules: [ - CoreModule, ModelingModule ] }); From 93e8aca8715f17f7bc7567ecb04afbf8c1ebbbd0 Mon Sep 17 00:00:00 2001 From: Philipp Date: Wed, 1 Mar 2023 09:30:50 +0100 Subject: [PATCH 7/7] chore: make diagram options optional * options are optional * core module is added by default --- lib/Diagram.d.ts | 2 +- lib/Diagram.js | 4 ++-- lib/Diagram.spec.ts | 4 +++- lib/core/Canvas.spec.ts | 7 +------ lib/core/ElementFactory.spec.ts | 7 +------ lib/core/ElementRegistry.spec.ts | 7 +------ lib/core/EventBus.spec.ts | 7 +------ lib/core/GraphicsFactory.spec.ts | 7 +------ lib/draw/BaseRenderer.spec.ts | 2 -- lib/features/overlays/Overlays.spec.ts | 2 +- 10 files changed, 12 insertions(+), 37 deletions(-) diff --git a/lib/Diagram.d.ts b/lib/Diagram.d.ts index c4746e584..899ab3ebb 100644 --- a/lib/Diagram.d.ts +++ b/lib/Diagram.d.ts @@ -54,7 +54,7 @@ export type DiagramOptions = { * @param injector An (optional) injector to bootstrap the diagram with. */ export default class Diagram { - constructor(options: DiagramOptions, injector?: Injector); + constructor(options?: DiagramOptions, injector?: Injector); /** * Resolves a diagram service. diff --git a/lib/Diagram.js b/lib/Diagram.js index fe679eb46..ddce01901 100644 --- a/lib/Diagram.js +++ b/lib/Diagram.js @@ -28,7 +28,7 @@ function bootstrap(modules) { /** * Creates an injector from passed options. * - * @param {DiagramOptions} options + * @param {DiagramOptions} [options] * * @return {Injector} */ @@ -90,7 +90,7 @@ function createInjector(options) { * * // 'shape ... was added to the diagram' logged to console * - * @param {DiagramOptions} options + * @param {DiagramOptions} [options] * @param {ModuleDeclaration[]} [options.modules] External modules to instantiate with the diagram. * @param {Injector} [injector] An (optional) injector to bootstrap the diagram with. */ diff --git a/lib/Diagram.spec.ts b/lib/Diagram.spec.ts index d79f03627..fa21edfcb 100644 --- a/lib/Diagram.spec.ts +++ b/lib/Diagram.spec.ts @@ -8,7 +8,9 @@ import EventBus from './core/EventBus'; import ModelingModule from './features/modeling'; import Modeling from './features/modeling/Modeling'; -const diagram = new Diagram({ +let diagram = new Diagram(); + +diagram = new Diagram({ modules: [ CoreModule, CommandModule, diff --git a/lib/core/Canvas.spec.ts b/lib/core/Canvas.spec.ts index e0ee39d66..3af59af05 100644 --- a/lib/core/Canvas.spec.ts +++ b/lib/core/Canvas.spec.ts @@ -1,14 +1,9 @@ import Diagram from '../Diagram'; -import CoreModule from '.'; import Canvas from './Canvas'; import ElementFactory from './ElementFactory'; -const diagram = new Diagram({ - modules: [ - CoreModule - ] -}); +const diagram = new Diagram(); const shapeLike = { id: 'shapeLike', diff --git a/lib/core/ElementFactory.spec.ts b/lib/core/ElementFactory.spec.ts index 4a386f4b7..b02310794 100644 --- a/lib/core/ElementFactory.spec.ts +++ b/lib/core/ElementFactory.spec.ts @@ -1,13 +1,8 @@ import Diagram from '../Diagram'; -import CoreModule from '.'; import ElementFactory from './ElementFactory'; -const diagram = new Diagram({ - modules: [ - CoreModule - ] -}); +const diagram = new Diagram(); const elementFactory = diagram.get('elementFactory'); diff --git a/lib/core/ElementRegistry.spec.ts b/lib/core/ElementRegistry.spec.ts index 02594f2ce..ef4300dc9 100644 --- a/lib/core/ElementRegistry.spec.ts +++ b/lib/core/ElementRegistry.spec.ts @@ -1,15 +1,10 @@ import Diagram from '../Diagram'; -import CoreModule from '.'; import ElementFactory from './ElementFactory'; import ElementRegistry from './ElementRegistry'; import GraphicsFactory from './GraphicsFactory'; -const diagram = new Diagram({ - modules: [ - CoreModule - ] -}); +const diagram = new Diagram(); const elementFactory = diagram.get('elementFactory'), elementRegistry = diagram.get('elementRegistry'), diff --git a/lib/core/EventBus.spec.ts b/lib/core/EventBus.spec.ts index 19af09e1c..efad7cc29 100644 --- a/lib/core/EventBus.spec.ts +++ b/lib/core/EventBus.spec.ts @@ -1,13 +1,8 @@ import Diagram from '../Diagram'; -import CoreModule from '.'; import EventBus, { Event } from './EventBus'; -const diagram = new Diagram({ - modules: [ - CoreModule - ] -}); +const diagram = new Diagram(); const eventBus = diagram.get('eventBus'); diff --git a/lib/core/GraphicsFactory.spec.ts b/lib/core/GraphicsFactory.spec.ts index 8869c9744..cafcb1195 100644 --- a/lib/core/GraphicsFactory.spec.ts +++ b/lib/core/GraphicsFactory.spec.ts @@ -1,14 +1,9 @@ import Diagram from '../Diagram'; -import CoreModule from '.'; import ElementFactory from './ElementFactory'; import GraphicsFactory from './GraphicsFactory'; -const diagram = new Diagram({ - modules: [ - CoreModule - ] -}); +const diagram = new Diagram(); const elementFactory = diagram.get('elementFactory'), graphicsFactory = diagram.get('graphicsFactory'); diff --git a/lib/draw/BaseRenderer.spec.ts b/lib/draw/BaseRenderer.spec.ts index f5a57790a..092557bbb 100644 --- a/lib/draw/BaseRenderer.spec.ts +++ b/lib/draw/BaseRenderer.spec.ts @@ -2,7 +2,6 @@ import { Base, Connection, Shape } from '../model'; import Diagram from '../Diagram'; -import CoreModule from '../core'; import ElementFactory from '../core/ElementFactory'; import GraphicsFactory from '../core/GraphicsFactory'; @@ -32,7 +31,6 @@ class CustomRenderer extends BaseRenderer { const diagram = new Diagram({ modules: [ - CoreModule, { __init__: [ 'customRenderer' ], customRenderer: [ 'type', CustomRenderer ] diff --git a/lib/features/overlays/Overlays.spec.ts b/lib/features/overlays/Overlays.spec.ts index cf228f3c7..1975f40b8 100644 --- a/lib/features/overlays/Overlays.spec.ts +++ b/lib/features/overlays/Overlays.spec.ts @@ -1,8 +1,8 @@ import Diagram from '../../Diagram'; -import OverlaysModule from '.'; import ElementFactory from '../../core/ElementFactory'; +import OverlaysModule from '.'; import Overlays, { OverlayAttrs } from './Overlays'; const diagram = new Diagram({