various bugfixes

development
mcyph 2021-03-22 17:41:22 +11:00
parent 371cd0c8be
commit 697353449a
19 changed files with 238 additions and 196 deletions

View File

@ -8,6 +8,7 @@ import mxClient from '../mxClient';
import mxToolbar from '../util/mxToolbar'; import mxToolbar from '../util/mxToolbar';
import mxGeometry from '../model/mxGeometry'; import mxGeometry from '../model/mxGeometry';
import mxUtils from '../util/mxUtils'; import mxUtils from '../util/mxUtils';
import mxEvent from "../util/mxEvent";
class mxDefaultToolbar { class mxDefaultToolbar {
/** /**

View File

@ -3,6 +3,8 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphAbstractHierarchyCell from "./mxGraphAbstractHierarchyCell";
import mxObjectIdentity from "../../../util/mxObjectIdentity";
class mxGraphHierarchyEdge extends mxGraphAbstractHierarchyCell { class mxGraphHierarchyEdge extends mxGraphAbstractHierarchyCell {
/** /**

View File

@ -4,7 +4,7 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxDictionary from 'FIXME'; import mxDictionary from "../../../util/mxDictionary";
class mxGraphHierarchyModel { class mxGraphHierarchyModel {
/** /**

View File

@ -3,6 +3,8 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphAbstractHierarchyCell from "./mxGraphAbstractHierarchyCell";
import mxObjectIdentity from "../../../util/mxObjectIdentity";
class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell { class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell {
/** /**
@ -84,7 +86,7 @@ class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell {
for (let i = 0; i < this.connectsAsTarget.length; i += 1) { for (let i = 0; i < this.connectsAsTarget.length; i += 1) {
const edge = this.connectsAsTarget[i]; const edge = this.connectsAsTarget[i];
if (edge.maxRank == -1 || edge.maxRank == layer + 1) { if (edge.maxRank === -1 || edge.maxRank === layer + 1) {
// Either edge is not in any rank or // Either edge is not in any rank or
// no dummy nodes in edge, add node of other side of edge // no dummy nodes in edge, add node of other side of edge
this.nextLayerConnectedCells[0].push(edge.source); this.nextLayerConnectedCells[0].push(edge.source);
@ -111,7 +113,7 @@ class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell {
for (let i = 0; i < this.connectsAsSource.length; i += 1) { for (let i = 0; i < this.connectsAsSource.length; i += 1) {
const edge = this.connectsAsSource[i]; const edge = this.connectsAsSource[i];
if (edge.minRank == -1 || edge.minRank == layer - 1) { if (edge.minRank === -1 || edge.minRank === layer - 1) {
// No dummy nodes in edge, add node of other side of edge // No dummy nodes in edge, add node of other side of edge
this.previousLayerConnectedCells[0].push(edge.target); this.previousLayerConnectedCells[0].push(edge.target);
} else { } else {
@ -163,7 +165,7 @@ class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell {
otherNode.hashCode != null && otherNode.hashCode != null &&
this.hashCode.length < otherNode.hashCode.length this.hashCode.length < otherNode.hashCode.length
) { ) {
if (this.hashCode == otherNode.hashCode) { if (this.hashCode === otherNode.hashCode) {
return true; return true;
} }
@ -176,7 +178,7 @@ class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell {
// the arrays are different length, and we do not want to // the arrays are different length, and we do not want to
// perform another array copy. // perform another array copy.
for (let i = 0; i < this.hashCode.length; i += 1) { for (let i = 0; i < this.hashCode.length; i += 1) {
if (this.hashCode[i] != otherNode.hashCode[i]) { if (this.hashCode[i] !== otherNode.hashCode[i]) {
return false; return false;
} }
} }

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2018, Gaudenz Alder * Copyright (c) 2006-2018, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxUtils from "../../../util/mxUtils";
import mxGraphHierarchyNode from "./mxGraphHierarchyNode";
import mxGraphHierarchyEdge from "./mxGraphHierarchyEdge";
import mxCellPath from "../../../model/mxCellPath";
class mxSwimlaneModel { class mxSwimlaneModel {
/** /**
@ -152,7 +156,7 @@ class mxSwimlaneModel {
if ( if (
internalTargetCell != null && internalTargetCell != null &&
internalVertices[i] != internalTargetCell internalVertices[i] !== internalTargetCell
) { ) {
internalEdge.target = internalTargetCell; internalEdge.target = internalTargetCell;
@ -201,8 +205,8 @@ class mxSwimlaneModel {
this.vertexMapper.put(vertices[i], internalVertices[i]); this.vertexMapper.put(vertices[i], internalVertices[i]);
internalVertices[i].swimlaneIndex = -1; internalVertices[i].swimlaneIndex = -1;
for (let ii = 0; ii < swimlanes.length; ii++) { for (let ii = 0; ii < swimlanes.length; ii += 1) {
if (graph.model.getParent(vertices[i]) == swimlanes[ii]) { if (graph.model.getParent(vertices[i]) === swimlanes[ii]) {
internalVertices[i].swimlaneIndex = ii; internalVertices[i].swimlaneIndex = ii;
break; break;
} }
@ -216,12 +220,12 @@ class mxSwimlaneModel {
// Create internal edges, but don't do any rank assignment yet // Create internal edges, but don't do any rank assignment yet
// First use the information from the greedy cycle remover to // First use the information from the greedy cycle remover to
// invert the leftward edges internally // invert the leftward edges internally
for (let j = 0; j < conns.length; j++) { for (let j = 0; j < conns.length; j += 1) {
const cell = layout.getVisibleTerminal(conns[j], false); const cell = layout.getVisibleTerminal(conns[j], false);
// Looking for outgoing edges only // Looking for outgoing edges only
if ( if (
cell != vertices[i] && cell !== vertices[i] &&
layout.graph.model.isVertex(cell) && layout.graph.model.isVertex(cell) &&
!layout.isVertexIgnored(cell) !layout.isVertexIgnored(cell)
) { ) {
@ -253,7 +257,7 @@ class mxSwimlaneModel {
) { ) {
const internalEdge = new mxGraphHierarchyEdge(undirectedEdges); const internalEdge = new mxGraphHierarchyEdge(undirectedEdges);
for (let k = 0; k < undirectedEdges.length; k++) { for (let k = 0; k < undirectedEdges.length; k += 1) {
const edge = undirectedEdges[k]; const edge = undirectedEdges[k];
this.edgeMapper.put(edge, internalEdge); this.edgeMapper.put(edge, internalEdge);
@ -315,7 +319,7 @@ class mxSwimlaneModel {
const upperRank = []; const upperRank = [];
for (let i = this.ranksPerGroup.length - 1; i >= 0; i--) { for (let i = this.ranksPerGroup.length - 1; i >= 0; i--) {
if (i == this.ranksPerGroup.length - 1) { if (i === this.ranksPerGroup.length - 1) {
lowerRank[i] = 0; lowerRank[i] = 0;
} else { } else {
lowerRank[i] = upperRank[i + 1] + 1; lowerRank[i] = upperRank[i + 1] + 1;
@ -355,7 +359,7 @@ class mxSwimlaneModel {
for (let i = 0; i < layerDeterminingEdges.length; i += 1) { for (let i = 0; i < layerDeterminingEdges.length; i += 1) {
const internalEdge = layerDeterminingEdges[i]; const internalEdge = layerDeterminingEdges[i];
if (internalEdge.temp[0] == 5270620) { if (internalEdge.temp[0] === 5270620) {
// This edge has been scanned, get the layer of the // This edge has been scanned, get the layer of the
// node on the other end // node on the other end
const otherNode = internalEdge.source; const otherNode = internalEdge.source;
@ -388,7 +392,7 @@ class mxSwimlaneModel {
const otherNode = internalEdge.target; const otherNode = internalEdge.target;
// Only add node if it hasn't been assigned a layer // Only add node if it hasn't been assigned a layer
if (otherNode.temp[0] == -1) { if (otherNode.temp[0] === -1) {
startNodes.push(otherNode); startNodes.push(otherNode);
// Mark this other node as neither being // Mark this other node as neither being
@ -407,7 +411,7 @@ class mxSwimlaneModel {
const removedCell = startNodes.shift(); const removedCell = startNodes.shift();
startNodes.push(internalNode); startNodes.push(internalNode);
if (removedCell == internalNode && startNodes.length == 1) { if (removedCell === internalNode && startNodes.length === 1) {
// This is an error condition, we can't get out of // This is an error condition, we can't get out of
// this loop. It could happen for more than one node // this loop. It could happen for more than one node
// but that's a lot harder to detect. Log the error // but that's a lot harder to detect. Log the error
@ -495,7 +499,7 @@ class mxSwimlaneModel {
mxUtils.clone(seen, null, true), mxUtils.clone(seen, null, true),
0 0
); );
} else if (root.swimlaneIndex == targetNode.swimlaneIndex) { } else if (root.swimlaneIndex === targetNode.swimlaneIndex) {
this.maxChainDfs( this.maxChainDfs(
root, root,
targetNode, targetNode,
@ -542,7 +546,7 @@ class mxSwimlaneModel {
this.visit( this.visit(
(parent, node, edge, layer, seen) => { (parent, node, edge, layer, seen) => {
if (seen == 0 && node.maxRank < 0 && node.minRank < 0) { if (seen === 0 && node.maxRank < 0 && node.minRank < 0) {
rankList[node.temp[0]].push(node); rankList[node.temp[0]].push(node);
node.maxRank = node.temp[0]; node.maxRank = node.temp[0];
node.minRank = node.temp[0]; node.minRank = node.temp[0];
@ -620,7 +624,7 @@ class mxSwimlaneModel {
} }
} }
this.dfsCount++; this.dfsCount += 1;
} }
}; };
@ -723,7 +727,7 @@ class mxSwimlaneModel {
// start of the parent hash code does not equal the start of // start of the parent hash code does not equal the start of
// this nodes hash code, indicating the code was set on a // this nodes hash code, indicating the code was set on a
// previous run of this dfs. // previous run of this dfs.
if (root.hashCode == null || root.hashCode[0] != parent.hashCode[0]) { if (root.hashCode == null || root.hashCode[0] !== parent.hashCode[0]) {
const hashCodeLength = parent.hashCode.length + 1; const hashCodeLength = parent.hashCode.length + 1;
root.hashCode = parent.hashCode.slice(); root.hashCode = parent.hashCode.slice();
root.hashCode[hashCodeLength - 1] = childHash; root.hashCode[hashCodeLength - 1] = childHash;

View File

@ -3,6 +3,15 @@
* Copyright (c) 2006-2018, Gaudenz Alder * Copyright (c) 2006-2018, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphLayout from "../mxGraphLayout";
import mxConstants from "../../util/mxConstants";
import mxHierarchicalEdgeStyle from "./mxHierarchicalEdgeStyle";
import mxDictionary from "../../util/mxDictionary";
import mxGraphHierarchyModel from "./model/mxGraphHierarchyModel";
import mxObjectIdentity from "../../util/mxObjectIdentity";
import mxMinimumCycleRemover from "./stage/mxMinimumCycleRemover";
import mxMedianHybridCrossingReduction from "./stage/mxMedianHybridCrossingReduction";
import mxCoordinateAssignment from "./stage/mxCoordinateAssignment";
class mxHierarchicalLayout extends mxGraphLayout { class mxHierarchicalLayout extends mxGraphLayout {
/** /**
@ -224,7 +233,7 @@ class mxHierarchicalLayout extends mxGraphLayout {
this.parentY = null; this.parentY = null;
if ( if (
parent != this.root && parent !== this.root &&
model.isVertex(parent) != null && model.isVertex(parent) != null &&
this.maintainParentLocation this.maintainParentLocation
) { ) {

View File

@ -4,6 +4,17 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphLayout from "../mxGraphLayout";
import mxConstants from "../../util/mxConstants";
import mxHierarchicalEdgeStyle from "./mxHierarchicalEdgeStyle";
import mxDictionary from "../../util/mxDictionary";
import mxRectangle from "../../util/mxRectangle";
import mxSwimlaneModel from "./model/mxSwimlaneModel";
import mxObjectIdentity from "../../util/mxObjectIdentity";
import mxSwimlaneOrdering from "./stage/mxSwimlaneOrdering";
import mxMedianHybridCrossingReduction from "./stage/mxMedianHybridCrossingReduction";
import mxCoordinateAssignment from "./stage/mxCoordinateAssignment";
class mxSwimlaneLayout extends mxGraphLayout { class mxSwimlaneLayout extends mxGraphLayout {
/** /**
* Variable: roots * Variable: roots
@ -237,7 +248,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
this.parentY = null; this.parentY = null;
if ( if (
parent != this.root && parent !== this.root &&
model.isVertex(parent) != null && model.isVertex(parent) != null &&
this.maintainParentLocation this.maintainParentLocation
) { ) {
@ -256,7 +267,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
for (let i = 0; i < swimlanes.length; i += 1) { for (let i = 0; i < swimlanes.length; i += 1) {
const children = this.graph.getChildCells(swimlanes[i]); const children = this.graph.getChildCells(swimlanes[i]);
if (children == null || children.length == 0) { if (children == null || children.length === 0) {
const vertex = this.graph.insertVertex( const vertex = this.graph.insertVertex(
swimlanes[i], swimlanes[i],
null, null,
@ -371,7 +382,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
const newGeo = geo.clone(); const newGeo = geo.clone();
const leftGroupBorder = const leftGroupBorder =
i == 0 ? this.parentBorder : this.interRankCellSpacing / 2; i === 0 ? this.parentBorder : this.interRankCellSpacing / 2;
const w = size.width + leftGroupBorder; const w = size.width + leftGroupBorder;
const x = childBounds[i].x - w; const x = childBounds[i].x - w;
const y = layoutBounds.y - this.parentBorder; const y = layoutBounds.y - this.parentBorder;
@ -427,19 +438,19 @@ class mxSwimlaneLayout extends mxGraphLayout {
for (let k = 0; k < conns.length; k++) { for (let k = 0; k < conns.length; k++) {
const src = this.getVisibleTerminal(conns[k], true); const src = this.getVisibleTerminal(conns[k], true);
if (src == cell) { if (src === cell) {
// Only count connection within this swimlane // Only count connection within this swimlane
const other = this.getVisibleTerminal(conns[k], false); const other = this.getVisibleTerminal(conns[k], false);
if (model.isAncestor(parent, other)) { if (model.isAncestor(parent, other)) {
fanOut++; fanOut += 1;
} }
} else if (model.isAncestor(parent, src)) { } else if (model.isAncestor(parent, src)) {
fanIn++; fanIn += 1;
} }
} }
if (fanIn == 0 && fanOut > 0) { if (fanIn === 0 && fanOut > 0) {
roots.push(cell); roots.push(cell);
} }
@ -452,7 +463,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
} }
} }
if (roots.length == 0 && best != null) { if (roots.length === 0 && best != null) {
roots.push(best); roots.push(best);
} }
} }
@ -499,16 +510,16 @@ class mxSwimlaneLayout extends mxGraphLayout {
const target = this.getVisibleTerminal(edges[i], false); const target = this.getVisibleTerminal(edges[i], false);
if ( if (
source == target || source === target ||
(source != target && (source !== target &&
((target == cell && ((target === cell &&
(this.parent == null || (this.parent == null ||
this.graph.isValidAncestor( this.graph.isValidAncestor(
source, source,
this.parent, this.parent,
this.traverseAncestors this.traverseAncestors
))) || ))) ||
(source == cell && (source === cell &&
(this.parent == null || (this.parent == null ||
this.graph.isValidAncestor( this.graph.isValidAncestor(
target, target,
@ -613,7 +624,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
filledVertexSet filledVertexSet
); );
if (candidateRoots.length == 0) { if (candidateRoots.length === 0) {
laneCounter++; laneCounter++;
continue; continue;
} }
@ -701,8 +712,8 @@ class mxSwimlaneLayout extends mxGraphLayout {
if ( if (
model.isVertex(cell) && model.isVertex(cell) &&
cell != this.parent && cell !== this.parent &&
model.getParent(cell) != this.parent && model.getParent(cell) !== this.parent &&
this.graph.isCellVisible(cell) this.graph.isCellVisible(cell)
) { ) {
result[mxObjectIdentity.get(cell)] = cell; result[mxObjectIdentity.get(cell)] = cell;
@ -710,7 +721,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
if ( if (
this.traverseAncestors || this.traverseAncestors ||
(cell == this.parent && this.graph.isCellVisible(cell)) (cell === this.parent && this.graph.isCellVisible(cell))
) { ) {
const childCount = model.getChildCount(cell); const childCount = model.getChildCount(cell);
@ -768,8 +779,8 @@ class mxSwimlaneLayout extends mxGraphLayout {
const trg = this.getVisibleTerminal(edges[i], false); const trg = this.getVisibleTerminal(edges[i], false);
if ( if (
(src == source && trg == target) || (src === source && trg === target) ||
(!directed && src == target && trg == source) (!directed && src === target && trg === source)
) { ) {
result.push(edges[i]); result.push(edges[i]);
} }
@ -831,7 +842,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
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);
const isSource = otherVertex == vertex; const isSource = otherVertex === vertex;
if (isSource) { if (isSource) {
otherVertex = this.getVisibleTerminal(edges[i], false); otherVertex = this.getVisibleTerminal(edges[i], false);
@ -858,7 +869,7 @@ class mxSwimlaneLayout extends mxGraphLayout {
// vertex is greater than that of this vertex // vertex is greater than that of this vertex
if ( if (
otherIndex > swimlaneIndex || otherIndex > swimlaneIndex ||
((!directed || isSource) && otherIndex == swimlaneIndex) ((!directed || isSource) && otherIndex === swimlaneIndex)
) { ) {
currentComp = this.traverse( currentComp = this.traverse(
otherVertex, otherVertex,

View File

@ -0,0 +1,25 @@
class MedianCellSorter {
constructor() {
// empty
}
/**
* Function: compare
*
* Compares two MedianCellSorters.
*/
compare = (a, b) => {
if (a != null && b != null) {
if (b.medianValue > a.medianValue) {
return -1;
}
if (b.medianValue < a.medianValue) {
return 1;
}
return 0;
}
return 0;
};
}
export default MedianCellSorter;

View File

@ -4,6 +4,12 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage'; import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage';
import mxConstants from "../../../util/mxConstants";
import mxLog from "../../../util/mxLog";
import WeightedCellSorter from "../../WeightedCellSorter";
import mxDictionary from "../../../util/mxDictionary";
import mxPoint from "../../../util/mxPoint";
import mxHierarchicalEdgeStyle from "../mxHierarchicalEdgeStyle";
class mxCoordinateAssignment extends mxHierarchicalLayoutStage { class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
/** /**
@ -269,7 +275,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// this.printStatus(); // this.printStatus();
// Median Heuristic // Median Heuristic
if (i != 0) { if (i !== 0) {
this.medianPos(i, model); this.medianPos(i, model);
this.minNode(model); this.minNode(model);
} }
@ -325,7 +331,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
for (let i = 0; i <= model.maxRank; i += 1) { for (let i = 0; i <= model.maxRank; i += 1) {
rank[i] = model.ranks[i]; rank[i] = model.ranks[i];
for (let j = 0; j < rank[i].length; j++) { for (let j = 0; j < rank[i].length; j += 1) {
// Use the weight to store the rank and visited to store whether // Use the weight to store the rank and visited to store whether
// or not the cell is in the list // or not the cell is in the list
const node = rank[i][j]; const node = rank[i][j];
@ -388,7 +394,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
let positionChanged = false; let positionChanged = false;
if (cellMedian < currentPosition - tolerance) { if (cellMedian < currentPosition - tolerance) {
if (rankIndex == 0) { if (rankIndex === 0) {
cell.setGeneralPurposeVariable(rankValue, cellMedian); cell.setGeneralPurposeVariable(rankValue, cellMedian);
positionChanged = true; positionChanged = true;
} else { } else {
@ -414,7 +420,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
} else if (cellMedian > currentPosition + tolerance) { } else if (cellMedian > currentPosition + tolerance) {
const rankSize = rank[rankValue].length; const rankSize = rank[rankValue].length;
if (rankIndex == rankSize - 1) { if (rankIndex === rankSize - 1) {
cell.setGeneralPurposeVariable(rankValue, cellMedian); cell.setGeneralPurposeVariable(rankValue, cellMedian);
positionChanged = true; positionChanged = true;
} else { } else {
@ -468,7 +474,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
} }
cellWrapper.visited = false; cellWrapper.visited = false;
count++; count += 1;
} }
}; };
@ -484,7 +490,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
*/ */
medianPos = (i, model) => { medianPos = (i, model) => {
// Reverse sweep direction each time through this method // Reverse sweep direction each time through this method
const downwardSweep = i % 2 == 0; const downwardSweep = i % 2 === 0;
if (downwardSweep) { if (downwardSweep) {
for (let j = model.maxRank; j > 0; j--) { for (let j = model.maxRank; j > 0; j--) {
@ -544,7 +550,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
); );
} }
weightedValues.sort(compare); weightedValues.sort(new WeightedCellSorter().compare);
// Set the new position of each node within the rank using // Set the new position of each node within the rank using
// its temp variable // its temp variable
@ -675,7 +681,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
const cell = collection[i]; const cell = collection[i];
if (currentCell.isVertex() && cell.isVertex()) { if (currentCell.isVertex() && cell.isVertex()) {
totalWeight++; totalWeight += 1;
} else if (currentCell.isEdge() && cell.isEdge()) { } else if (currentCell.isEdge() && cell.isEdge()) {
totalWeight += 8; totalWeight += 8;
} else { } else {
@ -698,7 +704,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
* rankValue - the layer number of this rank * rankValue - the layer number of this rank
*/ */
medianXValue = (connectedCells, rankValue) => { medianXValue = (connectedCells, rankValue) => {
if (connectedCells.length == 0) { if (connectedCells.length === 0) {
return 0; return 0;
} }
@ -712,7 +718,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
return a - b; return a - b;
}); });
if (connectedCells.length % 2 == 1) { if (connectedCells.length % 2 === 1) {
// For odd numbers of adjacent vertices return the median // For odd numbers of adjacent vertices return the median
return medianValues[Math.floor(connectedCells.length / 2)]; return medianValues[Math.floor(connectedCells.length / 2)];
} }
@ -784,8 +790,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
if (bounds != null) { if (bounds != null) {
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_SOUTH this.orientation === mxConstants.DIRECTION_SOUTH
) { ) {
node.width = bounds.width; node.width = bounds.width;
node.height = bounds.height; node.height = bounds.height;
@ -846,7 +852,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
this.rankWidths = []; this.rankWidths = [];
this.rankY = []; this.rankY = [];
for (let rankValue = model.maxRank; rankValue >= 0; rankValue--) { for (let rankValue = model.maxRank; rankValue >= 0; rankValue -= 1) {
// Keep track of the widest cell on this rank // Keep track of the widest cell on this rank
let maxCellHeight = 0.0; let maxCellHeight = 0.0;
const rank = model.ranks[rankValue]; const rank = model.ranks[rankValue];
@ -864,8 +870,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
if (bounds != null) { if (bounds != null) {
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_SOUTH this.orientation === mxConstants.DIRECTION_SOUTH
) { ) {
node.width = bounds.width; node.width = bounds.width;
node.height = bounds.height; node.height = bounds.height;
@ -919,8 +925,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
lastRankMaxCellHeight = maxCellHeight; lastRankMaxCellHeight = maxCellHeight;
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_WEST this.orientation === mxConstants.DIRECTION_WEST
) { ) {
y += distanceToNextRank; y += distanceToNextRank;
} else { } else {
@ -970,11 +976,11 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
for (let i = cell.minRank + 2; i < cell.maxRank; i += 1) { for (let i = cell.minRank + 2; i < cell.maxRank; i += 1) {
const x = cell.getGeneralPurposeVariable(i); const x = cell.getGeneralPurposeVariable(i);
if (referenceX != x) { if (referenceX !== x) {
edgeStraight = false; edgeStraight = false;
referenceX = x; referenceX = x;
} else { } else {
refSegCount++; refSegCount += 1;
} }
} }
@ -991,12 +997,12 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// next segment up with the current control point. // next segment up with the current control point.
const nextX = cell.getX(i + 1); const nextX = cell.getX(i + 1);
if (currentX == nextX) { if (currentX === nextX) {
upXPositions[i - cell.minRank - 1] = currentX; upXPositions[i - cell.minRank - 1] = currentX;
upSegCount++; upSegCount += 1;
} else if (this.repositionValid(model, cell, i + 1, currentX)) { } else if (this.repositionValid(model, cell, i + 1, currentX)) {
upXPositions[i - cell.minRank - 1] = currentX; upXPositions[i - cell.minRank - 1] = currentX;
upSegCount++; upSegCount += 1;
// Leave currentX at same value // Leave currentX at same value
} else { } else {
upXPositions[i - cell.minRank - 1] = nextX; upXPositions[i - cell.minRank - 1] = nextX;
@ -1011,12 +1017,12 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// next segment down with the current control point. // next segment down with the current control point.
const nextX = cell.getX(i - 1); const nextX = cell.getX(i - 1);
if (currentX == nextX) { if (currentX === nextX) {
downXPositions[i - cell.minRank - 2] = currentX; downXPositions[i - cell.minRank - 2] = currentX;
downSegCount++; downSegCount += 1;
} else if (this.repositionValid(model, cell, i - 1, currentX)) { } else if (this.repositionValid(model, cell, i - 1, currentX)) {
downXPositions[i - cell.minRank - 2] = currentX; downXPositions[i - cell.minRank - 2] = currentX;
downSegCount++; downSegCount += 1;
// Leave currentX at same value // Leave currentX at same value
} else { } else {
downXPositions[i - cell.minRank - 2] = cell.getX(i - 1); downXPositions[i - cell.minRank - 2] = cell.getX(i - 1);
@ -1064,7 +1070,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
let rankIndex = -1; let rankIndex = -1;
for (let i = 0; i < rankArray.length; i += 1) { for (let i = 0; i < rankArray.length; i += 1) {
if (cell == rankArray[i]) { if (cell === rankArray[i]) {
rankIndex = i; rankIndex = i;
break; break;
} }
@ -1078,7 +1084,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
if (position < currentX) { if (position < currentX) {
// Trying to move node to the left. // Trying to move node to the left.
if (rankIndex == 0) { if (rankIndex === 0) {
// Left-most node, can move anywhere // Left-most node, can move anywhere
return true; return true;
} }
@ -1088,14 +1094,11 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
leftLimit = leftLimit =
leftLimit + leftCell.width / 2 + this.intraCellSpacing + cell.width / 2; leftLimit + leftCell.width / 2 + this.intraCellSpacing + cell.width / 2;
if (leftLimit <= position) { return leftLimit <= position;
return true;
}
return false;
} }
if (position > currentX) { if (position > currentX) {
// Trying to move node to the right. // Trying to move node to the right.
if (rankIndex == rankArray.length - 1) { if (rankIndex === rankArray.length - 1) {
// Right-most node, can move anywhere // Right-most node, can move anywhere
return true; return true;
} }
@ -1108,12 +1111,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
this.intraCellSpacing - this.intraCellSpacing -
cell.width / 2; cell.width / 2;
if (rightLimit >= position) { return rightLimit >= position;
return true;
}
return false;
} }
return true; return true;
}; };
@ -1150,9 +1149,9 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// Post process edge styles. Needs the vertex locations set for initial // Post process edge styles. Needs the vertex locations set for initial
// values of the top and bottoms of each rank // values of the top and bottoms of each rank
if ( if (
this.layout.edgeStyle == mxHierarchicalEdgeStyle.ORTHOGONAL || this.layout.edgeStyle === mxHierarchicalEdgeStyle.ORTHOGONAL ||
this.layout.edgeStyle == mxHierarchicalEdgeStyle.POLYLINE || this.layout.edgeStyle === mxHierarchicalEdgeStyle.POLYLINE ||
this.layout.edgeStyle == mxHierarchicalEdgeStyle.CURVE this.layout.edgeStyle === mxHierarchicalEdgeStyle.CURVE
) { ) {
this.localEdgeProcessing(model); this.localEdgeProcessing(model);
} }
@ -1176,10 +1175,10 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
localEdgeProcessing = model => { localEdgeProcessing = model => {
// Iterate through each vertex, look at the edges connected in // Iterate through each vertex, look at the edges connected in
// both directions. // both directions.
for (let rankIndex = 0; rankIndex < model.ranks.length; rankIndex++) { for (let rankIndex = 0; rankIndex < model.ranks.length; rankIndex += 1) {
const rank = model.ranks[rankIndex]; const rank = model.ranks[rankIndex];
for (let cellIndex = 0; cellIndex < rank.length; cellIndex++) { for (let cellIndex = 0; cellIndex < rank.length; cellIndex += 1) {
const cell = rank[cellIndex]; const cell = rank[cellIndex];
if (cell.isVertex()) { if (cell.isVertex()) {
@ -1188,7 +1187,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
let currentRank = rankIndex - 1; let currentRank = rankIndex - 1;
// Two loops, last connected cells, and next // Two loops, last connected cells, and next
for (let k = 0; k < 2; k++) { for (let k = 0; k < 2; k += 1) {
if ( if (
currentRank > -1 && currentRank > -1 &&
currentRank < model.ranks.length && currentRank < model.ranks.length &&
@ -1205,7 +1204,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
sortedCells.push(sorter); sortedCells.push(sorter);
} }
sortedCells.sort(compare); sortedCells.sort(new WeightedCellSorter().compare);
let leftLimit = cell.x[0] - cell.width / 2; let leftLimit = cell.x[0] - cell.width / 2;
let rightLimit = leftLimit + cell.width; let rightLimit = leftLimit + cell.width;
@ -1222,7 +1221,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
if (innerCell.isVertex()) { if (innerCell.isVertex()) {
// Get the connecting edge // Get the connecting edge
if (k == 0) { if (k === 0) {
connections = cell.connectsAsSource; connections = cell.connectsAsSource;
} else { } else {
connections = cell.connectsAsTarget; connections = cell.connectsAsTarget;
@ -1231,21 +1230,21 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
for ( for (
let connIndex = 0; let connIndex = 0;
connIndex < connections.length; connIndex < connections.length;
connIndex++ connIndex += 1
) { ) {
if ( if (
connections[connIndex].source == innerCell || connections[connIndex].source === innerCell ||
connections[connIndex].target == innerCell connections[connIndex].target === innerCell
) { ) {
connectedEdgeCount += connections[connIndex].edges.length; connectedEdgeCount += connections[connIndex].edges.length;
connectedEdgeGroupCount++; connectedEdgeGroupCount += 1;
connectedEdges.push(connections[connIndex]); connectedEdges.push(connections[connIndex]);
} }
} }
} else { } else {
connectedEdgeCount += innerCell.edges.length; connectedEdgeCount += innerCell.edges.length;
connectedEdgeGroupCount++; connectedEdgeGroupCount += 1;
connectedEdges.push(innerCell); connectedEdges.push(innerCell);
} }
} }
@ -1283,7 +1282,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// Ignore the case if equals, this means the second of 2 // Ignore the case if equals, this means the second of 2
// jettys with the same y (even number of edges) // jettys with the same y (even number of edges)
for (let m = 0; m < numActualEdges; m++) { for (let m = 0; m < numActualEdges; m += 1) {
pos[m * 4 + k * 2] = currentX; pos[m * 4 + k * 2] = currentX;
currentX += edgeSpacing; currentX += edgeSpacing;
pos[m * 4 + k * 2 + 1] = currentYOffset; pos[m * 4 + k * 2 + 1] = currentYOffset;
@ -1313,11 +1312,11 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
let offsetX = 0; let offsetX = 0;
// Only set the edge control points once // Only set the edge control points once
if (cell.temp[0] != 101207) { if (cell.temp[0] !== 101207) {
let { maxRank } = cell; let { maxRank } = cell;
let { minRank } = cell; let { minRank } = cell;
if (maxRank == minRank) { if (maxRank === minRank) {
maxRank = cell.source.maxRank; maxRank = cell.source.maxRank;
minRank = cell.target.minRank; minRank = cell.target.minRank;
} }
@ -1328,8 +1327,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
const source = cell.isReversed ? cell.target.cell : cell.source.cell; const source = cell.isReversed ? cell.target.cell : cell.source.cell;
const { graph } = this.layout; const { graph } = this.layout;
const layoutReversed = const layoutReversed =
this.orientation == mxConstants.DIRECTION_EAST || this.orientation === mxConstants.DIRECTION_EAST ||
this.orientation == mxConstants.DIRECTION_SOUTH; this.orientation === mxConstants.DIRECTION_SOUTH;
for (let i = 0; i < cell.edges.length; i += 1) { for (let i = 0; i < cell.edges.length; i += 1) {
const realEdge = cell.edges[i]; const realEdge = cell.edges[i];
@ -1343,7 +1342,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// control points, we just say the edge isn't reversed in this section // control points, we just say the edge isn't reversed in this section
let reversed = cell.isReversed; let reversed = cell.isReversed;
if (realSource != source) { if (realSource !== source) {
// The real edges include all core model edges and these can go // The real edges include all core model edges and these can go
// in both directions. If the source of the hierarchical model edge // in both directions. If the source of the hierarchical model edge
// isn't the source of the specific real edge in this iteration // isn't the source of the specific real edge in this iteration
@ -1363,7 +1362,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
: this.rankBottomY[maxRank]; : this.rankBottomY[maxRank];
let jetty = jettys[parallelEdgeCount * 4 + 1 + arrayOffset]; let jetty = jettys[parallelEdgeCount * 4 + 1 + arrayOffset];
if (reversed != layoutReversed) { if (reversed !== layoutReversed) {
jetty = -jetty; jetty = -jetty;
} }
@ -1374,7 +1373,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
if ( if (
this.layout.isPort(modelSource) && this.layout.isPort(modelSource) &&
graph.model.getParent(modelSource) == realSource graph.model.getParent(modelSource) === realSource
) { ) {
const state = graph.view.getState(modelSource); const state = graph.view.getState(modelSource);
@ -1388,18 +1387,18 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
} }
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_SOUTH this.orientation === mxConstants.DIRECTION_SOUTH
) { ) {
newPoints.push(new mxPoint(x, y)); newPoints.push(new mxPoint(x, y));
if (this.layout.edgeStyle == mxHierarchicalEdgeStyle.CURVE) { if (this.layout.edgeStyle === mxHierarchicalEdgeStyle.CURVE) {
newPoints.push(new mxPoint(x, y + jetty)); newPoints.push(new mxPoint(x, y + jetty));
} }
} else { } else {
newPoints.push(new mxPoint(y, x)); newPoints.push(new mxPoint(y, x));
if (this.layout.edgeStyle == mxHierarchicalEdgeStyle.CURVE) { if (this.layout.edgeStyle === mxHierarchicalEdgeStyle.CURVE) {
newPoints.push(new mxPoint(y + jetty, x)); newPoints.push(new mxPoint(y + jetty, x));
} }
} }
@ -1423,7 +1422,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// reverse order // reverse order
for ( for (
let j = loopStart; let j = loopStart;
cell.maxRank != cell.minRank && j != loopLimit; cell.maxRank !== cell.minRank && j !== loopLimit;
j += loopDelta j += loopDelta
) { ) {
// The horizontal position in a vertical layout // The horizontal position in a vertical layout
@ -1445,8 +1444,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
} }
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_SOUTH this.orientation === mxConstants.DIRECTION_SOUTH
) { ) {
newPoints.push(new mxPoint(positionX, topChannelY)); newPoints.push(new mxPoint(positionX, topChannelY));
newPoints.push(new mxPoint(positionX, bottomChannelY)); newPoints.push(new mxPoint(positionX, bottomChannelY));
@ -1471,7 +1470,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
: this.rankTopY[minRank]; : this.rankTopY[minRank];
let jetty = jettys[parallelEdgeCount * 4 + 3 - arrayOffset]; let jetty = jettys[parallelEdgeCount * 4 + 3 - arrayOffset];
if (reversed != layoutReversed) { if (reversed !== layoutReversed) {
jetty = -jetty; jetty = -jetty;
} }
const y = rankY - jetty; const y = rankY - jetty;
@ -1482,7 +1481,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
if ( if (
this.layout.isPort(modelTarget) && this.layout.isPort(modelTarget) &&
graph.model.getParent(modelTarget) == realTarget graph.model.getParent(modelTarget) === realTarget
) { ) {
const state = graph.view.getState(modelTarget); const state = graph.view.getState(modelTarget);
@ -1496,16 +1495,16 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
} }
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_SOUTH this.orientation === mxConstants.DIRECTION_SOUTH
) { ) {
if (this.layout.edgeStyle == mxHierarchicalEdgeStyle.CURVE) { if (this.layout.edgeStyle === mxHierarchicalEdgeStyle.CURVE) {
newPoints.push(new mxPoint(x, y - jetty)); newPoints.push(new mxPoint(x, y - jetty));
} }
newPoints.push(new mxPoint(x, y)); newPoints.push(new mxPoint(x, y));
} else { } else {
if (this.layout.edgeStyle == mxHierarchicalEdgeStyle.CURVE) { if (this.layout.edgeStyle === mxHierarchicalEdgeStyle.CURVE) {
newPoints.push(new mxPoint(y - jetty, x)); newPoints.push(new mxPoint(y - jetty, x));
} }
@ -1521,7 +1520,7 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
// Increase offset so next edge is drawn next to // Increase offset so next edge is drawn next to
// this one // this one
if (offsetX == 0.0) { if (offsetX === 0.0) {
offsetX = this.parallelEdgeSpacing; offsetX = this.parallelEdgeSpacing;
} else if (offsetX > 0) { } else if (offsetX > 0) {
offsetX = -offsetX; offsetX = -offsetX;
@ -1560,8 +1559,8 @@ class mxCoordinateAssignment extends mxHierarchicalLayoutStage {
); );
if ( if (
this.orientation == mxConstants.DIRECTION_NORTH || this.orientation === mxConstants.DIRECTION_NORTH ||
this.orientation == mxConstants.DIRECTION_SOUTH this.orientation === mxConstants.DIRECTION_SOUTH
) { ) {
this.layout.setVertexLocation(realCell, positionX, positionY); this.layout.setVertexLocation(realCell, positionX, positionY);
} else { } else {

View File

@ -4,6 +4,7 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage'; import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage';
import MedianCellSorter from "./MedianCellSorter";
class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage { class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
/** /**
@ -134,10 +135,10 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
iterationsWithoutImprovement = 0; iterationsWithoutImprovement = 0;
// Store the current rankings as the best ones // Store the current rankings as the best ones
for (let j = 0; j < this.nestedBestRanks.length; j++) { for (let j = 0; j < this.nestedBestRanks.length; j += 1) {
const rank = model.ranks[j]; const rank = model.ranks[j];
for (let k = 0; k < rank.length; k++) { for (let k = 0; k < rank.length; k += 1) {
const cell = rank[k]; const cell = rank[k];
this.nestedBestRanks[j][cell.getGeneralPurposeVariable(j)] = cell; this.nestedBestRanks[j][cell.getGeneralPurposeVariable(j)] = cell;
} }
@ -145,20 +146,20 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
} else { } else {
// Increase count of iterations where we haven't improved the // Increase count of iterations where we haven't improved the
// layout // layout
iterationsWithoutImprovement++; iterationsWithoutImprovement += 1;
// Restore the best values to the cells // Restore the best values to the cells
for (let j = 0; j < this.nestedBestRanks.length; j++) { for (let j = 0; j < this.nestedBestRanks.length; j += 1) {
const rank = model.ranks[j]; const rank = model.ranks[j];
for (let k = 0; k < rank.length; k++) { for (let k = 0; k < rank.length; k += 1) {
const cell = rank[k]; const cell = rank[k];
cell.setGeneralPurposeVariable(j, k); cell.setGeneralPurposeVariable(j, k);
} }
} }
} }
if (currentBestCrossings == 0) { if (currentBestCrossings === 0) {
// Do nothing further // Do nothing further
break; break;
} }
@ -174,7 +175,7 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
} }
for (let i = 0; i < this.nestedBestRanks.length; i += 1) { for (let i = 0; i < this.nestedBestRanks.length; i += 1) {
for (let j = 0; j < this.nestedBestRanks[i].length; j++) { for (let j = 0; j < this.nestedBestRanks[i].length; j += 1) {
rankList[i].push(this.nestedBestRanks[i][j]); rankList[i].push(this.nestedBestRanks[i][j]);
} }
} }
@ -224,13 +225,13 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
const tmpIndices = []; const tmpIndices = [];
// Iterate over the top rank and fill in the connection information // Iterate over the top rank and fill in the connection information
for (let j = 0; j < rank.length; j++) { for (let j = 0; j < rank.length; j += 1) {
const node = rank[j]; const node = rank[j];
const rankPosition = node.getGeneralPurposeVariable(i); const rankPosition = node.getGeneralPurposeVariable(i);
const connectedCells = node.getPreviousLayerConnectedCells(i); const connectedCells = node.getPreviousLayerConnectedCells(i);
const nodeIndices = []; const nodeIndices = [];
for (let k = 0; k < connectedCells.length; k++) { for (let k = 0; k < connectedCells.length; k += 1) {
const connectedNode = connectedCells[k]; const connectedNode = connectedCells[k];
const otherCellRankPosition = connectedNode.getGeneralPurposeVariable( const otherCellRankPosition = connectedNode.getGeneralPurposeVariable(
i - 1 i - 1
@ -265,7 +266,7 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
tree[j] = 0; tree[j] = 0;
} }
for (let j = 0; j < indices.length; j++) { for (let j = 0; j < indices.length; j += 1) {
const index = indices[j]; const index = indices[j];
let treeIndex = index + firstIndex; let treeIndex = index + firstIndex;
++tree[treeIndex]; ++tree[treeIndex];
@ -304,7 +305,7 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
// On certain iterations allow allow swapping of cell pairs with // On certain iterations allow allow swapping of cell pairs with
// equal edge crossings switched or not switched. This help to // equal edge crossings switched or not switched. This help to
// nudge a stuck layout into a lower crossing total. // nudge a stuck layout into a lower crossing total.
const nudge = mainLoopIteration % 2 == 1 && count % 2 == 1; const nudge = mainLoopIteration % 2 === 1 && count % 2 === 1;
improved = false; improved = false;
for (let i = 0; i < model.ranks.length; i += 1) { for (let i = 0; i < model.ranks.length; i += 1) {
@ -342,7 +343,7 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
// On every cell pair except the first on each rank, we // On every cell pair except the first on each rank, we
// can save processing using the previous values for the // can save processing using the previous values for the
// right cell on the new left cell // right cell on the new left cell
if (j == 0) { if (j === 0) {
leftCell = orderedCells[j]; leftCell = orderedCells[j];
leftCellAboveConnections = leftCell.getNextLayerConnectedCells(i); leftCellAboveConnections = leftCell.getNextLayerConnectedCells(i);
leftCellBelowConnections = leftCell.getPreviousLayerConnectedCells( leftCellBelowConnections = leftCell.getPreviousLayerConnectedCells(
@ -394,33 +395,33 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
let totalCurrentCrossings = 0; let totalCurrentCrossings = 0;
let totalSwitchedCrossings = 0; let totalSwitchedCrossings = 0;
for (let k = 0; k < leftAbovePositions.length; k++) { for (let k = 0; k < leftAbovePositions.length; k += 1) {
for (let ik = 0; ik < rightAbovePositions.length; ik++) { for (let ik = 0; ik < rightAbovePositions.length; ik += 1) {
if (leftAbovePositions[k] > rightAbovePositions[ik]) { if (leftAbovePositions[k] > rightAbovePositions[ik]) {
totalCurrentCrossings++; totalCurrentCrossings += 1;
} }
if (leftAbovePositions[k] < rightAbovePositions[ik]) { if (leftAbovePositions[k] < rightAbovePositions[ik]) {
totalSwitchedCrossings++; totalSwitchedCrossings += 1;
} }
} }
} }
for (let k = 0; k < leftBelowPositions.length; k++) { for (let k = 0; k < leftBelowPositions.length; k += 1) {
for (let ik = 0; ik < rightBelowPositions.length; ik++) { for (let ik = 0; ik < rightBelowPositions.length; ik += 1) {
if (leftBelowPositions[k] > rightBelowPositions[ik]) { if (leftBelowPositions[k] > rightBelowPositions[ik]) {
totalCurrentCrossings++; totalCurrentCrossings += 1;
} }
if (leftBelowPositions[k] < rightBelowPositions[ik]) { if (leftBelowPositions[k] < rightBelowPositions[ik]) {
totalSwitchedCrossings++; totalSwitchedCrossings += 1;
} }
} }
} }
if ( if (
totalSwitchedCrossings < totalCurrentCrossings || totalSwitchedCrossings < totalCurrentCrossings ||
(totalSwitchedCrossings == totalCurrentCrossings && nudge) (totalSwitchedCrossings === totalCurrentCrossings && nudge)
) { ) {
const temp = leftCell.getGeneralPurposeVariable(i); const temp = leftCell.getGeneralPurposeVariable(i);
leftCell.setGeneralPurposeVariable( leftCell.setGeneralPurposeVariable(
@ -464,13 +465,13 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
*/ */
weightedMedian = (iteration, model) => { weightedMedian = (iteration, model) => {
// Reverse sweep direction each time through this method // Reverse sweep direction each time through this method
const downwardSweep = iteration % 2 == 0; const downwardSweep = iteration % 2 === 0;
if (downwardSweep) { if (downwardSweep) {
for (let j = model.maxRank - 1; j >= 0; j--) { for (let j = model.maxRank - 1; j >= 0; j -= 1) {
this.medianRank(j, downwardSweep); this.medianRank(j, downwardSweep);
} }
} else { } else {
for (let j = 1; j < model.maxRank; j++) { for (let j = 1; j < model.maxRank; j += 1) {
this.medianRank(j, downwardSweep); this.medianRank(j, downwardSweep);
} }
} }
@ -521,7 +522,7 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
if ( if (
nextLevelConnectedCells != null && nextLevelConnectedCells != null &&
nextLevelConnectedCells.length != 0 nextLevelConnectedCells.length !== 0
) { ) {
sorterEntry.medianValue = this.medianValue( sorterEntry.medianValue = this.medianValue(
nextLevelConnectedCells, nextLevelConnectedCells,
@ -535,7 +536,7 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
} }
} }
medianValues.sort(compare); medianValues.sort(new MedianCellSorter().compare);
// Set the new position of each node within the rank using // Set the new position of each node within the rank using
// its temp variable // its temp variable
@ -575,11 +576,11 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
return a - b; return a - b;
}); });
if (arrayCount % 2 == 1) { if (arrayCount % 2 === 1) {
// For odd numbers of adjacent vertices return the median // For odd numbers of adjacent vertices return the median
return medianValues[Math.floor(arrayCount / 2)]; return medianValues[Math.floor(arrayCount / 2)];
} }
if (arrayCount == 2) { if (arrayCount === 2) {
return (medianValues[0] + medianValues[1]) / 2.0; return (medianValues[0] + medianValues[1]) / 2.0;
} }
const medianPoint = arrayCount / 2; const medianPoint = arrayCount / 2;
@ -593,28 +594,6 @@ class mxMedianHybridCrossingReduction extends mxHierarchicalLayoutStage {
(leftMedian + rightMedian) (leftMedian + rightMedian)
); );
}; };
MedianCellSorter() {
// empty
}
/**
* Function: compare
*
* Compares two MedianCellSorters.
*/
compare = (a, b) => {
if (a != null && b != null) {
if (b.medianValue > a.medianValue) {
return -1;
}
if (b.medianValue < a.medianValue) {
return 1;
}
return 0;
}
return 0;
};
} }
export default mxMedianHybridCrossingReduction; export default mxMedianHybridCrossingReduction;

View File

@ -4,6 +4,7 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage'; import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage';
import mxUtils from "../../../util/mxUtils";
class mxMinimumCycleRemover extends mxHierarchicalLayoutStage { class mxMinimumCycleRemover extends mxHierarchicalLayoutStage {
/** /**

View File

@ -4,6 +4,8 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage'; import mxHierarchicalLayoutStage from './mxHierarchicalLayoutStage';
import mxUtils from "../../../util/mxUtils";
import mxCellPath from "../../../model/mxCellPath";
class mxSwimlaneOrdering extends mxHierarchicalLayoutStage { class mxSwimlaneOrdering extends mxHierarchicalLayoutStage {
/** /**
@ -62,7 +64,7 @@ class mxSwimlaneOrdering extends mxHierarchicalLayoutStage {
// Ancestor hashes only line up within a swimlane // Ancestor hashes only line up within a swimlane
const isAncestor = const isAncestor =
parent != null && parent != null &&
parent.swimlaneIndex == node.swimlaneIndex && parent.swimlaneIndex === node.swimlaneIndex &&
node.isAncestor(parent); node.isAncestor(parent);
// If the source->target swimlane indices go from higher to // If the source->target swimlane indices go from higher to
@ -71,7 +73,7 @@ class mxSwimlaneOrdering extends mxHierarchicalLayoutStage {
parent != null && parent != null &&
connectingEdge != null && connectingEdge != null &&
parent.swimlaneIndex < node.swimlaneIndex && parent.swimlaneIndex < node.swimlaneIndex &&
connectingEdge.source == node; connectingEdge.source === node;
if (isAncestor) { if (isAncestor) {
connectingEdge.invert(); connectingEdge.invert();

View File

@ -3,6 +3,7 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphLayout from "./mxGraphLayout";
class mxCircleLayout extends mxGraphLayout { class mxCircleLayout extends mxGraphLayout {
/** /**

View File

@ -4,8 +4,9 @@
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxDictionary from 'FIXME'; import mxDictionary from "../util/mxDictionary";
import mxPoint from 'FIXME'; import mxPoint from "../util/mxPoint";
import mxGraphLayout from "./mxGraphLayout";
class mxCompactTreeLayout extends mxGraphLayout { class mxCompactTreeLayout extends mxGraphLayout {
/** /**

View File

@ -3,6 +3,7 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphLayout from "./mxGraphLayout";
class mxCompositeLayout extends mxGraphLayout { class mxCompositeLayout extends mxGraphLayout {
/** /**

View File

@ -204,7 +204,7 @@ class mxFastOrganicLayout extends mxGraphLayout {
isVertexIgnored = vertex => { isVertexIgnored = vertex => {
return ( return (
super.isVertexIgnored(vertex) || super.isVertexIgnored(vertex) ||
this.graph.getConnections(vertex).length == 0 this.graph.getConnections(vertex).length === 0
); );
}; };
@ -321,7 +321,7 @@ class mxFastOrganicLayout extends mxGraphLayout {
this.temperature = this.initialTemp; this.temperature = this.initialTemp;
// If max number of iterations has not been set, guess it // If max number of iterations has not been set, guess it
if (this.maxIterations == 0) { if (this.maxIterations === 0) {
this.maxIterations = 20 * Math.sqrt(n); this.maxIterations = 20 * Math.sqrt(n);
} }
@ -452,7 +452,7 @@ class mxFastOrganicLayout extends mxGraphLayout {
const j = this.neighbours[i][k]; const j = this.neighbours[i][k];
// Do not proceed self-loops // Do not proceed self-loops
if (i != j && this.isMoveable[i] && this.isMoveable[j]) { if (i !== j && this.isMoveable[i] && this.isMoveable[j]) {
const xDelta = this.cellLocation[i][0] - this.cellLocation[j][0]; const xDelta = this.cellLocation[i][0] - this.cellLocation[j][0];
const yDelta = this.cellLocation[i][1] - this.cellLocation[j][1]; const yDelta = this.cellLocation[i][1] - this.cellLocation[j][1];

View File

@ -178,7 +178,7 @@ class mxGraphLayout {
if (edgeCount > 0) { if (edgeCount > 0) {
for (let i = 0; i < edgeCount; i += 1) { for (let i = 0; i < edgeCount; i += 1) {
const e = this.graph.model.getEdgeAt(vertex, i); const e = this.graph.model.getEdgeAt(vertex, i);
const isSource = this.graph.model.getTerminal(e, true) == vertex; const isSource = this.graph.model.getTerminal(e, true) === vertex;
if (!directed || isSource) { if (!directed || isSource) {
const next = this.graph.view.getVisibleTerminal(e, !isSource); const next = this.graph.view.getVisibleTerminal(e, !isSource);
@ -204,18 +204,18 @@ class mxGraphLayout {
*/ */
isAncestor = (parent, child, traverseAncestors) => { isAncestor = (parent, child, traverseAncestors) => {
if (!traverseAncestors) { if (!traverseAncestors) {
return this.graph.model.getParent(child) == parent; return this.graph.model.getParent(child) === parent;
} }
if (child == parent) { if (child === parent) {
return false; return false;
} }
while (child != null && child != parent) { while (child != null && child !== parent) {
child = this.graph.model.getParent(child); child = this.graph.model.getParent(child);
} }
return child == parent; return child === parent;
}; };
/** /**
@ -302,13 +302,13 @@ class mxGraphLayout {
getParentOffset = parent => { getParentOffset = parent => {
const result = new mxPoint(); const result = new mxPoint();
if (parent != null && parent != this.parent) { if (parent != null && parent !== this.parent) {
const model = this.graph.getModel(); const model = this.graph.getModel();
if (model.isAncestor(this.parent, parent)) { if (model.isAncestor(this.parent, parent)) {
let parentGeo = model.getGeometry(parent); let parentGeo = model.getGeometry(parent);
while (parent != this.parent) { while (parent !== this.parent) {
result.x += parentGeo.x; result.x += parentGeo.x;
result.y += parentGeo.y; result.y += parentGeo.y;
@ -407,7 +407,7 @@ class mxGraphLayout {
if (this.parent != null) { if (this.parent != null) {
const parent = model.getParent(cell); const parent = model.getParent(cell);
if (parent != null && parent != this.parent) { if (parent != null && parent !== this.parent) {
const parentOffset = this.getParentOffset(parent); const parentOffset = this.getParentOffset(parent);
x -= parentOffset.x; x -= parentOffset.x;
@ -415,7 +415,7 @@ class mxGraphLayout {
} }
} }
if (geometry.x != x || geometry.y != y) { if (geometry.x !== x || geometry.y !== y) {
geometry = geometry.clone(); geometry = geometry.clone();
geometry.x = x; geometry.x = x;
geometry.y = y; geometry.y = y;
@ -470,7 +470,7 @@ class mxGraphLayout {
const parent = this.graph.getModel().getParent(cell); const parent = this.graph.getModel().getParent(cell);
geo = geo.clone(); geo = geo.clone();
if (parent != null && parent != this.parent) { if (parent != null && parent !== this.parent) {
const parentOffset = this.getParentOffset(parent); const parentOffset = this.getParentOffset(parent);
geo.x += parentOffset.x; geo.x += parentOffset.x;
geo.y += parentOffset.y; geo.y += parentOffset.y;

View File

@ -5,7 +5,7 @@
*/ */
import mxRectangle from '../util/mxRectangle'; import mxRectangle from '../util/mxRectangle';
import mxGraphLayout from "./mxGraphLayout"; import mxGraphLayout from './mxGraphLayout';
class mxPartitionLayout extends mxGraphLayout { class mxPartitionLayout extends mxGraphLayout {
/** /**

View File

@ -3,6 +3,10 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxGraphLayout from "./mxGraphLayout";
import mxRectangle from "../util/mxRectangle";
import mxUtils from "../util/mxUtils";
import mxConstants from "../util/mxConstants";
class mxStackLayout extends mxGraphLayout { class mxStackLayout extends mxGraphLayout {
/** /**
@ -199,7 +203,7 @@ class mxStackLayout extends mxGraphLayout {
for (i = 0; i < childCount; i += 1) { for (i = 0; i < childCount; i += 1) {
const child = model.getChildAt(parent, i); const child = model.getChildAt(parent, i);
if (child != cell) { if (child !== cell) {
const bounds = model.getGeometry(child); const bounds = model.getGeometry(child);
if (bounds != null) { if (bounds != null) {
@ -240,7 +244,7 @@ class mxStackLayout extends mxGraphLayout {
if ( if (
this.graph.container != null && this.graph.container != null &&
((pgeo == null && model.isLayer(parent)) || ((pgeo == null && model.isLayer(parent)) ||
parent == this.graph.getView().currentRoot) parent === this.graph.getView().currentRoot)
) { ) {
const width = this.graph.container.offsetWidth - 1; const width = this.graph.container.offsetWidth - 1;
const height = this.graph.container.offsetHeight - 1; const height = this.graph.container.offsetHeight - 1;
@ -274,12 +278,12 @@ class mxStackLayout extends mxGraphLayout {
const geo2 = this.graph.getCellGeometry(c2); const geo2 = this.graph.getCellGeometry(c2);
return this.horizontal return this.horizontal
? geo1.x == geo2.x ? geo1.x === geo2.x
? 0 ? 0
: geo1.x > geo2.x > 0 : geo1.x > geo2.x > 0
? 1 ? 1
: -1 : -1
: geo1.y == geo2.y : geo1.y === geo2.y
? 0 ? 0
: geo1.y > geo2.y > 0 : geo1.y > geo2.y > 0
? 1 ? 1
@ -343,7 +347,7 @@ class mxStackLayout extends mxGraphLayout {
mxConstants.DEFAULT_STARTSIZE mxConstants.DEFAULT_STARTSIZE
); );
const horz = const horz =
mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true) == 1; mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true) === 1;
if (pgeo != null) { if (pgeo != null) {
if (horz) { if (horz) {
@ -353,7 +357,7 @@ class mxStackLayout extends mxGraphLayout {
} }
} }
if (horizontal == horz) { if (horizontal === horz) {
fillValue -= start; fillValue -= start;
} }
@ -528,10 +532,10 @@ class mxStackLayout extends mxGraphLayout {
if ( if (
geo2 == null || geo2 == null ||
geo.x != geo2.x || geo.x !== geo2.x ||
geo.y != geo2.y || geo.y !== geo2.y ||
geo.width != geo2.width || geo.width !== geo2.width ||
geo.height != geo2.height geo.height !== geo2.height
) { ) {
this.graph.getModel().setGeometry(child, geo); this.graph.getModel().setGeometry(child, geo);
} }
@ -573,10 +577,10 @@ class mxStackLayout extends mxGraphLayout {
} }
if ( if (
pgeo.x != pgeo2.x || pgeo.x !== pgeo2.x ||
pgeo.y != pgeo2.y || pgeo.y !== pgeo2.y ||
pgeo.width != pgeo2.width || pgeo.width !== pgeo2.width ||
pgeo.height != pgeo2.height pgeo.height !== pgeo2.height
) { ) {
model.setGeometry(parent, pgeo2); model.setGeometry(parent, pgeo2);
} }