mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-22 06:37:56 +01:00
Migrate layout classes Ts
This commit is contained in:
parent
c0068b4fee
commit
036cf40f0c
@ -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(
|
||||
|
@ -1044,7 +1044,6 @@ abstract class Topic extends NodeGraph {
|
||||
const connector = targetTopic.getShrinkConnector();
|
||||
if (connector) {
|
||||
connector.setVisibility(false);
|
||||
targetTopic.setChildrenShrunken(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/** */
|
||||
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user