fix: types of Hierarchical and Swimlane Layout #96

development
Anatoliy Mayorov 2022-10-08 21:43:35 +03:00
parent f84a4a5836
commit 1603729a9b
5 changed files with 115 additions and 85 deletions

View File

@ -15,6 +15,7 @@ limitations under the License.
*/ */
import { DIRECTION } from './util/Constants'; import { DIRECTION } from './util/Constants';
import Dictionary from './util/Dictionary';
import type Cell from './view/cell/Cell'; import type Cell from './view/cell/Cell';
import type CellState from './view/cell/CellState'; import type CellState from './view/cell/CellState';
import EventSource from './view/event/EventSource'; import EventSource from './view/event/EventSource';
@ -22,6 +23,7 @@ import type InternalMouseEvent from './view/event/InternalMouseEvent';
import type Shape from './view/geometry/Shape'; import type Shape from './view/geometry/Shape';
import type { Graph } from './view/Graph'; import type { Graph } from './view/Graph';
import type ImageBox from './view/image/ImageBox'; import type ImageBox from './view/image/ImageBox';
import GraphHierarchyNode from './view/layout/datatypes/GraphHierarchyNode';
export type CellMap = { export type CellMap = {
[id: string]: Cell; [id: string]: Cell;
@ -316,3 +318,26 @@ export interface PopupMenuItem extends HTMLElement {
activeRow: PopupMenuItem | null; activeRow: PopupMenuItem | null;
eventReceiver: HTMLElement | null; eventReceiver: HTMLElement | null;
} }
// GraphLayout
export interface GraphLayoutTraverseArgs {
vertex: Cell | null;
directed: boolean | null;
func: Function | null;
edge: Cell | null;
visited: Dictionary<Cell, boolean> | null;
}
export interface HierarchicalGraphLayoutTraverseArgs
extends GraphLayoutTraverseArgs{
allVertices: { [key: string]: Cell } | null,
currentComp: { [key: string]: Cell | null },
hierarchyVertices: GraphHierarchyNode[],
filledVertexSet: { [key: string]: Cell } | null
}
export interface SwimlaneGraphLayoutTraverseArgs
extends HierarchicalGraphLayoutTraverseArgs{
swimlaneIndex: number
}

View File

@ -22,6 +22,7 @@ import Geometry from '../geometry/Geometry';
import Point from '../geometry/Point'; import Point from '../geometry/Point';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import { GraphLayoutTraverseArgs } from '../../types';
/** /**
* @class GraphLayout * @class GraphLayout
@ -141,13 +142,7 @@ class GraphLayout {
* null for the first step of the traversal. * null for the first step of the traversal.
* @param visited Optional {@link Dictionary} of cell paths for the visited cells. * @param visited Optional {@link Dictionary} of cell paths for the visited cells.
*/ */
traverse( traverse({vertex, directed, func, edge, visited}: GraphLayoutTraverseArgs): void {
vertex: Cell,
directed?: boolean,
func?: Function,
edge?: Cell,
visited?: Dictionary<Cell, boolean>
): void {
if (func != null && vertex != null) { if (func != null && vertex != null) {
directed = directed != null ? directed : true; directed = directed != null ? directed : true;
visited = visited || new Dictionary(); visited = visited || new Dictionary();
@ -161,12 +156,18 @@ class GraphLayout {
if (edgeCount > 0) { if (edgeCount > 0) {
for (let i = 0; i < edgeCount; i += 1) { for (let i = 0; i < edgeCount; i += 1) {
const e = vertex.getEdgeAt(i); const e: Cell = vertex.getEdgeAt(i);
const isSource = e.getTerminal(true) === vertex; const isSource = e.getTerminal(true) === vertex;
if (!directed || isSource) { if (!directed || isSource) {
const next = this.graph.view.getVisibleTerminal(e, !isSource); const next = this.graph.view.getVisibleTerminal(e, !isSource);
this.traverse(<Cell>next, directed, func, e, visited); this.traverse({
vertex: next,
directed,
func,
edge: e,
visited
});
} }
} }
} }

View File

@ -27,7 +27,7 @@ import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingRe
import CoordinateAssignment from './hierarchical/CoordinateAssignment'; import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../../view/Graph'; import { Graph } from '../../view/Graph';
import Cell from '../../view/cell/Cell'; import Cell from '../../view/cell/Cell';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; import { HierarchicalGraphLayoutTraverseArgs } from '../../types';
/** /**
* A hierarchical layout algorithm. * A hierarchical layout algorithm.
@ -444,15 +444,17 @@ class HierarchicalLayout extends GraphLayout {
const vertexSet = Object(); const vertexSet = Object();
hierarchyVertices.push(vertexSet); hierarchyVertices.push(vertexSet);
this.traverse( this.traverse({
candidateRoots[i], vertex: candidateRoots[i],
true, directed: true,
null, edge: null,
allVertexSet, allVertices: allVertexSet,
vertexSet, currentComp: vertexSet,
hierarchyVertices, hierarchyVertices: hierarchyVertices,
filledVertexSet filledVertexSet: filledVertexSet,
); func: null,
visited: null
});
} }
for (let i = 0; i < candidateRoots.length; i += 1) { for (let i = 0; i < candidateRoots.length; i += 1) {
@ -477,15 +479,17 @@ class HierarchicalLayout extends GraphLayout {
const vertexSet = Object(); const vertexSet = Object();
hierarchyVertices.push(vertexSet); hierarchyVertices.push(vertexSet);
this.traverse( this.traverse({
roots[i], vertex: roots[i],
true, directed: true,
null, edge: null,
allVertexSet, allVertices: allVertexSet,
vertexSet, currentComp: vertexSet,
hierarchyVertices, hierarchyVertices: hierarchyVertices,
null filledVertexSet: null,
); func: null,
visited: null
});
} }
} }
@ -600,16 +604,14 @@ class HierarchicalLayout extends GraphLayout {
* null for the first step of the traversal. * null for the first step of the traversal.
* @param allVertices Array of cell paths for the visited cells. * @param allVertices Array of cell paths for the visited cells.
*/ */
// @ts-ignore traverse({
traverse( vertex,
vertex: Cell, directed,
directed: boolean = false, allVertices,
edge: Cell | null = null, currentComp,
allVertices: { [key: string]: Cell } | null = null, hierarchyVertices,
currentComp: { [key: string]: Cell | null }, filledVertexSet
hierarchyVertices: GraphHierarchyNode[], }: HierarchicalGraphLayoutTraverseArgs) {
filledVertexSet: { [key: string]: Cell } | null = null
) {
if (vertex != null && allVertices != null) { if (vertex != null && allVertices != null) {
// Has this vertex been seen before in any traversal // Has this vertex been seen before in any traversal
// And if the filled vertex set is populated, only // And if the filled vertex set is populated, only
@ -666,15 +668,17 @@ class HierarchicalLayout extends GraphLayout {
} }
if (netCount >= 0) { if (netCount >= 0) {
currentComp = this.traverse( currentComp = this.traverse({
<Cell>next, vertex: next,
directed, directed,
edges[i], edge: edges[i],
allVertices, allVertices,
currentComp, currentComp,
hierarchyVertices, hierarchyVertices,
filledVertexSet filledVertexSet,
); func: null,
visited: null
});
} }
} }
} }

View File

@ -29,7 +29,7 @@ import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import Geometry from '../../view/geometry/Geometry'; import Geometry from '../../view/geometry/Geometry';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; import { SwimlaneGraphLayoutTraverseArgs } from '../../types';
/** /**
* A hierarchical layout algorithm. * A hierarchical layout algorithm.
@ -579,16 +579,18 @@ class SwimlaneLayout extends GraphLayout {
const vertexSet = Object(); const vertexSet = Object();
hierarchyVertices.push(vertexSet); hierarchyVertices.push(vertexSet);
this.traverse( this.traverse({
candidateRoots[i], vertex: candidateRoots[i],
true, directed: true,
null, edge: null,
allVertexSet, allVertices: allVertexSet,
vertexSet, currentComp: vertexSet,
hierarchyVertices, hierarchyVertices,
filledVertexSet, filledVertexSet,
laneCounter swimlaneIndex: laneCounter,
); func: null,
visited: null
});
} }
for (let i = 0; i < candidateRoots.length; i += 1) { for (let i = 0; i < candidateRoots.length; i += 1) {
@ -612,16 +614,18 @@ class SwimlaneLayout extends GraphLayout {
for (let i = 0; i < roots.length; i += 1) { for (let i = 0; i < roots.length; i += 1) {
const vertexSet = Object(); const vertexSet = Object();
hierarchyVertices.push(vertexSet); hierarchyVertices.push(vertexSet);
this.traverse( this.traverse({
roots[i], vertex: roots[i],
true, directed: true,
null, edge: null,
allVertexSet, allVertices: allVertexSet,
vertexSet, currentComp: vertexSet,
hierarchyVertices, hierarchyVertices,
null, filledVertexSet: null,
i swimlaneIndex: i,
); // CHECK THIS PARAM!! ==================== func: null,
visited: null
}); // CHECK THIS PARAM!! ====================
} }
} }
@ -731,17 +735,15 @@ class SwimlaneLayout extends GraphLayout {
* @param allVertices Array of cell paths for the visited cells. * @param allVertices Array of cell paths for the visited cells.
* @param swimlaneIndex the laid out order index of the swimlane vertex is contained in * @param swimlaneIndex the laid out order index of the swimlane vertex is contained in
*/ */
// @ts-ignore traverse({
traverse( vertex,
vertex: Cell | null = null, directed,
directed: boolean, allVertices,
edge: Cell | null, currentComp,
allVertices: { [key: string]: Cell } | null = null, hierarchyVertices,
currentComp: { [key: string]: Cell }, filledVertexSet,
hierarchyVertices: GraphHierarchyNode[], swimlaneIndex
filledVertexSet: { [key: string]: Cell } | null = null, }: SwimlaneGraphLayoutTraverseArgs) {
swimlaneIndex: number
) {
if (vertex != null && allVertices != null) { if (vertex != null && allVertices != null) {
// Has this vertex been seen before in any traversal // Has this vertex been seen before in any traversal
// And if the filled vertex set is populated, only // And if the filled vertex set is populated, only
@ -764,7 +766,6 @@ class SwimlaneLayout extends GraphLayout {
} }
const edges = this.getEdges(vertex); const edges = this.getEdges(vertex);
const { model } = this.graph;
for (let i = 0; i < edges.length; i += 1) { for (let i = 0; i < edges.length; i += 1) {
let otherVertex = this.getVisibleTerminal(edges[i], true); let otherVertex = this.getVisibleTerminal(edges[i], true);
@ -775,16 +776,15 @@ class SwimlaneLayout extends GraphLayout {
} }
let otherIndex = 0; let otherIndex = 0;
const swimlanes = this.swimlanes as Cell[];
// Get the swimlane index of the other terminal // Get the swimlane index of the other terminal
for (otherIndex = 0; otherIndex < swimlanes.length; otherIndex++) { for (otherIndex = 0; otherIndex < this.swimlanes!.length; otherIndex++) {
if (swimlanes[otherIndex].isAncestor(otherVertex)) { if (this.swimlanes![otherIndex].isAncestor(otherVertex)) {
break; break;
} }
} }
if (otherIndex >= swimlanes.length) { if (otherIndex >= this.swimlanes!.length) {
continue; continue;
} }
@ -795,16 +795,18 @@ class SwimlaneLayout extends GraphLayout {
otherIndex > swimlaneIndex || otherIndex > swimlaneIndex ||
((!directed || isSource) && otherIndex === swimlaneIndex) ((!directed || isSource) && otherIndex === swimlaneIndex)
) { ) {
currentComp = this.traverse( currentComp = this.traverse({
<Cell>otherVertex, vertex: otherVertex,
directed, directed,
edges[i], edge: edges[i],
allVertices, allVertices,
currentComp, currentComp,
hierarchyVertices, hierarchyVertices,
filledVertexSet, filledVertexSet,
otherIndex swimlaneIndex: otherIndex,
); func: null,
visited: null
});
} }
} }
} else if (currentComp[vertexID] == null) { } else if (currentComp[vertexID] == null) {

View File

@ -13,9 +13,7 @@
"noEmit": true, "noEmit": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noImplicitReturns": true, "noImplicitReturns": true
// TODO required because some type definitions in the @maxgraph/core package generate errors: https://github.com/maxGraph/maxGraph/issues/96
"skipLibCheck": true
}, },
"include": ["src"] "include": ["src"]
} }