diff --git a/packages/mindplot/src/components/DragTopic.ts b/packages/mindplot/src/components/DragTopic.ts index f099f54b..32aee308 100644 --- a/packages/mindplot/src/components/DragTopic.ts +++ b/packages/mindplot/src/components/DragTopic.ts @@ -67,7 +67,7 @@ class DragTopic { const cy = Math.ceil(y - size.height / 2); this._elem2d.setPosition(cx, cy); - // In case is not free, pivot must be draw ... + // In case is not free, pivot must be drawn ... if (this.isConnected()) { const parent = this.getConnectedToTopic(); const predict = this._layoutManager.predict( diff --git a/packages/mindplot/src/components/Topic.ts b/packages/mindplot/src/components/Topic.ts index c790902c..5eef5d9c 100644 --- a/packages/mindplot/src/components/Topic.ts +++ b/packages/mindplot/src/components/Topic.ts @@ -1044,7 +1044,6 @@ abstract class Topic extends NodeGraph { const connector = targetTopic.getShrinkConnector(); if (connector) { connector.setVisibility(false); - targetTopic.setChildrenShrunken(true); } } diff --git a/packages/mindplot/src/components/layout/AbstractBasicSorter.ts b/packages/mindplot/src/components/layout/AbstractBasicSorter.ts index 8ccce86d..52a2116b 100644 --- a/packages/mindplot/src/components/layout/AbstractBasicSorter.ts +++ b/packages/mindplot/src/components/layout/AbstractBasicSorter.ts @@ -24,21 +24,25 @@ import RootedTreeSet from './RootedTreeSet'; abstract class AbstractBasicSorter extends ChildrenSorterStrategy { private INTERNODE_VERTICAL_PADDING = 5; - computeChildrenIdByHeights(treeSet: RootedTreeSet, node: Node) { - const result = {}; + computeChildrenIdByHeights(treeSet: RootedTreeSet, node: Node): Map { + const result = new Map(); this._computeChildrenHeight(treeSet, node, result); return result; } - protected _getVerticalPadding() { + getVerticalPadding(): number { return this.INTERNODE_VERTICAL_PADDING; } - protected _computeChildrenHeight(treeSet: RootedTreeSet, node: Node, heightCache?) { + _computeChildrenHeight( + treeSet: RootedTreeSet, + node: Node, + heightCache?: Map, + ): number { // 2* Top and down padding; - const height = node.getSize().height + this._getVerticalPadding() * 2; + const height = node.getSize().height + this.getVerticalPadding() * 2; - let result; + let result: number; const children = treeSet.getChildren(node); if (children.length === 0 || node.areChildrenShrunken()) { result = height; @@ -53,8 +57,7 @@ abstract class AbstractBasicSorter extends ChildrenSorterStrategy { } if (heightCache) { - // eslint-disable-next-line no-param-reassign - heightCache[node.getId()] = result; + heightCache.set(node.getId(), result); } return result; diff --git a/packages/mindplot/src/components/layout/BalancedSorter.ts b/packages/mindplot/src/components/layout/BalancedSorter.ts index f2ec375d..cf649ba0 100644 --- a/packages/mindplot/src/components/layout/BalancedSorter.ts +++ b/packages/mindplot/src/components/layout/BalancedSorter.ts @@ -233,13 +233,13 @@ class BalancedSorter extends AbstractBasicSorter { return 'Balanced Sorter'; } - protected _getChildrenForOrder(parent: Node, graph: RootedTreeSet, order: number): Node[] { + _getChildrenForOrder(parent: Node, graph: RootedTreeSet, order: number): Node[] { return this._getSortedChildren(graph, parent).filter( (child) => child.getOrder() % 2 === order % 2, ); } - protected _getVerticalPadding(): number { + getVerticalPadding(): number { return BalancedSorter.INTERNODE_VERTICAL_PADDING; } } diff --git a/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts b/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts index 3b0b852f..0806d30e 100644 --- a/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts +++ b/packages/mindplot/src/components/layout/ChildrenSorterStrategy.ts @@ -20,7 +20,7 @@ import Node from './Node'; import PositionType from '../PositionType'; abstract class ChildrenSorterStrategy { - abstract computeChildrenIdByHeights(treeSet: RootedTreeSet, node: Node): void; + abstract computeChildrenIdByHeights(treeSet: RootedTreeSet, node: Node): Map; abstract computeOffsets(treeSet: RootedTreeSet, node: Node): void; @@ -33,13 +33,15 @@ abstract class ChildrenSorterStrategy { parent: Node, node: Node | null, position: PositionType | null, - ); + ): void; abstract verify(treeSet: RootedTreeSet, node: Node): void; abstract getChildDirection(treeSet: RootedTreeSet, node: Node): 1 | -1; abstract toString(): string; + + abstract getVerticalPadding(): number; } export default ChildrenSorterStrategy; diff --git a/packages/mindplot/src/components/layout/Node.ts b/packages/mindplot/src/components/layout/Node.ts index c2f8c4ee..af05655d 100644 --- a/packages/mindplot/src/components/layout/Node.ts +++ b/packages/mindplot/src/components/layout/Node.ts @@ -33,6 +33,10 @@ class Node { // eslint-disable-next-line no-use-before-define _children!: Node[]; + _branchHeight: number; + + _heightChanged: boolean; + constructor(id: number, size: SizeType, position: PositionType, sorter: ChildrenSorterStrategy) { $assert(typeof id === 'number' && Number.isFinite(id), 'id can not be null'); this._id = id; @@ -42,6 +46,8 @@ class Node { this.setSize(size); this.setPosition(position); this.setShrunken(false); + this._branchHeight = -1; + this._heightChanged = false; } /** */ diff --git a/packages/mindplot/src/components/layout/OriginalLayout.js b/packages/mindplot/src/components/layout/OriginalLayout.ts similarity index 77% rename from packages/mindplot/src/components/layout/OriginalLayout.js rename to packages/mindplot/src/components/layout/OriginalLayout.ts index 61df0be7..4c492cc7 100644 --- a/packages/mindplot/src/components/layout/OriginalLayout.js +++ b/packages/mindplot/src/components/layout/OriginalLayout.ts @@ -19,27 +19,26 @@ import { $assert, $defined } from '@wisemapping/core-js'; import Node from './Node'; import SymmetricSorter from './SymmetricSorter'; import BalancedSorter from './BalancedSorter'; +import RootedTreeSet from './RootedTreeSet'; +import SizeType from '../SizeType'; +import PositionType from '../PositionType'; +import ChildrenSorterStrategy from './ChildrenSorterStrategy'; class OriginalLayout { - constructor(treeSet) { + private _treeSet: RootedTreeSet; + + constructor(treeSet: RootedTreeSet) { this._treeSet = treeSet; } - /** */ - // eslint-disable-next-line class-methods-use-this - createNode(id, size, position, type) { + createNode(id: number, size: SizeType, position: PositionType, type: string): Node { $assert($defined(id), 'id can not be null'); - $assert(size, 'size can not be null'); - $assert(position, 'position can not be null'); - $assert(type, 'type can not be null'); - - const strategy = + const strategy: ChildrenSorterStrategy = type === 'root' ? OriginalLayout.BALANCED_SORTER : OriginalLayout.SYMMETRIC_SORTER; return new Node(id, size, position, strategy); } - /** */ - connectNode(parentId, childId, order) { + connectNode(parentId: number, childId: number, order: number): void { const parent = this._treeSet.find(parentId); const child = this._treeSet.find(childId); @@ -54,11 +53,12 @@ class OriginalLayout { sorter.verify(this._treeSet, parent); } - /** */ - disconnectNode(nodeId) { + disconnectNode(nodeId: number): void { const node = this._treeSet.find(nodeId); const parent = this._treeSet.getParent(node); - $assert(parent, 'Node already disconnected'); + if (!parent) { + throw new Error('Node already disconnected'); + } // Make it fixed node.setFree(false); @@ -75,21 +75,18 @@ class OriginalLayout { parent.getSorter().verify(this._treeSet, parent); } - /** */ - layout() { + layout(): void { const roots = this._treeSet.getTreeRoots(); roots.forEach((node) => { // Calculate all node heights ... const sorter = node.getSorter(); - const heightById = sorter.computeChildrenIdByHeights(this._treeSet, node); this._layoutChildren(node, heightById); - this._fixOverlapping(node, heightById); }); } - _layoutChildren(node, heightById) { + private _layoutChildren(node: Node, heightById: Map): void { const nodeId = node.getId(); const children = this._treeSet.getChildren(node); const parent = this._treeSet.getParent(node); @@ -98,9 +95,9 @@ class OriginalLayout { // If ether any of the nodes has been changed of position or the height of the children is not // the same, children nodes must be repositioned .... - const newBranchHeight = heightById[nodeId]; + const newBranchHeight = heightById.get(nodeId)!; - const parentHeightChanged = $defined(parent) ? parent._heightChanged : false; + const parentHeightChanged = parent ? parent._heightChanged : false; const heightChanged = node._branchHeight !== newBranchHeight; // eslint-disable-next-line no-param-reassign node._heightChanged = heightChanged || parentHeightChanged; @@ -141,7 +138,6 @@ class OriginalLayout { me._treeSet.updateBranchPosition(child, newPos); }); - // eslint-disable-next-line no-param-reassign node._branchHeight = newBranchHeight; } @@ -151,7 +147,7 @@ class OriginalLayout { }); } - _calculateAlignOffset(node, child, heightById) { + private _calculateAlignOffset(node: Node, child: Node, heightById: Map): number { if (child.isFree()) { return 0; } @@ -167,8 +163,8 @@ class OriginalLayout { ) { if (this._treeSet.hasSinglePathToSingleLeaf(child)) { offset = - heightById[child.getId()] / 2 - - (childHeight + child.getSorter()._getVerticalPadding() * 2) / 2; + heightById.get(child.getId())! / 2 - + (childHeight + child.getSorter().getVerticalPadding() * 2) / 2; } else { offset = this._treeSet.isLeaf(child) ? 0 : -(childHeight - nodeHeight) / 2; } @@ -189,13 +185,14 @@ class OriginalLayout { return offset; } - static _branchIsTaller(node, heightById) { + static _branchIsTaller(node: Node, heightById: Map): boolean { return ( - heightById[node.getId()] > node.getSize().height + node.getSorter()._getVerticalPadding() * 2 + heightById.get(node.getId())! > + node.getSize().height + node.getSorter().getVerticalPadding() * 2 ); } - _fixOverlapping(node, heightById) { + private _fixOverlapping(node: Node, heightById: Map): void { const children = this._treeSet.getChildren(node); if (node.isFree()) { @@ -206,7 +203,7 @@ class OriginalLayout { }); } - _shiftBranches(node, heightById) { + _shiftBranches(node: Node, heightById: Map): void { const shiftedBranches = [node]; const siblingsToShift = this._treeSet.getSiblingsInVerticalDirection( @@ -238,28 +235,22 @@ class OriginalLayout { }); } - static _branchesOverlap(branchA, branchB, heightById) { + static _branchesOverlap(branchA: Node, branchB: Node, heightById: Map): boolean { // a branch doesn't really overlap with itself if (branchA === branchB) { return false; } - const topA = branchA.getPosition().y - heightById[branchA.getId()] / 2; - const bottomA = branchA.getPosition().y + heightById[branchA.getId()] / 2; - const topB = branchB.getPosition().y - heightById[branchB.getId()] / 2; - const bottomB = branchB.getPosition().y + heightById[branchB.getId()] / 2; + const topA = branchA.getPosition().y - heightById.get(branchA.getId())! / 2; + const bottomA = branchA.getPosition().y + heightById.get(branchA.getId())! / 2; + const topB = branchB.getPosition().y - heightById.get(branchB.getId())! / 2; + const bottomB = branchB.getPosition().y + heightById.get(branchB.getId())! / 2; return !(topA >= bottomB || bottomA <= topB); } + + static SYMMETRIC_SORTER: ChildrenSorterStrategy = new SymmetricSorter(); + + static BALANCED_SORTER: ChildrenSorterStrategy = new BalancedSorter(); } - -/** - * @type {mindplot.layout.SymmetricSorter} - */ -OriginalLayout.SYMMETRIC_SORTER = new SymmetricSorter(); -/** - * @type {mindplot.layout.BalancedSorter} - */ -OriginalLayout.BALANCED_SORTER = new BalancedSorter(); - export default OriginalLayout; diff --git a/packages/mindplot/src/components/layout/SymmetricSorter.ts b/packages/mindplot/src/components/layout/SymmetricSorter.ts index d6b03941..8473bcc7 100644 --- a/packages/mindplot/src/components/layout/SymmetricSorter.ts +++ b/packages/mindplot/src/components/layout/SymmetricSorter.ts @@ -25,7 +25,13 @@ class SymmetricSorter extends AbstractBasicSorter { /** * Predict the order and position of a dragged node. */ - predict(graph: RootedTreeSet, parent: Node, node: Node, position: PositionType, free?: boolean) { + predict( + graph: RootedTreeSet, + parent: Node, + node: Node, + position: PositionType, + free?: boolean, + ): [number, PositionType] { const self = this; const rootNode = graph.getRootNode(parent); @@ -97,7 +103,7 @@ class SymmetricSorter extends AbstractBasicSorter { const last = parentChildren[parentChildren.length - 1]; for (let i = 0; i < parentChildren.length; i++) { const parentChild = parentChildren[i]; - const nodeAfter = i + 1 === parentChildren.length ? null : parentChildren[i + 1]; + const nodeAfter = parentChildren[i + 1]; // Fit at the bottom if (!nodeAfter && position.y > parentChild.getPosition().y) { @@ -291,7 +297,7 @@ class SymmetricSorter extends AbstractBasicSorter { return 'Symmetric Sorter'; } - protected _getVerticalPadding() { + getVerticalPadding() { return SymmetricSorter.INTERNODE_VERTICAL_PADDING; }