From 58c08b467eb1680cf0c4d741457925fcbcf69180 Mon Sep 17 00:00:00 2001 From: Paulo Gustavo Veiga Date: Mon, 28 Feb 2022 16:12:45 -0800 Subject: [PATCH] Change to typescript --- .../mindplot/src/components/CommandContext.ts | 2 +- .../mindplot/src/components/ConnectionLine.ts | 4 +- packages/mindplot/src/components/Designer.ts | 38 ++---- .../src/components/DesignerActionRunner.ts | 6 +- .../mindplot/src/components/DragManager.ts | 15 +-- packages/mindplot/src/components/DragTopic.ts | 42 +++--- packages/mindplot/src/components/Events.ts | 30 ++--- .../mindplot/src/components/Relationship.ts | 6 +- .../src/components/ShrinkConnector.ts | 4 +- .../components/StandaloneActionDispatcher.ts | 3 +- packages/mindplot/src/components/Topic.ts | 80 +++++------- .../mindplot/src/components/TopicFeature.js | 8 -- .../commands/AddFeatureToTopicCommand.ts | 7 - .../layout/ChildrenSorterStrategy.ts | 24 ++-- .../layout/{EventBus.js => EventBus.ts} | 33 +++-- ...BusDispatcher.js => EventBusDispatcher.ts} | 55 ++++---- .../{LayoutManager.js => LayoutManager.ts} | 121 +++++------------- .../src/components/layout/RootedTreeSet.ts | 15 +-- packages/web2d/src/components/ElementClass.js | 16 +-- .../src/components/peer/svg/ElementPeer.js | 13 +- packages/web2d/test/playground/shapes.html | 2 +- packages/web2d/test/playground/shapes.js | 13 +- 22 files changed, 191 insertions(+), 346 deletions(-) rename packages/mindplot/src/components/layout/{EventBus.js => EventBus.ts} (60%) rename packages/mindplot/src/components/layout/{EventBusDispatcher.js => EventBusDispatcher.ts} (57%) rename packages/mindplot/src/components/layout/{LayoutManager.js => LayoutManager.ts} (64%) diff --git a/packages/mindplot/src/components/CommandContext.ts b/packages/mindplot/src/components/CommandContext.ts index 549d1306..3d489b78 100644 --- a/packages/mindplot/src/components/CommandContext.ts +++ b/packages/mindplot/src/components/CommandContext.ts @@ -116,7 +116,7 @@ class CommandContext { moveTopic(topic: Topic, position: Point) { $assert(topic, 'topic cannot be null'); $assert(position, 'position cannot be null'); - EventBus.instance.fireEvent(EventBus.events.NodeMoveEvent, { + EventBus.instance.fireEvent('topicMoved', { node: topic.getModel(), position, }); diff --git a/packages/mindplot/src/components/ConnectionLine.ts b/packages/mindplot/src/components/ConnectionLine.ts index d54817f5..8edd38d6 100644 --- a/packages/mindplot/src/components/ConnectionLine.ts +++ b/packages/mindplot/src/components/ConnectionLine.ts @@ -93,8 +93,8 @@ class ConnectionLine { return line; } - setVisibility(value: boolean): void { - this._line2d.setVisibility(value); + setVisibility(value: boolean, fade = 0): void { + this._line2d.setVisibility(value, fade); } isVisible() { diff --git a/packages/mindplot/src/components/Designer.ts b/packages/mindplot/src/components/Designer.ts index fef23da9..b1ab5dae 100644 --- a/packages/mindplot/src/components/Designer.ts +++ b/packages/mindplot/src/components/Designer.ts @@ -53,7 +53,6 @@ import Mindmap from './model/Mindmap'; import NodeModel from './model/NodeModel'; import Topic from './Topic'; import { DesignerOptions } from './DesignerOptionsBuilder'; -import MainTopic from './MainTopic'; import DragTopic from './DragTopic'; import CentralTopic from './CentralTopic'; import FeatureType from './model/FeatureType'; @@ -606,7 +605,7 @@ class Designer extends Events { this.goToNode(centralTopic); // Finally, sort the map ... - EventBus.instance.fireEvent(EventBus.events.DoLayout); + EventBus.instance.fireEvent('forceLayout'); this.fireEvent('loadSuccess'); } @@ -695,12 +694,6 @@ class Designer extends Events { mindmap.deleteRelationship(rel.getModel()); } - /** - * @private - * @param {mindplot.model.RelationshipModel} model - * @return {mindplot.Relationship} the new relationship with events registered - * @throws will throw an error if the target topic cannot be found - */ private _buildRelationshipShape(model: RelationshipModel): Relationship { const dmodel = this.getModel(); @@ -744,13 +737,9 @@ class Designer extends Events { return result; } - /** - * @param {mindplot.Topic} node the topic to remove - * removes the given topic and its children from Workspace, DesignerModel and NodeModel - */ - removeTopic(node) { + removeTopic(node: Topic): void { if (!node.isCentralTopic()) { - const parent = node._parent; + const parent = node.getParent(); node.disconnect(this._workspace); // remove children @@ -771,17 +760,13 @@ class Designer extends Events { } } - /** - * @private - */ - _resetEdition() { + private _resetEdition() { const screenManager = this._workspace.getScreenManager(); screenManager.fireEvent('update'); screenManager.fireEvent('mouseup'); this._relPivot.dispose(); } - /** */ deleteSelectedEntities() { // Is there some action in progress ?. this._resetEdition(); @@ -840,7 +825,7 @@ class Designer extends Events { /** */ changeBackgroundColor(color: string) { - const validateFunc = (topic) => topic.getShapeType() !== TopicShape.LINE; + const validateFunc = (topic: Topic) => topic.getShapeType() !== TopicShape.LINE; const validateError = 'Color can not be set to line topics.'; const topicsIds = this.getModel().filterTopicsIds(validateFunc, validateError); @@ -849,9 +834,8 @@ class Designer extends Events { } } - /** */ changeBorderColor(color: string) { - const validateFunc = (topic) => topic.getShapeType() !== TopicShape.LINE; + const validateFunc = (topic: Topic) => topic.getShapeType() !== TopicShape.LINE; const validateError = 'Color can not be set to line topics.'; const topicsIds = this.getModel().filterTopicsIds(validateFunc, validateError); if (topicsIds.length > 0) { @@ -859,7 +843,6 @@ class Designer extends Events { } } - /** */ changeFontSize(size: number) { const topicsIds = this.getModel().filterTopicsIds(); if (topicsIds.length > 0) { @@ -895,11 +878,7 @@ class Designer extends Events { } } - /** - * lets the selected topic open the link editor where the user can define or modify an - * existing link - */ - addLink() { + addLink(): void { const model = this.getModel(); const topic = model.selectedTopic(); if (topic) { @@ -908,8 +887,7 @@ class Designer extends Events { } } - /** */ - addNote() { + addNote(): void { const model = this.getModel(); const topic = model.selectedTopic(); if (topic) { diff --git a/packages/mindplot/src/components/DesignerActionRunner.ts b/packages/mindplot/src/components/DesignerActionRunner.ts index cd578c30..5f5c2096 100644 --- a/packages/mindplot/src/components/DesignerActionRunner.ts +++ b/packages/mindplot/src/components/DesignerActionRunner.ts @@ -42,19 +42,19 @@ class DesignerActionRunner { command.execute(this._context); this._undoManager.enqueue(command); this.fireChangeEvent(); - EventBus.instance.fireEvent(EventBus.events.DoLayout); + EventBus.instance.fireEvent('forceLayout'); } undo(): void { this._undoManager.execUndo(this._context); this.fireChangeEvent(); - EventBus.instance.fireEvent(EventBus.events.DoLayout); + EventBus.instance.fireEvent('forceLayout'); } redo(): void { this._undoManager.execRedo(this._context); this.fireChangeEvent(); - EventBus.instance.fireEvent(EventBus.events.DoLayout); + EventBus.instance.fireEvent('forceLayout'); } fireChangeEvent(): void { diff --git a/packages/mindplot/src/components/DragManager.ts b/packages/mindplot/src/components/DragManager.ts index 56bb3021..41607fcd 100644 --- a/packages/mindplot/src/components/DragManager.ts +++ b/packages/mindplot/src/components/DragManager.ts @@ -24,8 +24,6 @@ import Workspace from './Workspace'; class DragManager { private _workspace: Workspace; - private _designerModel: Workspace; - private _isDragInProcess: boolean; private _eventDispatcher: EventBusDispatcher; @@ -38,7 +36,6 @@ class DragManager { constructor(workspace: Workspace, eventDispatcher: EventBusDispatcher) { this._workspace = workspace; - this._designerModel = workspace; this._listeners = {}; this._isDragInProcess = false; this._eventDispatcher = eventDispatcher; @@ -68,7 +65,7 @@ class DragManager { // Register mouse up listeners ... const mouseUpListener = dragManager._buildMouseUpListener( - workspace, topic, dragNode, dragManager, + workspace, dragNode, dragManager, ); screen.addEvent('mouseup', mouseUpListener); @@ -115,7 +112,7 @@ class DragManager { return result; } - protected _buildMouseUpListener(workspace: Workspace, topic: Topic, dragNode, dragManager: DragManager) { + protected _buildMouseUpListener(workspace: Workspace, dragNode, dragManager: DragManager) { const screen = workspace.getScreenManager(); const me = this; const result = (event: Event) => { @@ -149,13 +146,7 @@ class DragManager { return result; } - /** - * type: - * - startdragging. - * - dragging - * - enddragging - */ - addEvent(type: string, listener) { + addEvent(type: 'startdragging' | 'dragging' | 'enddragging', listener) { this._listeners[type] = listener; } } diff --git a/packages/mindplot/src/components/DragTopic.ts b/packages/mindplot/src/components/DragTopic.ts index 9d9c23a4..be51a848 100644 --- a/packages/mindplot/src/components/DragTopic.ts +++ b/packages/mindplot/src/components/DragTopic.ts @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { $assert, $defined } from '@wisemapping/core-js'; +import { $assert } from '@wisemapping/core-js'; import { Point, ElementClass } from '@wisemapping/web2d'; import ActionDispatcher from './ActionDispatcher'; @@ -27,12 +27,19 @@ import Workspace from './Workspace'; class DragTopic { private _elem2d: ElementClass; + private _order: number | null; + private _draggedNode: NodeGraph; + private _layoutManager: LayoutManager; - private _position: any; + + private _position: Point; + private _isInWorkspace: boolean; - static _dragPivot: any; + + static _dragPivot: DragPivot = new DragPivot(); + constructor(dragShape: ElementClass, draggedNode: NodeGraph, layoutManger: LayoutManager) { $assert(dragShape, 'Rect can not be null.'); $assert(draggedNode, 'draggedNode can not be null.'); @@ -46,13 +53,13 @@ class DragTopic { this._isInWorkspace = false; } - setOrder(order: number) { + setOrder(order: number): void { this._order = order; } - setPosition(x: number, y: number) { + setPosition(x: number, y: number): void { // Update drag shadow position .... - let position = { x, y }; + const position = { x, y }; this._position.setValue(position.x, position.y); // Elements are positioned in the center. @@ -104,11 +111,7 @@ class DragTopic { $assert(parent, 'Parent connection node can not be null.'); // Where it should be connected ? - - // @todo: This is a hack for the access of the editor. - // It's required to review why this is needed forcing the declaration of a global variable. - - const predict = global.designer._eventBussDispatcher._layoutManager.predict( + const predict = this._layoutManager.predict( parent.getId(), this._draggedNode.getId(), this.getPosition(), @@ -154,8 +157,8 @@ class DragTopic { } } - _getDragPivot(): DragPivot { - return DragTopic.__getDragPivot(); + private _getDragPivot(): DragPivot { + return DragTopic._dragPivot; } getPosition(): Point { @@ -206,18 +209,9 @@ class DragTopic { static init(workspace: Workspace) { $assert(workspace, 'workspace can not be null'); - const pivot = DragTopic.__getDragPivot(); + const pivot = DragTopic._dragPivot; workspace.append(pivot); - }; - - static __getDragPivot() { - let result = DragTopic._dragPivot; - if (!$defined(result)) { - result = new DragPivot(); - DragTopic._dragPivot = result; - } - return result; - }; + } } export default DragTopic; diff --git a/packages/mindplot/src/components/Events.ts b/packages/mindplot/src/components/Events.ts index 80c39d12..41cf1277 100644 --- a/packages/mindplot/src/components/Events.ts +++ b/packages/mindplot/src/components/Events.ts @@ -17,24 +17,24 @@ */ class Events { - private $events; + private _handlerByType; constructor() { - this.$events = {}; + this._handlerByType = {}; } - static _removeOn(string: string) { - return string.replace(/^on([A-Z])/, (full, first) => first.toLowerCase()); + static _normalizeEventName(string: string) { + return string.replace(/^on([A-Z])/, (_full, first) => first.toLowerCase()); } addEvent(typeName: string, fn?, internal?: boolean): Events { - const type = Events._removeOn(typeName); + const type = Events._normalizeEventName(typeName); // Add function had not been added yet - const funByType = this.$events[type] ? this.$events[type] : []; + const funByType = this._handlerByType[type] ? this._handlerByType[type] : []; if (!funByType.includes(fn)) { funByType.push(fn); - this.$events[type] = funByType; + this._handlerByType[type] = funByType; } // Mark reference ... @@ -42,25 +42,21 @@ class Events { return this; } - fireEvent(typeName: string, eventArgs?, delay?: boolean): Events { - const type = Events._removeOn(typeName); - const events = this.$events[type]; + fireEvent(typeName: string, eventArgs?): Events { + const type = Events._normalizeEventName(typeName); + const events = this._handlerByType[type]; if (!events) return this; const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs]; events.forEach(((fn) => { - if (delay) { - fn.delay(delay, this, args); - } else { - fn.apply(this, args); - } + fn.apply(this, args); })); return this; } removeEvent(typeName: string, fn?): Events { - const type = Events._removeOn(typeName); - const events = this.$events[type]; + const type = Events._normalizeEventName(typeName); + const events = this._handlerByType[type]; if (events && !fn.internal) { const index = events.indexOf(fn); if (index !== -1) events.splice(index, 1); diff --git a/packages/mindplot/src/components/Relationship.ts b/packages/mindplot/src/components/Relationship.ts index 782477e1..8b6cd4d7 100644 --- a/packages/mindplot/src/components/Relationship.ts +++ b/packages/mindplot/src/components/Relationship.ts @@ -277,10 +277,10 @@ class Relationship extends ConnectionLine { return this._isInWorkspace; } - setVisibility(value: boolean) { - super.setVisibility(value); + setVisibility(value: boolean, fade = 0) { + super.setVisibility(value, fade); if (this._showEndArrow) this._endArrow.setVisibility(this._showEndArrow); - this._startArrow.setVisibility(this._showStartArrow && value); + this._startArrow.setVisibility(this._showStartArrow && value, fade); } setOpacity(opacity: number) { diff --git a/packages/mindplot/src/components/ShrinkConnector.ts b/packages/mindplot/src/components/ShrinkConnector.ts index 271e690c..6d354722 100644 --- a/packages/mindplot/src/components/ShrinkConnector.ts +++ b/packages/mindplot/src/components/ShrinkConnector.ts @@ -78,8 +78,8 @@ class ShirinkConnector { this._isShrink = isShrink; } - setVisibility(value: boolean): void { - this._ellipse.setVisibility(value); + setVisibility(value: boolean, fade = 0): void { + this._ellipse.setVisibility(value, fade); } setOpacity(opacity: number): void { diff --git a/packages/mindplot/src/components/StandaloneActionDispatcher.ts b/packages/mindplot/src/components/StandaloneActionDispatcher.ts index 6d8c8f2e..011f8d44 100644 --- a/packages/mindplot/src/components/StandaloneActionDispatcher.ts +++ b/packages/mindplot/src/components/StandaloneActionDispatcher.ts @@ -81,7 +81,7 @@ class StandaloneActionDispatcher extends ActionDispatcher { const commandFunc = (topic: Topic, pos: Point) => { const result = topic.getPosition(); - EventBus.instance.fireEvent(EventBus.events.NodeMoveEvent, { + EventBus.instance.fireEvent('topicMoved', { node: topic.getModel(), position: pos, }); @@ -252,7 +252,6 @@ class StandaloneActionDispatcher extends ActionDispatcher { this.execute(command); } - /** */ addFeatureToTopic(topicId: number, featureType: FeatureType, attributes) { const command = new AddFeatureToTopicCommand(topicId, featureType, attributes); this.execute(command); diff --git a/packages/mindplot/src/components/Topic.ts b/packages/mindplot/src/components/Topic.ts index c31fd1bc..92b0080e 100644 --- a/packages/mindplot/src/components/Topic.ts +++ b/packages/mindplot/src/components/Topic.ts @@ -28,7 +28,6 @@ import TopicStyle from './TopicStyle'; import TopicFeatureFactory from './TopicFeature'; import ConnectionLine from './ConnectionLine'; import IconGroup from './IconGroup'; -import FadeEffect from './util/FadeEffect'; import EventBus from './layout/EventBus'; import ShirinkConnector from './ShrinkConnector'; import NoteEditor from './widget/NoteEditor'; @@ -337,11 +336,6 @@ abstract class Topic extends NodeGraph { return result; } - /** - * assigns the new feature model to the topic's node model and adds the respective icon - * @param {mindplot.model.FeatureModel} featureModel - * @return {mindplot.Icon} the icon corresponding to the feature model - */ addFeature(featureModel: FeatureModel): Icon { const iconGroup = this.getOrBuildIconGroup(); this.closeEditors(); @@ -350,7 +344,7 @@ abstract class Topic extends NodeGraph { const model = this.getModel(); model.addFeature(featureModel); - const result = TopicFeatureFactory.createIcon(this, featureModel, this.isReadOnly()); + const result: Icon = TopicFeatureFactory.createIcon(this, featureModel, this.isReadOnly()); iconGroup.addIcon( result, featureModel.getType() === TopicFeatureFactory.Icon.id && !this.isReadOnly(), @@ -360,7 +354,6 @@ abstract class Topic extends NodeGraph { return result; } - /** */ findFeatureById(id: number) { const model = this.getModel(); return model.findFeatureById(id); @@ -707,34 +700,21 @@ abstract class Topic extends NodeGraph { // Change render base on the state. const shrinkConnector = this.getShrinkConnector(); - if ($defined(shrinkConnector)) { + if (shrinkConnector) { shrinkConnector.changeRender(value); } // Do some fancy animation .... const elements = this._flatten2DElements(this); - const fade = new FadeEffect(elements, !value); - const me = this; - fade.addEvent('complete', () => { - // Set focus on the parent node ... - if (value) { - me.setOnFocus(true); - } - - // Set focus in false for all the children ... - elements.forEach((elem) => { - if (elem.setOnFocus) { - elem.setOnFocus(false); - } - }); + elements.forEach((elem) => { + elem.setVisibility(!value, 250) }); - fade.start(); - EventBus.instance.fireEvent(EventBus.events.NodeShrinkEvent, model); + EventBus.instance.fireEvent('childShrinked', model); + } - /** */ - getShrinkConnector(): ShirinkConnector { + getShrinkConnector(): ShirinkConnector | undefined { let result = this._connector; if (this._connector == null) { this._connector = new ShirinkConnector(this); @@ -925,19 +905,19 @@ abstract class Topic extends NodeGraph { } /** */ - setVisibility(value: boolean): void { - this._setTopicVisibility(value); + setVisibility(value: boolean, fade = 0): void { + this._setTopicVisibility(value, fade); // Hide all children... - this._setChildrenVisibility(value); + this._setChildrenVisibility(value, fade); // If there there are connection to the node, topic must be hidden. - this._setRelationshipLinesVisibility(value); + this._setRelationshipLinesVisibility(value, fade); // If it's connected, the connection must be rendered. const outgoingLine = this.getOutgoingLine(); if (outgoingLine) { - outgoingLine.setVisibility(value); + outgoingLine.setVisibility(value, fade); } } @@ -971,7 +951,7 @@ abstract class Topic extends NodeGraph { return elem.isVisible(); } - private _setRelationshipLinesVisibility(value: boolean): void { + private _setRelationshipLinesVisibility(value: boolean, fade = 0): void { this._relationships.forEach((relationship) => { const sourceTopic = relationship.getSourceTopic(); const targetTopic = relationship.getTargetTopic(); @@ -981,28 +961,28 @@ abstract class Topic extends NodeGraph { relationship.setVisibility( value && (targetParent == null || !targetParent.areChildrenShrunken()) - && (sourceParent == null || !sourceParent.areChildrenShrunken()), - ); + && (sourceParent == null || !sourceParent.areChildrenShrunken()) + , fade); }); } - private _setTopicVisibility(value: boolean) { + private _setTopicVisibility(value: boolean, fade = 0) { const elem = this.get2DElement(); - elem.setVisibility(value); + elem.setVisibility(value, fade); if (this.getIncomingLines().length > 0) { const connector = this.getShrinkConnector(); if ($defined(connector)) { - connector.setVisibility(value); + connector.setVisibility(value, fade); } } // Hide inner shape ... - this.getInnerShape().setVisibility(value); + this.getInnerShape().setVisibility(value, fade); // Hide text shape ... const textShape = this.getTextShape(); - textShape.setVisibility(this.getShapeType() !== TopicShape.IMAGE ? value : false); + textShape.setVisibility(this.getShapeType() !== TopicShape.IMAGE ? value : false, fade); } /** */ @@ -1018,14 +998,14 @@ abstract class Topic extends NodeGraph { textShape.setOpacity(opacity); } - private _setChildrenVisibility(isVisible: boolean) { + private _setChildrenVisibility(value: boolean, fade = 0) { // Hide all children. const children = this.getChildren(); const model = this.getModel(); - const visibility = isVisible ? !model.areChildrenShrunken() : isVisible; + const visibility = value ? !model.areChildrenShrunken() : value; children.forEach((child) => { - child.setVisibility(visibility); + child.setVisibility(visibility, fade); const outgoingLine = child.getOutgoingLine(); outgoingLine.setVisibility(visibility); }); @@ -1066,7 +1046,7 @@ abstract class Topic extends NodeGraph { this._updatePositionOnChangeSize(oldSize, roundedSize); if (hasSizeChanged) { - EventBus.instance.fireEvent(EventBus.events.NodeResizeEvent, { + EventBus.instance.fireEvent('topicResize', { node: this.getModel(), size: roundedSize, }); @@ -1097,7 +1077,7 @@ abstract class Topic extends NodeGraph { outgoingLine.removeFromWorkspace(workspace); // Remove from workspace. - EventBus.instance.fireEvent(EventBus.events.NodeDisconnectEvent, this.getModel()); + EventBus.instance.fireEvent('topicDisconect', this.getModel()); // Change text based on the current connection ... const model = this.getModel(); @@ -1180,7 +1160,7 @@ abstract class Topic extends NodeGraph { // Fire connection event ... if (this.isInWorkspace()) { - EventBus.instance.fireEvent(EventBus.events.NodeConnectEvent, { + EventBus.instance.fireEvent('topicConnected', { parentNode: targetTopic.getModel(), childNode: this.getModel(), }); @@ -1218,7 +1198,7 @@ abstract class Topic extends NodeGraph { workspace.removeChild(line); } this._isInWorkspace = false; - EventBus.instance.fireEvent(EventBus.events.NodeRemoved, this.getModel()); + EventBus.instance.fireEvent('topicRemoved', this.getModel()); } addToWorkspace(workspace: Workspace) { @@ -1226,11 +1206,11 @@ abstract class Topic extends NodeGraph { workspace.append(elem); if (!this.isInWorkspace()) { if (!this.isCentralTopic()) { - EventBus.instance.fireEvent(EventBus.events.NodeAdded, this.getModel()); + EventBus.instance.fireEvent('topicAdded', this.getModel()); } if (this.getModel().isConnected()) { - EventBus.instance.fireEvent(EventBus.events.NodeConnectEvent, { + EventBus.instance.fireEvent('topicConnected', { parentNode: this.getOutgoingConnectedTopic().getModel(), childNode: this.getModel(), }); @@ -1300,7 +1280,7 @@ abstract class Topic extends NodeGraph { } } - private _flatten2DElements(topic: Topic) { + private _flatten2DElements(topic: Topic): (Topic | Relationship)[] { let result = []; const children = topic.getChildren(); diff --git a/packages/mindplot/src/components/TopicFeature.js b/packages/mindplot/src/components/TopicFeature.js index cf63f48b..96c3e3a6 100644 --- a/packages/mindplot/src/components/TopicFeature.js +++ b/packages/mindplot/src/components/TopicFeature.js @@ -40,14 +40,6 @@ const TopicFeatureFactory = { icon: NoteIcon, }, - /** - * @param {mindplot.Topic} topic - * @param {mindplot.model.FeatureModel} model - * @param {Boolean} readOnly true if the editor is running in read-only mode - * @throws will throw an error if topic is null or undefined - * @throws will throw v an error if model is null or undefined - * @return {mindplot.n,nmn mn4 r be5qnwwddwsz5on} a new instance of the icon subclass matching the topic feature - */ createIcon(topic, model, readOnly) { $assert(topic, 'topic can not be null'); $assert(model, 'model can not be null'); diff --git a/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.ts b/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.ts index 952e6562..539edf5a 100644 --- a/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.ts +++ b/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.ts @@ -52,9 +52,6 @@ class AddFeatureToTopicCommand extends Command { this._featureModel = null; } - /** - * Overrides abstract parent method - */ execute(commandContext: CommandContext) { const topic = commandContext.findTopics([this._topicId])[0]; @@ -66,10 +63,6 @@ class AddFeatureToTopicCommand extends Command { topic.addFeature(this._featureModel); } - /** - * Overrides abstract parent method - * @see {@link mindplot.Command.undoExecute} - */ undoExecute(commandContext: CommandContext) { const topic = commandContext.findTopics([this._topicId])[0]; topic.removeFeature(this._featureModel); diff --git a/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts b/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts index 0f69ea38..34419adb 100644 --- a/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts +++ b/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts @@ -1,6 +1,4 @@ -/* eslint-disable no-unused-vars */ -/* eslint-disable class-methods-use-this */ -/* +/** * Copyright [2021] [wisemapping] * * Licensed under WiseMapping Public License, Version 1.0 (the "License"). @@ -17,22 +15,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import RootedTreeSet from "./RootedTreeSet"; +import Node from './Node'; +import PositionType from "../PositionType"; + abstract class ChildrenSorterStrategy { - abstract computeChildrenIdByHeights(treeSet, node); + abstract computeChildrenIdByHeights(treeSet: RootedTreeSet, node: Node); - abstract computeOffsets(treeSet, node); + abstract computeOffsets(treeSet: RootedTreeSet, node: Node); - abstract insert(treeSet, parent, child, order); + abstract insert(treeSet: RootedTreeSet, parent: Node, child: Node, order: number); - abstract detach(treeSet, node); + abstract detach(treeSet: RootedTreeSet, node: Node); - abstract predict(treeSet, parent, node, position, free); + abstract predict(treeSet: RootedTreeSet, parent, node: Node, position: PositionType); - abstract verify(treeSet, node); + abstract verify(treeSet: RootedTreeSet, node: Node); - abstract getChildDirection(treeSet, node); + abstract getChildDirection(treeSet: RootedTreeSet, node: Node); - abstract toString(); + abstract toString(): string; } export default ChildrenSorterStrategy; diff --git a/packages/mindplot/src/components/layout/EventBus.js b/packages/mindplot/src/components/layout/EventBus.ts similarity index 60% rename from packages/mindplot/src/components/layout/EventBus.js rename to packages/mindplot/src/components/layout/EventBus.ts index dca98b13..efb5c202 100644 --- a/packages/mindplot/src/components/layout/EventBus.js +++ b/packages/mindplot/src/components/layout/EventBus.ts @@ -17,25 +17,22 @@ */ import Events from '../Events'; +export type EventType = 'topicResize' | 'topicMoved' | 'childShrinked' | 'topicConnected' | 'topicAdded' | 'topicRemoved' | 'forceLayout' | 'topicDisconect'; class EventBus extends Events { + // eslint-disable-next-line no-use-before-define + static _instance: EventBus = new EventBus(); + + static get instance(): EventBus { + return this._instance; + } + + fireEvent(type: EventType, eventArgs?: unknown[] | unknown): Events { + return super.fireEvent(type, eventArgs); + } + + addEvent(type: EventType, fn?, internal?: boolean): Events { + return super.addEvent(type, fn, internal); + } } -/** - * Enum for events - * @enum {String} - */ -EventBus.events = { - NodeResizeEvent: 'NodeResizeEvent', - NodeMoveEvent: 'NodeMoveEvent', - NodeShrinkEvent: 'NodeShrinkEvent', - NodeConnectEvent: 'NodeConnectEvent', - NodeDisconnectEvent: 'NodeDisconnectEvent', - NodeAdded: 'NodeAdded', - NodeRemoved: 'NodeRemoved', - DoLayout: 'DoLayout', -}; - -/** instance */ -EventBus.instance = new EventBus(); - export default EventBus; diff --git a/packages/mindplot/src/components/layout/EventBusDispatcher.js b/packages/mindplot/src/components/layout/EventBusDispatcher.ts similarity index 57% rename from packages/mindplot/src/components/layout/EventBusDispatcher.js rename to packages/mindplot/src/components/layout/EventBusDispatcher.ts index e635a426..81b83ef9 100644 --- a/packages/mindplot/src/components/layout/EventBusDispatcher.js +++ b/packages/mindplot/src/components/layout/EventBusDispatcher.ts @@ -15,59 +15,57 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import PositionType from '../PositionType'; +import SizeType from '../SizeType'; +import Topic from '../Topic'; import EventBus from './EventBus'; +import LayoutManager from './LayoutManager'; class EventBusDispatcher { + private _layoutManager: LayoutManager; + constructor() { this.registerBusEvents(); } - /** - * @param {mindplot.layout.LayoutManager} layoutManager - */ - setLayoutManager(layoutManager) { + setLayoutManager(layoutManager: LayoutManager) { this._layoutManager = layoutManager; } - /** - * register bus events - */ registerBusEvents() { - EventBus.instance.addEvent(EventBus.events.NodeAdded, this._nodeAdded.bind(this)); - EventBus.instance.addEvent(EventBus.events.NodeRemoved, this._nodeRemoved.bind(this)); - EventBus.instance.addEvent(EventBus.events.NodeResizeEvent, this._nodeResizeEvent.bind(this)); - EventBus.instance.addEvent(EventBus.events.NodeMoveEvent, this._nodeMoveEvent.bind(this)); - EventBus.instance.addEvent( - EventBus.events.NodeDisconnectEvent, this._nodeDisconnectEvent.bind(this), - ); - EventBus.instance.addEvent(EventBus.events.NodeConnectEvent, this._nodeConnectEvent.bind(this)); - EventBus.instance.addEvent(EventBus.events.NodeShrinkEvent, this._nodeShrinkEvent.bind(this)); - EventBus.instance.addEvent(EventBus.events.DoLayout, this._doLayout.bind(this)); + EventBus.instance.addEvent('topicAdded', this._topicAdded.bind(this)); + EventBus.instance.addEvent('topicRemoved', this._topicRemoved.bind(this)); + EventBus.instance.addEvent('topicResize', this._topicResizeEvent.bind(this)); + EventBus.instance.addEvent('topicMoved', this._topicMoved.bind(this)); + EventBus.instance.addEvent('topicDisconect', this._topicDisconect.bind(this)); + EventBus.instance.addEvent('topicConnected', this._topicConnected.bind(this)); + EventBus.instance.addEvent('childShrinked', this._childShrinked.bind(this)); + EventBus.instance.addEvent('forceLayout', this._forceLayout.bind(this)); } - _nodeResizeEvent(args) { + private _topicResizeEvent(args: { node: Topic, size: SizeType }) { this._layoutManager.updateNodeSize(args.node.getId(), args.size); } - _nodeMoveEvent(args) { + private _topicMoved(args: { node: Topic, position: PositionType }) { this._layoutManager.moveNode(args.node.getId(), args.position); } - _nodeDisconnectEvent(node) { + private _topicDisconect(node: Topic) { this._layoutManager.disconnectNode(node.getId()); } - _nodeConnectEvent(args) { + private _topicConnected(args: { parentNode: Topic, childNode: Topic }) { this._layoutManager.connectNode( args.parentNode.getId(), args.childNode.getId(), args.childNode.getOrder(), ); } - _nodeShrinkEvent(node) { + private _childShrinked(node: Topic) { this._layoutManager.updateShrinkState(node.getId(), node.areChildrenShrunken()); } - _nodeAdded(node) { + private _topicAdded(node: Topic) { // Central topic must not be added twice ... if (node.getId() !== 0) { this._layoutManager.addNode(node.getId(), { width: 10, height: 10 }, node.getPosition()); @@ -75,21 +73,14 @@ class EventBusDispatcher { } } - _nodeRemoved(node) { + private _topicRemoved(node: Topic) { this._layoutManager.removeNode(node.getId()); } - _doLayout() { - // (function() { + private _forceLayout() { this._layoutManager.layout(true); - // console.log("---------"); - // this._layoutManager.dump(); - // console.log("---------"); - // console.log("---------"); - // }).delay(0, this); } - /** @return layout manager */ getLayoutManager() { return this._layoutManager; } diff --git a/packages/mindplot/src/components/layout/LayoutManager.js b/packages/mindplot/src/components/layout/LayoutManager.ts similarity index 64% rename from packages/mindplot/src/components/layout/LayoutManager.js rename to packages/mindplot/src/components/layout/LayoutManager.ts index 4f38b269..64c9a1b9 100644 --- a/packages/mindplot/src/components/layout/LayoutManager.js +++ b/packages/mindplot/src/components/layout/LayoutManager.ts @@ -21,9 +21,18 @@ import Events from '../Events'; import RootedTreeSet from './RootedTreeSet'; import OriginalLayout from './OriginalLayout'; import ChangeEvent from './ChangeEvent'; +import SizeType from '../SizeType'; +import Node from './Node'; +import PositionType from '../PositionType'; class LayoutManager extends Events { - constructor(rootNodeId, rootSize) { + private _treeSet: RootedTreeSet; + + private _layout: OriginalLayout; + + private _events: ChangeEvent[]; + + constructor(rootNodeId: number, rootSize: SizeType) { super(); $assert($defined(rootNodeId), 'rootNodeId can not be null'); $assert(rootSize, 'rootSize can not be null'); @@ -36,40 +45,22 @@ class LayoutManager extends Events { this._events = []; } - /** - * @param id - * @param size - * @throws will throw an error if id is null or undefined - */ - updateNodeSize(id, size) { + updateNodeSize(id: number, size: SizeType): void { $assert($defined(id), 'id can not be null'); const node = this._treeSet.find(id); node.setSize(size); } - /** - * @param id - * @param value - * @throws will throw an error if id is null or undefined - * @throws will throw an error if value is null or undefined - * @return this - */ - updateShrinkState(id, value) { + updateShrinkState(id: number, value: boolean): void { $assert($defined(id), 'id can not be null'); $assert($defined(value), 'value can not be null'); const node = this._treeSet.find(id); node.setShrunken(value); - - return this; } - /** - * @param id - * @return {@link RootedTreeSet}.find(id) - */ - find(id) { + find(id: number): Node { return this._treeSet.find(id); } @@ -81,31 +72,17 @@ class LayoutManager extends Events { * @throws will throw an error if the position's x property is null or undefined * @throws will throw an error if the position's y property is null or undefined */ - moveNode(id, position) { + moveNode(id: number, position: PositionType) { $assert($defined(id), 'id cannot be null'); $assert($defined(position), 'position cannot be null'); $assert($defined(position.x), 'x can not be null'); $assert($defined(position.y), 'y can not be null'); const node = this._treeSet.find(id); - // @Todo: this should not be here. This is broking the isolated node support... - // node.setFree(true); - // node.setFreeDisplacement( - // {x:position.x - node.getPosition().x, y:position.y - node.getPosition().y} - // ); node.setPosition(position); } - /** - * @param parentId - * @param childId - * @param order - * @throws will throw an error if parentId is null or undefined - * @throws will throw an error if childId is null or undefined - * @throws will throw an error if order is null or undefined - * @return this - */ - connectNode(parentId, childId, order) { + connectNode(parentId: number, childId: number, order: number) { $assert($defined(parentId), 'parentId cannot be null'); $assert($defined(childId), 'childId cannot be null'); $assert($defined(order), 'order cannot be null'); @@ -115,16 +92,9 @@ class LayoutManager extends Events { return this; } - /** - * @param id - * @throws will throw an error if id is null or undefined - * @return this - */ - disconnectNode(id) { + disconnectNode(id: number): void { $assert($defined(id), 'id can not be null'); this._layout.disconnectNode(id); - - return this; } /** @@ -134,7 +104,7 @@ class LayoutManager extends Events { * @throws will throw an error if id is null or undefined * @return this */ - addNode(id, size, position) { + addNode(id: number, size: SizeType, position: PositionType) { $assert($defined(id), 'id can not be null'); const result = this._layout.createNode(id, size, position, 'topic'); this._treeSet.add(result); @@ -142,13 +112,7 @@ class LayoutManager extends Events { return this; } - /** - * removes a node and its connection to parent if existing - * @param id - * @throws will throw an error if id is null or undefined - * @return this - */ - removeNode(id) { + removeNode(id: number) { $assert($defined(id), 'id can not be null'); const node = this._treeSet.find(id); @@ -163,47 +127,31 @@ class LayoutManager extends Events { return this; } - /** - * @param {Number} parentId - * @param {Number=} nodeId - * @param {String=} position the position to use as mindplot.layout.Node.properties position - * property as '(x,y)' - * @param {Boolean=} free true specifies free node positioning - * @throws will throw an error if parentId is null or undefined - */ - predict(parentId, nodeId, position, free) { + predict(parentId: number, nodeId: number, position: PositionType): { order: number, position: PositionType } { $assert($defined(parentId), 'parentId can not be null'); const parent = this._treeSet.find(parentId); const node = nodeId ? this._treeSet.find(nodeId) : null; const sorter = parent.getSorter(); - const result = sorter.predict(this._treeSet, parent, node, position, free); + const result = sorter.predict(this._treeSet, parent, node, position); return { order: result[0], position: result[1] }; } - /** - * logs dump to console - */ dump() { console.log(this._treeSet.dump()); } - /** - * @param containerId - * @param {width:Number, height:Number} size - * @throws will throw an error if containerId is null or undefined - * @return canvas - */ - plot(containerId, size = { width: 200, height: 200 }) { + plot(containerId: string, size = { width: 200, height: 200 }) { // this method is only used from tests that include Raphael - if (!global.Raphael) { + + if (!globalThis.Raphael) { console.warn('Raphael.js not found, exiting plot()'); return null; } $assert(containerId, 'containerId cannot be null'); const squaresize = 10; - const canvas = global.Raphael(containerId, size.width, size.height); + const canvas = globalThis.Raphael(containerId, size.width, size.height); canvas.drawGrid( 0, 0, @@ -217,40 +165,33 @@ class LayoutManager extends Events { return canvas; } - /** - * initializes the layout to be updated - * @param fireEvents - * @return this - */ - layout(fireEvents) { + layout(flush: boolean): LayoutManager { // File repositioning ... this._layout.layout(); // Collect changes ... - this._collectChanges(); + this._collectChanges(this._treeSet.getTreeRoots()); - if ($(fireEvents).length > 0 || fireEvents) { + if (flush) { this._flushEvents(); } return this; } - _flushEvents() { + private _flushEvents() { this._events.forEach(((event) => { this.fireEvent('change', event); })); this._events = []; } - _collectChanges(nodes) { - const nodesToCollect = nodes || this._treeSet.getTreeRoots(); - - nodesToCollect.forEach(((node) => { + private _collectChanges(nodes: Node[]) { + nodes.forEach(((node) => { if (node.hasOrderChanged() || node.hasPositionChanged()) { // Find or create a event ... const id = node.getId(); - let event = this._events.some((e) => e.id === id); + let event: ChangeEvent = this._events.find((e) => e.getId() === id); if (!event) { event = new ChangeEvent(id); } diff --git a/packages/mindplot/src/components/layout/RootedTreeSet.ts b/packages/mindplot/src/components/layout/RootedTreeSet.ts index 8fb53fce..4637fe96 100644 --- a/packages/mindplot/src/components/layout/RootedTreeSet.ts +++ b/packages/mindplot/src/components/layout/RootedTreeSet.ts @@ -28,31 +28,20 @@ class RootedTreeSet { this._rootNodes = []; } - /** - * @param root - * @throws will throw an error if root is null or undefined - */ setRoot(root: Node) { $assert(root, 'root can not be null'); this._rootNodes.push(this._decodate(root)); } - /** getter */ - getTreeRoots() { + getTreeRoots(): Node[] { return this._rootNodes; } - _decodate(node: Node) { + _decodate(node: Node): Node { node._children = []; return node; } - /** - * @param {mindplot.model.NodeModel} node - * @throws will throw an error if node is null or undefined - * @throws will throw an error if node with id already exists - * @throws will throw an error if node has been added already - */ add(node: Node) { $assert(node, 'node can not be null'); if (this.find(node.getId(), false)) { diff --git a/packages/web2d/src/components/ElementClass.js b/packages/web2d/src/components/ElementClass.js index ca38d4af..7ff3dd97 100644 --- a/packages/web2d/src/components/ElementClass.js +++ b/packages/web2d/src/components/ElementClass.js @@ -161,12 +161,12 @@ class ElementClass { setStroke(width, style, color, opacity) { if ( style != null - && style !== undefined - && style !== 'dash' - && style !== 'dot' - && style !== 'solid' - && style !== 'longdash' - && style !== 'dashdot' + && style !== undefined + && style !== 'dash' + && style !== 'dot' + && style !== 'solid' + && style !== 'longdash' + && style !== 'dashdot' ) { throw new Error(`Unsupported stroke style: '${style}'`); } @@ -255,8 +255,8 @@ class ElementClass { this.peer.setFill(null, opacity); } - setVisibility(isVisible) { - this.peer.setVisibility(isVisible); + setVisibility(value, fade) { + this.peer.setVisibility(value, fade); } isVisible() { diff --git a/packages/web2d/src/components/peer/svg/ElementPeer.js b/packages/web2d/src/components/peer/svg/ElementPeer.js index e09f4058..77901330 100644 --- a/packages/web2d/src/components/peer/svg/ElementPeer.js +++ b/packages/web2d/src/components/peer/svg/ElementPeer.js @@ -181,11 +181,14 @@ class ElementPeer { } } - /* - * style='visibility: visible' - */ - setVisibility(isVisible) { - this._native.setAttribute('visibility', isVisible ? 'visible' : 'hidden'); + setVisibility(value, fade) { + this._native.setAttribute('visibility', value ? 'visible' : 'hidden'); + this._native.style.opacity = value ? 1 : 0; + if (fade) { + this._native.style.transition = `visibility ${fade}ms, opacity ${fade}ms`; + } else { + this._native.style.transition = null; + } } isVisible() { diff --git a/packages/web2d/test/playground/shapes.html b/packages/web2d/test/playground/shapes.html index c2708db0..2e5e5f09 100755 --- a/packages/web2d/test/playground/shapes.html +++ b/packages/web2d/test/playground/shapes.html @@ -66,7 +66,7 @@ - Visibility. + Visibility with CSS Transition
diff --git a/packages/web2d/test/playground/shapes.js b/packages/web2d/test/playground/shapes.js index 5b086e3c..8fbbe031 100644 --- a/packages/web2d/test/playground/shapes.js +++ b/packages/web2d/test/playground/shapes.js @@ -225,15 +225,14 @@ const visibilityTest = () => { rect.setPosition(120, 20); workspace.append(rect); rect.addEvent('mouseover', () => { - alert('Mouse Over'); + rect.setVisibility(false, 500); }); - let isVisible = true; - const executer = function () { - isVisible = !isVisible; - rect.setVisibility(isVisible); - }; - // executer.periodical(100); + rect.addEvent('mouseout', () => { + rect.setVisibility(true, 500); + }); + + // executer.periodical(100); workspace.addItAsChildTo($('#visibility')); }; visibilityTest();