Migrate layout classes Ts

This commit is contained in:
Paulo Gustavo Veiga 2023-02-10 19:07:21 -08:00
parent c0068b4fee
commit 036cf40f0c
8 changed files with 68 additions and 61 deletions

View File

@ -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(

View File

@ -1044,7 +1044,6 @@ abstract class Topic extends NodeGraph {
const connector = targetTopic.getShrinkConnector();
if (connector) {
connector.setVisibility(false);
targetTopic.setChildrenShrunken(true);
}
}

View File

@ -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<number, number> {
const result = new Map<number, number>();
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, number>,
): 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;

View File

@ -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;
}
}

View File

@ -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<number, number>;
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;

View File

@ -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;
}
/** */

View File

@ -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<number, number>): 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, number>): 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<number, number>): 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<number, number>): void {
const children = this._treeSet.getChildren(node);
if (node.isFree()) {
@ -206,7 +203,7 @@ class OriginalLayout {
});
}
_shiftBranches(node, heightById) {
_shiftBranches(node: Node, heightById: Map<number, number>): 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<number, number>): 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;

View File

@ -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;
}