- The yFiles for HTML 2.6.0.2 demo applications are available in
+ The yFiles for HTML 2.6.0.3 demo applications are available in
both JavaScript and TypeScript.
Show TypeScript Demos. {
+ dendrogramComponent.addDragFinishedListener((cutOffValue) => {
removeClusterVisuals()
runHierarchicalClustering(cutOffValue)
})
@@ -474,7 +474,7 @@ function visualizeClusteringResult() {
// creates a map the holds for each cluster id, the list of nodes that belong to the particular cluster
const clustering = new Map()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let clusterId = result.nodeClusterIds.get(node)
// biconnected components returns -1 as cluster id when only one node is present.
// We change the clusterId manually here, as otherwise we'll get an exception in
@@ -592,7 +592,7 @@ function loadGraph(sampleData) {
{
data: sampleData.nodes,
id: 'id',
- layout: data => new Rect(data.x, data.y, data.w, data.h),
+ layout: (data) => new Rect(data.x, data.y, data.w, data.h),
labels: ['label']
}
],
@@ -623,10 +623,10 @@ function initializeUI() {
// edge-betweenness menu
const minInput = document.querySelector(`#ebMinClusterNumber`)
- minInput.addEventListener('change', _ => {
+ minInput.addEventListener('change', (_) => {
const value = parseFloat(minInput.value)
const maximumClusterNumber = parseFloat(document.querySelector(`#ebMaxClusterNumber`).value)
- if (isNaN(value) || value < 1) {
+ if (Number.isNaN(value) || value < 1) {
alert('Number of clusters should be non-negative.')
minInput.value = '1'
return
@@ -647,10 +647,10 @@ function initializeUI() {
})
const maxInput = document.querySelector(`#ebMaxClusterNumber`)
- maxInput.addEventListener('change', _ => {
+ maxInput.addEventListener('change', (_) => {
const value = parseFloat(maxInput.value)
const minimumClusterNumber = parseFloat(document.querySelector(`#ebMinClusterNumber`).value)
- if (isNaN(value) || value < minimumClusterNumber || minimumClusterNumber < 1) {
+ if (Number.isNaN(value) || value < minimumClusterNumber || minimumClusterNumber < 1) {
const message =
value < minimumClusterNumber
? 'Desired maximum number of clusters cannot be smaller than the desired minimum number of clusters.'
@@ -665,7 +665,7 @@ function initializeUI() {
const considerEdgeDirection = document.querySelector(`#directed`)
considerEdgeDirection.addEventListener('click', () => {
const isChecked = considerEdgeDirection.checked
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
graph.setStyle(edge, isChecked ? directedEdgeStyle : graph.edgeDefaults.style)
})
@@ -674,7 +674,7 @@ function initializeUI() {
const considerEdgeCosts = document.querySelector(`#edgeCosts`)
considerEdgeCosts.addEventListener('click', () => {
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (considerEdgeCosts.checked) {
const edgeCost = Math.floor(Math.random() * 200 + 1)
if (edge.labels.size > 0) {
@@ -683,7 +683,7 @@ function initializeUI() {
graph.addLabel(edge, `${edgeCost}`)
}
} else {
- edge.labels.toArray().forEach(label => {
+ edge.labels.toArray().forEach((label) => {
graph.remove(label)
})
}
@@ -695,9 +695,9 @@ function initializeUI() {
const distanceCombobox = document.querySelector(`#distance-metrics`)
distanceCombobox.addEventListener('change', runAlgorithm)
const kMeansInput = document.querySelector(`#kMeansMaxClusterNumber`)
- kMeansInput.addEventListener('change', _ => {
+ kMeansInput.addEventListener('change', (_) => {
const value = parseFloat(kMeansInput.value)
- if (isNaN(value) || value < 1) {
+ if (Number.isNaN(value) || value < 1) {
alert('Desired maximum number of clusters should be greater than zero.')
kMeansInput.value = '1'
return
@@ -705,9 +705,9 @@ function initializeUI() {
runAlgorithm()
})
const iterationInput = document.querySelector(`#iterations`)
- iterationInput.addEventListener('change', _ => {
+ iterationInput.addEventListener('change', (_) => {
const value = parseFloat(iterationInput.value)
- if (isNaN(value) || value < 0) {
+ if (Number.isNaN(value) || value < 0) {
alert('Desired maximum number of iterations should be non-negative.')
iterationInput.value = '0'
return
@@ -748,7 +748,7 @@ function getEdgeWeight(edge) {
if (edge.labels.size > 0) {
// ...try to return its value
const edgeWeight = parseFloat(edge.labels.first().text)
- if (!isNaN(edgeWeight)) {
+ if (!Number.isNaN(edgeWeight)) {
return edgeWeight > 0 ? edgeWeight : 1
}
}
diff --git a/demos/analysis/clustering/ClusteringDemo.ts b/demos/analysis/clustering/ClusteringDemo.ts
index 6c309e1ec..984f4778e 100644
--- a/demos/analysis/clustering/ClusteringDemo.ts
+++ b/demos/analysis/clustering/ClusteringDemo.ts
@@ -270,7 +270,7 @@ function configureUserInteraction(graphComponent: GraphComponent): void {
*/
function configureDendrogramComponent(dendrogramComponent: DendrogramComponent): void {
// add a dragging listener to run the hierarchical algorithm when the dragging of the cutoff line has finished
- dendrogramComponent.addDragFinishedListener(cutOffValue => {
+ dendrogramComponent.addDragFinishedListener((cutOffValue) => {
removeClusterVisuals()
runHierarchicalClustering(cutOffValue)
})
@@ -473,7 +473,7 @@ function visualizeClusteringResult(): void {
// creates a map the holds for each cluster id, the list of nodes that belong to the particular cluster
const clustering = new Map()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let clusterId: number = result.nodeClusterIds.get(node)!
// biconnected components returns -1 as cluster id when only one node is present.
// We change the clusterId manually here, as otherwise we'll get an exception in
@@ -622,12 +622,12 @@ function initializeUI(): void {
// edge-betweenness menu
const minInput = document.querySelector(`#ebMinClusterNumber`)!
- minInput.addEventListener('change', _ => {
+ minInput.addEventListener('change', (_) => {
const value = parseFloat(minInput.value)
const maximumClusterNumber = parseFloat(
document.querySelector(`#ebMaxClusterNumber`)!.value
)
- if (isNaN(value) || value < 1) {
+ if (Number.isNaN(value) || value < 1) {
alert('Number of clusters should be non-negative.')
minInput.value = '1'
return
@@ -648,12 +648,12 @@ function initializeUI(): void {
})
const maxInput = document.querySelector(`#ebMaxClusterNumber`)!
- maxInput.addEventListener('change', _ => {
+ maxInput.addEventListener('change', (_) => {
const value = parseFloat(maxInput.value)
const minimumClusterNumber = parseFloat(
document.querySelector(`#ebMinClusterNumber`)!.value
)
- if (isNaN(value) || value < minimumClusterNumber || minimumClusterNumber < 1) {
+ if (Number.isNaN(value) || value < minimumClusterNumber || minimumClusterNumber < 1) {
const message =
value < minimumClusterNumber
? 'Desired maximum number of clusters cannot be smaller than the desired minimum number of clusters.'
@@ -668,7 +668,7 @@ function initializeUI(): void {
const considerEdgeDirection = document.querySelector(`#directed`)!
considerEdgeDirection.addEventListener('click', () => {
const isChecked = considerEdgeDirection.checked
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
graph.setStyle(edge, isChecked ? directedEdgeStyle : graph.edgeDefaults.style)
})
@@ -677,7 +677,7 @@ function initializeUI(): void {
const considerEdgeCosts = document.querySelector(`#edgeCosts`)!
considerEdgeCosts.addEventListener('click', () => {
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (considerEdgeCosts.checked) {
const edgeCost = Math.floor(Math.random() * 200 + 1)
if (edge.labels.size > 0) {
@@ -686,7 +686,7 @@ function initializeUI(): void {
graph.addLabel(edge, `${edgeCost}`)
}
} else {
- edge.labels.toArray().forEach(label => {
+ edge.labels.toArray().forEach((label) => {
graph.remove(label)
})
}
@@ -698,9 +698,9 @@ function initializeUI(): void {
const distanceCombobox = document.querySelector(`#distance-metrics`)!
distanceCombobox.addEventListener('change', runAlgorithm)
const kMeansInput = document.querySelector(`#kMeansMaxClusterNumber`)!
- kMeansInput.addEventListener('change', _ => {
+ kMeansInput.addEventListener('change', (_) => {
const value = parseFloat(kMeansInput.value)
- if (isNaN(value) || value < 1) {
+ if (Number.isNaN(value) || value < 1) {
alert('Desired maximum number of clusters should be greater than zero.')
kMeansInput.value = '1'
return
@@ -708,9 +708,9 @@ function initializeUI(): void {
runAlgorithm()
})
const iterationInput = document.querySelector(`#iterations`)!
- iterationInput.addEventListener('change', _ => {
+ iterationInput.addEventListener('change', (_) => {
const value = parseFloat(iterationInput.value)
- if (isNaN(value) || value < 0) {
+ if (Number.isNaN(value) || value < 0) {
alert('Desired maximum number of iterations should be non-negative.')
iterationInput.value = '0'
return
@@ -751,7 +751,7 @@ function getEdgeWeight(edge: IEdge): number {
if (edge.labels.size > 0) {
// ...try to return its value
const edgeWeight = parseFloat(edge.labels.first().text)
- if (!isNaN(edgeWeight)) {
+ if (!Number.isNaN(edgeWeight)) {
return edgeWeight > 0 ? edgeWeight : 1
}
}
diff --git a/demos/analysis/clustering/DemoVisuals.js b/demos/analysis/clustering/DemoVisuals.js
index 643c77b64..979d74897 100644
--- a/demos/analysis/clustering/DemoVisuals.js
+++ b/demos/analysis/clustering/DemoVisuals.js
@@ -99,7 +99,7 @@ export class VoronoiVisual extends BaseClass(IVisualCreator) {
container.appendChild(svgPath)
})
- this.clusters.centroids.forEach(point => {
+ this.clusters.centroids.forEach((point) => {
VoronoiVisual.drawClusterCenter(point, container)
})
@@ -172,7 +172,7 @@ export class PolygonVisual extends BaseClass(IVisualCreator) {
let generalPath = new GeneralPath()
if (clusterNodeBounds.length > 1) {
const points = new YList()
- clusterNodeBounds.forEach(layout => {
+ clusterNodeBounds.forEach((layout) => {
const offset = 0
const x = layout.x
const y = layout.y
diff --git a/demos/analysis/clustering/DemoVisuals.ts b/demos/analysis/clustering/DemoVisuals.ts
index f1c018c05..40ff835a7 100644
--- a/demos/analysis/clustering/DemoVisuals.ts
+++ b/demos/analysis/clustering/DemoVisuals.ts
@@ -104,7 +104,7 @@ export class VoronoiVisual
container.appendChild(svgPath)
})
- this.clusters.centroids.forEach(point => {
+ this.clusters.centroids.forEach((point) => {
VoronoiVisual.drawClusterCenter(point, container)
})
@@ -185,7 +185,7 @@ export class PolygonVisual
let generalPath: GeneralPath = new GeneralPath()
if (clusterNodeBounds.length > 1) {
const points = new YList()
- clusterNodeBounds.forEach(layout => {
+ clusterNodeBounds.forEach((layout) => {
const offset = 0
const x = layout.x
const y = layout.y
@@ -254,7 +254,10 @@ export class AxisVisual
extends BaseClass(IVisualCreator)
implements IVisualCreator
{
- constructor(private maxY: number, private rect: Rect) {
+ constructor(
+ private maxY: number,
+ private rect: Rect
+ ) {
super()
}
@@ -338,7 +341,10 @@ export class CutoffVisual
{
public cutOffValue: number
- constructor(public rectangle: IRectangle, private readonly maxY: number) {
+ constructor(
+ public rectangle: IRectangle,
+ private readonly maxY: number
+ ) {
super()
this.rectangle = rectangle
this.maxY = maxY
diff --git a/demos/analysis/clustering/DendrogramSupport.js b/demos/analysis/clustering/DendrogramSupport.js
index 13e106940..a2ae01a2d 100644
--- a/demos/analysis/clustering/DendrogramSupport.js
+++ b/demos/analysis/clustering/DendrogramSupport.js
@@ -227,14 +227,14 @@ export class DendrogramComponent {
layers.set(hierarchicClusteredNode, layer)
maxLayer = Math.max(layer, maxLayer)
- node.children.forEach(child => {
+ node.children.forEach((child) => {
stack.push(child)
})
}
// calculate the distance values and move all leaf-nodes to the bottommost layer
const distanceValues = new Mapper()
- hierarchicalGraph.nodes.forEach(node => {
+ hierarchicalGraph.nodes.forEach((node) => {
// move all leaves at the bottom-most layers
if (hierarchicalGraph.outDegree(node) === 0) {
layers.set(node, maxLayer - 1)
@@ -365,8 +365,8 @@ export class DendrogramComponent {
)
this.visited = new Set()
- result.clusters.forEach(cluster => {
- cluster.nodes.forEach(node => {
+ result.clusters.forEach((cluster) => {
+ cluster.nodes.forEach((node) => {
// get the color of the cluster in the original graph
const color = colors[result.nodeClusterIds.get(node)]
if (result.getDendrogramNode(node)) {
@@ -380,7 +380,7 @@ export class DendrogramComponent {
this.updateNodeStyle(hierarchicalParent, color)
// update the style of the out-edges
- this.dendrogramComponent.graph.outEdgesAt(hierarchicalParent).forEach(edge => {
+ this.dendrogramComponent.graph.outEdgesAt(hierarchicalParent).forEach((edge) => {
this.updateEdgeStyle(edge, color)
})
this.visited.add(parent)
@@ -441,7 +441,7 @@ export class DendrogramComponent {
const stack = [dendrogramNode]
while (stack.length > 0) {
const descendant = stack.pop()
- descendant.children.forEach(childNode => {
+ descendant.children.forEach((childNode) => {
highlightIndicatorManager.addHighlight(this.dendro2hierarchical.get(childNode))
stack.push(childNode)
})
@@ -590,7 +590,7 @@ class DendrogramLayout extends BaseClass(ILayoutAlgorithm) {
const distanceValues = graph.getDataProvider(DendrogramLayout.DISTANCE_VALUES_DP_KEY)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const edges = node.outEdges.toArray()
if (edges.length > 0) {
// apply port constraints so that one of the edges adjacent to the source node uses the right side while
@@ -604,7 +604,7 @@ class DendrogramLayout extends BaseClass(ILayoutAlgorithm) {
})
// use the difference of the distances between the source and the target node as minimum length
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const edgeLength = distanceValues.get(edge.source) - distanceValues.get(edge.target)
edgeLayoutDescriptors.set(
edge,
@@ -630,7 +630,7 @@ class DendrogramLayout extends BaseClass(ILayoutAlgorithm) {
let maxYValue = -Number.MIN_VALUE
let maxDistanceValue = -Number.MIN_VALUE
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const layer = layers.get(node)
if (!layersMap.get(layer)) {
layersMap.set(layer, [])
@@ -641,18 +641,18 @@ class DendrogramLayout extends BaseClass(ILayoutAlgorithm) {
})
this.maxY = -Number.MIN_VALUE
- layersMap.forEach(layerNodes => {
- layerNodes.forEach(node => {
+ layersMap.forEach((layerNodes) => {
+ layerNodes.forEach((node) => {
const distanceValue = distanceValues.get(node)
const newY = maxYValue - distanceValue
// adjust the node center
graph.setCenter(node, graph.getCenterX(node), newY)
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
// move also the bends
const points = graph.getPointList(edge)
const newBendPositions = new YList()
- points.forEach(point => {
+ points.forEach((point) => {
newBendPositions.add(new YPoint(point.x, newY))
})
graph.setPoints(edge, newBendPositions)
@@ -666,7 +666,7 @@ class DendrogramLayout extends BaseClass(ILayoutAlgorithm) {
// bends of the
this.adjustXCoordinates(graph, graph.nodes.at(0))
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const updatedPath = new YList()
updatedPath.add(new YPoint(graph.getCenterX(edge.target), graph.getCenterY(edge.source)))
graph.setPoints(edge, updatedPath)
@@ -686,7 +686,7 @@ class DendrogramLayout extends BaseClass(ILayoutAlgorithm) {
if (root == null) {
return
}
- root.outEdges.forEach(edge => {
+ root.outEdges.forEach((edge) => {
this.adjustXCoordinates(graph, edge.target)
})
diff --git a/demos/analysis/clustering/DendrogramSupport.ts b/demos/analysis/clustering/DendrogramSupport.ts
index 065561f11..e7af28b59 100644
--- a/demos/analysis/clustering/DendrogramSupport.ts
+++ b/demos/analysis/clustering/DendrogramSupport.ts
@@ -225,14 +225,14 @@ export class DendrogramComponent {
layers.set(hierarchicClusteredNode, layer)
maxLayer = Math.max(layer, maxLayer)
- node.children.forEach(child => {
+ node.children.forEach((child) => {
stack.push(child)
})
}
// calculate the distance values and move all leaf-nodes to the bottommost layer
const distanceValues = new Mapper()
- hierarchicalGraph.nodes.forEach(node => {
+ hierarchicalGraph.nodes.forEach((node) => {
// move all leaves at the bottom-most layers
if (hierarchicalGraph.outDegree(node) === 0) {
layers.set(node, maxLayer - 1)
@@ -363,8 +363,8 @@ export class DendrogramComponent {
)
this.visited = new Set()
- result.clusters.forEach(cluster => {
- cluster.nodes.forEach(node => {
+ result.clusters.forEach((cluster) => {
+ cluster.nodes.forEach((node) => {
// get the color of the cluster in the original graph
const color = colors[result.nodeClusterIds.get(node)!]
if (result.getDendrogramNode(node)) {
@@ -378,7 +378,7 @@ export class DendrogramComponent {
this.updateNodeStyle(hierarchicalParent, color)
// update the style of the out-edges
- this.dendrogramComponent.graph.outEdgesAt(hierarchicalParent).forEach(edge => {
+ this.dendrogramComponent.graph.outEdgesAt(hierarchicalParent).forEach((edge) => {
this.updateEdgeStyle(edge, color)
})
this.visited.add(parent)
@@ -439,7 +439,7 @@ export class DendrogramComponent {
const stack: DendrogramNode[] = [dendrogramNode]
while (stack.length > 0) {
const descendant = stack.pop()!
- descendant.children.forEach(childNode => {
+ descendant.children.forEach((childNode) => {
highlightIndicatorManager.addHighlight(this.dendro2hierarchical.get(childNode)!)
stack.push(childNode)
})
@@ -588,7 +588,7 @@ class DendrogramLayout
const distanceValues = graph.getDataProvider(DendrogramLayout.DISTANCE_VALUES_DP_KEY)!
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const edges = node.outEdges.toArray()
if (edges.length > 0) {
// apply port constraints so that one of the edges adjacent to the source node uses the right side while
@@ -602,7 +602,7 @@ class DendrogramLayout
})
// use the difference of the distances between the source and the target node as minimum length
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const edgeLength = distanceValues.get(edge.source) - distanceValues.get(edge.target)
edgeLayoutDescriptors.set(
edge,
@@ -628,7 +628,7 @@ class DendrogramLayout
let maxYValue: number = -Number.MIN_VALUE
let maxDistanceValue: number = -Number.MIN_VALUE
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const layer = layers.get(node)
if (!layersMap.get(layer)) {
layersMap.set(layer, [])
@@ -639,18 +639,18 @@ class DendrogramLayout
})
this.maxY = -Number.MIN_VALUE
- layersMap.forEach(layerNodes => {
- layerNodes.forEach(node => {
+ layersMap.forEach((layerNodes) => {
+ layerNodes.forEach((node) => {
const distanceValue = distanceValues.get(node)
const newY = maxYValue - distanceValue
// adjust the node center
graph.setCenter(node, graph.getCenterX(node), newY)
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
// move also the bends
const points = graph.getPointList(edge)
const newBendPositions = new YList()
- points.forEach(point => {
+ points.forEach((point) => {
newBendPositions.add(new YPoint(point.x, newY))
})
graph.setPoints(edge, newBendPositions)
@@ -664,7 +664,7 @@ class DendrogramLayout
// bends of the
this.adjustXCoordinates(graph, graph.nodes.at(0))
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const updatedPath = new YList()
updatedPath.add(new YPoint(graph.getCenterX(edge.target), graph.getCenterY(edge.source)))
graph.setPoints(edge, updatedPath)
@@ -683,7 +683,7 @@ class DendrogramLayout
if (root == null) {
return
}
- root.outEdges.forEach(edge => {
+ root.outEdges.forEach((edge) => {
this.adjustXCoordinates(graph, edge.target)
})
diff --git a/demos/analysis/clustering/VoronoiDiagram.js b/demos/analysis/clustering/VoronoiDiagram.js
index cc99d72ca..57976f5b1 100644
--- a/demos/analysis/clustering/VoronoiDiagram.js
+++ b/demos/analysis/clustering/VoronoiDiagram.js
@@ -91,7 +91,7 @@ export class VoronoiDiagram {
const existOnlyTwoFaces = faces.size === 2
let externalFaceFound = false
- faces.forEach(face => {
+ faces.forEach((face) => {
// for each face, except the outerFace add a Voronoi node for this face that lies on the faces circumcenter
if (!face.outer || (existOnlyTwoFaces && externalFaceFound)) {
const circumcenter = face.calculateCircumcenter()
@@ -135,10 +135,10 @@ export class VoronoiDiagram {
const edges = outerFace != null ? outerFace.edges : []
const outerFaceEdges = new Set(edges)
const visitedEdges = new Set()
- faces.forEach(face => {
+ faces.forEach((face) => {
if (!face.outer || (existOnlyTwoFaces && face.circumcenter)) {
const circumcenter = face.circumcenter
- face.edges.forEach(edge => {
+ face.edges.forEach((edge) => {
const oppositeEdge = edge.target.getEdge(edge.source)
if (!visitedEdges.has(edge) && !visitedEdges.has(oppositeEdge)) {
visitedEdges.add(edge)
@@ -334,7 +334,7 @@ export class VoronoiDiagram {
// determine which nodes of the graph belong to the boundary so that we connect the consecutive ones and create
// the Voronoi areas
const boundaryNodes = []
- voronoiGraph.nodes.forEach(node => {
+ voronoiGraph.nodes.forEach((node) => {
if (this.belongsToBoundary(voronoiNodeCoordinates.get(node))) {
boundaryNodes.push(node)
}
@@ -381,7 +381,7 @@ export class VoronoiDiagram {
// remove nodes that might lie on the exterior of the graph's bounding box, these can occur only if a
// circumcenter lies on the exterior of the bounding box after the triangulation
- voronoiGraph.nodes.toArray().forEach(node => {
+ voronoiGraph.nodes.toArray().forEach((node) => {
if (node.degree === 0) {
voronoiGraph.removeNode(node)
}
@@ -404,7 +404,7 @@ export class VoronoiDiagram {
const revMap = delauneyGraph.createEdgeMap()
// fill the pointData with the coordinates of the nodes of the delauney graph
- this.centroids.forEach(centroid => {
+ this.centroids.forEach((centroid) => {
const center = delauneyGraph.createNode()
pointData.set(center, new YPoint(centroid.x, centroid.y))
})
@@ -443,7 +443,7 @@ export class VoronoiDiagram {
calculateDelauneyFaces(graph, reversedEdgesMap, coordinatesMap, edge2face) {
const mark = []
const faceList = new List()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (!mark[edge.index]) {
const face = this.createFace(edge, mark, reversedEdgesMap)
faceList.add(face)
@@ -451,8 +451,8 @@ export class VoronoiDiagram {
}
})
- faceList.forEach(face => {
- face.edges.forEach(edge => {
+ faceList.forEach((face) => {
+ face.edges.forEach((edge) => {
this.addEdgeToFace(edge, face, edge2face)
this.addEdgeToFace(reversedEdgesMap.get(edge), face, edge2face)
})
@@ -616,7 +616,7 @@ export class VoronoiDiagram {
// for each edge segment, we create two darts, one for each direction s -> t and t -> s
let index = -1
- voronoiGraph.edges.forEach(edge => {
+ voronoiGraph.edges.forEach((edge) => {
const source = edge.source
const target = edge.target
const dart1 = new VoronoiDart(source, target, edge, index++)
@@ -640,7 +640,7 @@ export class VoronoiDiagram {
})
// for each dart, we calculate the angle that creates with the x-axis in counter-clockwise order
- darts.forEach(dart => {
+ darts.forEach((dart) => {
const sourceCenter = voronoiNodeCoordinates.get(dart.source)
const targetCenter = voronoiNodeCoordinates.get(dart.target)
const angle = Math.atan2(sourceCenter.y - targetCenter.y, sourceCenter.x - targetCenter.x)
@@ -648,7 +648,7 @@ export class VoronoiDiagram {
})
// we sort the darts around their origin based on the angle the form with the x-axis
- voronoiGraph.nodes.forEach(node => {
+ voronoiGraph.nodes.forEach((node) => {
const nodeDarts = node2Darts.get(node)
if (nodeDarts !== null) {
nodeDarts.sort((dart1, dart2) => {
@@ -668,7 +668,7 @@ export class VoronoiDiagram {
// we iterate over the darts to create the faces
const faces = []
- darts.forEach(dart => {
+ darts.forEach((dart) => {
const face = []
if (!dart.marked) {
let d = dart
@@ -697,7 +697,7 @@ export class VoronoiDiagram {
// we create the general paths that form the geometric face
const voronoiFaces = []
- faces.forEach(face => {
+ faces.forEach((face) => {
if (face.length > 2) {
const facePath = new GeneralPath()
for (let i = 0; i < face.length - 1; i++) {
@@ -856,8 +856,6 @@ class VoronoiFace {
*/
outer = false
- constructor() {}
-
/**
* Adds the given edges to the list of edges of the given face.
* @param {!Edge} edge The edge to add
diff --git a/demos/analysis/clustering/VoronoiDiagram.ts b/demos/analysis/clustering/VoronoiDiagram.ts
index 7476aadc3..b1a66b29d 100644
--- a/demos/analysis/clustering/VoronoiDiagram.ts
+++ b/demos/analysis/clustering/VoronoiDiagram.ts
@@ -89,7 +89,7 @@ export class VoronoiDiagram {
const existOnlyTwoFaces = faces.size === 2
let externalFaceFound = false
- faces.forEach(face => {
+ faces.forEach((face) => {
// for each face, except the outerFace add a Voronoi node for this face that lies on the faces circumcenter
if (!face.outer || (existOnlyTwoFaces && externalFaceFound)) {
const circumcenter = face.calculateCircumcenter()
@@ -133,10 +133,10 @@ export class VoronoiDiagram {
const edges: Edge[] = outerFace != null ? (outerFace as VoronoiFace).edges : []
const outerFaceEdges = new Set(edges)
const visitedEdges = new Set()
- faces.forEach(face => {
+ faces.forEach((face) => {
if (!face.outer || (existOnlyTwoFaces && face.circumcenter)) {
const circumcenter = face.circumcenter!
- face.edges.forEach(edge => {
+ face.edges.forEach((edge) => {
const oppositeEdge = edge.target.getEdge(edge.source)!
if (!visitedEdges.has(edge) && !visitedEdges.has(oppositeEdge)) {
visitedEdges.add(edge)
@@ -332,7 +332,7 @@ export class VoronoiDiagram {
// determine which nodes of the graph belong to the boundary so that we connect the consecutive ones and create
// the Voronoi areas
const boundaryNodes: YNode[] = []
- voronoiGraph.nodes.forEach(node => {
+ voronoiGraph.nodes.forEach((node) => {
if (this.belongsToBoundary(voronoiNodeCoordinates.get(node))) {
boundaryNodes.push(node)
}
@@ -379,7 +379,7 @@ export class VoronoiDiagram {
// remove nodes that might lie on the exterior of the graph's bounding box, these can occur only if a
// circumcenter lies on the exterior of the bounding box after the triangulation
- voronoiGraph.nodes.toArray().forEach(node => {
+ voronoiGraph.nodes.toArray().forEach((node) => {
if (node.degree === 0) {
voronoiGraph.removeNode(node)
}
@@ -405,7 +405,7 @@ export class VoronoiDiagram {
const revMap = delauneyGraph.createEdgeMap()
// fill the pointData with the coordinates of the nodes of the delauney graph
- this.centroids.forEach(centroid => {
+ this.centroids.forEach((centroid) => {
const center = delauneyGraph.createNode()
pointData.set(center, new YPoint(centroid.x, centroid.y))
})
@@ -449,7 +449,7 @@ export class VoronoiDiagram {
): IEnumerable {
const mark: boolean[] = []
const faceList = new List()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (!mark[edge.index]) {
const face = this.createFace(edge, mark, reversedEdgesMap)
faceList.add(face)
@@ -457,8 +457,8 @@ export class VoronoiDiagram {
}
})
- faceList.forEach(face => {
- face.edges.forEach(edge => {
+ faceList.forEach((face) => {
+ face.edges.forEach((edge) => {
this.addEdgeToFace(edge, face, edge2face)
this.addEdgeToFace(reversedEdgesMap.get(edge), face, edge2face)
})
@@ -627,7 +627,7 @@ export class VoronoiDiagram {
// for each edge segment, we create two darts, one for each direction s -> t and t -> s
let index = -1
- voronoiGraph.edges.forEach(edge => {
+ voronoiGraph.edges.forEach((edge) => {
const source = edge.source
const target = edge.target
const dart1 = new VoronoiDart(source, target, edge, index++)
@@ -651,7 +651,7 @@ export class VoronoiDiagram {
})
// for each dart, we calculate the angle that creates with the x-axis in counter-clockwise order
- darts.forEach(dart => {
+ darts.forEach((dart) => {
const sourceCenter = voronoiNodeCoordinates.get(dart.source)
const targetCenter = voronoiNodeCoordinates.get(dart.target)
const angle = Math.atan2(sourceCenter.y - targetCenter.y, sourceCenter.x - targetCenter.x)
@@ -659,7 +659,7 @@ export class VoronoiDiagram {
})
// we sort the darts around their origin based on the angle the form with the x-axis
- voronoiGraph.nodes.forEach(node => {
+ voronoiGraph.nodes.forEach((node) => {
const nodeDarts = node2Darts.get(node)
if (nodeDarts !== null) {
nodeDarts.sort((dart1, dart2) => {
@@ -679,7 +679,7 @@ export class VoronoiDiagram {
// we iterate over the darts to create the faces
const faces: VoronoiDart[][] = []
- darts.forEach(dart => {
+ darts.forEach((dart) => {
const face: VoronoiDart[] = []
if (!dart.marked) {
let d: VoronoiDart = dart
@@ -708,7 +708,7 @@ export class VoronoiDiagram {
// we create the general paths that form the geometric face
const voronoiFaces: GeneralPath[] = []
- faces.forEach(face => {
+ faces.forEach((face) => {
if (face.length > 2) {
const facePath = new GeneralPath()
for (let i = 0; i < face.length - 1; i++) {
@@ -866,8 +866,6 @@ class VoronoiFace {
*/
outer = false
- constructor() {}
-
/**
* Adds the given edges to the list of edges of the given face.
* @param edge The edge to add
diff --git a/demos/analysis/clustering/index.html b/demos/analysis/clustering/index.html
index d7a37a7b3..6be434b0d 100644
--- a/demos/analysis/clustering/index.html
+++ b/demos/analysis/clustering/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.js b/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.js
index 793634b18..3fde2234f 100644
--- a/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.js
+++ b/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.js
@@ -102,7 +102,7 @@ function showResult(graphComponent) {
const startNodeStyle = createDemoNodeStyle('demo-palette-402')
const finishNodeStyle = createDemoNodeStyle('demo-palette-403')
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const sourceNode = edge.sourceNode
const targetNode = edge.targetNode
@@ -181,7 +181,7 @@ function loadSampleGraph(graphComponent) {
builder.buildGraph()
// we add a label that shows the duration of each task
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.labels.get(0).text !== 'START' && node.labels.get(0).text !== 'FINISH') {
graph.addLabel(node, `${node.tag.duration} d`, InteriorLabelModel.CENTER)
}
diff --git a/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.ts b/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.ts
index efa0ec2bd..94fc84b22 100644
--- a/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.ts
+++ b/demos/analysis/criticalpathanalysis/CriticalPathAnalysisDemo.ts
@@ -101,7 +101,7 @@ function showResult(graphComponent: GraphComponent) {
const startNodeStyle = createDemoNodeStyle('demo-palette-402')
const finishNodeStyle = createDemoNodeStyle('demo-palette-403')
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const sourceNode = edge.sourceNode!
const targetNode = edge.targetNode!
@@ -180,7 +180,7 @@ function loadSampleGraph(graphComponent: GraphComponent) {
builder.buildGraph()
// we add a label that shows the duration of each task
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.labels.get(0).text !== 'START' && node.labels.get(0).text !== 'FINISH') {
graph.addLabel(node, `${node.tag.duration} d`, InteriorLabelModel.CENTER)
}
diff --git a/demos/analysis/criticalpathanalysis/CriticalPathHelper.js b/demos/analysis/criticalpathanalysis/CriticalPathHelper.js
index be361bcc2..a3f077ff6 100644
--- a/demos/analysis/criticalpathanalysis/CriticalPathHelper.js
+++ b/demos/analysis/criticalpathanalysis/CriticalPathHelper.js
@@ -51,9 +51,9 @@ import {
export function calculateCriticalPathEdges(graphComponent) {
const graph = graphComponent.graph
// the duration of each task is stored in the node's tag
- const taskDuration = node => node.tag.duration | 0
+ const taskDuration = (node) => node.tag.duration | 0
// the duration when moving from the source's task to the target's task
- const transitionDuration = edge => edge.tag.transitionDuration | 0
+ const transitionDuration = (edge) => edge.tag.transitionDuration | 0
// runs the rank assignment algorithm to calculate the ranks and the slacks
const results = calculateRanksAndSlacks(graph, taskDuration, transitionDuration)
@@ -74,7 +74,7 @@ export function calculateCriticalPathEdges(graphComponent) {
// adds the result information to the edges' tags
const criticalEdgeSet = new Set(criticalPathEdges)
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge.tag.slack = results.slack(edge)
if (criticalEdgeSet.has(edge)) {
edge.tag.critical = true
@@ -88,7 +88,7 @@ export function calculateCriticalPathEdges(graphComponent) {
*/
export function findHighestLowestNodes(graph) {
const order = graph.nodes.orderBy(
- node => node.tag.layerId || 0,
+ (node) => node.tag.layerId || 0,
(a, b) => Math.sign(Number(a) - Number(b))
)
const lowestNode = order.first()
@@ -108,23 +108,23 @@ export function findHighestLowestNodes(graph) {
function calculateRanksAndSlacks(graph, taskDuration, transitionDuration) {
// for each edge the min distance is the time needed for the task of each source node to be completed
// plus the time needed to move from the source task to the target task
- const minDistance = edge => {
+ const minDistance = (edge) => {
return transitionDuration(edge) + taskDuration(edge.sourceNode)
}
// run the rank assignment algorithm
const rankAssignmentResult = new RankAssignment({
- minimumEdgeLengths: edge => transitionDuration(edge) + taskDuration(edge.sourceNode)
+ minimumEdgeLengths: (edge) => transitionDuration(edge) + taskDuration(edge.sourceNode)
}).run(graph)
// store the ranking of each node at its tag
const rankIds = rankAssignmentResult.nodeRankIds
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
node.tag.layerId = rankIds.get(node) || 0
})
return {
- slack: edge =>
+ slack: (edge) =>
(rankIds.get(edge.targetNode) || 0) - (rankIds.get(edge.sourceNode) || 0) - minDistance(edge)
}
}
@@ -148,9 +148,9 @@ export async function runLayout(graphComponent) {
const layoutData = new HierarchicLayoutData({
// the information about the layering is stored in the node tags
- givenLayersLayererIds: node => node.tag.layerId,
+ givenLayersLayererIds: (node) => node.tag.layerId,
// edges that belong to the critical path have priority
- criticalEdgePriorities: edge => (edge.tag.critical ? 1 : 0),
+ criticalEdgePriorities: (edge) => (edge.tag.critical ? 1 : 0),
// configure the edge placement
edgeLabelPreferredPlacement: () => {
const preferredPlacementDescriptor = new PreferredPlacementDescriptor()
diff --git a/demos/analysis/criticalpathanalysis/CriticalPathHelper.ts b/demos/analysis/criticalpathanalysis/CriticalPathHelper.ts
index d056f57e9..3b25be6da 100644
--- a/demos/analysis/criticalpathanalysis/CriticalPathHelper.ts
+++ b/demos/analysis/criticalpathanalysis/CriticalPathHelper.ts
@@ -74,7 +74,7 @@ export function calculateCriticalPathEdges(graphComponent: GraphComponent) {
// adds the result information to the edges' tags
const criticalEdgeSet = new Set(criticalPathEdges)
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge.tag.slack = results.slack(edge)
if (criticalEdgeSet.has(edge)) {
edge.tag.critical = true
@@ -88,7 +88,7 @@ export function calculateCriticalPathEdges(graphComponent: GraphComponent) {
*/
export function findHighestLowestNodes(graph: IGraph) {
const order = graph.nodes.orderBy(
- node => node.tag.layerId || 0,
+ (node) => node.tag.layerId || 0,
(a, b) => Math.sign(Number(a) - Number(b))
)
const lowestNode = order.first()
@@ -117,17 +117,17 @@ function calculateRanksAndSlacks(
// run the rank assignment algorithm
const rankAssignmentResult = new RankAssignment({
- minimumEdgeLengths: edge => transitionDuration(edge) + taskDuration(edge.sourceNode!)
+ minimumEdgeLengths: (edge) => transitionDuration(edge) + taskDuration(edge.sourceNode!)
}).run(graph)
// store the ranking of each node at its tag
const rankIds = rankAssignmentResult.nodeRankIds
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
node.tag.layerId = rankIds.get(node) || 0
})
return {
- slack: edge =>
+ slack: (edge) =>
(rankIds.get(edge.targetNode) || 0) - (rankIds.get(edge.sourceNode) || 0) - minDistance(edge)
}
}
@@ -150,9 +150,9 @@ export async function runLayout(graphComponent: GraphComponent): Promise {
const layoutData = new HierarchicLayoutData({
// the information about the layering is stored in the node tags
- givenLayersLayererIds: node => node.tag.layerId,
+ givenLayersLayererIds: (node) => node.tag.layerId,
// edges that belong to the critical path have priority
- criticalEdgePriorities: edge => (edge.tag.critical ? 1 : 0),
+ criticalEdgePriorities: (edge) => (edge.tag.critical ? 1 : 0),
// configure the edge placement
edgeLabelPreferredPlacement: () => {
const preferredPlacementDescriptor = new PreferredPlacementDescriptor()
diff --git a/demos/analysis/criticalpathanalysis/index.html b/demos/analysis/criticalpathanalysis/index.html
index 4643e4bb2..536203ae0 100644
--- a/demos/analysis/criticalpathanalysis/index.html
+++ b/demos/analysis/criticalpathanalysis/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/analysis/intersection-detection/DemoVisuals.js b/demos/analysis/intersection-detection/DemoVisuals.js
index 944ff156a..0c3772399 100644
--- a/demos/analysis/intersection-detection/DemoVisuals.js
+++ b/demos/analysis/intersection-detection/DemoVisuals.js
@@ -55,13 +55,6 @@ const LABEL_INTERSECTION_COLOR_STROKE = Color.from(colorSets['demo-green'].strok
export class IntersectionVisualCreator extends BaseClass(IVisualCreator) {
intersections = []
- /**
- * Creates a new instance.
- */
- constructor() {
- super()
- }
-
/**
* Creates the visual showing the intersections found by the intersection algorithm.
* @param {!IRenderContext} context The context that describes where the visual will be used
diff --git a/demos/analysis/intersection-detection/DemoVisuals.ts b/demos/analysis/intersection-detection/DemoVisuals.ts
index df7273cbf..38cb1e768 100644
--- a/demos/analysis/intersection-detection/DemoVisuals.ts
+++ b/demos/analysis/intersection-detection/DemoVisuals.ts
@@ -58,13 +58,6 @@ export class IntersectionVisualCreator
{
public intersections: Intersection[] = []
- /**
- * Creates a new instance.
- */
- constructor() {
- super()
- }
-
/**
* Creates the visual showing the intersections found by the intersection algorithm.
* @param context The context that describes where the visual will be used
diff --git a/demos/analysis/intersection-detection/IntersectionDetectionDemo.js b/demos/analysis/intersection-detection/IntersectionDetectionDemo.js
index 6e03f312b..0169b0260 100644
--- a/demos/analysis/intersection-detection/IntersectionDetectionDemo.js
+++ b/demos/analysis/intersection-detection/IntersectionDetectionDemo.js
@@ -178,7 +178,7 @@ function runIntersectionAlgorithm() {
// whether to consider only the selected elements
if (considerSelectionBox.checked) {
- intersections.affectedItems.delegate = item => graphComponent.selection.isSelected(item)
+ intersections.affectedItems.delegate = (item) => graphComponent.selection.isSelected(item)
}
// run the algorithm and obtain the result
@@ -250,10 +250,10 @@ function initializeIntersectionVisual() {
function loadSampleGraph(graph) {
const builder = new GraphBuilder(graph)
const ns = builder.createNodesSource({
- data: GraphData.nodeList.filter(data => !data.isGroup),
+ data: GraphData.nodeList.filter((data) => !data.isGroup),
id: 'id',
layout: 'layout',
- parentId: dataItem => dataItem.parent
+ parentId: (dataItem) => dataItem.parent
})
ns.nodeCreator.addNodeCreatedListener((_, evt) => {
if (evt.dataItem.isEllipse) {
@@ -268,8 +268,10 @@ function loadSampleGraph(graph) {
)
}
})
- const nodeLabelCreator = ns.nodeCreator.createLabelsSource(data => data.labels || []).labelCreator
- nodeLabelCreator.textProvider = data => data.text || ''
+ const nodeLabelCreator = ns.nodeCreator.createLabelsSource(
+ (data) => data.labels || []
+ ).labelCreator
+ nodeLabelCreator.textProvider = (data) => data.text || ''
nodeLabelCreator.addLabelAddedListener((_, evt) => {
const label = evt.item
const data = evt.dataItem
@@ -284,14 +286,14 @@ function loadSampleGraph(graph) {
})
const groupSource = builder.createGroupNodesSource({
- data: GraphData.nodeList.filter(data => data.isGroup),
+ data: GraphData.nodeList.filter((data) => data.isGroup),
id: 'id',
layout: 'layout'
})
const groupLabelCreator = groupSource.nodeCreator.createLabelsSource(
- data => data.labels
+ (data) => data.labels
).labelCreator
- groupLabelCreator.textProvider = data => data.text || ''
+ groupLabelCreator.textProvider = (data) => data.text || ''
const es = builder.createEdgesSource({
data: GraphData.edgeList,
@@ -300,8 +302,10 @@ function loadSampleGraph(graph) {
targetId: 'target',
bends: 'bends'
})
- const edgeLabelCreator = es.edgeCreator.createLabelsSource(data => data.labels || []).labelCreator
- edgeLabelCreator.textProvider = data => data.text || ''
+ const edgeLabelCreator = es.edgeCreator.createLabelsSource(
+ (data) => data.labels || []
+ ).labelCreator
+ edgeLabelCreator.textProvider = (data) => data.text || ''
edgeLabelCreator.addLabelAddedListener((_, evt) => {
const label = evt.item
const data = evt.dataItem
@@ -317,7 +321,7 @@ function loadSampleGraph(graph) {
builder.buildGraph()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (edge.tag.sourcePort) {
graph.setPortLocation(edge.sourcePort, Point.from(edge.tag.sourcePort))
}
@@ -363,7 +367,7 @@ function initializeGraph(graphComponent) {
graph.decorator.portDecorator.edgePathCropperDecorator.setImplementation(
new DefaultEdgePathCropper({ cropAtPort: false, extraCropLength: 0 })
)
- graph.decorator.labelDecorator.positionHandlerDecorator.setFactory(label => {
+ graph.decorator.labelDecorator.positionHandlerDecorator.setFactory((label) => {
const positionHandler = new LabelPositionHandler(label)
positionHandler.visualization = Visualization.LIVE
return positionHandler
diff --git a/demos/analysis/intersection-detection/IntersectionDetectionDemo.ts b/demos/analysis/intersection-detection/IntersectionDetectionDemo.ts
index d60693897..1f47003eb 100644
--- a/demos/analysis/intersection-detection/IntersectionDetectionDemo.ts
+++ b/demos/analysis/intersection-detection/IntersectionDetectionDemo.ts
@@ -174,7 +174,7 @@ function runIntersectionAlgorithm(): void {
// whether to consider only the selected elements
if (considerSelectionBox.checked) {
- intersections.affectedItems.delegate = item => graphComponent.selection.isSelected(item)
+ intersections.affectedItems.delegate = (item) => graphComponent.selection.isSelected(item)
}
// run the algorithm and obtain the result
@@ -243,10 +243,10 @@ function initializeIntersectionVisual(): void {
function loadSampleGraph(graph: IGraph): void {
const builder = new GraphBuilder(graph)
const ns = builder.createNodesSource({
- data: GraphData.nodeList.filter(data => !data.isGroup),
+ data: GraphData.nodeList.filter((data) => !data.isGroup),
id: 'id',
layout: 'layout',
- parentId: dataItem => dataItem.parent
+ parentId: (dataItem) => dataItem.parent
})
ns.nodeCreator.addNodeCreatedListener((_, evt) => {
if (evt.dataItem.isEllipse) {
@@ -261,8 +261,10 @@ function loadSampleGraph(graph: IGraph): void {
)
}
})
- const nodeLabelCreator = ns.nodeCreator.createLabelsSource(data => data.labels || []).labelCreator
- nodeLabelCreator.textProvider = data => data.text || ''
+ const nodeLabelCreator = ns.nodeCreator.createLabelsSource(
+ (data) => data.labels || []
+ ).labelCreator
+ nodeLabelCreator.textProvider = (data) => data.text || ''
nodeLabelCreator.addLabelAddedListener((_, evt) => {
const label = evt.item
const data = evt.dataItem
@@ -277,14 +279,14 @@ function loadSampleGraph(graph: IGraph): void {
})
const groupSource = builder.createGroupNodesSource({
- data: GraphData.nodeList.filter(data => data.isGroup),
+ data: GraphData.nodeList.filter((data) => data.isGroup),
id: 'id',
layout: 'layout'
})
const groupLabelCreator = groupSource.nodeCreator.createLabelsSource(
- data => data.labels
+ (data) => data.labels
).labelCreator
- groupLabelCreator.textProvider = data => data.text || ''
+ groupLabelCreator.textProvider = (data) => data.text || ''
const es = builder.createEdgesSource({
data: GraphData.edgeList,
@@ -293,8 +295,10 @@ function loadSampleGraph(graph: IGraph): void {
targetId: 'target',
bends: 'bends'
})
- const edgeLabelCreator = es.edgeCreator.createLabelsSource(data => data.labels || []).labelCreator
- edgeLabelCreator.textProvider = data => data.text || ''
+ const edgeLabelCreator = es.edgeCreator.createLabelsSource(
+ (data) => data.labels || []
+ ).labelCreator
+ edgeLabelCreator.textProvider = (data) => data.text || ''
edgeLabelCreator.addLabelAddedListener((_, evt) => {
const label = evt.item
const data = evt.dataItem
@@ -310,7 +314,7 @@ function loadSampleGraph(graph: IGraph): void {
builder.buildGraph()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (edge.tag.sourcePort) {
graph.setPortLocation(edge.sourcePort!, Point.from(edge.tag.sourcePort))
}
@@ -355,7 +359,7 @@ function initializeGraph(graphComponent: GraphComponent): void {
graph.decorator.portDecorator.edgePathCropperDecorator.setImplementation(
new DefaultEdgePathCropper({ cropAtPort: false, extraCropLength: 0 })
)
- graph.decorator.labelDecorator.positionHandlerDecorator.setFactory(label => {
+ graph.decorator.labelDecorator.positionHandlerDecorator.setFactory((label) => {
const positionHandler = new LabelPositionHandler(label)
positionHandler.visualization = Visualization.LIVE
return positionHandler
diff --git a/demos/analysis/intersection-detection/TooltipHelper.js b/demos/analysis/intersection-detection/TooltipHelper.js
index f04cb3f7a..caee8cbb5 100644
--- a/demos/analysis/intersection-detection/TooltipHelper.js
+++ b/demos/analysis/intersection-detection/TooltipHelper.js
@@ -38,7 +38,7 @@ import { IEdge, IModelItem, INode, Intersection, Point } from 'yfiles'
*/
export function createToolTipContent(item, intersectionInfoArray) {
const filteredIntersections = intersectionInfoArray.filter(
- intersection => item === intersection.item1 || item === intersection.item2
+ (intersection) => item === intersection.item1 || item === intersection.item2
)
if (filteredIntersections.length === 0) {
return null
diff --git a/demos/analysis/intersection-detection/TooltipHelper.ts b/demos/analysis/intersection-detection/TooltipHelper.ts
index 263c7522b..ff00b5d8e 100644
--- a/demos/analysis/intersection-detection/TooltipHelper.ts
+++ b/demos/analysis/intersection-detection/TooltipHelper.ts
@@ -38,7 +38,7 @@ export function createToolTipContent(
intersectionInfoArray: Intersection[]
): HTMLElement | null {
const filteredIntersections = intersectionInfoArray.filter(
- intersection => item === intersection.item1 || item === intersection.item2
+ (intersection) => item === intersection.item1 || item === intersection.item2
)
if (filteredIntersections.length === 0) {
return null
diff --git a/demos/analysis/intersection-detection/index.html b/demos/analysis/intersection-detection/index.html
index b742a94f6..69da9c4e4 100644
--- a/demos/analysis/intersection-detection/index.html
+++ b/demos/analysis/intersection-detection/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/analysis/networkflows/DemoStyles.js b/demos/analysis/networkflows/DemoStyles.js
index d4b2f9d06..0e1fc8f0c 100644
--- a/demos/analysis/networkflows/DemoStyles.js
+++ b/demos/analysis/networkflows/DemoStyles.js
@@ -552,7 +552,7 @@ export class NetworkFlowEdgeStyle extends EdgeStyleBase {
gradientsToRemove.push(child)
}
}
- gradientsToRemove.forEach(gradient => defs.removeChild(gradient))
+ gradientsToRemove.forEach((gradient) => defs.removeChild(gradient))
}
/**
@@ -609,7 +609,7 @@ export class NetworkFlowEdgeStyle extends EdgeStyleBase {
const path = new GeneralPath()
path.moveTo(edge.sourcePort.location)
path.lineTo(edge.sourcePort.location.add(new Point(5, 0)))
- edge.bends.forEach(bend => path.lineTo(bend.location))
+ edge.bends.forEach((bend) => path.lineTo(bend.location))
path.lineTo(edge.targetPort.location.subtract(new Point(5, 0)))
path.lineTo(edge.targetPort.location)
return path
@@ -692,7 +692,7 @@ function createAnimatedGradient(linearGradient) {
let previousTime = null
- const frameRequestCallback = timestamp => {
+ const frameRequestCallback = (timestamp) => {
// calculate the time since the last animation frame
if (previousTime == null) {
previousTime = timestamp
diff --git a/demos/analysis/networkflows/DemoStyles.ts b/demos/analysis/networkflows/DemoStyles.ts
index fa59dedf3..d180356dd 100644
--- a/demos/analysis/networkflows/DemoStyles.ts
+++ b/demos/analysis/networkflows/DemoStyles.ts
@@ -560,7 +560,7 @@ export class NetworkFlowEdgeStyle extends EdgeStyleBase {
gradientsToRemove.push(child)
}
}
- gradientsToRemove.forEach(gradient => defs.removeChild(gradient))
+ gradientsToRemove.forEach((gradient) => defs.removeChild(gradient))
}
/**
@@ -617,7 +617,7 @@ export class NetworkFlowEdgeStyle extends EdgeStyleBase {
const path = new GeneralPath()
path.moveTo(edge.sourcePort!.location)
path.lineTo(edge.sourcePort!.location.add(new Point(5, 0)))
- edge.bends.forEach(bend => path.lineTo(bend.location))
+ edge.bends.forEach((bend) => path.lineTo(bend.location))
path.lineTo(edge.targetPort!.location.subtract(new Point(5, 0)))
path.lineTo(edge.targetPort!.location)
return path
@@ -882,7 +882,10 @@ export class MinCutLine extends BaseClass(IVisualCreator) implements IVisualCrea
* The equals method detects if the cache has changed.
*/
class MclRenderDataCache {
- constructor(private bounds: Rect, private visible: boolean) {}
+ constructor(
+ private bounds: Rect,
+ private visible: boolean
+ ) {}
/**
* Checks if the data stored in the given cache is equal to data in this cache.
diff --git a/demos/analysis/networkflows/NetworkFlowsDemo.js b/demos/analysis/networkflows/NetworkFlowsDemo.js
index daa7fcb0c..030849b88 100644
--- a/demos/analysis/networkflows/NetworkFlowsDemo.js
+++ b/demos/analysis/networkflows/NetworkFlowsDemo.js
@@ -285,7 +285,7 @@ function createEditorInputMode() {
const deletedCompoundEdit = graphComponent.graph.beginEdit('Element deleted', 'Element deleted')
// if an edge was removed, calculate the new node size of its endpoints
if (nodesToChange.length > 0) {
- nodesToChange.forEach(node => {
+ nodesToChange.forEach((node) => {
if (graphComponent.graph.contains(node)) {
calculateNodeSize(node)
}
@@ -300,7 +300,7 @@ function createEditorInputMode() {
inputMode.addDeletingSelectionListener((_, evt) => {
edgePopup.currentItem = null
// collect all nodes that are endpoints of removed edges
- evt.selection.forEach(item => {
+ evt.selection.forEach((item) => {
if (item instanceof IEdge) {
nodesToChange.push(item.sourceNode)
nodesToChange.push(item.targetNode)
@@ -365,8 +365,8 @@ function createEditorInputMode() {
function calculateNodeSize(node) {
const graph = graphComponent.graph
- const incomingCapacity = graph.inEdgesAt(node).sum(inEdge => inEdge.tag.capacity)
- const outgoingCapacity = graph.outEdgesAt(node).sum(outEdge => outEdge.tag.capacity)
+ const incomingCapacity = graph.inEdgesAt(node).sum((inEdge) => inEdge.tag.capacity)
+ const outgoingCapacity = graph.outEdgesAt(node).sum((outEdge) => outEdge.tag.capacity)
const height = Math.max(incomingCapacity, outgoingCapacity)
const newBounds = new Rect(node.layout.x, node.layout.y, node.layout.width, Math.max(height, 30))
@@ -411,7 +411,7 @@ function runFlowAlgorithm() {
}
// update the node tags
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
node.tag = { ...node.tag, cut: false, source: false, sink: false }
})
@@ -458,7 +458,7 @@ function calculateMaxFlowMinCut(minCut) {
return 0
}
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const labels = edge.labels
if (labels.size > 1) {
graph.remove(labels.get(1))
@@ -473,13 +473,13 @@ function calculateMaxFlowMinCut(minCut) {
sources: sourceNodes,
sinks: sinkNodes,
// the capacity of an edge is stored in its tag
- capacities: edge => edge.tag.capacity
+ capacities: (edge) => edge.tag.capacity
})
const maxFlowMinCutResult = maxFlowMinCut.run(graph)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const flow = (graph.inDegree(node) > 0 ? graph.inEdgesAt(node) : graph.outEdgesAt(node)).sum(
- edge => maxFlowMinCutResult.flow.get(edge) || 0
+ (edge) => maxFlowMinCutResult.flow.get(edge) || 0
)
node.tag = {
flow,
@@ -488,17 +488,17 @@ function calculateMaxFlowMinCut(minCut) {
}
})
- sourceNodes.forEach(sourceNode => (sourceNode.tag.source = true))
- sinkNodes.forEach(sinkNode => (sinkNode.tag.sink = true))
+ sourceNodes.forEach((sourceNode) => (sourceNode.tag.source = true))
+ sinkNodes.forEach((sinkNode) => (sinkNode.tag.sink = true))
// add the flow values as tags to edges
maxFlowMinCutResult.flow.forEach(({ key, value }) => (key.tag.flow = value))
if (minCut) {
// add tags for the nodes that belong to the cut
- maxFlowMinCutResult.sourcePartition.forEach(node => (node.tag.cut = true))
+ maxFlowMinCutResult.sourcePartition.forEach((node) => (node.tag.cut = true))
- maxFlowMinCutResult.sinkPartition.forEach(node => (node.tag.cut = false))
+ maxFlowMinCutResult.sinkPartition.forEach((node) => (node.tag.cut = false))
}
// show the result
@@ -515,10 +515,10 @@ function calculateMinCostFlow() {
let minCostFlowResult = null
try {
const minCostFlow = new MinimumCostFlow({
- maximumCapacities: edge => edge.tag.capacity,
- costs: edge => (edge.tag && edge.tag.cost ? edge.tag.cost : 0),
+ maximumCapacities: (edge) => edge.tag.capacity,
+ costs: (edge) => (edge.tag && edge.tag.cost ? edge.tag.cost : 0),
// the supply or demand of a node was calculated in calculateMaxFlow and set as node tag
- supply: node => (node.tag.supply ? node.tag.supply * node.layout.height : 0)
+ supply: (node) => (node.tag.supply ? node.tag.supply * node.layout.height : 0)
})
minCostFlowResult = minCostFlow.run(graph)
@@ -526,7 +526,7 @@ function calculateMinCostFlow() {
alert(err)
} finally {
// store the flow for each edge in its tag
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge.tag.flow = minCostFlowResult ? minCostFlowResult.flow.get(edge) || 0 : 0
if (edge.labels.size > 1) {
@@ -547,9 +547,9 @@ function calculateMinCostFlow() {
visualizeResult()
let flow = 0
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.inDegree(node) > 0) {
- flow = graph.inEdgesAt(node).sum(edge => edge.tag.flow)
+ flow = graph.inEdgesAt(node).sum((edge) => edge.tag.flow)
}
node.tag = {
flow,
@@ -558,8 +558,8 @@ function calculateMinCostFlow() {
}
})
- getSupplyNodes(graph).forEach(supplyNode => (supplyNode.tag.source = true))
- getDemandNodes(graph).forEach(demandNode => (demandNode.tag.sink = true))
+ getSupplyNodes(graph).forEach((supplyNode) => (supplyNode.tag.source = true))
+ getDemandNodes(graph).forEach((demandNode) => (demandNode.tag.sink = true))
}
return minCostFlowResult ? minCostFlowResult.totalCost : 0
}
@@ -571,7 +571,7 @@ function calculateMinCostFlow() {
*/
function getSupplyNodes(graph) {
const supplyNodes = []
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.supply > 0) {
supplyNodes.push(node)
}
@@ -586,7 +586,7 @@ function getSupplyNodes(graph) {
*/
function getDemandNodes(graph) {
const demandNodes = []
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.supply < 0) {
demandNodes.push(node)
}
@@ -617,7 +617,7 @@ async function runLayout(incremental, additionalIncrementalNodes) {
layoutAlgorithm.backLoopRouting = true
const layoutData = new HierarchicLayoutData({
- edgeThickness: edge => edge.tag.capacity
+ edgeThickness: (edge) => edge.tag.capacity
})
if (incremental && algorithmComboBox.selectedIndex !== MAX_FLOW_MIN_CUT) {
@@ -626,14 +626,14 @@ async function runLayout(incremental, additionalIncrementalNodes) {
// mark all sources and sinks as well as passed additional nodes as incremental
const hintsFactory = layoutAlgorithm.createIncrementalHintsFactory()
const incrementalNodesMapper = new Mapper()
- getSourceNodes().forEach(node =>
+ getSourceNodes().forEach((node) =>
incrementalNodesMapper.set(node, hintsFactory.createLayerIncrementallyHint(node))
)
- getSinkNodes().forEach(node =>
+ getSinkNodes().forEach((node) =>
incrementalNodesMapper.set(node, hintsFactory.createLayerIncrementallyHint(node))
)
if (additionalIncrementalNodes) {
- additionalIncrementalNodes.forEach(node =>
+ additionalIncrementalNodes.forEach((node) =>
incrementalNodesMapper.set(node, hintsFactory.createLayerIncrementallyHint(node))
)
}
@@ -644,9 +644,9 @@ async function runLayout(incremental, additionalIncrementalNodes) {
// sources will be in the first layer, sinks in the last layer
const layerConstraints = layoutData.layerConstraints
- getSourceNodes().forEach(node => layerConstraints.placeAtTop(node))
+ getSourceNodes().forEach((node) => layerConstraints.placeAtTop(node))
- getSinkNodes().forEach(node => layerConstraints.placeAtBottom(node))
+ getSinkNodes().forEach((node) => layerConstraints.placeAtBottom(node))
if (algorithmComboBox.selectedIndex === MAX_FLOW_MIN_CUT) {
layoutData.partitionGridData = new PartitionGridData({
@@ -655,7 +655,7 @@ async function runLayout(incremental, additionalIncrementalNodes) {
})
}
- layoutData.edgeLabelPreferredPlacement.delegate = key => {
+ layoutData.edgeLabelPreferredPlacement.delegate = (key) => {
const preferredPlacementDescriptor = new PreferredPlacementDescriptor()
if (key.tag === 'cost') {
preferredPlacementDescriptor.sideOfEdge = LabelPlacements.LEFT_OF_EDGE
@@ -669,7 +669,7 @@ async function runLayout(incremental, additionalIncrementalNodes) {
}
await graphComponent.morphLayout(layoutAlgorithm, '1s', layoutData)
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (lastFlowMap.get(edge) !== edge.tag.flow) {
graphComponent.highlightIndicatorManager.addHighlight(edge)
lastFlowMap.set(edge, edge.tag.flow)
@@ -695,7 +695,7 @@ async function runLayout(incremental, additionalIncrementalNodes) {
function getSourceNodes() {
const sourceNodes = []
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.inDegree(node) === 0 && graph.outDegree(node) !== 0) {
sourceNodes.push(node)
}
@@ -704,7 +704,7 @@ function getSourceNodes() {
if (sourceNodes.length === 0) {
sourceNodes.push(graph.nodes.first())
}
- sourceNodes.forEach(node => (node.tag.source = true))
+ sourceNodes.forEach((node) => (node.tag.source = true))
return sourceNodes
}
@@ -715,19 +715,19 @@ function getSourceNodes() {
function getSinkNodes() {
const sinkNodes = []
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.outDegree(node) === 0 && graph.inDegree(node) !== 0) {
sinkNodes.push(node)
}
})
// Special case: No node with out-degree 0 was found, take the first node of the graph that is not already marked as source
if (sinkNodes.length === 0) {
- const randomSink = graph.nodes.find(node => !node.tag.source)
+ const randomSink = graph.nodes.find((node) => !node.tag.source)
if (randomSink) {
sinkNodes.push(randomSink)
}
}
- sinkNodes.forEach(node => (node.tag.sink = true))
+ sinkNodes.forEach((node) => (node.tag.sink = true))
return sinkNodes
}
@@ -746,7 +746,7 @@ function updateMinCutLine() {
minCutLine.visible = true
let minX = Number.NEGATIVE_INFINITY
let maxX = Number.POSITIVE_INFINITY
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.cut) {
minX = Math.max(minX, node.layout.maxX)
} else {
@@ -754,7 +754,7 @@ function updateMinCutLine() {
}
})
- if (isFinite(minX) && isFinite(maxX)) {
+ if (Number.isFinite(minX) && Number.isFinite(maxX)) {
minCutLine.bounds = new Rect(
(minX + maxX) * 0.5 - 5,
graphBounds.y - 30,
@@ -791,7 +791,7 @@ function visualizeResult() {
const extrema = calculateExtrema(graph, false)
const diff = extrema.max - extrema.min
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
let colorIndex = 0
if (edge.tag.capacity !== 0) {
if (diff === 0) {
@@ -826,7 +826,7 @@ function calculateExtrema(graph, useCapacity) {
let min = Number.MAX_VALUE
let max = -Number.MAX_VALUE
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
let value = 0
if (edge.tag && edge.tag.capacity !== 0) {
value = useCapacity ? edge.tag.capacity : (edge.tag.flow * 100) / edge.tag.capacity
@@ -904,7 +904,7 @@ async function onAlgorithmChanged() {
minCutLine.visible = algorithmComboBox.selectedIndex === MAX_FLOW_MIN_CUT
// make sure that there is flow in case the algorithm changed to "Minimum Cost Problem"
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.inDegree(node) === 0) {
node.tag.supply = 0.5
} else if (graph.outDegree(node) === 0) {
@@ -1118,9 +1118,9 @@ function createSampleGraph() {
}
})
- graph.edges.forEach(edge => updateEdgeThickness(edge))
+ graph.edges.forEach((edge) => updateEdgeThickness(edge))
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let supply = 0
if (graph.inDegree(node) === 0) {
supply = 0.5
diff --git a/demos/analysis/networkflows/NetworkFlowsDemo.ts b/demos/analysis/networkflows/NetworkFlowsDemo.ts
index 6dc010873..7c3e27e6b 100644
--- a/demos/analysis/networkflows/NetworkFlowsDemo.ts
+++ b/demos/analysis/networkflows/NetworkFlowsDemo.ts
@@ -278,7 +278,7 @@ function createEditorInputMode(): void {
const deletedCompoundEdit = graphComponent.graph.beginEdit('Element deleted', 'Element deleted')
// if an edge was removed, calculate the new node size of its endpoints
if (nodesToChange.length > 0) {
- nodesToChange.forEach(node => {
+ nodesToChange.forEach((node) => {
if (graphComponent.graph.contains(node)) {
calculateNodeSize(node)
}
@@ -293,7 +293,7 @@ function createEditorInputMode(): void {
inputMode.addDeletingSelectionListener((_, evt) => {
edgePopup.currentItem = null
// collect all nodes that are endpoints of removed edges
- evt.selection.forEach(item => {
+ evt.selection.forEach((item) => {
if (item instanceof IEdge) {
nodesToChange.push(item.sourceNode!)
nodesToChange.push(item.targetNode!)
@@ -358,8 +358,8 @@ function createEditorInputMode(): void {
function calculateNodeSize(node: INode): void {
const graph = graphComponent.graph
- const incomingCapacity = graph.inEdgesAt(node).sum(inEdge => inEdge.tag.capacity)
- const outgoingCapacity = graph.outEdgesAt(node).sum(outEdge => outEdge.tag.capacity)
+ const incomingCapacity = graph.inEdgesAt(node).sum((inEdge) => inEdge.tag.capacity)
+ const outgoingCapacity = graph.outEdgesAt(node).sum((outEdge) => outEdge.tag.capacity)
const height = Math.max(incomingCapacity, outgoingCapacity)
const newBounds = new Rect(node.layout.x, node.layout.y, node.layout.width, Math.max(height, 30))
@@ -404,7 +404,7 @@ function runFlowAlgorithm(): void {
}
// update the node tags
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
node.tag = { ...node.tag, cut: false, source: false, sink: false }
})
@@ -451,7 +451,7 @@ function calculateMaxFlowMinCut(minCut: boolean): number {
return 0
}
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const labels = edge.labels
if (labels.size > 1) {
graph.remove(labels.get(1))
@@ -466,11 +466,11 @@ function calculateMaxFlowMinCut(minCut: boolean): number {
sources: sourceNodes,
sinks: sinkNodes,
// the capacity of an edge is stored in its tag
- capacities: edge => edge.tag.capacity
+ capacities: (edge) => edge.tag.capacity
})
const maxFlowMinCutResult = maxFlowMinCut.run(graph)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const flow = (graph.inDegree(node) > 0 ? graph.inEdgesAt(node) : graph.outEdgesAt(node)).sum(
(edge: IEdge): number => maxFlowMinCutResult.flow.get(edge) || 0
)
@@ -481,17 +481,17 @@ function calculateMaxFlowMinCut(minCut: boolean): number {
}
})
- sourceNodes.forEach(sourceNode => (sourceNode.tag.source = true))
- sinkNodes.forEach(sinkNode => (sinkNode.tag.sink = true))
+ sourceNodes.forEach((sourceNode) => (sourceNode.tag.source = true))
+ sinkNodes.forEach((sinkNode) => (sinkNode.tag.sink = true))
// add the flow values as tags to edges
maxFlowMinCutResult.flow.forEach(({ key, value }) => (key.tag.flow = value))
if (minCut) {
// add tags for the nodes that belong to the cut
- maxFlowMinCutResult.sourcePartition.forEach(node => (node.tag.cut = true))
+ maxFlowMinCutResult.sourcePartition.forEach((node) => (node.tag.cut = true))
- maxFlowMinCutResult.sinkPartition.forEach(node => (node.tag.cut = false))
+ maxFlowMinCutResult.sinkPartition.forEach((node) => (node.tag.cut = false))
}
// show the result
@@ -508,10 +508,10 @@ function calculateMinCostFlow(): number {
let minCostFlowResult: MinimumCostFlowResult | null = null
try {
const minCostFlow = new MinimumCostFlow({
- maximumCapacities: edge => edge.tag.capacity,
- costs: edge => (edge.tag && edge.tag.cost ? edge.tag.cost : 0),
+ maximumCapacities: (edge) => edge.tag.capacity,
+ costs: (edge) => (edge.tag && edge.tag.cost ? edge.tag.cost : 0),
// the supply or demand of a node was calculated in calculateMaxFlow and set as node tag
- supply: node => (node.tag.supply ? node.tag.supply * node.layout.height : 0)
+ supply: (node) => (node.tag.supply ? node.tag.supply * node.layout.height : 0)
})
minCostFlowResult = minCostFlow.run(graph)
@@ -519,7 +519,7 @@ function calculateMinCostFlow(): number {
alert(err)
} finally {
// store the flow for each edge in its tag
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge.tag.flow = minCostFlowResult ? minCostFlowResult.flow.get(edge) || 0 : 0
if (edge.labels.size > 1) {
@@ -540,9 +540,9 @@ function calculateMinCostFlow(): number {
visualizeResult()
let flow = 0
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.inDegree(node) > 0) {
- flow = graph.inEdgesAt(node).sum(edge => edge.tag.flow)
+ flow = graph.inEdgesAt(node).sum((edge) => edge.tag.flow)
}
node.tag = {
flow,
@@ -551,8 +551,8 @@ function calculateMinCostFlow(): number {
}
})
- getSupplyNodes(graph).forEach(supplyNode => (supplyNode.tag.source = true))
- getDemandNodes(graph).forEach(demandNode => (demandNode.tag.sink = true))
+ getSupplyNodes(graph).forEach((supplyNode) => (supplyNode.tag.source = true))
+ getDemandNodes(graph).forEach((demandNode) => (demandNode.tag.sink = true))
}
return minCostFlowResult ? minCostFlowResult.totalCost : 0
}
@@ -564,7 +564,7 @@ function calculateMinCostFlow(): number {
*/
function getSupplyNodes(graph: IGraph): INode[] {
const supplyNodes: INode[] = []
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.supply > 0) {
supplyNodes.push(node)
}
@@ -579,7 +579,7 @@ function getSupplyNodes(graph: IGraph): INode[] {
*/
function getDemandNodes(graph: IGraph): INode[] {
const demandNodes: INode[] = []
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.supply < 0) {
demandNodes.push(node)
}
@@ -611,7 +611,7 @@ async function runLayout(
layoutAlgorithm.backLoopRouting = true
const layoutData = new HierarchicLayoutData({
- edgeThickness: edge => edge.tag.capacity
+ edgeThickness: (edge) => edge.tag.capacity
})
if (incremental && algorithmComboBox.selectedIndex !== MAX_FLOW_MIN_CUT) {
@@ -620,14 +620,14 @@ async function runLayout(
// mark all sources and sinks as well as passed additional nodes as incremental
const hintsFactory = layoutAlgorithm.createIncrementalHintsFactory()!
const incrementalNodesMapper = new Mapper()
- getSourceNodes().forEach(node =>
+ getSourceNodes().forEach((node) =>
incrementalNodesMapper.set(node, hintsFactory.createLayerIncrementallyHint(node))
)
- getSinkNodes().forEach(node =>
+ getSinkNodes().forEach((node) =>
incrementalNodesMapper.set(node, hintsFactory.createLayerIncrementallyHint(node))
)
if (additionalIncrementalNodes) {
- additionalIncrementalNodes.forEach(node =>
+ additionalIncrementalNodes.forEach((node) =>
incrementalNodesMapper.set(node, hintsFactory.createLayerIncrementallyHint(node))
)
}
@@ -638,9 +638,9 @@ async function runLayout(
// sources will be in the first layer, sinks in the last layer
const layerConstraints = layoutData.layerConstraints
- getSourceNodes().forEach(node => layerConstraints.placeAtTop(node))
+ getSourceNodes().forEach((node) => layerConstraints.placeAtTop(node))
- getSinkNodes().forEach(node => layerConstraints.placeAtBottom(node))
+ getSinkNodes().forEach((node) => layerConstraints.placeAtBottom(node))
if (algorithmComboBox.selectedIndex === MAX_FLOW_MIN_CUT) {
layoutData.partitionGridData = new PartitionGridData({
@@ -650,7 +650,7 @@ async function runLayout(
})
}
- layoutData.edgeLabelPreferredPlacement.delegate = key => {
+ layoutData.edgeLabelPreferredPlacement.delegate = (key) => {
const preferredPlacementDescriptor = new PreferredPlacementDescriptor()
if (key.tag === 'cost') {
preferredPlacementDescriptor.sideOfEdge = LabelPlacements.LEFT_OF_EDGE
@@ -690,7 +690,7 @@ async function runLayout(
function getSourceNodes(): INode[] {
const sourceNodes: INode[] = []
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.inDegree(node) === 0 && graph.outDegree(node) !== 0) {
sourceNodes.push(node)
}
@@ -699,7 +699,7 @@ function getSourceNodes(): INode[] {
if (sourceNodes.length === 0) {
sourceNodes.push(graph.nodes.first())
}
- sourceNodes.forEach(node => (node.tag.source = true))
+ sourceNodes.forEach((node) => (node.tag.source = true))
return sourceNodes
}
@@ -710,19 +710,19 @@ function getSourceNodes(): INode[] {
function getSinkNodes(): INode[] {
const sinkNodes: INode[] = []
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.outDegree(node) === 0 && graph.inDegree(node) !== 0) {
sinkNodes.push(node)
}
})
// Special case: No node with out-degree 0 was found, take the first node of the graph that is not already marked as source
if (sinkNodes.length === 0) {
- const randomSink = graph.nodes.find(node => !node.tag.source)
+ const randomSink = graph.nodes.find((node) => !node.tag.source)
if (randomSink) {
sinkNodes.push(randomSink)
}
}
- sinkNodes.forEach(node => (node.tag.sink = true))
+ sinkNodes.forEach((node) => (node.tag.sink = true))
return sinkNodes
}
@@ -741,7 +741,7 @@ function updateMinCutLine(): void {
minCutLine.visible = true
let minX: number = Number.NEGATIVE_INFINITY
let maxX: number = Number.POSITIVE_INFINITY
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.cut) {
minX = Math.max(minX, node.layout.maxX)
} else {
@@ -749,7 +749,7 @@ function updateMinCutLine(): void {
}
})
- if (isFinite(minX) && isFinite(maxX)) {
+ if (Number.isFinite(minX) && Number.isFinite(maxX)) {
minCutLine.bounds = new Rect(
(minX + maxX) * 0.5 - 5,
graphBounds.y - 30,
@@ -786,7 +786,7 @@ function visualizeResult(): void {
const extrema = calculateExtrema(graph, false)
const diff = extrema.max - extrema.min
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
let colorIndex = 0
if (edge.tag.capacity !== 0) {
if (diff === 0) {
@@ -820,7 +820,7 @@ function calculateExtrema(graph: IGraph, useCapacity: boolean): { min: number; m
let min: number = Number.MAX_VALUE
let max: number = -Number.MAX_VALUE
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
let value = 0
if (edge.tag && edge.tag.capacity !== 0) {
value = useCapacity ? edge.tag.capacity : (edge.tag.flow * 100) / edge.tag.capacity
@@ -902,7 +902,7 @@ async function onAlgorithmChanged() {
minCutLine.visible = algorithmComboBox.selectedIndex === MAX_FLOW_MIN_CUT
// make sure that there is flow in case the algorithm changed to "Minimum Cost Problem"
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (graph.inDegree(node) === 0) {
node.tag.supply = 0.5
} else if (graph.outDegree(node) === 0) {
@@ -1116,9 +1116,9 @@ function createSampleGraph(): void {
}
})
- graph.edges.forEach(edge => updateEdgeThickness(edge))
+ graph.edges.forEach((edge) => updateEdgeThickness(edge))
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let supply = 0
if (graph.inDegree(node) === 0) {
supply = 0.5
diff --git a/demos/analysis/networkflows/index.html b/demos/analysis/networkflows/index.html
index 29093eff7..eb46c8281 100644
--- a/demos/analysis/networkflows/index.html
+++ b/demos/analysis/networkflows/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/analysis/transitivity/TransitivityDemo.js b/demos/analysis/transitivity/TransitivityDemo.js
index 8d4f8f8e4..560786ba7 100644
--- a/demos/analysis/transitivity/TransitivityDemo.js
+++ b/demos/analysis/transitivity/TransitivityDemo.js
@@ -493,7 +493,7 @@ async function loadGraph() {
const graph = builder.buildGraph()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const label = node.labels.first()
const nodeLayout = new Rect(
node.layout.x,
@@ -525,7 +525,7 @@ async function loadGraph() {
*/
function getInitialPackage(packageName) {
let initialPackageNode = null
- filteredGraph.wrappedGraph.nodes.forEach(node => {
+ filteredGraph.wrappedGraph.nodes.forEach((node) => {
if (packageName === node.labels.get(0).text) {
initialPackageNode = node
}
@@ -573,7 +573,7 @@ function applyAlgorithm() {
const transitivityClosureResult = transitivityClosure.run(graph)
const newEdges = transitivityClosureResult.edgesToAdd
- newEdges.forEach(edge => {
+ newEdges.forEach((edge) => {
const newEdge = graph.createEdge(edge.source, edge.target)
graph.setStyle(newEdge, addedEdgeStyle)
@@ -595,7 +595,7 @@ function applyAlgorithm() {
}
const transitiveEdges = transitivityReductionResult.edgesToRemove
- transitiveEdges.forEach(edge => {
+ transitiveEdges.forEach((edge) => {
if (showTransitiveEdges) {
graph.setStyle(edge, removedEdgeStyle)
incrementalEdges.push(edge)
@@ -667,7 +667,7 @@ async function filterGraph(clickedNode) {
startNode = clickedNode
// take all in-edges and mark the other endpoint as a neighbor of clickedNode
- fullGraph.inEdgesAt(clickedNode).forEach(edge => {
+ fullGraph.inEdgesAt(clickedNode).forEach((edge) => {
const oppositeNode = edge.opposite(clickedNode)
// we have to check if the node is already taken into consideration in the calculation of dependents
if (!filteredNodes.has(oppositeNode)) {
@@ -685,7 +685,7 @@ async function filterGraph(clickedNode) {
// check if new nodes are inserted in the graph
if (existingNodes) {
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
if (!existingNodes.has(node)) {
incrementalNodes.push(node)
}
@@ -712,7 +712,7 @@ function collectConnectedNodes(initialNode, graph, out) {
while (stack.length > 0) {
const node = stack.pop()
const edges = out ? graph.outEdgesAt(node) : graph.inEdgesAt(node)
- edges.forEach(edge => {
+ edges.forEach((edge) => {
filteredEdges.add(edge)
const oppositeNode = edge.opposite(node)
stack.push(oppositeNode)
@@ -735,7 +735,7 @@ function collectConnectedNodes(initialNode, graph, out) {
*/
function resetGraph() {
if (addedEdges.length !== 0) {
- addedEdges.forEach(edge => filteredGraph.remove(edge))
+ addedEdges.forEach((edge) => filteredGraph.remove(edge))
addedEdges = []
}
@@ -743,9 +743,9 @@ function resetGraph() {
removedEdgesSet = null
filteredGraph.edgePredicateChanged()
- filteredGraph.edges.forEach(edge => filteredGraph.setStyle(edge, normalEdgeStyle))
+ filteredGraph.edges.forEach((edge) => filteredGraph.setStyle(edge, normalEdgeStyle))
- filteredGraph.nodes.forEach(node => (node.tag.highlight = false))
+ filteredGraph.nodes.forEach((node) => (node.tag.highlight = false))
}
/**
@@ -781,10 +781,10 @@ async function applyLayout(incremental) {
if (incremental) {
layout.layoutMode = LayoutMode.INCREMENTAL
- layoutData.incrementalHints.incrementalLayeringNodes = incrementalNodes.filter(node =>
+ layoutData.incrementalHints.incrementalLayeringNodes = incrementalNodes.filter((node) =>
filteredGraph.contains(node)
)
- layoutData.incrementalHints.incrementalSequencingItems = incrementalEdges.filter(edge =>
+ layoutData.incrementalHints.incrementalSequencingItems = incrementalEdges.filter((edge) =>
filteredGraph.contains(edge)
)
@@ -828,7 +828,7 @@ function prepareSmoothLayoutAnimation() {
layout.removeBends = true
const layoutData = new PlaceNodesAtBarycenterStageData({
- affectedNodes: node => incrementalNodes.includes(node) && filteredGraph.contains(node)
+ affectedNodes: (node) => incrementalNodes.includes(node) && filteredGraph.contains(node)
})
graph.applyLayout(layout, layoutData)
diff --git a/demos/analysis/transitivity/TransitivityDemo.ts b/demos/analysis/transitivity/TransitivityDemo.ts
index 3926641fa..35f35934d 100644
--- a/demos/analysis/transitivity/TransitivityDemo.ts
+++ b/demos/analysis/transitivity/TransitivityDemo.ts
@@ -472,7 +472,7 @@ async function loadGraph(): Promise {
const graph = builder.buildGraph()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const label = node.labels.first()
const nodeLayout = new Rect(
node.layout.x,
@@ -503,7 +503,7 @@ async function loadGraph(): Promise {
*/
function getInitialPackage(packageName: string): INode | null {
let initialPackageNode: INode | null = null
- filteredGraph.wrappedGraph!.nodes.forEach(node => {
+ filteredGraph.wrappedGraph!.nodes.forEach((node) => {
if (packageName === node.labels.get(0).text) {
initialPackageNode = node
}
@@ -552,7 +552,7 @@ function applyAlgorithm(): void {
const transitivityClosureResult = transitivityClosure.run(graph)
const newEdges = transitivityClosureResult.edgesToAdd
- newEdges.forEach(edge => {
+ newEdges.forEach((edge) => {
const newEdge = graph.createEdge(edge.source, edge.target)
graph.setStyle(newEdge, addedEdgeStyle)
@@ -574,7 +574,7 @@ function applyAlgorithm(): void {
}
const transitiveEdges = transitivityReductionResult.edgesToRemove
- transitiveEdges.forEach(edge => {
+ transitiveEdges.forEach((edge) => {
if (showTransitiveEdges) {
graph.setStyle(edge, removedEdgeStyle)
incrementalEdges.push(edge)
@@ -641,7 +641,7 @@ async function filterGraph(clickedNode: INode): Promise {
startNode = clickedNode
// take all in-edges and mark the other endpoint as a neighbor of clickedNode
- fullGraph.inEdgesAt(clickedNode).forEach(edge => {
+ fullGraph.inEdgesAt(clickedNode).forEach((edge) => {
const oppositeNode = edge.opposite(clickedNode) as INode
// we have to check if the node is already taken into consideration in the calculation of dependents
if (!filteredNodes!.has(oppositeNode)) {
@@ -659,7 +659,7 @@ async function filterGraph(clickedNode: INode): Promise {
// check if new nodes are inserted in the graph
if (existingNodes) {
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
if (!existingNodes.has(node)) {
incrementalNodes.push(node)
}
@@ -686,7 +686,7 @@ function collectConnectedNodes(initialNode: INode, graph: IGraph, out: boolean):
while (stack.length > 0) {
const node = stack.pop()!
const edges = out ? graph.outEdgesAt(node) : graph.inEdgesAt(node)
- edges.forEach(edge => {
+ edges.forEach((edge) => {
filteredEdges!.add(edge)
const oppositeNode = edge.opposite(node)! as INode
stack.push(oppositeNode)
@@ -709,7 +709,7 @@ function collectConnectedNodes(initialNode: INode, graph: IGraph, out: boolean):
*/
function resetGraph(): void {
if (addedEdges.length !== 0) {
- addedEdges.forEach(edge => filteredGraph.remove(edge))
+ addedEdges.forEach((edge) => filteredGraph.remove(edge))
addedEdges = []
}
@@ -717,9 +717,9 @@ function resetGraph(): void {
removedEdgesSet = null
filteredGraph.edgePredicateChanged()
- filteredGraph.edges.forEach(edge => filteredGraph.setStyle(edge, normalEdgeStyle))
+ filteredGraph.edges.forEach((edge) => filteredGraph.setStyle(edge, normalEdgeStyle))
- filteredGraph.nodes.forEach(node => (node.tag.highlight = false))
+ filteredGraph.nodes.forEach((node) => (node.tag.highlight = false))
}
/**
@@ -754,10 +754,10 @@ async function applyLayout(incremental: boolean): Promise {
if (incremental) {
layout.layoutMode = LayoutMode.INCREMENTAL
- layoutData.incrementalHints.incrementalLayeringNodes = incrementalNodes.filter(node =>
+ layoutData.incrementalHints.incrementalLayeringNodes = incrementalNodes.filter((node) =>
filteredGraph.contains(node)
)
- layoutData.incrementalHints.incrementalSequencingItems = incrementalEdges.filter(edge =>
+ layoutData.incrementalHints.incrementalSequencingItems = incrementalEdges.filter((edge) =>
filteredGraph.contains(edge)
)
@@ -801,7 +801,7 @@ function prepareSmoothLayoutAnimation(): void {
layout.removeBends = true
const layoutData = new PlaceNodesAtBarycenterStageData({
- affectedNodes: node => incrementalNodes.includes(node) && filteredGraph.contains(node)
+ affectedNodes: (node) => incrementalNodes.includes(node) && filteredGraph.contains(node)
})
graph.applyLayout(layout, layoutData)
diff --git a/demos/analysis/transitivity/index.html b/demos/analysis/transitivity/index.html
index eaf177254..61bd42105 100644
--- a/demos/analysis/transitivity/index.html
+++ b/demos/analysis/transitivity/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/accessibility/AccessibilityDemo.js b/demos/application-features/accessibility/AccessibilityDemo.js
index 8d20981e1..35a9cd077 100644
--- a/demos/application-features/accessibility/AccessibilityDemo.js
+++ b/demos/application-features/accessibility/AccessibilityDemo.js
@@ -111,26 +111,26 @@ function buildGraph(graph, graphData) {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
- .edgeCreator.createLabelBinding(item => item.label)
+ .edgeCreator.createLabelBinding((item) => item.label)
graphBuilder.buildGraph()
}
diff --git a/demos/application-features/accessibility/AccessibilityDemo.ts b/demos/application-features/accessibility/AccessibilityDemo.ts
index b62b7ee75..10181d3b1 100644
--- a/demos/application-features/accessibility/AccessibilityDemo.ts
+++ b/demos/application-features/accessibility/AccessibilityDemo.ts
@@ -108,26 +108,26 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
- .edgeCreator.createLabelBinding(item => item.label)
+ .edgeCreator.createLabelBinding((item) => item.label)
graphBuilder.buildGraph()
}
diff --git a/demos/application-features/accessibility/index.html b/demos/application-features/accessibility/index.html
index f5f14108d..c28d9bff5 100644
--- a/demos/application-features/accessibility/index.html
+++ b/demos/application-features/accessibility/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/background-image/BackgroundImageDemo.js b/demos/application-features/background-image/BackgroundImageDemo.js
index 2eaac0c60..7dc78c626 100644
--- a/demos/application-features/background-image/BackgroundImageDemo.js
+++ b/demos/application-features/background-image/BackgroundImageDemo.js
@@ -110,22 +110,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/background-image/BackgroundImageDemo.ts b/demos/application-features/background-image/BackgroundImageDemo.ts
index d2cb8f8d9..dc6ebd998 100644
--- a/demos/application-features/background-image/BackgroundImageDemo.ts
+++ b/demos/application-features/background-image/BackgroundImageDemo.ts
@@ -106,22 +106,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/background-image/index.html b/demos/application-features/background-image/index.html
index 5105abe56..7e17de66e 100644
--- a/demos/application-features/background-image/index.html
+++ b/demos/application-features/background-image/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/building-graph-from-data/BuildingGraphFromDataDemo.js b/demos/application-features/building-graph-from-data/BuildingGraphFromDataDemo.js
index 72e1bf047..4d3cfcbee 100644
--- a/demos/application-features/building-graph-from-data/BuildingGraphFromDataDemo.js
+++ b/demos/application-features/building-graph-from-data/BuildingGraphFromDataDemo.js
@@ -103,7 +103,7 @@ function buildGraph(graph, graphData) {
const nodes = {}
// Iterate the group data and create the according group nodes.
- graphData.groupsSource.forEach(groupData => {
+ graphData.groupsSource.forEach((groupData) => {
groups[groupData.id] = graph.createGroupNode({
labels: groupData.label != null ? [groupData.label] : [],
layout: groupData.layout,
@@ -112,7 +112,7 @@ function buildGraph(graph, graphData) {
})
// Iterate the node data and create the according nodes.
- graphData.nodesSource.forEach(nodeData => {
+ graphData.nodesSource.forEach((nodeData) => {
const node = graph.createNode({
labels: nodeData.label != null ? [nodeData.label] : [],
layout: nodeData.layout,
@@ -128,14 +128,14 @@ function buildGraph(graph, graphData) {
})
// Set the parent groups after all nodes/groups are created.
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.tag.group) {
graph.setParent(node, groups[node.tag.group])
}
})
// Iterate the edge data and create the according edges.
- graphData.edgesSource.forEach(edgeData => {
+ graphData.edgesSource.forEach((edgeData) => {
// Note that nodes and groups need to have disjoint sets of ids, otherwise it is impossible to determine
// which node is the correct source/target.
graph.createEdge({
@@ -147,7 +147,7 @@ function buildGraph(graph, graphData) {
})
// If given, apply the edge layout information
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const edgeData = edge.tag
if (edgeData.sourcePort) {
graph.setPortLocation(edge.sourcePort, Point.from(edgeData.sourcePort))
@@ -156,7 +156,7 @@ function buildGraph(graph, graphData) {
graph.setPortLocation(edge.targetPort, Point.from(edgeData.targetPort))
}
if (edgeData.bends) {
- edgeData.bends.forEach(bendLocation => {
+ edgeData.bends.forEach((bendLocation) => {
graph.addBend(edge, bendLocation)
})
}
diff --git a/demos/application-features/building-graph-from-data/index.html b/demos/application-features/building-graph-from-data/index.html
index e54055b30..6b968ab9f 100644
--- a/demos/application-features/building-graph-from-data/index.html
+++ b/demos/application-features/building-graph-from-data/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/building-swimlanes-from-data/BuildingSwimlanesFromDataDemo.js b/demos/application-features/building-swimlanes-from-data/BuildingSwimlanesFromDataDemo.js
index 1e7e6cf35..dfbdd62a1 100644
--- a/demos/application-features/building-swimlanes-from-data/BuildingSwimlanesFromDataDemo.js
+++ b/demos/application-features/building-swimlanes-from-data/BuildingSwimlanesFromDataDemo.js
@@ -147,7 +147,7 @@ function configureTableEditing(graphComponent) {
graphComponent.clipboard = clipboard
// prevent selection of the table node
- graphEditorInputMode.selectablePredicate = item => {
+ graphEditorInputMode.selectablePredicate = (item) => {
return !(INode.isInstance(item) && item.lookup(ITable.$class))
}
}
@@ -233,7 +233,7 @@ function buildGraph(graph, graphData) {
const tableGroupNode = graph.createGroupNode(null, table.layout.toRect(), tableStyle)
// Iterate the node data and create the according nodes.
- graphData.nodesSource.forEach(nodeData => {
+ graphData.nodesSource.forEach((nodeData) => {
const size = nodeData.size || [50, 50]
const node = graph.createNode({
labels: nodeData.label != null ? [nodeData.label] : [],
@@ -264,7 +264,7 @@ function buildGraph(graph, graphData) {
})
// Iterate the edge data and create the according edges.
- graphData.edgesSource.forEach(edgeData => {
+ graphData.edgesSource.forEach((edgeData) => {
// Note that nodes and groups need to have disjoint sets of ids, otherwise it is impossible to determine
// which node is the correct source/target.
graph.createEdge({
@@ -289,7 +289,7 @@ function writeToJSON(graph) {
}
// find the table, we assume there is only one
- const tableNode = graph.nodes.find(node => !!node.lookup(ITable.$class))
+ const tableNode = graph.nodes.find((node) => !!node.lookup(ITable.$class))
const table = tableNode ? tableNode.lookup(ITable.$class) : null
// serialize the nodes with their swimlane information
@@ -321,7 +321,7 @@ function writeToJSON(graph) {
const columnId = `lane${table.findColumn(tableNode, node.layout.center).index}`
jsonNode.lane = columnId
// store new lanes in the json
- if (!jsonOutput.lanesSource.find(lane => lane.id === columnId)) {
+ if (!jsonOutput.lanesSource.find((lane) => lane.id === columnId)) {
const jsonLane = { id: columnId }
if (column.labels.size > 0) {
jsonNode.label = column.labels.first().text
@@ -333,7 +333,7 @@ function writeToJSON(graph) {
})
// serialize the edges
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const sourceId = node2id.get(edge.sourceNode)
const targetId = node2id.get(edge.targetNode)
jsonOutput.edgesSource.push({
diff --git a/demos/application-features/building-swimlanes-from-data/index.html b/demos/application-features/building-swimlanes-from-data/index.html
index fa3977f64..58ab3811c 100644
--- a/demos/application-features/building-swimlanes-from-data/index.html
+++ b/demos/application-features/building-swimlanes-from-data/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.js b/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.js
index 0e88a9d99..4571acf08 100644
--- a/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.js
+++ b/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.js
@@ -96,23 +96,23 @@ function buildGraph(graph, graphData) {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.styleBindings.addBinding('shape', item => item.tag)
+ .nodeCreator.styleBindings.addBinding('shape', (item) => item.tag)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.ts b/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.ts
index b1e37c77f..f197ed965 100644
--- a/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.ts
+++ b/demos/application-features/complex-highlight-decorator/ComplexHighlightDecoratorDemo.ts
@@ -94,23 +94,23 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.styleBindings.addBinding('shape', item => item.tag)
+ .nodeCreator.styleBindings.addBinding('shape', (item) => item.tag)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/complex-highlight-decorator/index.html b/demos/application-features/complex-highlight-decorator/index.html
index 502844c29..b1dc997d2 100644
--- a/demos/application-features/complex-highlight-decorator/index.html
+++ b/demos/application-features/complex-highlight-decorator/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/custom-graphml/CustomGraphMLDemo.js b/demos/application-features/custom-graphml/CustomGraphMLDemo.js
index a57e773ff..3f35442b9 100644
--- a/demos/application-features/custom-graphml/CustomGraphMLDemo.js
+++ b/demos/application-features/custom-graphml/CustomGraphMLDemo.js
@@ -117,22 +117,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -212,7 +212,7 @@ function createGraphMLIOHandler() {
graphMLIOHandler.addInputMapper(
INode.$class,
YObject.$class,
- element => GraphMLIOHandler.matchesName(element, DATE_TIME_MAPPER_KEY),
+ (element) => GraphMLIOHandler.matchesName(element, DATE_TIME_MAPPER_KEY),
dateMapper,
(sender, e) => {
// The actual value is a text node that can be retrieved from the event
diff --git a/demos/application-features/custom-graphml/CustomGraphMLDemo.ts b/demos/application-features/custom-graphml/CustomGraphMLDemo.ts
index 803d77d5b..ca76db028 100644
--- a/demos/application-features/custom-graphml/CustomGraphMLDemo.ts
+++ b/demos/application-features/custom-graphml/CustomGraphMLDemo.ts
@@ -115,22 +115,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/custom-graphml/index.html b/demos/application-features/custom-graphml/index.html
index effad492e..1322680fc 100644
--- a/demos/application-features/custom-graphml/index.html
+++ b/demos/application-features/custom-graphml/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.js b/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.js
index b384117f5..924f7fa46 100644
--- a/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.js
+++ b/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.js
@@ -109,22 +109,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -139,7 +139,7 @@ function configureDragAndDrop() {
// By default the mode available in GraphEditorInputMode is disabled, so first enable it.
nodeDropInputMode.enabled = true
// Certain nodes should be created as group nodes. In this case, we distinguish them by their style.
- nodeDropInputMode.isGroupNodePredicate = draggedNode =>
+ nodeDropInputMode.isGroupNodePredicate = (draggedNode) =>
draggedNode.style instanceof GroupNodeStyle
// When dragging the node within the GraphComponent, we want to show a preview of that node.
nodeDropInputMode.showPreview = true
@@ -162,7 +162,7 @@ function initializeDragAndDropPanel() {
const nodeStyles = [defaultNodeStyle, otherNodeStyle, defaultGroupNodeStyle]
// add a visual for each node style to the palette
- nodeStyles.forEach(style => {
+ nodeStyles.forEach((style) => {
addNodeVisual(style, panel)
})
}
@@ -216,7 +216,7 @@ function addNodeVisual(style, panel) {
img.addEventListener(
'mousedown',
- event => {
+ (event) => {
startDrag()
event.preventDefault()
},
@@ -224,7 +224,7 @@ function addNodeVisual(style, panel) {
)
img.addEventListener(
'touchstart',
- event => {
+ (event) => {
startDrag()
event.preventDefault()
},
diff --git a/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.ts b/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.ts
index 3905c3958..a10c3f983 100644
--- a/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.ts
+++ b/demos/application-features/drag-and-drop/SimpleDragAndDropDemo.ts
@@ -106,22 +106,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/drag-and-drop/index.html b/demos/application-features/drag-and-drop/index.html
index aade230c0..d5464461d 100644
--- a/demos/application-features/drag-and-drop/index.html
+++ b/demos/application-features/drag-and-drop/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/external-links/ExternalLinksDemo.js b/demos/application-features/external-links/ExternalLinksDemo.js
index 8e07e531e..e76c67377 100644
--- a/demos/application-features/external-links/ExternalLinksDemo.js
+++ b/demos/application-features/external-links/ExternalLinksDemo.js
@@ -106,23 +106,23 @@ function buildGraph(graph, graphData) {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -142,7 +142,7 @@ function initializeLinkListener() {
url = label.text.startsWith('www.') || label.text.startsWith('http') ? label.text : ''
} else if (INode.isInstance(clickedItem) || IEdge.isInstance(clickedItem)) {
// if a node or edge was clicked, we see whether it has any label that resembles a link
- clickedItem.labels.forEach(label => {
+ clickedItem.labels.forEach((label) => {
const text = label.text
if (text.startsWith('www.') || text.startsWith('http')) {
url = text
diff --git a/demos/application-features/external-links/ExternalLinksDemo.ts b/demos/application-features/external-links/ExternalLinksDemo.ts
index 5aae8bdf7..be00cdde3 100644
--- a/demos/application-features/external-links/ExternalLinksDemo.ts
+++ b/demos/application-features/external-links/ExternalLinksDemo.ts
@@ -103,23 +103,23 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/external-links/LinkItemHoverInputMode.js b/demos/application-features/external-links/LinkItemHoverInputMode.js
index dd46aa194..b7aefb921 100644
--- a/demos/application-features/external-links/LinkItemHoverInputMode.js
+++ b/demos/application-features/external-links/LinkItemHoverInputMode.js
@@ -104,7 +104,7 @@ export default class LinkItemHoverInputMode extends ItemHoverInputMode {
if (ILabel.isInstance(item) && (item.text.startsWith('www.') || item.text.startsWith('http'))) {
labelLink = item
} else if (INode.isInstance(item) || IEdge.isInstance(item)) {
- item.labels.forEach(label => {
+ item.labels.forEach((label) => {
const text = label.text
if (text.startsWith('www.') || text.startsWith('http')) {
labelLink = label
diff --git a/demos/application-features/external-links/index.html b/demos/application-features/external-links/index.html
index 4156fa507..f0ec28424 100644
--- a/demos/application-features/external-links/index.html
+++ b/demos/application-features/external-links/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/file-operations/index.html b/demos/application-features/file-operations/index.html
index 12690dfa4..72d6461bc 100644
--- a/demos/application-features/file-operations/index.html
+++ b/demos/application-features/file-operations/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/file-operations/json-support.js b/demos/application-features/file-operations/json-support.js
index 3199ebf5b..6168e23af 100644
--- a/demos/application-features/file-operations/json-support.js
+++ b/demos/application-features/file-operations/json-support.js
@@ -51,30 +51,30 @@ export function readJSON(graphComponent, text) {
graphComponent.graph.clear()
const graphBuilder = new GraphBuilder(graphComponent.graph)
const nodesSource = graphBuilder.createNodesSource({
- data: data.nodeList.filter(item => item.isGroup !== true),
- id: item => item.id,
- parentId: item => item.parentId,
- layout: item => item.layout
+ data: data.nodeList.filter((item) => item.isGroup !== true),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId,
+ layout: (item) => item.layout
})
nodesSource.nodeCreator.createLabelsSource({
- data: data => data.labels || [],
- text: data => data.text,
- layoutParameter: data =>
+ data: (data) => data.labels || [],
+ text: (data) => data.text,
+ layoutParameter: (data) =>
data.layoutParameter
? ILabelModelParameter.deserializeParameter(data.layoutParameter)
: null
})
const groupNodesSource = graphBuilder.createGroupNodesSource({
- data: data.nodeList.filter(item => item.isGroup === true),
- id: item => item.id,
- parentId: item => item.parentId,
- layout: item => item.layout
+ data: data.nodeList.filter((item) => item.isGroup === true),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId,
+ layout: (item) => item.layout
})
groupNodesSource.nodeCreator.createLabelsSource({
- data: data => data.labels || [],
- text: data => data.text,
- layoutParameter: data =>
+ data: (data) => data.labels || [],
+ text: (data) => data.text,
+ layoutParameter: (data) =>
data.layoutParameter
? ILabelModelParameter.deserializeParameter(data.layoutParameter)
: null
@@ -82,18 +82,18 @@ export function readJSON(graphComponent, text) {
const { edgeCreator } = graphBuilder.createEdgesSource(
data.edgeList,
- item => item.source,
- item => item.target
+ (item) => item.source,
+ (item) => item.target
)
edgeCreator.createLabelsSource({
- data: data => data.labels || [],
- text: data => data.text,
- layoutParameter: data =>
+ data: (data) => data.labels || [],
+ text: (data) => data.text,
+ layoutParameter: (data) =>
data.layoutParameter
? ILabelModelParameter.deserializeParameter(data.layoutParameter)
: null
})
- edgeCreator.bendsProvider = item => item.bends
+ edgeCreator.bendsProvider = (item) => item.bends
// Ports are not handled by GraphBuilder by default, so we use the EdgeCreated event for this.
const tryDeserializePortParameter = (portParameter, port, graph) => {
diff --git a/demos/application-features/file-operations/json-support.ts b/demos/application-features/file-operations/json-support.ts
index 6d22f006c..213256702 100644
--- a/demos/application-features/file-operations/json-support.ts
+++ b/demos/application-features/file-operations/json-support.ts
@@ -52,30 +52,30 @@ export function readJSON(graphComponent: GraphComponent, text: string): void {
graphComponent.graph.clear()
const graphBuilder = new GraphBuilder(graphComponent.graph)
const nodesSource = graphBuilder.createNodesSource({
- data: data.nodeList.filter(item => item.isGroup !== true),
- id: item => item.id,
- parentId: item => item.parentId,
- layout: item => item.layout
+ data: data.nodeList.filter((item) => item.isGroup !== true),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId,
+ layout: (item) => item.layout
})
nodesSource.nodeCreator.createLabelsSource({
- data: data => data.labels || [],
- text: data => data.text,
- layoutParameter: data =>
+ data: (data) => data.labels || [],
+ text: (data) => data.text,
+ layoutParameter: (data) =>
data.layoutParameter
? ILabelModelParameter.deserializeParameter(data.layoutParameter)
: null
})
const groupNodesSource = graphBuilder.createGroupNodesSource({
- data: data.nodeList.filter(item => item.isGroup === true),
- id: item => item.id,
- parentId: item => item.parentId,
- layout: item => item.layout
+ data: data.nodeList.filter((item) => item.isGroup === true),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId,
+ layout: (item) => item.layout
})
groupNodesSource.nodeCreator.createLabelsSource({
- data: data => data.labels || [],
- text: data => data.text,
- layoutParameter: data =>
+ data: (data) => data.labels || [],
+ text: (data) => data.text,
+ layoutParameter: (data) =>
data.layoutParameter
? ILabelModelParameter.deserializeParameter(data.layoutParameter)
: null
@@ -83,13 +83,13 @@ export function readJSON(graphComponent: GraphComponent, text: string): void {
const { edgeCreator } = graphBuilder.createEdgesSource(
data.edgeList,
- item => item.source,
- item => item.target
+ (item) => item.source,
+ (item) => item.target
)
edgeCreator.createLabelsSource({
- data: data => data.labels || [],
- text: data => data.text,
- layoutParameter: data =>
+ data: (data) => data.labels || [],
+ text: (data) => data.text,
+ layoutParameter: (data) =>
data.layoutParameter
? ILabelModelParameter.deserializeParameter(data.layoutParameter)
: null
diff --git a/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.js b/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.js
index 6f2a2cee3..c8af2930a 100644
--- a/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.js
+++ b/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.js
@@ -119,22 +119,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -156,8 +156,8 @@ function enableFilteringAndFolding() {
initializeGraph(fullGraph)
// we want to hide items whose tag contains the string 'filtered'
- const nodePredicate = node => !node.tag || !node.tag.filtered
- const edgePredicate = edge => !edge.tag || !edge.tag.filtered
+ const nodePredicate = (node) => !node.tag || !node.tag.filtered
+ const edgePredicate = (edge) => !edge.tag || !edge.tag.filtered
// create a filtered graph
const filteredGraph = new FilteredGraphWrapper(fullGraph, nodePredicate, edgePredicate)
@@ -231,10 +231,10 @@ function initializeUI() {
filterItemsButton.addEventListener('click', () => {
// mark the selected items such that the nodePredicate or edgePredicate will filter them
- graphComponent.selection.selectedNodes.forEach(node => {
+ graphComponent.selection.selectedNodes.forEach((node) => {
filterItemWithUndoUnit(node, true)
})
- graphComponent.selection.selectedEdges.forEach(edge => {
+ graphComponent.selection.selectedEdges.forEach((edge) => {
filterItemWithUndoUnit(edge, true)
})
@@ -251,10 +251,10 @@ function initializeUI() {
// access the unfiltered, unfolded graph to remove the filter mark from all items
const filteredGraph = graphComponent.graph.foldingView.manager.masterGraph
const fullGraph = filteredGraph.wrappedGraph
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
filterItemWithUndoUnit(node, false)
})
- fullGraph.edges.forEach(edge => {
+ fullGraph.edges.forEach((edge) => {
filterItemWithUndoUnit(edge, false)
})
@@ -279,8 +279,8 @@ function updateResetButtonState() {
const filteredGraph = graphComponent.graph.foldingView.manager.masterGraph
const fullGraph = filteredGraph.wrappedGraph
const hasFilteredItems =
- fullGraph.nodes.some(node => node.tag && node.tag.filtered) ||
- fullGraph.edges.some(edge => edge.tag && edge.tag.filtered)
+ fullGraph.nodes.some((node) => node.tag && node.tag.filtered) ||
+ fullGraph.edges.some((edge) => edge.tag && edge.tag.filtered)
// set the reset button
document.querySelector('#reset-filter').disabled = !hasFilteredItems
}
diff --git a/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.ts b/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.ts
index bb43f4fc2..74463491e 100644
--- a/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.ts
+++ b/demos/application-features/filtering-with-folding/FilteringWithFoldingDemo.ts
@@ -116,22 +116,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -227,10 +227,10 @@ function initializeUI(): void {
filterItemsButton.addEventListener('click', (): void => {
// mark the selected items such that the nodePredicate or edgePredicate will filter them
- graphComponent.selection.selectedNodes.forEach(node => {
+ graphComponent.selection.selectedNodes.forEach((node) => {
filterItemWithUndoUnit(node, true)
})
- graphComponent.selection.selectedEdges.forEach(edge => {
+ graphComponent.selection.selectedEdges.forEach((edge) => {
filterItemWithUndoUnit(edge, true)
})
@@ -249,10 +249,10 @@ function initializeUI(): void {
const filteredGraph = graphComponent.graph.foldingView!.manager
.masterGraph as FilteredGraphWrapper
const fullGraph = filteredGraph.wrappedGraph!
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
filterItemWithUndoUnit(node, false)
})
- fullGraph.edges.forEach(edge => {
+ fullGraph.edges.forEach((edge) => {
filterItemWithUndoUnit(edge, false)
})
@@ -278,8 +278,8 @@ function updateResetButtonState(): void {
.masterGraph as FilteredGraphWrapper
const fullGraph = filteredGraph.wrappedGraph!
const hasFilteredItems =
- fullGraph.nodes.some(node => node.tag && node.tag.filtered) ||
- fullGraph.edges.some(edge => edge.tag && edge.tag.filtered)
+ fullGraph.nodes.some((node) => node.tag && node.tag.filtered) ||
+ fullGraph.edges.some((edge) => edge.tag && edge.tag.filtered)
// set the reset button
document.querySelector('#reset-filter')!.disabled = !hasFilteredItems
}
diff --git a/demos/application-features/filtering-with-folding/index.html b/demos/application-features/filtering-with-folding/index.html
index d328974b4..a5a01f7b0 100644
--- a/demos/application-features/filtering-with-folding/index.html
+++ b/demos/application-features/filtering-with-folding/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/filtering/FilteringDemo.js b/demos/application-features/filtering/FilteringDemo.js
index 2aa8a8efb..48ae8242a 100644
--- a/demos/application-features/filtering/FilteringDemo.js
+++ b/demos/application-features/filtering/FilteringDemo.js
@@ -128,22 +128,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -162,8 +162,8 @@ function createFilterGraph() {
initializeGraph(fullGraph)
// we want to hide items whose tag contains the string 'filtered'
- const nodePredicate = node => !node.tag || !node.tag.filtered
- const edgePredicate = edge => !edge.tag || !edge.tag.filtered
+ const nodePredicate = (node) => !node.tag || !node.tag.filtered
+ const edgePredicate = (edge) => !edge.tag || !edge.tag.filtered
// create a filtered graph
return new FilteredGraphWrapper(fullGraph, nodePredicate, edgePredicate)
@@ -174,10 +174,10 @@ function createFilterGraph() {
*/
function filterItems() {
// mark the selected items such that the nodePredicate or edgePredicate will filter them
- graphComponent.selection.selectedNodes.forEach(node => {
+ graphComponent.selection.selectedNodes.forEach((node) => {
filterItemWithUndoUnit(node, true)
})
- graphComponent.selection.selectedEdges.forEach(edge => {
+ graphComponent.selection.selectedEdges.forEach((edge) => {
filterItemWithUndoUnit(edge, true)
})
@@ -194,10 +194,10 @@ function restoreItems() {
// access the unfiltered, unfolded graph to remove the filter mark from all items
const filteredGraph = graphComponent.graph
const fullGraph = filteredGraph.wrappedGraph
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
filterItemWithUndoUnit(node, false)
})
- fullGraph.edges.forEach(edge => {
+ fullGraph.edges.forEach((edge) => {
filterItemWithUndoUnit(edge, false)
})
@@ -287,8 +287,8 @@ function initializeUI() {
function updateResetButtonState() {
const fullGraph = graphComponent.graph.wrappedGraph
const hasFilteredItems =
- fullGraph.nodes.some(node => node.tag && node.tag.filtered) ||
- fullGraph.edges.some(edge => edge.tag && edge.tag.filtered)
+ fullGraph.nodes.some((node) => node.tag && node.tag.filtered) ||
+ fullGraph.edges.some((edge) => edge.tag && edge.tag.filtered)
// set the reset button
document.querySelector('#reset-filter').disabled = !hasFilteredItems
}
diff --git a/demos/application-features/filtering/FilteringDemo.ts b/demos/application-features/filtering/FilteringDemo.ts
index 280807c70..c4a67b77b 100644
--- a/demos/application-features/filtering/FilteringDemo.ts
+++ b/demos/application-features/filtering/FilteringDemo.ts
@@ -125,22 +125,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -171,10 +171,10 @@ function createFilterGraph(): FilteredGraphWrapper {
*/
function filterItems(): void {
// mark the selected items such that the nodePredicate or edgePredicate will filter them
- graphComponent.selection.selectedNodes.forEach(node => {
+ graphComponent.selection.selectedNodes.forEach((node) => {
filterItemWithUndoUnit(node, true)
})
- graphComponent.selection.selectedEdges.forEach(edge => {
+ graphComponent.selection.selectedEdges.forEach((edge) => {
filterItemWithUndoUnit(edge, true)
})
@@ -191,10 +191,10 @@ function restoreItems(): void {
// access the unfiltered, unfolded graph to remove the filter mark from all items
const filteredGraph = graphComponent.graph as FilteredGraphWrapper
const fullGraph = filteredGraph.wrappedGraph!
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
filterItemWithUndoUnit(node, false)
})
- fullGraph.edges.forEach(edge => {
+ fullGraph.edges.forEach((edge) => {
filterItemWithUndoUnit(edge, false)
})
@@ -282,8 +282,8 @@ function initializeUI(): void {
function updateResetButtonState(): void {
const fullGraph = (graphComponent.graph as FilteredGraphWrapper).wrappedGraph!
const hasFilteredItems =
- fullGraph.nodes.some(node => node.tag && node.tag.filtered) ||
- fullGraph.edges.some(edge => edge.tag && edge.tag.filtered)
+ fullGraph.nodes.some((node) => node.tag && node.tag.filtered) ||
+ fullGraph.edges.some((edge) => edge.tag && edge.tag.filtered)
// set the reset button
document.querySelector('#reset-filter')!.disabled = !hasFilteredItems
}
diff --git a/demos/application-features/filtering/index.html b/demos/application-features/filtering/index.html
index 2642ed946..29a0b2ab4 100644
--- a/demos/application-features/filtering/index.html
+++ b/demos/application-features/filtering/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/folding/FoldingDemo.js b/demos/application-features/folding/FoldingDemo.js
index 5d0c33f56..7acc6a314 100644
--- a/demos/application-features/folding/FoldingDemo.js
+++ b/demos/application-features/folding/FoldingDemo.js
@@ -101,22 +101,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/folding/FoldingDemo.ts b/demos/application-features/folding/FoldingDemo.ts
index 0bcca11b1..77455c8c6 100644
--- a/demos/application-features/folding/FoldingDemo.ts
+++ b/demos/application-features/folding/FoldingDemo.ts
@@ -98,22 +98,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/folding/index.html b/demos/application-features/folding/index.html
index c0682afcb..b14351164 100644
--- a/demos/application-features/folding/index.html
+++ b/demos/application-features/folding/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/graph-copy/GraphCopyDemo.js b/demos/application-features/graph-copy/GraphCopyDemo.js
index f9d9e1a33..4fccc60f6 100644
--- a/demos/application-features/graph-copy/GraphCopyDemo.js
+++ b/demos/application-features/graph-copy/GraphCopyDemo.js
@@ -108,22 +108,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -146,7 +146,7 @@ function copyGraph() {
copyGraphComponent.graph.clear()
graphCopier.copy(
originalGraphComponent.graph,
- item => {
+ (item) => {
const selection = originalGraphComponent.selection
if (INode.isInstance(item)) {
// copy selected node
diff --git a/demos/application-features/graph-copy/GraphCopyDemo.ts b/demos/application-features/graph-copy/GraphCopyDemo.ts
index 3797d3712..1c1306b5f 100644
--- a/demos/application-features/graph-copy/GraphCopyDemo.ts
+++ b/demos/application-features/graph-copy/GraphCopyDemo.ts
@@ -106,22 +106,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/graph-copy/index.html b/demos/application-features/graph-copy/index.html
index a5bdfea7a..474459146 100644
--- a/demos/application-features/graph-copy/index.html
+++ b/demos/application-features/graph-copy/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/graph-decorator/GraphDecoratorDemo.js b/demos/application-features/graph-decorator/GraphDecoratorDemo.js
index 05058c40f..ecb484f3b 100644
--- a/demos/application-features/graph-decorator/GraphDecoratorDemo.js
+++ b/demos/application-features/graph-decorator/GraphDecoratorDemo.js
@@ -96,22 +96,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -146,7 +146,7 @@ function configurePortCandidateProvider(graph) {
// IPortCandidateProvider.fromExistingPorts provides port candidates at the locations of already existing ports.
// IPortCandidateProvider.fromNodeCenter provides a single port candidate at the center of the node.
// IPortCandidateProvider.fromShapeGeometry provides several port candidates based on the shape of the node's style.
- portCandidateProviderDecorator.setFactory(node =>
+ portCandidateProviderDecorator.setFactory((node) =>
IPortCandidateProvider.combine([
IPortCandidateProvider.fromExistingPorts(node),
IPortCandidateProvider.fromNodeCenter(node),
diff --git a/demos/application-features/graph-decorator/GraphDecoratorDemo.ts b/demos/application-features/graph-decorator/GraphDecoratorDemo.ts
index 66ee1e769..7ef1c64a5 100644
--- a/demos/application-features/graph-decorator/GraphDecoratorDemo.ts
+++ b/demos/application-features/graph-decorator/GraphDecoratorDemo.ts
@@ -93,22 +93,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/graph-decorator/index.html b/demos/application-features/graph-decorator/index.html
index dcf612c9d..d1108e202 100644
--- a/demos/application-features/graph-decorator/index.html
+++ b/demos/application-features/graph-decorator/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/graph-search/GraphSearchDemo.js b/demos/application-features/graph-search/GraphSearchDemo.js
index 2efd63031..4e97e1b62 100644
--- a/demos/application-features/graph-search/GraphSearchDemo.js
+++ b/demos/application-features/graph-search/GraphSearchDemo.js
@@ -93,15 +93,15 @@ async function run() {
function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
- const nodesSource = graphBuilder.createNodesSource(graphData.nodeList, item => item.id)
- nodesSource.nodeCreator.layoutProvider = item =>
+ const nodesSource = graphBuilder.createNodesSource(graphData.nodeList, (item) => item.id)
+ nodesSource.nodeCreator.layoutProvider = (item) =>
item.label === 'Hobbies' ? new Rect(0, 0, 130, 70) : new Rect(0, 0, 80, 40)
- nodesSource.nodeCreator.createLabelBinding(data => data.label)
+ nodesSource.nodeCreator.createLabelBinding((data) => data.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -138,7 +138,7 @@ function updateSearch(searchText) {
// first remove previous highlights
manager.clearHighlights()
if (searchText.trim() !== '') {
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
if (matches(node, searchText)) {
// if the node is a match, highlight it
manager.addHighlight(node)
@@ -154,7 +154,7 @@ function updateSearch(searchText) {
* @returns {boolean} True if the node matches the text, false otherwise
*/
function matches(node, text) {
- return node.labels.some(label => label.text.toLowerCase().includes(text.toLowerCase()))
+ return node.labels.some((label) => label.text.toLowerCase().includes(text.toLowerCase()))
}
/**
@@ -177,7 +177,7 @@ function initializeGraph(graph) {
*/
function initializeUI() {
// adds the listener to the search box
- document.querySelector('#searchBox').addEventListener('input', e => {
+ document.querySelector('#searchBox').addEventListener('input', (e) => {
updateSearch(e.target.value)
})
}
diff --git a/demos/application-features/graph-search/GraphSearchDemo.ts b/demos/application-features/graph-search/GraphSearchDemo.ts
index 07197a633..674efc561 100644
--- a/demos/application-features/graph-search/GraphSearchDemo.ts
+++ b/demos/application-features/graph-search/GraphSearchDemo.ts
@@ -91,15 +91,15 @@ async function run(): Promise {
function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
- const nodesSource = graphBuilder.createNodesSource(graphData.nodeList, item => item.id)
- nodesSource.nodeCreator.layoutProvider = item =>
+ const nodesSource = graphBuilder.createNodesSource(graphData.nodeList, (item) => item.id)
+ nodesSource.nodeCreator.layoutProvider = (item) =>
item.label === 'Hobbies' ? new Rect(0, 0, 130, 70) : new Rect(0, 0, 80, 40)
- nodesSource.nodeCreator.createLabelBinding(data => data.label)
+ nodesSource.nodeCreator.createLabelBinding((data) => data.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -136,7 +136,7 @@ function updateSearch(searchText: string): void {
// first remove previous highlights
manager.clearHighlights()
if (searchText.trim() !== '') {
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
if (matches(node, searchText)) {
// if the node is a match, highlight it
manager.addHighlight(node)
@@ -152,7 +152,7 @@ function updateSearch(searchText: string): void {
* @returns True if the node matches the text, false otherwise
*/
function matches(node: INode, text: string): boolean {
- return node.labels.some(label => label.text.toLowerCase().includes(text.toLowerCase()))
+ return node.labels.some((label) => label.text.toLowerCase().includes(text.toLowerCase()))
}
/**
diff --git a/demos/application-features/graph-search/index.html b/demos/application-features/graph-search/index.html
index eac0511b7..747a781e7 100644
--- a/demos/application-features/graph-search/index.html
+++ b/demos/application-features/graph-search/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/grid-snapping/GridSnappingDemo.js b/demos/application-features/grid-snapping/GridSnappingDemo.js
index 9f7de9c5b..22f6ac8c0 100644
--- a/demos/application-features/grid-snapping/GridSnappingDemo.js
+++ b/demos/application-features/grid-snapping/GridSnappingDemo.js
@@ -118,22 +118,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -327,7 +327,7 @@ function createColorPicker(sortedGridColors) {
// Remove styling from previous selection
gridColorPicker
.querySelectorAll('.selected-color')
- .forEach(rect => rect.classList.remove('selected-color'))
+ .forEach((rect) => rect.classList.remove('selected-color'))
rect.classList.add('selected-color')
updateGridColor(fill)
}.bind(null, Fill.from(colorName.replace(' ', '-')), rect)
diff --git a/demos/application-features/grid-snapping/GridSnappingDemo.ts b/demos/application-features/grid-snapping/GridSnappingDemo.ts
index 1dc23601a..202f7a391 100644
--- a/demos/application-features/grid-snapping/GridSnappingDemo.ts
+++ b/demos/application-features/grid-snapping/GridSnappingDemo.ts
@@ -115,22 +115,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/grid-snapping/index.html b/demos/application-features/grid-snapping/index.html
index 27edda3f9..48945e61a 100644
--- a/demos/application-features/grid-snapping/index.html
+++ b/demos/application-features/grid-snapping/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/input-output/InputOutputDemo.js b/demos/application-features/input-output/InputOutputDemo.js
index c50753979..06df1fde7 100644
--- a/demos/application-features/input-output/InputOutputDemo.js
+++ b/demos/application-features/input-output/InputOutputDemo.js
@@ -106,22 +106,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/input-output/InputOutputDemo.ts b/demos/application-features/input-output/InputOutputDemo.ts
index cdb3538d5..f969af1b3 100644
--- a/demos/application-features/input-output/InputOutputDemo.ts
+++ b/demos/application-features/input-output/InputOutputDemo.ts
@@ -103,22 +103,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/input-output/index.html b/demos/application-features/input-output/index.html
index 77e4ebb42..065b305bf 100644
--- a/demos/application-features/input-output/index.html
+++ b/demos/application-features/input-output/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.js b/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.js
index 4e93d6558..d4b8683e2 100644
--- a/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.js
+++ b/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.js
@@ -76,32 +76,32 @@ let graphComponent = null
let aggregateGraph = null
// selectors for shape and/or color
-const shapeSelector = n => n.style.shape
+const shapeSelector = (n) => n.style.shape
-const fillColorSelector = n => {
+const fillColorSelector = (n) => {
const fill = n.style.fill
return fill.color
}
-const shapeAndFillSelector = n => new ShapeAndFill(shapeSelector(n), fillColorSelector(n))
+const shapeAndFillSelector = (n) => new ShapeAndFill(shapeSelector(n), fillColorSelector(n))
const grayBorder = new Stroke('#77776E', 2.0)
// style factories for aggregation nodes
-const shapeStyle = shape =>
+const shapeStyle = (shape) =>
new ShapeNodeStyle({
fill: '#C7C7A6',
shape: shape,
stroke: grayBorder
})
-const fillStyle = fillColor =>
+const fillStyle = (fillColor) =>
new ShapeNodeStyle({
fill: new SolidColorFill(fillColor),
shape: ShapeNodeShape.ELLIPSE,
stroke: grayBorder
})
-const shapeAndFillStyle = shapeAndFill =>
+const shapeAndFillStyle = (shapeAndFill) =>
new ShapeNodeStyle({
fill: new SolidColorFill(shapeAndFill.fillColor),
shape: shapeAndFill.shape,
@@ -169,7 +169,7 @@ function configureContextMenu(graphComponent) {
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
@@ -208,7 +208,7 @@ function populateContextMenu(contextMenu, _sender, e) {
const selectedNodes = graphComponent.selection.selectedNodes
if (selectedNodes.size > 0) {
// only allow aggregation operations on nodes that are not aggregation nodes already
- const aggregateAllowed = selectedNodes.some(n => !aggregateGraph.isAggregationItem(n))
+ const aggregateAllowed = selectedNodes.some((n) => !aggregateGraph.isAggregationItem(n))
if (aggregateAllowed) {
// add aggregation menu items
@@ -226,7 +226,7 @@ function populateContextMenu(contextMenu, _sender, e) {
)
}
- const separateAllowed = selectedNodes.some(n => aggregateGraph.isAggregationItem(n))
+ const separateAllowed = selectedNodes.some((n) => aggregateGraph.isAggregationItem(n))
if (separateAllowed) {
contextMenu.addMenuItem('Separate', () => separate(selectedNodes.toList()))
@@ -246,7 +246,7 @@ function populateContextMenu(contextMenu, _sender, e) {
aggregateAll(shapeAndFillSelector, shapeAndFillStyle)
)
- const separateAllowed = graphComponent.graph.nodes.some(node =>
+ const separateAllowed = graphComponent.graph.nodes.some((node) =>
aggregateGraph.isAggregationItem(node)
)
@@ -332,9 +332,9 @@ function buildGraph(graph, graphData) {
graphBuilder.createNodesSource({
data: graphData.nodeList,
- id: item => item.id,
- parentId: item => item.parentId
- }).nodeCreator.styleProvider = item => {
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
+ }).nodeCreator.styleProvider = (item) => {
switch (item.tag) {
case 'b1':
return new ShapeNodeStyle({
@@ -383,8 +383,8 @@ function buildGraph(graph, graphData) {
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -401,15 +401,15 @@ function buildGraph(graph, graphData) {
function aggregateSame(nodes, selector, styleFactory) {
// get one representative of each kind of node (determined by the selector) ignoring aggregation nodes
const distinctNodes = nodes
- .filter(n => !aggregateGraph.isAggregationItem(n))
+ .filter((n) => !aggregateGraph.isAggregationItem(n))
.groupBy({
keySelector: selector,
resultCreator: (key, enumerable) => ({ key: key, enumerable: enumerable })
})
- .map(grouping => grouping.enumerable.first())
+ .map((grouping) => grouping.enumerable.first())
.toList()
- distinctNodes.forEach(node => {
+ distinctNodes.forEach((node) => {
// aggregate all nodes of the same kind as the representing node
const nodesOfSameKind = collectNodesOfSameKind(node, selector)
aggregate(nodesOfSameKind, selector(node), styleFactory)
@@ -428,8 +428,8 @@ function aggregateSame(nodes, selector, styleFactory) {
function collectNodesOfSameKind(node, selector) {
const nodeKind = selector(node)
return graphComponent.graph.nodes
- .filter(n => !aggregateGraph.isAggregationItem(n))
- .filter(n => YObject.equals(selector(n), nodeKind))
+ .filter((n) => !aggregateGraph.isAggregationItem(n))
+ .filter((n) => YObject.equals(selector(n), nodeKind))
.toList()
}
@@ -450,7 +450,7 @@ function aggregateAll(selector, styleFactory) {
resultCreator: (key, enumerable) => ({ key: key, enumerable: enumerable })
})
.toList()
- .forEach(arg => {
+ .forEach((arg) => {
aggregate(arg.enumerable.toList(), arg.key, styleFactory)
})
@@ -478,7 +478,7 @@ function aggregate(nodes, key, styleFactory) {
* @param {!IEnumerable.} nodes the nodes to separate
*/
function separate(nodes) {
- nodes.forEach(node => {
+ nodes.forEach((node) => {
if (aggregateGraph.isAggregationItem(node)) {
aggregateGraph.separate(node)
}
diff --git a/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.ts b/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.ts
index df29cee6a..17fb4294a 100644
--- a/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.ts
+++ b/demos/application-features/interactiveaggregation/InteractiveAggregationDemo.ts
@@ -166,7 +166,7 @@ function configureContextMenu(graphComponent: GraphComponent): void {
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
@@ -244,7 +244,7 @@ function populateContextMenu(
aggregateAll(shapeAndFillSelector, shapeAndFillStyle)
)
- const separateAllowed = graphComponent.graph.nodes.some(node =>
+ const separateAllowed = graphComponent.graph.nodes.some((node) =>
aggregateGraph.isAggregationItem(node)
)
@@ -328,9 +328,9 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder.createNodesSource({
data: graphData.nodeList,
- id: item => item.id,
- parentId: item => item.parentId
- }).nodeCreator.styleProvider = item => {
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
+ }).nodeCreator.styleProvider = (item) => {
switch (item.tag) {
case 'b1':
return new ShapeNodeStyle({
@@ -379,8 +379,8 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
@@ -400,15 +400,15 @@ function aggregateSame(
): void {
// get one representative of each kind of node (determined by the selector) ignoring aggregation nodes
const distinctNodes: IList = nodes
- .filter(n => !aggregateGraph.isAggregationItem(n))
+ .filter((n) => !aggregateGraph.isAggregationItem(n))
.groupBy({
keySelector: selector,
resultCreator: (key, enumerable) => ({ key: key, enumerable: enumerable })
})
- .map(grouping => grouping.enumerable.first())
+ .map((grouping) => grouping.enumerable.first())
.toList()
- distinctNodes.forEach(node => {
+ distinctNodes.forEach((node) => {
// aggregate all nodes of the same kind as the representing node
const nodesOfSameKind = collectNodesOfSameKind(node, selector)
aggregate(nodesOfSameKind, selector(node), styleFactory)
@@ -425,8 +425,8 @@ function aggregateSame(
function collectNodesOfSameKind(node: INode, selector: (arg: INode) => TKey): IList {
const nodeKind = selector(node)
return graphComponent.graph.nodes
- .filter(n => !aggregateGraph.isAggregationItem(n))
- .filter(n => YObject.equals(selector(n), nodeKind))
+ .filter((n) => !aggregateGraph.isAggregationItem(n))
+ .filter((n) => YObject.equals(selector(n), nodeKind))
.toList()
}
@@ -447,7 +447,7 @@ function aggregateAll(
resultCreator: (key, enumerable) => ({ key: key, enumerable: enumerable })
})
.toList()
- .forEach(arg => {
+ .forEach((arg) => {
aggregate(arg.enumerable.toList(), arg.key, styleFactory)
})
@@ -478,7 +478,7 @@ function aggregate(
* @param nodes the nodes to separate
*/
function separate(nodes: IEnumerable): void {
- nodes.forEach(node => {
+ nodes.forEach((node) => {
if (aggregateGraph.isAggregationItem(node)) {
aggregateGraph.separate(node)
}
diff --git a/demos/application-features/interactiveaggregation/index.html b/demos/application-features/interactiveaggregation/index.html
index 3296d0c3c..cbf3b33e6 100644
--- a/demos/application-features/interactiveaggregation/index.html
+++ b/demos/application-features/interactiveaggregation/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/label-text-wrapping/index.html b/demos/application-features/label-text-wrapping/index.html
index 4f973b342..fcc37cc54 100644
--- a/demos/application-features/label-text-wrapping/index.html
+++ b/demos/application-features/label-text-wrapping/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/native-listeners/NativeListenersDemo.js b/demos/application-features/native-listeners/NativeListenersDemo.js
index deaf04dc6..6f3fad014 100644
--- a/demos/application-features/native-listeners/NativeListenersDemo.js
+++ b/demos/application-features/native-listeners/NativeListenersDemo.js
@@ -90,22 +90,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/native-listeners/NativeListenersDemo.ts b/demos/application-features/native-listeners/NativeListenersDemo.ts
index 6bdb82357..808874a61 100644
--- a/demos/application-features/native-listeners/NativeListenersDemo.ts
+++ b/demos/application-features/native-listeners/NativeListenersDemo.ts
@@ -87,22 +87,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/native-listeners/NodeStyleDecorator.js b/demos/application-features/native-listeners/NodeStyleDecorator.js
index 98ee1366b..05f6e68ce 100644
--- a/demos/application-features/native-listeners/NodeStyleDecorator.js
+++ b/demos/application-features/native-listeners/NodeStyleDecorator.js
@@ -87,7 +87,7 @@ export default class NodeStyleDecorator extends NodeStyleBase {
// register a native click listener on the SVG element
button.addEventListener('click', showToast)
// the input mode should not handle any event on the the button where we registered a native click listener
- button.addEventListener('mousedown', e => e.preventDefault())
+ button.addEventListener('mousedown', (e) => e.preventDefault())
const decorationVisual = new SvgVisual(button)
diff --git a/demos/application-features/native-listeners/index.html b/demos/application-features/native-listeners/index.html
index 78fe37f35..8a9617a24 100644
--- a/demos/application-features/native-listeners/index.html
+++ b/demos/application-features/native-listeners/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.js b/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.js
index 03a55ba71..5867feef6 100644
--- a/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.js
+++ b/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.js
@@ -96,22 +96,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.ts b/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.ts
index 04b204d03..867a4b4ff 100644
--- a/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.ts
+++ b/demos/application-features/orthogonal-edges/OrthogonalEdgesDemo.ts
@@ -93,22 +93,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/orthogonal-edges/index.html b/demos/application-features/orthogonal-edges/index.html
index b527945f1..c8f3ce64b 100644
--- a/demos/application-features/orthogonal-edges/index.html
+++ b/demos/application-features/orthogonal-edges/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/overview/OverviewComponentDemo.js b/demos/application-features/overview/OverviewComponentDemo.js
index 89e4d3819..0cc4bd3b8 100644
--- a/demos/application-features/overview/OverviewComponentDemo.js
+++ b/demos/application-features/overview/OverviewComponentDemo.js
@@ -118,22 +118,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/overview/OverviewComponentDemo.ts b/demos/application-features/overview/OverviewComponentDemo.ts
index 3bb248abb..66d20bfe2 100644
--- a/demos/application-features/overview/OverviewComponentDemo.ts
+++ b/demos/application-features/overview/OverviewComponentDemo.ts
@@ -115,22 +115,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/overview/index.html b/demos/application-features/overview/index.html
index ec9b1f83e..fb62d7d7b 100644
--- a/demos/application-features/overview/index.html
+++ b/demos/application-features/overview/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.js b/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.js
index 9866ef55e..7a42df74e 100644
--- a/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.js
+++ b/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.js
@@ -116,22 +116,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.ts b/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.ts
index e751f7b94..24f08b376 100644
--- a/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.ts
+++ b/demos/application-features/rectangular-indicator/RectangularIndicatorDemo.ts
@@ -112,22 +112,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/rectangular-indicator/index.html b/demos/application-features/rectangular-indicator/index.html
index 1175eb5c1..0d11cfd7d 100644
--- a/demos/application-features/rectangular-indicator/index.html
+++ b/demos/application-features/rectangular-indicator/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/rotatablenodes/RotatableNodeLabels.js b/demos/application-features/rotatablenodes/RotatableNodeLabels.js
index 645c3a719..ea2d614d8 100644
--- a/demos/application-features/rotatablenodes/RotatableNodeLabels.js
+++ b/demos/application-features/rotatablenodes/RotatableNodeLabels.js
@@ -85,7 +85,7 @@ export class RotatableNodeLabelModelDecorator extends BaseClass(
* Provides custom implementations of {@link ILabelModelParameterProvider} and
* {@link ILabelModelParameterFinder} that consider the nodes rotation.
* Wraps the default implementations in a special wrapper which supports rotation.
- * @template {*} T
+ * @template T
* @param {!Class.} type
* @returns {?T}
*/
@@ -326,7 +326,7 @@ class RotatedNodeLabelModelParameterProvider extends BaseClass(ILabelModelParame
const wrapperModel = model
const parameters = this.wrappedProvider.getParameters(label, wrapperModel.wrapped)
const result = new List()
- parameters.forEach(parameter => {
+ parameters.forEach((parameter) => {
result.add(wrapperModel.createWrappingParameter(parameter))
})
return result
@@ -390,10 +390,6 @@ export class RotatableNodeLabelModelDecoratorExtension extends MarkupExtension {
_useNodeRotation = true
_wrapped = null
- constructor() {
- super()
- }
-
/**
* @type {boolean}
*/
diff --git a/demos/application-features/rotatablenodes/RotatableNodeLabels.ts b/demos/application-features/rotatablenodes/RotatableNodeLabels.ts
index 7e0bfeed3..37d75c950 100644
--- a/demos/application-features/rotatablenodes/RotatableNodeLabels.ts
+++ b/demos/application-features/rotatablenodes/RotatableNodeLabels.ts
@@ -86,7 +86,7 @@ export class RotatableNodeLabelModelDecorator
* Wraps the default implementations in a special wrapper which supports rotation.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
if (type === ILabelModelParameterProvider.$class) {
const provider = this.wrapped.lookup(ILabelModelParameterProvider.$class)
if (provider) {
@@ -295,7 +295,7 @@ class RotatedNodeLabelModelParameterProvider
const wrapperModel = model as RotatableNodeLabelModelDecorator
const parameters = this.wrappedProvider.getParameters(label, wrapperModel.wrapped)
const result = new List()
- parameters.forEach(parameter => {
+ parameters.forEach((parameter) => {
result.add(wrapperModel.createWrappingParameter(parameter))
})
return result
@@ -361,10 +361,6 @@ export class RotatableNodeLabelModelDecoratorExtension extends MarkupExtension {
private _useNodeRotation = true
private _wrapped: ILabelModel = null!
- constructor() {
- super()
- }
-
get useNodeRotation(): boolean {
return this._useNodeRotation
}
diff --git a/demos/application-features/rotatablenodes/RotatableNodes.js b/demos/application-features/rotatablenodes/RotatableNodes.js
index ee86df364..b2cb34cf5 100644
--- a/demos/application-features/rotatablenodes/RotatableNodes.js
+++ b/demos/application-features/rotatablenodes/RotatableNodes.js
@@ -710,7 +710,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
this.portHandles.clear()
const portContext = new DelegatingContext(inputModeContext)
- this.node.ports.forEach(port => {
+ this.node.ports.forEach((port) => {
const portHandle = new DummyPortLocationModelParameterHandle(port)
portHandle.initializeDrag(portContext)
this.portHandles.add(portHandle)
@@ -779,7 +779,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.handleMove(portContext, this.dummyLocation, newLocation)
})
if (this.reshapeHandler) {
@@ -859,7 +859,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
this.initialLayout.size.toSize()
)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.cancelDrag(portContext, originalLocation)
})
this.portHandles.clear()
@@ -883,7 +883,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
this.dummySize
)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.dragFinished(portContext, originalLocation, newLocation)
})
this.portHandles.clear()
@@ -1178,7 +1178,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
this.portHandles.clear()
const portContext = new DelegatingContext(inputModeContext)
- this.node.ports.forEach(port => {
+ this.node.ports.forEach((port) => {
const portHandle = new DummyPortLocationModelParameterHandle(port)
portHandle.initializeDrag(portContext)
this.portHandles.add(portHandle)
@@ -1193,7 +1193,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
// only collect nodes that are in the viewport
const rotatedNodes = canvas
.getCanvasObjects()
- .filter(co => {
+ .filter((co) => {
const userObject = co.userObject
return (
userObject !== this.node &&
@@ -1202,11 +1202,11 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
canvas.viewport.intersects(userObject.layout.toRect())
)
})
- .map(co => co.userObject)
+ .map((co) => co.userObject)
// Group nodes by identical angles
this.nodeAngles = rotatedNodes.reduce((groups, node) => {
const angle = node.style.angle
- const group = groups.find(g => g.angle === angle)
+ const group = groups.find((g) => g.angle === angle)
if (group) {
group.nodes.push(node)
} else {
@@ -1236,7 +1236,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
this.setAngle(inputModeContext, angle)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.handleMove(portContext, originalLocation, newLocation)
})
if (this.reshapeHandler) {
@@ -1278,7 +1278,8 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
const candidate = this.nodeAngles
.sort((nodeAngle1, nodeAngle2) => nodeAngle2.angle - nodeAngle1.angle)
.find(
- nodeAngle => normalizeAngle(Math.abs(nodeAngle.angle - angle)) < this.snapToSameAngleDelta
+ (nodeAngle) =>
+ normalizeAngle(Math.abs(nodeAngle.angle - angle)) < this.snapToSameAngleDelta
)
if (candidate) {
// Add highlight to every matching node
@@ -1286,7 +1287,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
if (this.sameAngleHighlightedNodes !== candidate.nodes) {
this.clearSameAngleHighlights(inputModeContext)
}
- candidate.nodes.forEach(matchingNode => {
+ candidate.nodes.forEach((matchingNode) => {
canvas.highlightIndicatorManager.addHighlight(matchingNode)
})
this.sameAngleHighlightedNodes = candidate.nodes
@@ -1312,7 +1313,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
this.setAngle(context, this.initialAngle)
const portContext = new DelegatingContext(context)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.cancelDrag(portContext, originalLocation)
})
this.portHandles.clear()
@@ -1349,7 +1350,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
}
const portContext = new DelegatingContext(context)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.dragFinished(portContext, originalLocation, newLocation)
})
this.portHandles.clear()
@@ -1384,7 +1385,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
*/
clearSameAngleHighlights(context) {
if (this.sameAngleHighlightedNodes) {
- this.sameAngleHighlightedNodes.forEach(highlightedNode => {
+ this.sameAngleHighlightedNodes.forEach((highlightedNode) => {
context.canvasComponent.highlightIndicatorManager.removeHighlight(highlightedNode)
})
this.sameAngleHighlightedNodes = null
@@ -1764,7 +1765,7 @@ class DelegatingContext extends BaseClass(IInputModeContext) {
/**
* Delegates to the wrapped context's lookup but cancels the snap context.
- * @template {*} T
+ * @template T
* @param {!Class.} type
* @returns {?T}
*/
@@ -1817,10 +1818,6 @@ export class RotatableNodeStyleDecoratorExtension extends MarkupExtension {
_angle = 0
_wrapped
- constructor() {
- super()
- }
-
/**
* @type {number}
*/
diff --git a/demos/application-features/rotatablenodes/RotatableNodes.ts b/demos/application-features/rotatablenodes/RotatableNodes.ts
index c0ee862fc..ee4e374d6 100644
--- a/demos/application-features/rotatablenodes/RotatableNodes.ts
+++ b/demos/application-features/rotatablenodes/RotatableNodes.ts
@@ -652,7 +652,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
this.portHandles.clear()
const portContext = new DelegatingContext(inputModeContext)
- this.node.ports.forEach(port => {
+ this.node.ports.forEach((port) => {
const portHandle = new DummyPortLocationModelParameterHandle(port)
portHandle.initializeDrag(portContext)
this.portHandles.add(portHandle)
@@ -722,7 +722,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.handleMove(portContext, this.dummyLocation, newLocation)
})
if (this.reshapeHandler) {
@@ -792,7 +792,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
this.initialLayout.size.toSize()
)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.cancelDrag(portContext, originalLocation)
})
this.portHandles.clear()
@@ -817,7 +817,7 @@ class RotatedNodeResizeHandle extends BaseClass(IHandle, IPoint) {
this.dummySize
)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.dragFinished(portContext, originalLocation, newLocation)
})
this.portHandles.clear()
@@ -1005,7 +1005,10 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
/**
* Creates a new instance.
*/
- constructor(private node: INode, private reshapeHandler: IReshapeHandler) {
+ constructor(
+ private node: INode,
+ private reshapeHandler: IReshapeHandler
+ ) {
super()
this.snapDelta = 0
this.snapStep = 0
@@ -1082,7 +1085,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
this.portHandles.clear()
const portContext = new DelegatingContext(inputModeContext)
- this.node.ports.forEach(port => {
+ this.node.ports.forEach((port) => {
const portHandle = new DummyPortLocationModelParameterHandle(port)
portHandle.initializeDrag(portContext)
this.portHandles.add(portHandle)
@@ -1097,7 +1100,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
// only collect nodes that are in the viewport
const rotatedNodes = canvas
.getCanvasObjects()
- .filter(co => {
+ .filter((co) => {
const userObject = co.userObject
return (
userObject !== this.node &&
@@ -1106,11 +1109,11 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
canvas.viewport.intersects(userObject.layout.toRect())
)
})
- .map(co => co.userObject)
+ .map((co) => co.userObject)
// Group nodes by identical angles
this.nodeAngles = rotatedNodes.reduce((groups: SameAngleGroup[], node: INode) => {
const angle = (node.style as RotatableNodeStyleDecorator).angle
- const group = groups.find(g => g.angle === angle)
+ const group = groups.find((g) => g.angle === angle)
if (group) {
group.nodes.push(node)
} else {
@@ -1141,7 +1144,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
this.setAngle(inputModeContext, angle)
const portContext = new DelegatingContext(inputModeContext)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.handleMove(portContext, originalLocation, newLocation)
})
if (this.reshapeHandler) {
@@ -1181,7 +1184,8 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
nodeAngle2.angle - nodeAngle1.angle
)
.find(
- nodeAngle => normalizeAngle(Math.abs(nodeAngle.angle - angle)) < this.snapToSameAngleDelta
+ (nodeAngle) =>
+ normalizeAngle(Math.abs(nodeAngle.angle - angle)) < this.snapToSameAngleDelta
)
if (candidate) {
// Add highlight to every matching node
@@ -1189,7 +1193,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
if (this.sameAngleHighlightedNodes !== candidate.nodes) {
this.clearSameAngleHighlights(inputModeContext)
}
- candidate.nodes.forEach(matchingNode => {
+ candidate.nodes.forEach((matchingNode) => {
canvas.highlightIndicatorManager.addHighlight(matchingNode)
})
this.sameAngleHighlightedNodes = candidate.nodes
@@ -1213,7 +1217,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
this.setAngle(context, this.initialAngle)
const portContext = new DelegatingContext(context)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.cancelDrag(portContext, originalLocation)
})
this.portHandles.clear()
@@ -1247,7 +1251,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
}
const portContext = new DelegatingContext(context)
- this.portHandles.forEach(portHandle => {
+ this.portHandles.forEach((portHandle) => {
portHandle.dragFinished(portContext, originalLocation, newLocation)
})
this.portHandles.clear()
@@ -1281,7 +1285,7 @@ export class NodeRotateHandle extends BaseClass(IHandle, IPoint) {
*/
clearSameAngleHighlights(context: IInputModeContext): void {
if (this.sameAngleHighlightedNodes) {
- this.sameAngleHighlightedNodes.forEach(highlightedNode => {
+ this.sameAngleHighlightedNodes.forEach((highlightedNode) => {
;(context.canvasComponent as GraphComponent).highlightIndicatorManager.removeHighlight(
highlightedNode
)
@@ -1618,7 +1622,7 @@ class DelegatingContext extends BaseClass(IInputModeContext) {
* Delegates to the wrapped context's lookup but cancels the snap context.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
return type === SnapContext.$class ? null : this.context.lookup(type)
}
@@ -1660,10 +1664,6 @@ export class RotatableNodeStyleDecoratorExtension extends MarkupExtension {
private _angle = 0
private _wrapped!: INodeStyle
- constructor() {
- super()
- }
-
get angle(): number {
return this._angle
}
diff --git a/demos/application-features/rotatablenodes/RotatableNodesDemo.js b/demos/application-features/rotatablenodes/RotatableNodesDemo.js
index 6bf612adb..e70b2c840 100644
--- a/demos/application-features/rotatablenodes/RotatableNodesDemo.js
+++ b/demos/application-features/rotatablenodes/RotatableNodesDemo.js
@@ -145,7 +145,7 @@ function initializeInputMode() {
const handleInputMode = graphComponent.inputMode.handleInputMode
handleInputMode.addDraggedListener((src, evt) => {
if (src.currentHandle instanceof RotatableNodes.NodeRotateHandle) {
- const rotatedNode = src.affectedItems.find(item => item instanceof INode)
+ const rotatedNode = src.affectedItems.find((item) => item instanceof INode)
if (
rotatedNode &&
rotatedNode.style instanceof RotatableNodes.RotatableNodeStyleDecorator &&
@@ -193,7 +193,7 @@ function initializeGraph() {
// For rotated nodes, need to provide port candidates that are backed by a rotatable port location model
// If you want to support non-rotated port candidates, you can just provide undecorated instances here
decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
- node => node.style instanceof RotatableNodes.RotatableNodeStyleDecorator,
+ (node) => node.style instanceof RotatableNodes.RotatableNodeStyleDecorator,
createPortCandidateProvider
)
@@ -367,7 +367,7 @@ function createPortCandidateProvider(node) {
const shapeProvider = IPortCandidateProvider.fromShapeGeometry(dummyNode, 0)
const shapeCandidates = shapeProvider.getAllTargetPortCandidates(null)
const rotatingCandidates = shapeCandidates.map(
- candidate =>
+ (candidate) =>
new DefaultPortCandidate(
node,
rotatedPortModel.createWrappingParameter(candidate.locationParameter)
@@ -423,14 +423,14 @@ function loadGraph(sample) {
const nodesSource = builder.createNodesSource({
data: data.nodes,
id: 'id',
- layout: data => new Rect(data.cx, data.cy, defaultNodeSize.width, defaultNodeSize.height),
- style: data => {
+ layout: (data) => new Rect(data.cx, data.cy, defaultNodeSize.width, defaultNodeSize.height),
+ style: (data) => {
const nodeStyle = graph.nodeDefaults.getStyleInstance()
nodeStyle.angle = data.angle
return nodeStyle
}
})
- nodesSource.nodeCreator.createLabelBinding(data => `${data.angle}°`)
+ nodesSource.nodeCreator.createLabelBinding((data) => `${data.angle}°`)
builder.createEdgesSource(data.edges, 'source', 'target')
builder.buildGraph()
@@ -440,7 +440,7 @@ function loadGraph(sample) {
INode.$class,
YObject.$class,
RotatedNodeLayoutStage.ROTATED_NODE_LAYOUT_DP_KEY,
- node => {
+ (node) => {
const style = node.style
return {
outline: getOutline(style, node),
@@ -494,7 +494,7 @@ async function applyLayout() {
INode.$class,
YObject.$class,
RotatedNodeLayoutStage.ROTATED_NODE_LAYOUT_DP_KEY,
- node => {
+ (node) => {
const style = node.style
return {
outline: getOutline(style, node),
@@ -607,7 +607,7 @@ function initializeUI() {
inputMode.orthogonalEdgeEditingContext.enabled = orthogonalEditing.checked
})
- addNavigationButtons(selectSample).addEventListener('change', e => {
+ addNavigationButtons(selectSample).addEventListener('change', (e) => {
loadGraph(e.target.value)
})
@@ -622,12 +622,12 @@ function initializeUI() {
*/
function addRotatedStyles() {
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (!graph.isGroupNode(node)) {
if (!(node.style instanceof RotatableNodes.RotatableNodeStyleDecorator)) {
graph.setStyle(node, new RotatableNodes.RotatableNodeStyleDecorator(node.style))
}
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
if (
!(
label.layoutParameter instanceof
@@ -642,7 +642,7 @@ function addRotatedStyles() {
)
}
})
- node.ports.forEach(port => {
+ node.ports.forEach((port) => {
if (
!(
port.locationParameter instanceof
diff --git a/demos/application-features/rotatablenodes/RotatableNodesDemo.ts b/demos/application-features/rotatablenodes/RotatableNodesDemo.ts
index 17afb2b90..7d6b5dcf1 100644
--- a/demos/application-features/rotatablenodes/RotatableNodesDemo.ts
+++ b/demos/application-features/rotatablenodes/RotatableNodesDemo.ts
@@ -137,7 +137,7 @@ function initializeInputMode(): void {
const handleInputMode = (graphComponent.inputMode as GraphEditorInputMode).handleInputMode
handleInputMode.addDraggedListener((src, evt) => {
if (src.currentHandle instanceof RotatableNodes.NodeRotateHandle) {
- const rotatedNode = src.affectedItems.find(item => item instanceof INode) as INode
+ const rotatedNode = src.affectedItems.find((item) => item instanceof INode) as INode
if (
rotatedNode &&
rotatedNode.style instanceof RotatableNodes.RotatableNodeStyleDecorator &&
@@ -185,7 +185,7 @@ function initializeGraph(): void {
// For rotated nodes, need to provide port candidates that are backed by a rotatable port location model
// If you want to support non-rotated port candidates, you can just provide undecorated instances here
decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
- node => node.style instanceof RotatableNodes.RotatableNodeStyleDecorator,
+ (node) => node.style instanceof RotatableNodes.RotatableNodeStyleDecorator,
createPortCandidateProvider
)
@@ -358,7 +358,7 @@ function createPortCandidateProvider(node: INode) {
const shapeProvider = IPortCandidateProvider.fromShapeGeometry(dummyNode, 0)
const shapeCandidates = shapeProvider.getAllTargetPortCandidates(null!)
const rotatingCandidates = shapeCandidates.map(
- candidate =>
+ (candidate) =>
new DefaultPortCandidate(
node,
rotatedPortModel.createWrappingParameter(candidate.locationParameter)
@@ -411,14 +411,14 @@ function loadGraph(sample: 'sine' | 'circle'): void {
const nodesSource = builder.createNodesSource({
data: data.nodes,
id: 'id',
- layout: data => new Rect(data.cx, data.cy, defaultNodeSize.width, defaultNodeSize.height),
- style: data => {
+ layout: (data) => new Rect(data.cx, data.cy, defaultNodeSize.width, defaultNodeSize.height),
+ style: (data) => {
const nodeStyle = graph.nodeDefaults.getStyleInstance() as RotatableNodeStyleDecorator
nodeStyle.angle = data.angle
return nodeStyle
}
})
- nodesSource.nodeCreator.createLabelBinding(data => `${data.angle}°`)
+ nodesSource.nodeCreator.createLabelBinding((data) => `${data.angle}°`)
builder.createEdgesSource(data.edges, 'source', 'target')
builder.buildGraph()
@@ -428,7 +428,7 @@ function loadGraph(sample: 'sine' | 'circle'): void {
INode.$class,
YObject.$class,
RotatedNodeLayoutStage.ROTATED_NODE_LAYOUT_DP_KEY,
- node => {
+ (node) => {
const style = node.style
return {
outline: getOutline(style, node),
@@ -472,7 +472,7 @@ async function applyLayout() {
INode.$class,
YObject.$class,
RotatedNodeLayoutStage.ROTATED_NODE_LAYOUT_DP_KEY,
- node => {
+ (node) => {
const style = node.style
return {
outline: getOutline(style, node),
@@ -600,12 +600,12 @@ function initializeUI(): void {
*/
function addRotatedStyles(): void {
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (!graph.isGroupNode(node)) {
if (!(node.style instanceof RotatableNodes.RotatableNodeStyleDecorator)) {
graph.setStyle(node, new RotatableNodes.RotatableNodeStyleDecorator(node.style))
}
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
if (
!(
label.layoutParameter instanceof
@@ -620,7 +620,7 @@ function addRotatedStyles(): void {
)
}
})
- node.ports.forEach(port => {
+ node.ports.forEach((port) => {
if (
!(
port.locationParameter instanceof
diff --git a/demos/application-features/rotatablenodes/RotatablePorts.js b/demos/application-features/rotatablenodes/RotatablePorts.js
index e548989f8..bbf5f0789 100644
--- a/demos/application-features/rotatablenodes/RotatablePorts.js
+++ b/demos/application-features/rotatablenodes/RotatablePorts.js
@@ -72,13 +72,6 @@ export class RotatablePortLocationModelDecorator extends BaseClass(
RotatablePortLocationModelDecorator.$INSTANCE = INSTANCE
}
- /**
- * Creates a new instance wrapping a {@link FreeNodePortLocationModel}.
- */
- constructor() {
- super()
- }
-
/**
* Delegates to the wrapped location model's lookup.
* @template T
diff --git a/demos/application-features/rotatablenodes/RotatablePorts.ts b/demos/application-features/rotatablenodes/RotatablePorts.ts
index 6f551e535..9d8d53a32 100644
--- a/demos/application-features/rotatablenodes/RotatablePorts.ts
+++ b/demos/application-features/rotatablenodes/RotatablePorts.ts
@@ -60,13 +60,6 @@ export class RotatablePortLocationModelDecorator extends BaseClass(
static INSTANCE: RotatablePortLocationModelDecorator = new RotatablePortLocationModelDecorator()
- /**
- * Creates a new instance wrapping a {@link FreeNodePortLocationModel}.
- */
- constructor() {
- super()
- }
-
/**
* Delegates to the wrapped location model's lookup.
*/
diff --git a/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.js b/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.js
index dd615554a..e9a9e2486 100644
--- a/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.js
+++ b/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.js
@@ -65,14 +65,6 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
/** How to connect edges from the bounding box to the actual shape. */
edgeRoutingMode = 'shortest-straight-path-to-border'
- /**
- * Creates a new instance with an optional core layout algorithm.
- * @param {?ILayoutAlgorithm} [coreLayout=null]
- */
- constructor(coreLayout = null) {
- super(coreLayout)
- }
-
/**
* The {@link IDataProvider} key to register a data provider that provides the outline and
* oriented layout to this stage.
@@ -135,7 +127,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
}
try {
const originalDimensions = Maps.createHashedNodeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const { outline, orientedLayout } = boundsProvider.get(node)
if (orientedLayout) {
// if the current node is rotated: apply fixes
@@ -173,7 +165,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
)
// for each out edge
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
// create a strong port constraint for the side which is closest to the port location (without rotation)
const constraint = sourcePortConstraints.get(edge)
if (!constraint) {
@@ -182,7 +174,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
sourcePortConstraints.set(edge, PortConstraint.create(side, true))
}
})
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
// create a strong port constraint for the side which is closest to the port location (without rotation)
const constraint = targetPortConstraints.get(edge)
if (!constraint) {
@@ -196,12 +188,12 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
// For source and target port constraints: fix the PortSide according to the rotation
const angle = Math.atan2(orientedLayout.upY, orientedLayout.upX)
if (sourcePortConstraints) {
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
this.fixPortConstraintSide(sourcePortConstraints, edge, angle)
})
}
if (targetPortConstraints) {
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
this.fixPortConstraintSide(targetPortConstraints, edge, angle)
})
}
@@ -218,7 +210,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
layout.applyLayout(graph)
const groups = graph.getDataProvider(GroupingKeys.GROUP_DP_KEY)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (groups && groups.getBoolean(node)) {
// groups don't need to be adjusted to their former size and location because their bounds are entirely
// calculated by the layout algorithm and they are not rotated
@@ -245,7 +237,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
if (this.edgeRoutingMode === 'no-routing') {
// NoRouting still needs fix for self-loops
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
if (edge.selfLoop) {
this.fixPorts(graph, edge, path, false)
this.fixPorts(graph, edge, path, true)
@@ -260,10 +252,10 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
// enlarge the adjacent segment to the oriented rectangle (represented by the path)
// handling in and out edges separately will automatically cause self-loops to be handled correctly
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
this.fixPorts(graph, edge, path, false)
})
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
this.fixPorts(graph, edge, path, true)
})
})
diff --git a/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.ts b/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.ts
index 2e52c88b8..dbaa068f5 100644
--- a/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.ts
+++ b/demos/application-features/rotatablenodes/RotatedNodeLayoutStage.ts
@@ -65,13 +65,6 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
public edgeRoutingMode: 'shortest-straight-path-to-border' | 'no-routing' | 'fixed-port' =
'shortest-straight-path-to-border'
- /**
- * Creates a new instance with an optional core layout algorithm.
- */
- constructor(coreLayout: ILayoutAlgorithm | null = null) {
- super(coreLayout)
- }
-
/**
* The {@link IDataProvider} key to register a data provider that provides the outline and
* oriented layout to this stage.
@@ -132,7 +125,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
}
try {
const originalDimensions = Maps.createHashedNodeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const { outline, orientedLayout } = boundsProvider.get(node) as {
outline: GeneralPath
orientedLayout: IOrientedRectangle
@@ -173,7 +166,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
)
// for each out edge
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
// create a strong port constraint for the side which is closest to the port location (without rotation)
const constraint = sourcePortConstraints!.get(edge)
if (!constraint) {
@@ -182,7 +175,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
sourcePortConstraints!.set(edge, PortConstraint.create(side, true))
}
})
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
// create a strong port constraint for the side which is closest to the port location (without rotation)
const constraint = targetPortConstraints!.get(edge)
if (!constraint) {
@@ -196,12 +189,12 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
// For source and target port constraints: fix the PortSide according to the rotation
const angle = Math.atan2(orientedLayout.upY, orientedLayout.upX)
if (sourcePortConstraints) {
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
this.fixPortConstraintSide(sourcePortConstraints!, edge, angle)
})
}
if (targetPortConstraints) {
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
this.fixPortConstraintSide(targetPortConstraints!, edge, angle)
})
}
@@ -218,7 +211,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
layout.applyLayout(graph)
const groups = graph.getDataProvider(GroupingKeys.GROUP_DP_KEY)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (groups && groups.getBoolean(node)) {
// groups don't need to be adjusted to their former size and location because their bounds are entirely
// calculated by the layout algorithm and they are not rotated
@@ -245,7 +238,7 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
if (this.edgeRoutingMode === 'no-routing') {
// NoRouting still needs fix for self-loops
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
if (edge.selfLoop) {
this.fixPorts(graph, edge, path, false)
this.fixPorts(graph, edge, path, true)
@@ -260,10 +253,10 @@ export default class RotatedNodeLayoutStage extends LayoutStageBase {
// enlarge the adjacent segment to the oriented rectangle (represented by the path)
// handling in and out edges separately will automatically cause self-loops to be handled correctly
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
this.fixPorts(graph, edge, path, false)
})
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
this.fixPorts(graph, edge, path, true)
})
})
diff --git a/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.js b/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.js
index a00277ee6..f38d92868 100644
--- a/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.js
+++ b/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.js
@@ -50,7 +50,7 @@ export default class RotationAwareGroupBoundsCalculator extends BaseClass(IGroup
*/
calculateBounds(graph, groupNode) {
let bounds = Rect.EMPTY
- graph.getChildren(groupNode).forEach(node => {
+ graph.getChildren(groupNode).forEach((node) => {
const style = node.style
if (style instanceof RotatableNodeStyleDecorator) {
// if the node supports rotation: add the outer bounds of the rotated layout
diff --git a/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.ts b/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.ts
index 67a5dc8e8..dd79aeaf8 100644
--- a/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.ts
+++ b/demos/application-features/rotatablenodes/RotationAwareGroupBoundsCalculator.ts
@@ -47,7 +47,7 @@ export default class RotationAwareGroupBoundsCalculator extends BaseClass(IGroup
*/
calculateBounds(graph: IGraph, groupNode: INode): Rect {
let bounds = Rect.EMPTY
- graph.getChildren(groupNode).forEach(node => {
+ graph.getChildren(groupNode).forEach((node) => {
const style = node.style
if (style instanceof RotatableNodeStyleDecorator) {
// if the node supports rotation: add the outer bounds of the rotated layout
diff --git a/demos/application-features/rotatablenodes/index.html b/demos/application-features/rotatablenodes/index.html
index 32e717956..fa5ccd0fe 100644
--- a/demos/application-features/rotatablenodes/index.html
+++ b/demos/application-features/rotatablenodes/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.js b/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.js
index 4bbed7a89..2616bef7f 100644
--- a/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.js
+++ b/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.js
@@ -100,22 +100,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.ts b/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.ts
index 66fa0c259..a0530f3e5 100644
--- a/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.ts
+++ b/demos/application-features/simple-highlight-decorator/SimpleHighlightDecoratorDemo.ts
@@ -98,22 +98,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/simple-highlight-decorator/index.html b/demos/application-features/simple-highlight-decorator/index.html
index 4d2764357..70fea463c 100644
--- a/demos/application-features/simple-highlight-decorator/index.html
+++ b/demos/application-features/simple-highlight-decorator/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/smart-click-navigation/index.html b/demos/application-features/smart-click-navigation/index.html
index 208440fe2..458c7e122 100644
--- a/demos/application-features/smart-click-navigation/index.html
+++ b/demos/application-features/smart-click-navigation/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/snapping/SnappingDemo.js b/demos/application-features/snapping/SnappingDemo.js
index c52733ca9..6e43a038b 100644
--- a/demos/application-features/snapping/SnappingDemo.js
+++ b/demos/application-features/snapping/SnappingDemo.js
@@ -95,22 +95,22 @@ function buildGraph(graph, graphData) {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/snapping/SnappingDemo.ts b/demos/application-features/snapping/SnappingDemo.ts
index f16b7602d..18bdff7fb 100644
--- a/demos/application-features/snapping/SnappingDemo.ts
+++ b/demos/application-features/snapping/SnappingDemo.ts
@@ -92,22 +92,22 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
const graphBuilder = new GraphBuilder(graph)
graphBuilder.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/application-features/snapping/index.html b/demos/application-features/snapping/index.html
index caf379506..8af6ed459 100644
--- a/demos/application-features/snapping/index.html
+++ b/demos/application-features/snapping/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.js b/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.js
index 5491ba067..b84fd14d5 100644
--- a/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.js
+++ b/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.js
@@ -76,7 +76,7 @@ export class SubdivideEdgeDropInputMode extends NodeDropInputMode {
const hitItems = parentMode.findItems(
dragLocation,
[GraphItemTypes.EDGE],
- e => !foldingView?.isInFoldingState(e)
+ (e) => !foldingView?.isInFoldingState(e)
)
hitItem = hitItems.at(0)
}
@@ -99,7 +99,7 @@ export class SubdivideEdgeDropInputMode extends NodeDropInputMode {
if (dropTarget instanceof IEdge) {
const groupAtDropLocation = context
.lookup(GraphInputMode.$class)
- ?.findItems(context, this.dropLocation, [GraphItemTypes.NODE], item =>
+ ?.findItems(context, this.dropLocation, [GraphItemTypes.NODE], (item) =>
graph.isGroupNode(item)
)
?.at(0)
@@ -150,7 +150,7 @@ export class SubdivideEdgeDropInputMode extends NodeDropInputMode {
})
// copy the labels of the original edge to the newly created edges
- edge.labels.forEach(label => {
+ edge.labels.forEach((label) => {
targetGraph.addLabel(
newEdge1,
label.text,
diff --git a/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.ts b/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.ts
index 0b5bd83f9..1e8062be0 100644
--- a/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.ts
+++ b/demos/application-features/subdivide-edges/SubdivideEdgeDropInputMode.ts
@@ -74,7 +74,7 @@ export class SubdivideEdgeDropInputMode extends NodeDropInputMode {
const hitItems = parentMode.findItems(
dragLocation,
[GraphItemTypes.EDGE],
- e => !foldingView?.isInFoldingState(e)
+ (e) => !foldingView?.isInFoldingState(e)
)
hitItem = hitItems.at(0)
}
@@ -102,7 +102,7 @@ export class SubdivideEdgeDropInputMode extends NodeDropInputMode {
if (dropTarget instanceof IEdge) {
const groupAtDropLocation = context
.lookup(GraphInputMode.$class)
- ?.findItems(context, this.dropLocation, [GraphItemTypes.NODE], item =>
+ ?.findItems(context, this.dropLocation, [GraphItemTypes.NODE], (item) =>
graph.isGroupNode(item as INode)
)
?.at(0)
@@ -152,7 +152,7 @@ export class SubdivideEdgeDropInputMode extends NodeDropInputMode {
})
// copy the labels of the original edge to the newly created edges
- edge.labels.forEach(label => {
+ edge.labels.forEach((label) => {
targetGraph.addLabel(
newEdge1,
label.text,
diff --git a/demos/application-features/subdivide-edges/SubdivideEdgesDemo.js b/demos/application-features/subdivide-edges/SubdivideEdgesDemo.js
index 4f205df39..7cc19a476 100644
--- a/demos/application-features/subdivide-edges/SubdivideEdgesDemo.js
+++ b/demos/application-features/subdivide-edges/SubdivideEdgesDemo.js
@@ -96,7 +96,7 @@ function configureDragAndDrop() {
// create and configure the node drop input mode
const nodeDropInputMode = new SubdivideEdgeDropInputMode()
// nodes with GroupNodeStyle should be created as group nodes
- nodeDropInputMode.isGroupNodePredicate = draggedNode =>
+ nodeDropInputMode.isGroupNodePredicate = (draggedNode) =>
draggedNode.style instanceof GroupNodeStyle
// assign the new node input mode to the graphComponent
inputMode.nodeDropInputMode = nodeDropInputMode
@@ -121,7 +121,7 @@ function initializeDragAndDropPanel() {
const nodeStyles = [defaultNodeStyle, otherNodeStyle, defaultGroupNodeStyle]
// add a visual for each node style to the palette
- nodeStyles.forEach(style => {
+ nodeStyles.forEach((style) => {
addNodeVisual(style, panel)
})
}
@@ -175,7 +175,7 @@ function addNodeVisual(style, panel) {
img.addEventListener(
'mousedown',
- event => {
+ (event) => {
startDrag()
event.preventDefault()
},
@@ -183,7 +183,7 @@ function addNodeVisual(style, panel) {
)
img.addEventListener(
'touchstart',
- event => {
+ (event) => {
startDrag()
event.preventDefault()
},
diff --git a/demos/application-features/subdivide-edges/SubdivideEdgesDemo.ts b/demos/application-features/subdivide-edges/SubdivideEdgesDemo.ts
index cbf483378..1673ac46b 100644
--- a/demos/application-features/subdivide-edges/SubdivideEdgesDemo.ts
+++ b/demos/application-features/subdivide-edges/SubdivideEdgesDemo.ts
@@ -94,7 +94,7 @@ function configureDragAndDrop(): void {
// create and configure the node drop input mode
const nodeDropInputMode = new SubdivideEdgeDropInputMode()
// nodes with GroupNodeStyle should be created as group nodes
- nodeDropInputMode.isGroupNodePredicate = draggedNode =>
+ nodeDropInputMode.isGroupNodePredicate = (draggedNode) =>
draggedNode.style instanceof GroupNodeStyle
// assign the new node input mode to the graphComponent
inputMode.nodeDropInputMode = nodeDropInputMode
@@ -119,7 +119,7 @@ function initializeDragAndDropPanel(): void {
const nodeStyles = [defaultNodeStyle, otherNodeStyle, defaultGroupNodeStyle]
// add a visual for each node style to the palette
- nodeStyles.forEach(style => {
+ nodeStyles.forEach((style) => {
addNodeVisual(style, panel)
})
}
@@ -171,7 +171,7 @@ function addNodeVisual(style: INodeStyle, panel: Element): void {
img.addEventListener(
'mousedown',
- event => {
+ (event) => {
startDrag()
event.preventDefault()
},
@@ -179,7 +179,7 @@ function addNodeVisual(style: INodeStyle, panel: Element): void {
)
img.addEventListener(
'touchstart',
- event => {
+ (event) => {
startDrag()
event.preventDefault()
},
diff --git a/demos/application-features/subdivide-edges/index.html b/demos/application-features/subdivide-edges/index.html
index 4cc578aff..fd77327d7 100644
--- a/demos/application-features/subdivide-edges/index.html
+++ b/demos/application-features/subdivide-edges/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/tableeditor/DragAndDropSupport.js b/demos/application-features/tableeditor/DragAndDropSupport.js
index 64981656f..c890e65f7 100644
--- a/demos/application-features/tableeditor/DragAndDropSupport.js
+++ b/demos/application-features/tableeditor/DragAndDropSupport.js
@@ -62,12 +62,12 @@ export function configureDndInputMode(graph) {
const nodeDropInputMode = new NodeDropInputMode({
showPreview: true,
enabled: true,
- isGroupNodePredicate: draggedNode =>
+ isGroupNodePredicate: (draggedNode) =>
// tables and tagged nodes should be created as group nodes
draggedNode.lookup(ITable.$class) !== null || draggedNode.tag === 'GroupNode'
})
- nodeDropInputMode.isValidParentPredicate = node => {
+ nodeDropInputMode.isValidParentPredicate = (node) => {
const draggedNode = nodeDropInputMode.lastDragEventArgs.item.getData('yfiles.graph.INode')
if (draggedNode.lookup(ITable.$class) !== null && node !== null && graph.isGroupNode(node)) {
// this node has a table associated - disallow dragging into a group node.
diff --git a/demos/application-features/tableeditor/DragAndDropSupport.ts b/demos/application-features/tableeditor/DragAndDropSupport.ts
index 1da64872f..d3457ce9f 100644
--- a/demos/application-features/tableeditor/DragAndDropSupport.ts
+++ b/demos/application-features/tableeditor/DragAndDropSupport.ts
@@ -60,12 +60,12 @@ export function configureDndInputMode(graph: IGraph): NodeDropInputMode {
const nodeDropInputMode = new NodeDropInputMode({
showPreview: true,
enabled: true,
- isGroupNodePredicate: draggedNode =>
+ isGroupNodePredicate: (draggedNode) =>
// tables and tagged nodes should be created as group nodes
draggedNode.lookup(ITable.$class) !== null || draggedNode.tag === 'GroupNode'
})
- nodeDropInputMode.isValidParentPredicate = node => {
+ nodeDropInputMode.isValidParentPredicate = (node) => {
const draggedNode = nodeDropInputMode.lastDragEventArgs!.item.getData('yfiles.graph.INode')
if (draggedNode.lookup(ITable.$class) !== null && node !== null && graph.isGroupNode(node)) {
// this node has a table associated - disallow dragging into a group node.
diff --git a/demos/application-features/tableeditor/TableEditorDemo.js b/demos/application-features/tableeditor/TableEditorDemo.js
index c0c991184..643dc1dc9 100644
--- a/demos/application-features/tableeditor/TableEditorDemo.js
+++ b/demos/application-features/tableeditor/TableEditorDemo.js
@@ -178,16 +178,16 @@ function configureTableEditing() {
// provide no candidates for edge creation at pool nodes - this effectively disables
// edge creations for those nodes
graph.decorator.nodeDecorator.portCandidateProviderDecorator.setImplementation(
- node => node.lookup(ITable.$class) !== null,
+ (node) => node.lookup(ITable.$class) !== null,
IPortCandidateProvider.NO_CANDIDATES
)
// customize marquee selection handling for pool nodes
graph.decorator.nodeDecorator.marqueeTestableDecorator.setFactory(
- node => node.lookup(ITable.$class) !== null,
+ (node) => node.lookup(ITable.$class) !== null,
// the marquee testable for pool nodes. The pool node should only be selected by marquee, if the entire bounds are
// within the marquee.
- node =>
+ (node) =>
IMarqueeTestable.create((context, box) => {
const rectangle = node.layout
return box.contains(rectangle.topLeft) && box.contains(rectangle.bottomRight)
@@ -248,7 +248,7 @@ function configureContextMenu(tableEditorInputMode) {
// add event listeners to the various events that open the context menu. These listeners then
// call the provided callback function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (
graphInputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))
) {
@@ -313,7 +313,7 @@ function populateContextMenu(contextMenu, args, tableEditorInputMode) {
const tableNode = graphInputMode.findItems(
args.queryLocation,
[GraphItemTypes.NODE],
- item => item.lookup(ITable.$class) !== null
+ (item) => item.lookup(ITable.$class) !== null
)
if (tableNode !== null && tableNode.size > 0) {
contextMenu.addMenuItem(`ContextMenu for ${tableNode.at(0)}`, null)
diff --git a/demos/application-features/tableeditor/TableEditorDemo.ts b/demos/application-features/tableeditor/TableEditorDemo.ts
index 2dc10429c..75fce7047 100644
--- a/demos/application-features/tableeditor/TableEditorDemo.ts
+++ b/demos/application-features/tableeditor/TableEditorDemo.ts
@@ -173,16 +173,16 @@ function configureTableEditing(): TableEditorInputMode {
// provide no candidates for edge creation at pool nodes - this effectively disables
// edge creations for those nodes
graph.decorator.nodeDecorator.portCandidateProviderDecorator.setImplementation(
- node => node.lookup(ITable.$class) !== null,
+ (node) => node.lookup(ITable.$class) !== null,
IPortCandidateProvider.NO_CANDIDATES
)
// customize marquee selection handling for pool nodes
graph.decorator.nodeDecorator.marqueeTestableDecorator.setFactory(
- node => node.lookup(ITable.$class) !== null,
+ (node) => node.lookup(ITable.$class) !== null,
// the marquee testable for pool nodes. The pool node should only be selected by marquee, if the entire bounds are
// within the marquee.
- node =>
+ (node) =>
IMarqueeTestable.create((context: IInputModeContext, box: Rect): boolean => {
const rectangle = node.layout
return box.contains(rectangle.topLeft) && box.contains(rectangle.bottomRight)
@@ -243,7 +243,7 @@ function configureContextMenu(tableEditorInputMode: TableEditorInputMode): void
// add event listeners to the various events that open the context menu. These listeners then
// call the provided callback function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (
graphInputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))
) {
@@ -312,7 +312,7 @@ function populateContextMenu(
const tableNode = graphInputMode.findItems(
args.queryLocation,
[GraphItemTypes.NODE],
- item => item.lookup(ITable.$class) !== null
+ (item) => item.lookup(ITable.$class) !== null
)
if (tableNode !== null && tableNode.size > 0) {
contextMenu.addMenuItem(`ContextMenu for ${tableNode.at(0)}`, null)
diff --git a/demos/application-features/tableeditor/index.html b/demos/application-features/tableeditor/index.html
index 5d66e2a54..1726ac8d1 100644
--- a/demos/application-features/tableeditor/index.html
+++ b/demos/application-features/tableeditor/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/theming/ThemingDemo.js b/demos/application-features/theming/ThemingDemo.js
index a1474eb45..6fe79cef8 100644
--- a/demos/application-features/theming/ThemingDemo.js
+++ b/demos/application-features/theming/ThemingDemo.js
@@ -118,26 +118,26 @@ function buildGraph(graph, graphData) {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
- .edgeCreator.createLabelBinding(item => item.label)
+ .edgeCreator.createLabelBinding((item) => item.label)
graphBuilder.buildGraph()
}
diff --git a/demos/application-features/theming/ThemingDemo.ts b/demos/application-features/theming/ThemingDemo.ts
index f08efcaa9..868a5fdfc 100644
--- a/demos/application-features/theming/ThemingDemo.ts
+++ b/demos/application-features/theming/ThemingDemo.ts
@@ -113,26 +113,26 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
- .edgeCreator.createLabelBinding(item => item.label)
+ .edgeCreator.createLabelBinding((item) => item.label)
graphBuilder.buildGraph()
}
diff --git a/demos/application-features/theming/index.html b/demos/application-features/theming/index.html
index 096d0b736..567998d7a 100644
--- a/demos/application-features/theming/index.html
+++ b/demos/application-features/theming/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/tooltips/TooltipsDemo.js b/demos/application-features/tooltips/TooltipsDemo.js
index 46fa8244e..29f3cdc64 100644
--- a/demos/application-features/tooltips/TooltipsDemo.js
+++ b/demos/application-features/tooltips/TooltipsDemo.js
@@ -106,26 +106,26 @@ function buildGraph(graph, graphData) {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
- .edgeCreator.createLabelBinding(item => item.label)
+ .edgeCreator.createLabelBinding((item) => item.label)
graphBuilder.buildGraph()
}
diff --git a/demos/application-features/tooltips/TooltipsDemo.ts b/demos/application-features/tooltips/TooltipsDemo.ts
index 2a03968f7..72a99836a 100644
--- a/demos/application-features/tooltips/TooltipsDemo.ts
+++ b/demos/application-features/tooltips/TooltipsDemo.ts
@@ -103,26 +103,26 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder
.createNodesSource({
- data: graphData.nodeList.filter(item => !item.isGroup),
- id: item => item.id,
- parentId: item => item.parentId
+ data: graphData.nodeList.filter((item) => !item.isGroup),
+ id: (item) => item.id,
+ parentId: (item) => item.parentId
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createGroupNodesSource({
- data: graphData.nodeList.filter(item => item.isGroup),
- id: item => item.id
+ data: graphData.nodeList.filter((item) => item.isGroup),
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder
.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
- .edgeCreator.createLabelBinding(item => item.label)
+ .edgeCreator.createLabelBinding((item) => item.label)
graphBuilder.buildGraph()
}
diff --git a/demos/application-features/tooltips/index.html b/demos/application-features/tooltips/index.html
index de11670e1..e3f24e6fd 100644
--- a/demos/application-features/tooltips/index.html
+++ b/demos/application-features/tooltips/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/application-features/webgl-rendering/WebGLRenderingDemo.js b/demos/application-features/webgl-rendering/WebGLRenderingDemo.js
index 6089dad3f..2c68cb45a 100644
--- a/demos/application-features/webgl-rendering/WebGLRenderingDemo.js
+++ b/demos/application-features/webgl-rendering/WebGLRenderingDemo.js
@@ -147,7 +147,7 @@ async function createGraph(graph) {
const response = await fetch('./resources/hierarchic_2000_2100.json')
const graphData = await response.json()
- const getRandomInt = upper => Math.floor(Math.random() * upper)
+ const getRandomInt = (upper) => Math.floor(Math.random() * upper)
graph.clear()
// create a map to store the nodes for edge creation
@@ -182,7 +182,7 @@ async function createGraph(graph) {
// add the bends
if (edgeData.b != null) {
const bendData = edgeData.b
- bendData.forEach(bend => {
+ bendData.forEach((bend) => {
graph.addBend(edge, Point.from(bend))
})
}
diff --git a/demos/application-features/webgl-rendering/WebGLRenderingDemo.ts b/demos/application-features/webgl-rendering/WebGLRenderingDemo.ts
index e1c25112a..917042d7e 100644
--- a/demos/application-features/webgl-rendering/WebGLRenderingDemo.ts
+++ b/demos/application-features/webgl-rendering/WebGLRenderingDemo.ts
@@ -178,7 +178,7 @@ async function createGraph(graph: IGraph) {
// add the bends
if (edgeData.b != null) {
const bendData = edgeData.b as { x: number; y: number }[]
- bendData.forEach(bend => {
+ bendData.forEach((bend) => {
graph.addBend(edge, Point.from(bend))
})
}
diff --git a/demos/application-features/webgl-rendering/index.html b/demos/application-features/webgl-rendering/index.html
index 6fd318e62..036a164ae 100644
--- a/demos/application-features/webgl-rendering/index.html
+++ b/demos/application-features/webgl-rendering/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.js b/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.js
index a3de42d83..2ba31ad0b 100644
--- a/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.js
+++ b/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.js
@@ -122,7 +122,7 @@ export class EditAdjacencyNodesSourceDialog {
// CodeMirror requires the textArea to be in the DOM and visible already when instantiating
this.dialogContainerModal.style.removeProperty('display')
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
this.initialize()
diff --git a/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.ts b/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.ts
index cc18f2280..f0d05c64e 100644
--- a/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.ts
+++ b/demos/databinding/adjacencygraphbuilder/EditAdjacencyNodeSourceDialog.ts
@@ -126,7 +126,7 @@ export class EditAdjacencyNodesSourceDialog {
// CodeMirror requires the textArea to be in the DOM and visible already when instantiating
this.dialogContainerModal.style.removeProperty('display')
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
this.initialize()
diff --git a/demos/databinding/adjacencygraphbuilder/ModelClasses.js b/demos/databinding/adjacencygraphbuilder/ModelClasses.js
index a4e8f360b..8646415ef 100644
--- a/demos/databinding/adjacencygraphbuilder/ModelClasses.js
+++ b/demos/databinding/adjacencygraphbuilder/ModelClasses.js
@@ -115,7 +115,7 @@ export function createBinding(bindingString) {
const func = new Function(`return (${bindingString})`)()
// wrap the binding function with a function that catches and reports errors
// that occur in the binding functions
- return dataItem => {
+ return (dataItem) => {
try {
// eslint-disable-next-line no-useless-call
const result = func.apply(null, [dataItem])
@@ -129,10 +129,10 @@ export function createBinding(bindingString) {
}
}
} catch (ignored) {
- return dataItem => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
+ return (dataItem) => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
}
}
- return dataItem => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
+ return (dataItem) => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
}
/**
diff --git a/demos/databinding/adjacencygraphbuilder/SchemaComponent.js b/demos/databinding/adjacencygraphbuilder/SchemaComponent.js
index f18891bbf..b89477415 100644
--- a/demos/databinding/adjacencygraphbuilder/SchemaComponent.js
+++ b/demos/databinding/adjacencygraphbuilder/SchemaComponent.js
@@ -322,7 +322,7 @@ export class SchemaComponent {
const contextMenu = new ContextMenu(graphComponent)
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
const worldLocation = graphComponent.toWorldFromPage(location)
const showMenu = inputMode.contextMenuInputMode.shouldOpenMenu(worldLocation)
if (showMenu) {
@@ -384,20 +384,23 @@ export class SchemaComponent {
this.adjacencyGraphBuilder = new AdjacencyGraphBuilder(this.resultGraph)
const schemaGraphBuilder = new GraphBuilder(this.schemaGraphComponent.graph)
- const schemaNodesSource = schemaGraphBuilder.createNodesSource(sample.nodesSources, n => n.name)
+ const schemaNodesSource = schemaGraphBuilder.createNodesSource(
+ sample.nodesSources,
+ (n) => n.name
+ )
- schemaNodesSource.nodeCreator.createLabelBinding(n => n.name)
+ schemaNodesSource.nodeCreator.createLabelBinding((n) => n.name)
- schemaNodesSource.nodeCreator.tagProvider = sourceDefinition =>
+ schemaNodesSource.nodeCreator.tagProvider = (sourceDefinition) =>
this.createAdjacencyNodesSourceConnector(sourceDefinition)
- schemaNodesSource.nodeCreator.styleProvider = data =>
+ schemaNodesSource.nodeCreator.styleProvider = (data) =>
SchemaComponent.createSchemaNodeStyle(data)
const schemaEdgesSource = schemaGraphBuilder.createEdgesSource(
sample.edgesSource,
- e => e.thisSource,
- e => e.neighborSource
+ (e) => e.thisSource,
+ (e) => e.neighborSource
)
schemaEdgesSource.edgeCreator.addEdgeCreatedListener((_, evt) => {
this.createNeighborRelationship(
@@ -422,14 +425,14 @@ export class SchemaComponent {
// gather remaining source definitions
const adjacencyNodesSourcesDefinitions = []
- schemaGraph.nodes.forEach(node => {
+ schemaGraph.nodes.forEach((node) => {
const sourceConnector = node.tag
adjacencyNodesSourcesDefinitions.push(sourceConnector.sourceDefinition)
})
// gather remaining edge definitions
const edgesSourceDefinitions = []
- schemaGraph.edges.forEach(edge => {
+ schemaGraph.edges.forEach((edge) => {
const sourceConnector = edge.sourceNode.tag
const targetConnector = edge.targetNode.tag
@@ -470,7 +473,7 @@ export class SchemaComponent {
neighborType
}
- const neighborProvider = dataItem => edge.tag.binding(dataItem)
+ const neighborProvider = (dataItem) => edge.tag.binding(dataItem)
const neighborSource = targetConnector.nodesSource
if (neighborType === 'successor') {
@@ -591,7 +594,7 @@ export class SchemaComponent {
this.schemaGraphComponent.graph.nodeDefaults.size
// each edge creation should use another random target node color
- createEdgeInputMode.addGestureStartingListener(src => {
+ createEdgeInputMode.addGestureStartingListener((src) => {
const nodeStyle = new ShapeNodeStyle({
shape: 'ellipse',
fill: '#6495ED',
diff --git a/demos/databinding/adjacencygraphbuilder/SchemaComponent.ts b/demos/databinding/adjacencygraphbuilder/SchemaComponent.ts
index 765471eaf..1a54b18b9 100644
--- a/demos/databinding/adjacencygraphbuilder/SchemaComponent.ts
+++ b/demos/databinding/adjacencygraphbuilder/SchemaComponent.ts
@@ -372,9 +372,12 @@ export class SchemaComponent {
this.adjacencyGraphBuilder = new AdjacencyGraphBuilder(this.resultGraph)
const schemaGraphBuilder = new GraphBuilder(this.schemaGraphComponent.graph)
- const schemaNodesSource = schemaGraphBuilder.createNodesSource(sample.nodesSources, n => n.name)
+ const schemaNodesSource = schemaGraphBuilder.createNodesSource(
+ sample.nodesSources,
+ (n) => n.name
+ )
- schemaNodesSource.nodeCreator.createLabelBinding(n => n.name)
+ schemaNodesSource.nodeCreator.createLabelBinding((n) => n.name)
schemaNodesSource.nodeCreator.tagProvider = (
sourceDefinition
@@ -386,8 +389,8 @@ export class SchemaComponent {
const schemaEdgesSource = schemaGraphBuilder.createEdgesSource(
sample.edgesSource,
- e => e.thisSource,
- e => e.neighborSource
+ (e) => e.thisSource,
+ (e) => e.neighborSource
)
schemaEdgesSource.edgeCreator.addEdgeCreatedListener((_, evt) => {
this.createNeighborRelationship(
@@ -584,7 +587,7 @@ export class SchemaComponent {
this.schemaGraphComponent.graph.nodeDefaults.size
// each edge creation should use another random target node color
- createEdgeInputMode.addGestureStartingListener(src => {
+ createEdgeInputMode.addGestureStartingListener((src) => {
const nodeStyle = new ShapeNodeStyle({
shape: 'ellipse',
fill: '#6495ED',
diff --git a/demos/databinding/adjacencygraphbuilder/index.html b/demos/databinding/adjacencygraphbuilder/index.html
index b7dcf1f85..ca0e6d63a 100644
--- a/demos/databinding/adjacencygraphbuilder/index.html
+++ b/demos/databinding/adjacencygraphbuilder/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/databinding/graphbuilder/EditSourceDialog.js b/demos/databinding/graphbuilder/EditSourceDialog.js
index be1342ce7..d7a6f1a7d 100644
--- a/demos/databinding/graphbuilder/EditSourceDialog.js
+++ b/demos/databinding/graphbuilder/EditSourceDialog.js
@@ -59,7 +59,7 @@ export class SourceDialog {
// CodeMirror requires the textArea to be in the DOM and visible already when instantiating
this.dialogContainerModal.style.removeProperty('display')
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
this.initialize()
diff --git a/demos/databinding/graphbuilder/EditSourceDialog.ts b/demos/databinding/graphbuilder/EditSourceDialog.ts
index 708965196..95cba1d05 100644
--- a/demos/databinding/graphbuilder/EditSourceDialog.ts
+++ b/demos/databinding/graphbuilder/EditSourceDialog.ts
@@ -60,7 +60,7 @@ export abstract class SourceDialog {
// CodeMirror requires the textArea to be in the DOM and visible already when instantiating
this.dialogContainerModal.style.removeProperty('display')
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
this.initialize()
diff --git a/demos/databinding/graphbuilder/GraphBuilderDemo.js b/demos/databinding/graphbuilder/GraphBuilderDemo.js
index 7ba14deff..cee27799c 100644
--- a/demos/databinding/graphbuilder/GraphBuilderDemo.js
+++ b/demos/databinding/graphbuilder/GraphBuilderDemo.js
@@ -227,7 +227,7 @@ function loadSample(sample) {
const { nodesSourcesListBox, edgesSourcesListBox } = createSourcesLists(sourcesFactory)
- sampleClone.nodesSources.forEach(nodesSourceDefinition => {
+ sampleClone.nodesSources.forEach((nodesSourceDefinition) => {
const connector = sourcesFactory.createNodesSourceConnector(
nodesSourceDefinition.name,
nodesSourceDefinition
@@ -236,7 +236,7 @@ function loadSample(sample) {
nodesSourcesListBox.addDefinition(connector)
})
- sampleClone.edgesSources.forEach(edgesSourceDefinition => {
+ sampleClone.edgesSources.forEach((edgesSourceDefinition) => {
const connector = sourcesFactory.createEdgesSourceConnector(
edgesSourceDefinition.name,
edgesSourceDefinition
@@ -279,7 +279,7 @@ function createSourcesLists(sourcesFactory) {
removeAllChildren(edgesSourcesListRootElement)
const nodesSourcesListBox = new SourcesListBox(
- sourceName => sourcesFactory.createNodesSourceConnector(sourceName),
+ (sourceName) => sourcesFactory.createNodesSourceConnector(sourceName),
NodesSourceDialog,
nodeSourcesListRootElement,
() => {
@@ -288,7 +288,7 @@ function createSourcesLists(sourcesFactory) {
)
const edgesSourcesListBox = new SourcesListBox(
- sourceName => sourcesFactory.createEdgesSourceConnector(sourceName),
+ (sourceName) => sourcesFactory.createEdgesSourceConnector(sourceName),
EdgesSourceDialog,
edgesSourcesListRootElement,
() => {
diff --git a/demos/databinding/graphbuilder/GraphBuilderDemo.ts b/demos/databinding/graphbuilder/GraphBuilderDemo.ts
index 8a622358e..567dc26bc 100644
--- a/demos/databinding/graphbuilder/GraphBuilderDemo.ts
+++ b/demos/databinding/graphbuilder/GraphBuilderDemo.ts
@@ -222,7 +222,7 @@ function loadSample(sample: GraphBuilderSample): void {
const { nodesSourcesListBox, edgesSourcesListBox } = createSourcesLists(sourcesFactory)
- sampleClone.nodesSources.forEach(nodesSourceDefinition => {
+ sampleClone.nodesSources.forEach((nodesSourceDefinition) => {
const connector = sourcesFactory.createNodesSourceConnector(
nodesSourceDefinition.name,
nodesSourceDefinition
@@ -231,7 +231,7 @@ function loadSample(sample: GraphBuilderSample): void {
nodesSourcesListBox.addDefinition(connector)
})
- sampleClone.edgesSources.forEach(edgesSourceDefinition => {
+ sampleClone.edgesSources.forEach((edgesSourceDefinition) => {
const connector = sourcesFactory.createEdgesSourceConnector(
edgesSourceDefinition.name,
edgesSourceDefinition
@@ -273,7 +273,7 @@ function createSourcesLists(sourcesFactory: SourcesFactory): {
removeAllChildren(edgesSourcesListRootElement)
const nodesSourcesListBox = new SourcesListBox(
- sourceName => sourcesFactory.createNodesSourceConnector(sourceName),
+ (sourceName) => sourcesFactory.createNodesSourceConnector(sourceName),
NodesSourceDialog,
nodeSourcesListRootElement,
() => {
@@ -282,7 +282,7 @@ function createSourcesLists(sourcesFactory: SourcesFactory): {
)
const edgesSourcesListBox = new SourcesListBox(
- sourceName => sourcesFactory.createEdgesSourceConnector(sourceName),
+ (sourceName) => sourcesFactory.createEdgesSourceConnector(sourceName),
EdgesSourceDialog,
edgesSourcesListRootElement,
() => {
diff --git a/demos/databinding/graphbuilder/ModelClasses.js b/demos/databinding/graphbuilder/ModelClasses.js
index 48d75d5fd..aba0174dd 100644
--- a/demos/databinding/graphbuilder/ModelClasses.js
+++ b/demos/databinding/graphbuilder/ModelClasses.js
@@ -219,7 +219,7 @@ function createBinding(bindingString) {
// wrap the binding function with a function that catches and reports errors
// that occur in the binding functions
- return dataItem => {
+ return (dataItem) => {
try {
// eslint-disable-next-line no-useless-call
const result = func.apply(null, [dataItem])
@@ -233,10 +233,10 @@ function createBinding(bindingString) {
}
}
} catch (ignored) {
- return dataItem => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
+ return (dataItem) => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
}
}
- return dataItem => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
+ return (dataItem) => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
}
/**
@@ -315,9 +315,9 @@ export class SourcesFactory {
const edgesSource = this.graphBuilder.createEdgesSource(
[],
- edgeDataItem =>
+ (edgeDataItem) =>
definition.sourceProvider ? definition.sourceProvider(edgeDataItem) : undefined,
- edgeDataItem =>
+ (edgeDataItem) =>
definition.targetProvider ? definition.targetProvider(edgeDataItem) : undefined
)
@@ -327,7 +327,7 @@ export class SourcesFactory {
targetArrow: new Arrow({ color: '#662b00', type: 'triangle' })
})
edgeCreator.defaults.shareStyleInstance = false
- edgeCreator.styleBindings.addBinding('stroke', edgeDataItem =>
+ edgeCreator.styleBindings.addBinding('stroke', (edgeDataItem) =>
definition.strokeProvider ? definition.strokeProvider(edgeDataItem) : '#662b00'
)
@@ -336,7 +336,7 @@ export class SourcesFactory {
edgeCreator.updateLabels(evt.graph, evt.item, evt.dataItem)
})
- edgeCreator.createLabelBinding(edgeDataItem =>
+ edgeCreator.createLabelBinding((edgeDataItem) =>
definition.labelTextProvider ? definition.labelTextProvider(edgeDataItem) : undefined
)
diff --git a/demos/databinding/graphbuilder/ModelClasses.ts b/demos/databinding/graphbuilder/ModelClasses.ts
index b5a74bdd3..fb5b05bd9 100644
--- a/demos/databinding/graphbuilder/ModelClasses.ts
+++ b/demos/databinding/graphbuilder/ModelClasses.ts
@@ -320,9 +320,9 @@ export class SourcesFactory {
const edgesSource = this.graphBuilder.createEdgesSource(
[],
- edgeDataItem =>
+ (edgeDataItem) =>
definition.sourceProvider ? definition.sourceProvider(edgeDataItem) : undefined,
- edgeDataItem =>
+ (edgeDataItem) =>
definition.targetProvider ? definition.targetProvider(edgeDataItem) : undefined
)
@@ -332,7 +332,7 @@ export class SourcesFactory {
targetArrow: new Arrow({ color: '#662b00', type: 'triangle' })
})
edgeCreator.defaults.shareStyleInstance = false
- edgeCreator.styleBindings.addBinding('stroke', edgeDataItem =>
+ edgeCreator.styleBindings.addBinding('stroke', (edgeDataItem) =>
definition.strokeProvider ? definition.strokeProvider(edgeDataItem) : '#662b00'
)
@@ -341,7 +341,7 @@ export class SourcesFactory {
edgeCreator.updateLabels(evt.graph, evt.item, evt.dataItem)
})
- edgeCreator.createLabelBinding(edgeDataItem =>
+ edgeCreator.createLabelBinding((edgeDataItem) =>
definition.labelTextProvider ? definition.labelTextProvider(edgeDataItem) : undefined
)
diff --git a/demos/databinding/graphbuilder/SourcesListBox.js b/demos/databinding/graphbuilder/SourcesListBox.js
index bc175cf2a..b7f0131e2 100644
--- a/demos/databinding/graphbuilder/SourcesListBox.js
+++ b/demos/databinding/graphbuilder/SourcesListBox.js
@@ -46,7 +46,7 @@ export class SourcesListBox {
* connector via the factory class
* @param {!object} dialogFactory the Node- or Edge- {@link SourceDialog} to use
* @param {!HTMLElement} rootElement the HTMLElement used to display the list box
- * @param {!function} dataUpdatedCallback the callback arrow function used to update the graph after the
+ * @param {!function} dataUpdatedCallback the callback arrow function used to update the graph after
* the SourceDialog was closed as accepted
*/
constructor(factory, dialogFactory, rootElement, dataUpdatedCallback) {
@@ -87,11 +87,12 @@ export class SourcesListBox {
const label = document.createElement('span')
label.textContent = newDefinition.sourceDefinition.name
+ label.classList.add('sourceLabel')
const editButton = document.createElement('button')
editButton.classList.add('editButton')
editButton.addEventListener('click', () => {
- new this.DialogFactory(newDefinition, () => {
+ void new this.DialogFactory(newDefinition, () => {
label.textContent = newDefinition.sourceDefinition.name
this.dataUpdatedCallback()
}).show()
diff --git a/demos/databinding/graphbuilder/SourcesListBox.ts b/demos/databinding/graphbuilder/SourcesListBox.ts
index 3cfe5f72b..f0cd17f7e 100644
--- a/demos/databinding/graphbuilder/SourcesListBox.ts
+++ b/demos/databinding/graphbuilder/SourcesListBox.ts
@@ -53,7 +53,7 @@ export class SourcesListBox<
* connector via the factory class
* @param dialogFactory the Node- or Edge- {@link SourceDialog} to use
* @param rootElement the HTMLElement used to display the list box
- * @param dataUpdatedCallback the callback arrow function used to update the graph after the
+ * @param dataUpdatedCallback the callback arrow function used to update the graph after
* the SourceDialog was closed as accepted
*/
constructor(
@@ -100,11 +100,12 @@ export class SourcesListBox<
const label = document.createElement('span')
label.textContent = newDefinition.sourceDefinition.name
+ label.classList.add('sourceLabel')
const editButton = document.createElement('button')
editButton.classList.add('editButton')
editButton.addEventListener('click', () => {
- new this.DialogFactory(newDefinition, () => {
+ void new this.DialogFactory(newDefinition, () => {
label.textContent = newDefinition.sourceDefinition.name
this.dataUpdatedCallback()
}).show()
diff --git a/demos/databinding/graphbuilder/index.html b/demos/databinding/graphbuilder/index.html
index 733e559a1..70b79139c 100644
--- a/demos/databinding/graphbuilder/index.html
+++ b/demos/databinding/graphbuilder/index.html
@@ -1,4 +1,4 @@
-
+
@@ -103,19 +103,19 @@
padding: 10px;
margin: 0 0 5px;
position: relative;
+ display: flex;
+ align-items: baseline;
}
- .sourceCard button {
- position: absolute;
- width: 70px;
- top: 10px;
+ .sourceCard .sourceLabel {
+ flex: 1 0 auto;
}
-
- .sourceCard .editButton {
- right: 90px;
+ .sourceCard button.editButton {
+ width: 80px;
}
- .sourceCard .removeButton {
- right: 10px;
+ .sourceCard button.removeButton {
+ width: 80px;
+ margin-right: 0;
}
.buttonsContainer {
diff --git a/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.js b/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.js
index 1c7d98dc4..e2fa4c19e 100644
--- a/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.js
+++ b/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.js
@@ -418,12 +418,12 @@ class PortAwareEdgeCreator extends EdgeCreator {
// if no ID is specified: get the first port
const sourcePortId = this.getSourcePortId(data)
const sourcePort = sourcePortId
- ? source.ports.find(p => p.tag === sourcePortId)
+ ? source.ports.find((p) => p.tag === sourcePortId)
: source.ports.at(0)
// same for the target port
const targetPortId = this.getTargetPortId(data)
const targetPort = targetPortId
- ? target.ports.find(p => p.tag === targetPortId)
+ ? target.ports.find((p) => p.tag === targetPortId)
: target.ports.at(0)
// create the edges between source and target port. if no port is provided, add a default port.
@@ -455,13 +455,13 @@ class PortAwareEdgeCreator extends EdgeCreator {
const sourcePortId = this.getSourcePortId(data)
const sourcePort =
sourcePortId && sourcePortId !== edge.sourcePort.tag
- ? edge.sourcePort.owner.ports.find(p => p.tag === sourcePortId)
+ ? edge.sourcePort.owner.ports.find((p) => p.tag === sourcePortId)
: edge.sourcePort
// same for the target port
const targetPortId = this.getTargetPortId(data)
const targetPort =
targetPortId && targetPortId !== edge.targetPort.tag
- ? edge.targetPort.owner.ports.find(p => p.tag === targetPortId)
+ ? edge.targetPort.owner.ports.find((p) => p.tag === targetPortId)
: edge.targetPort
// remember the current source and target ports
const oldSource = edge.sourcePort
diff --git a/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.ts b/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.ts
index e69daa8e7..eed13e16f 100644
--- a/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.ts
+++ b/demos/databinding/port-aware-adjacency-graph-builder/AdjacencyGraphBuilder.ts
@@ -383,7 +383,10 @@ class PortAwareNodeCreator extends NodeCreator {
* Determines the port with that ID and connects the edge to that port.
*/
class PortAwareEdgeCreator extends EdgeCreator {
- constructor(private successor: boolean, defaults: IEdgeDefaults) {
+ constructor(
+ private successor: boolean,
+ defaults: IEdgeDefaults
+ ) {
super()
this.defaults = defaults
}
@@ -409,12 +412,12 @@ class PortAwareEdgeCreator extends EdgeCreator {
// if no ID is specified: get the first port
const sourcePortId = this.getSourcePortId(data)
const sourcePort = sourcePortId
- ? source.ports.find(p => p.tag === sourcePortId)
+ ? source.ports.find((p) => p.tag === sourcePortId)
: source.ports.at(0)
// same for the target port
const targetPortId = this.getTargetPortId(data)
const targetPort = targetPortId
- ? target.ports.find(p => p.tag === targetPortId)
+ ? target.ports.find((p) => p.tag === targetPortId)
: target.ports.at(0)
// create the edges between source and target port. if no port is provided, add a default port.
@@ -446,13 +449,13 @@ class PortAwareEdgeCreator extends EdgeCreator {
const sourcePortId = this.getSourcePortId(data)
const sourcePort =
sourcePortId && sourcePortId !== edge.sourcePort!.tag
- ? edge.sourcePort!.owner!.ports.find(p => p.tag === sourcePortId)
+ ? edge.sourcePort!.owner!.ports.find((p) => p.tag === sourcePortId)
: edge.sourcePort
// same for the target port
const targetPortId = this.getTargetPortId(data)
const targetPort =
targetPortId && targetPortId !== edge.targetPort!.tag
- ? edge.targetPort!.owner!.ports.find(p => p.tag === targetPortId)
+ ? edge.targetPort!.owner!.ports.find((p) => p.tag === targetPortId)
: edge.targetPort
// remember the current source and target ports
const oldSource = edge.sourcePort!
diff --git a/demos/databinding/port-aware-adjacency-graph-builder/index.html b/demos/databinding/port-aware-adjacency-graph-builder/index.html
index 6925fa32d..86d8093a5 100644
--- a/demos/databinding/port-aware-adjacency-graph-builder/index.html
+++ b/demos/databinding/port-aware-adjacency-graph-builder/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/databinding/port-aware-graph-builder/GraphBuilder.js b/demos/databinding/port-aware-graph-builder/GraphBuilder.js
index 5020f2b49..295310963 100644
--- a/demos/databinding/port-aware-graph-builder/GraphBuilder.js
+++ b/demos/databinding/port-aware-graph-builder/GraphBuilder.js
@@ -105,7 +105,7 @@ export function createPortAwareGraphBuilder(graph, sampleNodes, sampleEdges) {
})
// change the node creator but keep the original's defaults
nodesSource.nodeCreator = new TypeAwareNodeCreator({ defaults: nodesSource.nodeCreator.defaults })
- nodesSource.nodeCreator.styleProvider = nodeData => {
+ nodesSource.nodeCreator.styleProvider = (nodeData) => {
switch (nodeData.type) {
case 'or':
return new OrNodeStyle(false, '#A49966', '#625F50', '#FFFFFF')
@@ -132,8 +132,8 @@ export function createPortAwareGraphBuilder(graph, sampleNodes, sampleEdges) {
data: sampleEdges,
// we extract the node Id from source Id and target Id
// that way EdgeCreator.createEdgeCore will already get the correct source and target nodes
- sourceId: data => getNodeId(data.from),
- targetId: data => getNodeId(data.to),
+ sourceId: (data) => getNodeId(data.from),
+ targetId: (data) => getNodeId(data.to),
id: 'id'
})
edgesSource.edgeCreator = new PortAwareEdgeCreator({ defaults: edgesSource.edgeCreator.defaults })
@@ -188,7 +188,7 @@ class TypeAwareNodeCreator extends NodeCreator {
const node = super.createNodeCore(graph, groupNode, parent, layout, style, tag)
// add ports according to their type
- this.getPorts(nodeData).forEach(pin => {
+ this.getPorts(nodeData).forEach((pin) => {
this.addPort(graph, node, pin)
})
return node
@@ -392,11 +392,11 @@ class PortAwareEdgeCreator extends EdgeCreator {
// if no ID is specified: get the first port
const sourcePortId = this.getSourcePortId(edgeData)
const sourcePort = sourcePortId
- ? source.ports.find(p => p.tag === sourcePortId)
+ ? source.ports.find((p) => p.tag === sourcePortId)
: source.ports.at(0)
const targetPortId = this.getTargetPortId(edgeData)
const targetPort = targetPortId
- ? target.ports.find(p => p.tag === targetPortId)
+ ? target.ports.find((p) => p.tag === targetPortId)
: target.ports.at(0)
// create the edges between source and target port. If no port is provided add a default port.
@@ -424,13 +424,13 @@ class PortAwareEdgeCreator extends EdgeCreator {
const sourcePortId = this.getSourcePortId(dataItem)
const sourcePort =
sourcePortId && sourcePortId !== edge.sourcePort.tag
- ? edge.sourcePort.owner.ports.find(p => p.tag === sourcePortId)
+ ? edge.sourcePort.owner.ports.find((p) => p.tag === sourcePortId)
: edge.sourcePort
// same for the target port
const targetPortId = this.getTargetPortId(dataItem)
const targetPort =
targetPortId && targetPortId !== edge.targetPort.tag
- ? edge.targetPort.owner.ports.find(p => p.tag === targetPortId)
+ ? edge.targetPort.owner.ports.find((p) => p.tag === targetPortId)
: edge.targetPort
// remember the current source and target ports
const oldSource = edge.sourcePort
diff --git a/demos/databinding/port-aware-graph-builder/GraphBuilder.ts b/demos/databinding/port-aware-graph-builder/GraphBuilder.ts
index db1084939..58034aacf 100644
--- a/demos/databinding/port-aware-graph-builder/GraphBuilder.ts
+++ b/demos/databinding/port-aware-graph-builder/GraphBuilder.ts
@@ -111,7 +111,7 @@ export function createPortAwareGraphBuilder(
})
// change the node creator but keep the original's defaults
nodesSource.nodeCreator = new TypeAwareNodeCreator({ defaults: nodesSource.nodeCreator.defaults })
- nodesSource.nodeCreator.styleProvider = nodeData => {
+ nodesSource.nodeCreator.styleProvider = (nodeData) => {
switch (nodeData.type) {
case 'or':
return new OrNodeStyle(false, '#A49966', '#625F50', '#FFFFFF')
@@ -138,8 +138,8 @@ export function createPortAwareGraphBuilder(
data: sampleEdges,
// we extract the node Id from source Id and target Id
// that way EdgeCreator.createEdgeCore will already get the correct source and target nodes
- sourceId: data => getNodeId(data.from),
- targetId: data => getNodeId(data.to),
+ sourceId: (data) => getNodeId(data.from),
+ targetId: (data) => getNodeId(data.to),
id: 'id'
})
edgesSource.edgeCreator = new PortAwareEdgeCreator({ defaults: edgesSource.edgeCreator.defaults })
@@ -193,7 +193,7 @@ class TypeAwareNodeCreator extends NodeCreator {
const node = super.createNodeCore(graph, groupNode, parent, layout, style, tag)
// add ports according to their type
- this.getPorts(nodeData).forEach(pin => {
+ this.getPorts(nodeData).forEach((pin) => {
this.addPort(graph, node, pin)
})
return node
@@ -391,11 +391,11 @@ class PortAwareEdgeCreator extends EdgeCreator {
// if no ID is specified: get the first port
const sourcePortId = this.getSourcePortId(edgeData)
const sourcePort = sourcePortId
- ? source.ports.find(p => p.tag === sourcePortId)
+ ? source.ports.find((p) => p.tag === sourcePortId)
: source.ports.at(0)
const targetPortId = this.getTargetPortId(edgeData)
const targetPort = targetPortId
- ? target.ports.find(p => p.tag === targetPortId)
+ ? target.ports.find((p) => p.tag === targetPortId)
: target.ports.at(0)
// create the edges between source and target port. If no port is provided add a default port.
@@ -423,13 +423,13 @@ class PortAwareEdgeCreator extends EdgeCreator {
const sourcePortId = this.getSourcePortId(dataItem)
const sourcePort =
sourcePortId && sourcePortId !== edge.sourcePort!.tag
- ? edge.sourcePort!.owner!.ports.find(p => p.tag === sourcePortId)
+ ? edge.sourcePort!.owner!.ports.find((p) => p.tag === sourcePortId)
: edge.sourcePort
// same for the target port
const targetPortId = this.getTargetPortId(dataItem)
const targetPort =
targetPortId && targetPortId !== edge.targetPort!.tag
- ? edge.targetPort!.owner!.ports.find(p => p.tag === targetPortId)
+ ? edge.targetPort!.owner!.ports.find((p) => p.tag === targetPortId)
: edge.targetPort
// remember the current source and target ports
const oldSource = edge.sourcePort!
diff --git a/demos/databinding/port-aware-graph-builder/index.html b/demos/databinding/port-aware-graph-builder/index.html
index abd7d7b9d..a44204b1a 100644
--- a/demos/databinding/port-aware-graph-builder/index.html
+++ b/demos/databinding/port-aware-graph-builder/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/databinding/port-aware-tree-builder/TreeBuilder.js b/demos/databinding/port-aware-tree-builder/TreeBuilder.js
index 0f00060e2..372299278 100644
--- a/demos/databinding/port-aware-tree-builder/TreeBuilder.js
+++ b/demos/databinding/port-aware-tree-builder/TreeBuilder.js
@@ -383,12 +383,12 @@ class PortAwareEdgeCreator extends EdgeCreator {
// if no ID is specified: get the first port
const sourcePortId = this.getSourcePortId(data)
const sourcePort = sourcePortId
- ? source.ports.find(p => p.tag === sourcePortId)
+ ? source.ports.find((p) => p.tag === sourcePortId)
: source.ports.at(0)
// same for the target port
const targetPortId = this.getTargetPortId(data)
const targetPort = targetPortId
- ? target.ports.find(p => p.tag === targetPortId)
+ ? target.ports.find((p) => p.tag === targetPortId)
: target.ports.at(0)
// create the edges between source and target port. if no port is provided, add a default port.
@@ -416,13 +416,13 @@ class PortAwareEdgeCreator extends EdgeCreator {
const sourcePortId = this.getSourcePortId(dataItem)
const sourcePort =
sourcePortId && sourcePortId !== edge.sourcePort.tag
- ? edge.sourcePort.owner.ports.find(p => p.tag === sourcePortId)
+ ? edge.sourcePort.owner.ports.find((p) => p.tag === sourcePortId)
: edge.sourcePort
// same for the target port
const targetPortId = this.getTargetPortId(dataItem)
const targetPort =
targetPortId && targetPortId !== edge.targetPort.tag
- ? edge.targetPort.owner.ports.find(p => p.tag === targetPortId)
+ ? edge.targetPort.owner.ports.find((p) => p.tag === targetPortId)
: edge.targetPort
// remember the current source and target ports
const oldSource = edge.sourcePort
diff --git a/demos/databinding/port-aware-tree-builder/TreeBuilder.ts b/demos/databinding/port-aware-tree-builder/TreeBuilder.ts
index 6fecb3efb..be15e51ff 100644
--- a/demos/databinding/port-aware-tree-builder/TreeBuilder.ts
+++ b/demos/databinding/port-aware-tree-builder/TreeBuilder.ts
@@ -378,12 +378,12 @@ class PortAwareEdgeCreator extends EdgeCreator {
// if no ID is specified: get the first port
const sourcePortId = this.getSourcePortId(data)
const sourcePort = sourcePortId
- ? source.ports.find(p => p.tag === sourcePortId)
+ ? source.ports.find((p) => p.tag === sourcePortId)
: source.ports.at(0)
// same for the target port
const targetPortId = this.getTargetPortId(data)
const targetPort = targetPortId
- ? target.ports.find(p => p.tag === targetPortId)
+ ? target.ports.find((p) => p.tag === targetPortId)
: target.ports.at(0)
// create the edges between source and target port. if no port is provided, add a default port.
@@ -411,13 +411,13 @@ class PortAwareEdgeCreator extends EdgeCreator {
const sourcePortId = this.getSourcePortId(dataItem)
const sourcePort =
sourcePortId && sourcePortId !== edge.sourcePort!.tag
- ? edge.sourcePort!.owner!.ports.find(p => p.tag === sourcePortId)
+ ? edge.sourcePort!.owner!.ports.find((p) => p.tag === sourcePortId)
: edge.sourcePort
// same for the target port
const targetPortId = this.getTargetPortId(dataItem)
const targetPort =
targetPortId && targetPortId !== edge.targetPort!.tag
- ? edge.targetPort!.owner!.ports.find(p => p.tag === targetPortId)
+ ? edge.targetPort!.owner!.ports.find((p) => p.tag === targetPortId)
: edge.targetPort
// remember the current source and target ports
const oldSource = edge.sourcePort!
diff --git a/demos/databinding/port-aware-tree-builder/index.html b/demos/databinding/port-aware-tree-builder/index.html
index 5e37623e9..7d58f0eca 100644
--- a/demos/databinding/port-aware-tree-builder/index.html
+++ b/demos/databinding/port-aware-tree-builder/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.js b/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.js
index 17d99705f..781c6ec47 100644
--- a/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.js
+++ b/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.js
@@ -164,7 +164,7 @@ function createGraphBuilder(graph) {
parentId: 'parentGroup'
})
// Add some labels to the group nodes
- groupsSource.nodeCreator.createLabelBinding(group => group.id)
+ groupsSource.nodeCreator.createLabelBinding((group) => group.id)
graphBuilder.createEdgesSource({
// stores the edges of the graph
@@ -206,12 +206,12 @@ function createGraphBuilderWithImplicitGrouping(graph) {
// The children of each group are defined directly in the data
const childSource = nodesSource.createChildNodesSource(
// specifies how to retrieve the children for each group
- group => group.members,
+ (group) => group.members,
// specifies how the child nodes are identified globally
- item => item.id
+ (item) => item.id
)
// And the groups are additionally grouped again by location
- const parentSource = nodesSource.createParentNodesSource(group => group.location)
+ const parentSource = nodesSource.createParentNodesSource((group) => group.location)
// We want to set up reasonable defaults for the styles.
// Since the entities in the nodesSource and the parentsSource are both group nodes, they
@@ -219,8 +219,8 @@ function createGraphBuilderWithImplicitGrouping(graph) {
nodesSource.nodeCreator.defaults.style = parentSource.nodeCreator.defaults.style =
graph.groupNodeDefaults.style
// We also show labels for the groups
- nodesSource.nodeCreator.createLabelBinding(group => group.id)
- parentSource.nodeCreator.createLabelBinding(location => location)
+ nodesSource.nodeCreator.createLabelBinding((group) => group.id)
+ parentSource.nodeCreator.createLabelBinding((location) => location)
nodesSource.nodeCreator.defaults.labels = parentSource.nodeCreator.defaults.labels =
graph.groupNodeDefaults.labels
// The nodes in the childSource are just plain leaf nodes and are styles with a normal node style
@@ -260,7 +260,7 @@ function createTreeBuilder(graph, builderType) {
// identifies the property of a node object that contains its child nodes
const rootNodesSource = treeBuilder.createRootNodesSource(nodesSource)
// configure the recursive tree structure
- rootNodesSource.addChildNodesSource(data => data.children, rootNodesSource)
+ rootNodesSource.addChildNodesSource((data) => data.children, rootNodesSource)
return treeBuilder
}
@@ -285,7 +285,7 @@ function createAdjacencyGraphBuilder(graph, builderType) {
// configure the successor nodes
adjacencyNodesSource.addSuccessorsSource(
- data => data.children,
+ (data) => data.children,
adjacencyNodesSource,
new EdgeCreator({ defaults: graph.edgeDefaults })
)
@@ -300,7 +300,7 @@ function createAdjacencyGraphBuilder(graph, builderType) {
)
// Configure the successor nodes
adjacencyNodesSource.addSuccessorIds(
- data => data.children,
+ (data) => data.children,
new EdgeCreator({ defaults: graph.edgeDefaults })
)
}
@@ -361,7 +361,7 @@ async function arrangeGraph(graphComponent) {
* @param {!GraphComponent} graphComponent
*/
function initializeUI(graphComponent) {
- selectBox.addEventListener('change', async e => {
+ selectBox.addEventListener('change', async (e) => {
// build graph from new data
selectBox.disabled = true
buildGraph(graphComponent.graph, e.target.value)
diff --git a/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.ts b/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.ts
index 994bd2103..f3d112bd8 100644
--- a/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.ts
+++ b/demos/databinding/simplegraphbuilder/SimpleGraphBuilderDemo.ts
@@ -160,7 +160,7 @@ function createGraphBuilder(graph: IGraph): GraphBuilder {
parentId: 'parentGroup'
})
// Add some labels to the group nodes
- groupsSource.nodeCreator.createLabelBinding(group => group.id)
+ groupsSource.nodeCreator.createLabelBinding((group) => group.id)
graphBuilder.createEdgesSource({
// stores the edges of the graph
@@ -200,12 +200,12 @@ function createGraphBuilderWithImplicitGrouping(graph: IGraph): GraphBuilder {
// The children of each group are defined directly in the data
const childSource = nodesSource.createChildNodesSource(
// specifies how to retrieve the children for each group
- group => group.members,
+ (group) => group.members,
// specifies how the child nodes are identified globally
- item => item.id
+ (item) => item.id
)
// And the groups are additionally grouped again by location
- const parentSource = nodesSource.createParentNodesSource(group => group.location)
+ const parentSource = nodesSource.createParentNodesSource((group) => group.location)
// We want to set up reasonable defaults for the styles.
// Since the entities in the nodesSource and the parentsSource are both group nodes, they
@@ -213,8 +213,8 @@ function createGraphBuilderWithImplicitGrouping(graph: IGraph): GraphBuilder {
nodesSource.nodeCreator.defaults.style = parentSource.nodeCreator.defaults.style =
graph.groupNodeDefaults.style
// We also show labels for the groups
- nodesSource.nodeCreator.createLabelBinding(group => group.id)
- parentSource.nodeCreator.createLabelBinding(location => location)
+ nodesSource.nodeCreator.createLabelBinding((group) => group.id)
+ parentSource.nodeCreator.createLabelBinding((location) => location)
nodesSource.nodeCreator.defaults.labels = parentSource.nodeCreator.defaults.labels =
graph.groupNodeDefaults.labels
// The nodes in the childSource are just plain leaf nodes and are styles with a normal node style
@@ -344,7 +344,7 @@ async function arrangeGraph(graphComponent: GraphComponent): Promise {
* Registers the actions for the toolbar buttons during the creation of this application.
*/
function initializeUI(graphComponent: GraphComponent): void {
- selectBox.addEventListener('change', async e => {
+ selectBox.addEventListener('change', async (e) => {
// build graph from new data
selectBox.disabled = true
buildGraph(graphComponent.graph, (e.target as HTMLSelectElement).value)
diff --git a/demos/databinding/simplegraphbuilder/data-view.css b/demos/databinding/simplegraphbuilder/data-view.css
index 89921244d..c05afcbb6 100644
--- a/demos/databinding/simplegraphbuilder/data-view.css
+++ b/demos/databinding/simplegraphbuilder/data-view.css
@@ -29,7 +29,9 @@
#data-view {
width: 400px;
height: 340px;
- transition: width 1s, height 1s;
+ transition:
+ width 1s,
+ height 1s;
font-size: 13px;
}
#data-view.collapsed {
diff --git a/demos/databinding/simplegraphbuilder/index.html b/demos/databinding/simplegraphbuilder/index.html
index c337b3e59..1fd7e13e9 100644
--- a/demos/databinding/simplegraphbuilder/index.html
+++ b/demos/databinding/simplegraphbuilder/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/databinding/treebuilder/EditTreeNodeSourceDialog.js b/demos/databinding/treebuilder/EditTreeNodeSourceDialog.js
index 3088a2456..73c5785ec 100644
--- a/demos/databinding/treebuilder/EditTreeNodeSourceDialog.js
+++ b/demos/databinding/treebuilder/EditTreeNodeSourceDialog.js
@@ -123,7 +123,7 @@ export class EditTreeNodesSourceDialog {
// CodeMirror requires the textArea to be in the DOM and visible already when instantiating
this.dialogContainerModal.style.removeProperty('display')
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
this.initialize()
diff --git a/demos/databinding/treebuilder/EditTreeNodeSourceDialog.ts b/demos/databinding/treebuilder/EditTreeNodeSourceDialog.ts
index bb10d7537..e3bb57cef 100644
--- a/demos/databinding/treebuilder/EditTreeNodeSourceDialog.ts
+++ b/demos/databinding/treebuilder/EditTreeNodeSourceDialog.ts
@@ -127,7 +127,7 @@ export class EditTreeNodesSourceDialog {
// CodeMirror requires the textArea to be in the DOM and visible already when instantiating
this.dialogContainerModal.style.removeProperty('display')
- return new Promise(resolve => {
+ return new Promise((resolve) => {
setTimeout(() => {
this.initialize()
diff --git a/demos/databinding/treebuilder/ModelClasses.js b/demos/databinding/treebuilder/ModelClasses.js
index e31630c8e..4a370abfe 100644
--- a/demos/databinding/treebuilder/ModelClasses.js
+++ b/demos/databinding/treebuilder/ModelClasses.js
@@ -115,7 +115,7 @@ export function createBinding(bindingString) {
const func = new Function(`return (${bindingString})`)()
// wrap the binding function with a function that catches and reports errors
// that occur in the binding functions
- return dataItem => {
+ return (dataItem) => {
try {
// eslint-disable-next-line no-useless-call
const result = func.apply(null, [dataItem])
@@ -129,10 +129,10 @@ export function createBinding(bindingString) {
}
}
} catch (ignored) {
- return dataItem => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
+ return (dataItem) => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
}
}
- return dataItem => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
+ return (dataItem) => (bindingString.length > 0 ? dataItem[bindingString] : undefined)
}
/**
diff --git a/demos/databinding/treebuilder/SchemaComponent.js b/demos/databinding/treebuilder/SchemaComponent.js
index 69a6037dc..4c1baa7e2 100644
--- a/demos/databinding/treebuilder/SchemaComponent.js
+++ b/demos/databinding/treebuilder/SchemaComponent.js
@@ -300,20 +300,23 @@ export class SchemaComponent {
this.treeBuilder = new TreeBuilder(this.resultGraph)
const schemaGraphBuilder = new GraphBuilder(this.schemaGraphComponent.graph)
- const schemaNodesSource = schemaGraphBuilder.createNodesSource(sample.nodesSources, n => n.name)
+ const schemaNodesSource = schemaGraphBuilder.createNodesSource(
+ sample.nodesSources,
+ (n) => n.name
+ )
- schemaNodesSource.nodeCreator.createLabelBinding(n => n.name)
+ schemaNodesSource.nodeCreator.createLabelBinding((n) => n.name)
- schemaNodesSource.nodeCreator.tagProvider = sourceDefinition =>
+ schemaNodesSource.nodeCreator.tagProvider = (sourceDefinition) =>
this.createTreeNodesSourceConnector(sourceDefinition)
- schemaNodesSource.nodeCreator.styleProvider = data =>
+ schemaNodesSource.nodeCreator.styleProvider = (data) =>
SchemaComponent.createSchemaNodeStyle(data)
const schemaEdgesSource = schemaGraphBuilder.createEdgesSource(
sample.edgesSource,
- e => e.parentSource,
- e => e.childSource
+ (e) => e.parentSource,
+ (e) => e.childSource
)
schemaEdgesSource.edgeCreator.addEdgeCreatedListener((_, evt) => {
this.createChildRelationship(evt.dataItem.childBinding, evt.item)
@@ -334,14 +337,14 @@ export class SchemaComponent {
// gather remaining source definitions
const treeNodesSourcesDefinitions = []
- schemaGraph.nodes.forEach(node => {
+ schemaGraph.nodes.forEach((node) => {
const sourceConnector = node.tag
treeNodesSourcesDefinitions.push(sourceConnector.sourceDefinition)
})
// gather remaining edge definitions
const edgesSourceDefinitions = []
- schemaGraph.edges.forEach(edge => {
+ schemaGraph.edges.forEach((edge) => {
const sourceConnector = edge.sourceNode.tag
const targetConnector = edge.targetNode.tag
@@ -377,7 +380,7 @@ export class SchemaComponent {
edge.tag = { provider: childDataProvider, binding: createBinding(childDataProvider) }
sourceConnector.nodesSource.addChildNodesSource(
- dataItem => edge.tag.binding(dataItem),
+ (dataItem) => edge.tag.binding(dataItem),
targetConnector.nodesSource
)
@@ -485,7 +488,7 @@ export class SchemaComponent {
this.schemaGraphComponent.graph.nodeDefaults.size
// each edge creation should use another random target node color
- createEdgeInputMode.addGestureStartingListener(src => {
+ createEdgeInputMode.addGestureStartingListener((src) => {
const nodeStyle = new ShapeNodeStyle({
shape: 'ellipse',
fill: '#6495ED',
diff --git a/demos/databinding/treebuilder/SchemaComponent.ts b/demos/databinding/treebuilder/SchemaComponent.ts
index a1e5626f9..9b2997f86 100644
--- a/demos/databinding/treebuilder/SchemaComponent.ts
+++ b/demos/databinding/treebuilder/SchemaComponent.ts
@@ -290,9 +290,12 @@ export class SchemaComponent {
this.treeBuilder = new TreeBuilder(this.resultGraph)
const schemaGraphBuilder = new GraphBuilder(this.schemaGraphComponent.graph)
- const schemaNodesSource = schemaGraphBuilder.createNodesSource(sample.nodesSources, n => n.name)
+ const schemaNodesSource = schemaGraphBuilder.createNodesSource(
+ sample.nodesSources,
+ (n) => n.name
+ )
- schemaNodesSource.nodeCreator.createLabelBinding(n => n.name)
+ schemaNodesSource.nodeCreator.createLabelBinding((n) => n.name)
schemaNodesSource.nodeCreator.tagProvider = (
sourceDefinition
@@ -304,8 +307,8 @@ export class SchemaComponent {
const schemaEdgesSource = schemaGraphBuilder.createEdgesSource(
sample.edgesSource,
- e => e.parentSource,
- e => e.childSource
+ (e) => e.parentSource,
+ (e) => e.childSource
)
schemaEdgesSource.edgeCreator.addEdgeCreatedListener((_, evt) => {
this.createChildRelationship(evt.dataItem.childBinding, evt.item)
@@ -369,7 +372,7 @@ export class SchemaComponent {
edge.tag = { provider: childDataProvider, binding: createBinding(childDataProvider) }
sourceConnector.nodesSource.addChildNodesSource(
- dataItem => edge.tag.binding(dataItem),
+ (dataItem) => edge.tag.binding(dataItem),
targetConnector.nodesSource
)
@@ -476,7 +479,7 @@ export class SchemaComponent {
this.schemaGraphComponent.graph.nodeDefaults.size
// each edge creation should use another random target node color
- createEdgeInputMode.addGestureStartingListener(src => {
+ createEdgeInputMode.addGestureStartingListener((src) => {
const nodeStyle = new ShapeNodeStyle({
shape: 'ellipse',
fill: '#6495ED',
diff --git a/demos/databinding/treebuilder/index.html b/demos/databinding/treebuilder/index.html
index c263c7804..3b6679352 100644
--- a/demos/databinding/treebuilder/index.html
+++ b/demos/databinding/treebuilder/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/input/button-input-mode/ButtonInputMode.js b/demos/input/button-input-mode/ButtonInputMode.js
index 719d41aa6..f972ddd5b 100644
--- a/demos/input/button-input-mode/ButtonInputMode.js
+++ b/demos/input/button-input-mode/ButtonInputMode.js
@@ -377,7 +377,7 @@ export class ButtonInputMode extends InputModeBase {
if (item) {
this.buttonOwner = item
this.buttons = this.getButtons(item)
- this.buttons.forEach(button => {
+ this.buttons.forEach((button) => {
this.buttonLabels.add(button)
})
@@ -470,7 +470,7 @@ export class ButtonInputMode extends InputModeBase {
getHitButtons(context, location) {
return context.canvasComponent
.hitElementsAt(context, location, this.buttonLabelManager.canvasObjectGroup)
- .map(canvasObject => canvasObject.userObject)
+ .map((canvasObject) => canvasObject.userObject)
}
/**
@@ -840,7 +840,7 @@ export class ButtonInputMode extends InputModeBase {
}
// As bends don't have their own visualization, bend hit testing has to be explicitly checked
const hitBend = hitItem.bends.find(
- bend => bend.location.distanceTo(location) < context.hitTestRadius
+ (bend) => bend.location.distanceTo(location) < context.hitTestRadius
)
return hitBend ?? hitItem
}
diff --git a/demos/input/button-input-mode/ButtonInputMode.ts b/demos/input/button-input-mode/ButtonInputMode.ts
index 4e2f5e10d..200e5ec36 100644
--- a/demos/input/button-input-mode/ButtonInputMode.ts
+++ b/demos/input/button-input-mode/ButtonInputMode.ts
@@ -351,7 +351,7 @@ export class ButtonInputMode extends InputModeBase {
if (item) {
this.buttonOwner = item
this.buttons = this.getButtons(item)
- this.buttons.forEach(button => {
+ this.buttons.forEach((button) => {
this.buttonLabels.add(button)
})
@@ -440,7 +440,7 @@ export class ButtonInputMode extends InputModeBase {
private getHitButtons(context: IInputModeContext, location: Point) {
return context
.canvasComponent!.hitElementsAt(context, location, this.buttonLabelManager.canvasObjectGroup)
- .map(canvasObject => canvasObject.userObject as Button)
+ .map((canvasObject) => canvasObject.userObject as Button)
}
private getFirstHitButton(location: Point): Button | null {
@@ -743,7 +743,7 @@ export class ButtonInputMode extends InputModeBase {
}
// As bends don't have their own visualization, bend hit testing has to be explicitly checked
const hitBend = hitItem.bends.find(
- bend => bend.location.distanceTo(location) < context.hitTestRadius
+ (bend) => bend.location.distanceTo(location) < context.hitTestRadius
)
return hitBend ?? hitItem
}
diff --git a/demos/input/button-input-mode/ButtonInputModeDemo.js b/demos/input/button-input-mode/ButtonInputModeDemo.js
index 3be9f35b3..6fd165ed8 100644
--- a/demos/input/button-input-mode/ButtonInputModeDemo.js
+++ b/demos/input/button-input-mode/ButtonInputModeDemo.js
@@ -367,14 +367,14 @@ function buildGraph(graph, graphData) {
graphBuilder
.createNodesSource({
data: graphData.nodeList,
- id: item => item.id
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/input/button-input-mode/ButtonInputModeDemo.ts b/demos/input/button-input-mode/ButtonInputModeDemo.ts
index 47492a090..4bcaabf14 100644
--- a/demos/input/button-input-mode/ButtonInputModeDemo.ts
+++ b/demos/input/button-input-mode/ButtonInputModeDemo.ts
@@ -362,14 +362,14 @@ function buildGraph(graph: IGraph, graphData: JSONGraph): void {
graphBuilder
.createNodesSource({
data: graphData.nodeList,
- id: item => item.id
+ id: (item) => item.id
})
- .nodeCreator.createLabelBinding(item => item.label)
+ .nodeCreator.createLabelBinding((item) => item.label)
graphBuilder.createEdgesSource({
data: graphData.edgeList,
- sourceId: item => item.source,
- targetId: item => item.target
+ sourceId: (item) => item.source,
+ targetId: (item) => item.target
})
graphBuilder.buildGraph()
diff --git a/demos/input/button-input-mode/OffsetLabelModelWrapper.js b/demos/input/button-input-mode/OffsetLabelModelWrapper.js
index 22c4e0c13..66dbf9df6 100644
--- a/demos/input/button-input-mode/OffsetLabelModelWrapper.js
+++ b/demos/input/button-input-mode/OffsetLabelModelWrapper.js
@@ -170,7 +170,7 @@ export class OffsetLabelModelWrapper extends BaseClass(ILabelModel) {
}
/**
- * @template {*} T
+ * @template T
* @param {!Class.} type
* @returns {?T}
*/
diff --git a/demos/input/button-input-mode/OffsetLabelModelWrapper.ts b/demos/input/button-input-mode/OffsetLabelModelWrapper.ts
index b5c430488..273d96a49 100644
--- a/demos/input/button-input-mode/OffsetLabelModelWrapper.ts
+++ b/demos/input/button-input-mode/OffsetLabelModelWrapper.ts
@@ -145,7 +145,7 @@ export class OffsetLabelModelWrapper extends BaseClass(ILabelModel) {
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
return null
}
}
diff --git a/demos/input/button-input-mode/index.html b/demos/input/button-input-mode/index.html
index 89ce765f4..7e9711d4e 100644
--- a/demos/input/button-input-mode/index.html
+++ b/demos/input/button-input-mode/index.html
@@ -1,4 +1,4 @@
-
+
@@ -41,7 +41,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Running Web Worker
-
Cancel Layout
-
-
-
-
-
-
-
-
-
-
diff --git a/demos/loading/webworker-webpack/README.html b/demos/loading/webworker-webpack/README.html
index c05d66790..2f043eb08 100644
--- a/demos/loading/webworker-webpack/README.html
+++ b/demos/loading/webworker-webpack/README.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/loading/webworker-webpack/index.template.html b/demos/loading/webworker-webpack/index.template.html
index 8d5fe680d..38f968e3e 100644
--- a/demos/loading/webworker-webpack/index.template.html
+++ b/demos/loading/webworker-webpack/index.template.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/loading/webworker-webpack/package.json b/demos/loading/webworker-webpack/package.json
index 07ff6c19c..ac90fc838 100644
--- a/demos/loading/webworker-webpack/package.json
+++ b/demos/loading/webworker-webpack/package.json
@@ -14,18 +14,18 @@
"dependencies": {
"demo-resources": "../../resources",
"utils": "../../utils",
- "yfiles": "../../../lib-dev/yfiles-26.0.2+dev.tgz"
+ "yfiles": "../../../lib-dev/yfiles-26.0.3+dev.tgz"
},
"devDependencies": {
- "@yworks/optimizer": "^1.8.1",
+ "@yworks/optimizer": "^1.8.2",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "6.8.1",
"html-webpack-harddisk-plugin": "2.0.0",
"html-webpack-plugin": "5.5.3",
"mini-css-extract-plugin": "2.7.6",
- "ts-loader": "^9.4.3",
- "typescript": "~5.1.6",
- "webpack": "5.88.0",
+ "ts-loader": "^9.5.1",
+ "typescript": "~5.3.2",
+ "webpack": "5.89.0",
"webpack-cli": "5.1.4",
"webpack-dev-server": "4.15.1"
},
diff --git a/demos/loading/webworker-webpack/src/WebWorkerWebpackDemo.ts b/demos/loading/webworker-webpack/src/WebWorkerWebpackDemo.ts
index 4dae9eb11..e13ff7f25 100644
--- a/demos/loading/webworker-webpack/src/WebWorkerWebpackDemo.ts
+++ b/demos/loading/webworker-webpack/src/WebWorkerWebpackDemo.ts
@@ -94,7 +94,7 @@ async function runWebWorkerLayout(clearUndo: boolean): Promise {
// helper function that performs the actual message passing to the web worker
function webWorkerMessageHandler(data: unknown): Promise {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
worker.onmessage = (e: any) => resolve(e.data)
worker.postMessage(data)
})
diff --git a/demos/loading/webworker-webpack/src/WorkerLayout.ts b/demos/loading/webworker-webpack/src/WorkerLayout.ts
index cb4aaee12..08dcd56b2 100644
--- a/demos/loading/webworker-webpack/src/WorkerLayout.ts
+++ b/demos/loading/webworker-webpack/src/WorkerLayout.ts
@@ -49,7 +49,7 @@ function applyLayout(graph: LayoutGraph, layoutDescriptor: LayoutDescriptor): vo
addEventListener(
'message',
- e => {
+ (e) => {
// create a new remote layout executor
const executor = new LayoutExecutorAsyncWorker(applyLayout)
executor.process(e.data).then(postMessage).catch(postMessage)
diff --git a/demos/package.json b/demos/package.json
index a5b57518a..755bc9392 100644
--- a/demos/package.json
+++ b/demos/package.json
@@ -1,6 +1,6 @@
{
"name": "typescript-demos-for-yfiles-for-html",
- "version": "26.0.2",
+ "version": "26.0.3",
"author": "yWorks GmbH ",
"license": "https://www.yworks.com/products/yfiles-for-html/sla",
"private": true,
@@ -14,29 +14,28 @@
},
"dependencies": {
"@babel/standalone": "7.19.3",
- "@fortawesome/fontawesome-free": "6.4.0",
- "codemirror": "5.65.13",
+ "@fortawesome/fontawesome-free": "6.4.2",
+ "codemirror": "5.65.16",
"d3": "~7.8.5",
"demo-utils": "./utils",
"demo-resources": "./resources",
- "jspdf": "2.3.1",
+ "jspdf": "2.5.1",
"leaflet": "~1.9.4",
- "markdown-it": "13.0.1",
- "neo4j-driver": "5.9.1",
+ "markdown-it": "13.0.2",
+ "neo4j-driver": "5.14.0",
"quill": "1.3.7",
"react": "18.2.0",
"react-dom": "18.2.0",
- "svg2pdf.js": "2.1.0",
- "yfiles": "^26.0.0",
- "yfiles-umd": "^26.0.0"
+ "svg2pdf.js": "2.2.2",
+ "yfiles": "^26.0.0"
},
"devDependencies": {
- "@types/babel__standalone": "7.1.4",
- "@types/codemirror": "~5.60.8",
- "@types/d3": "~7.4.0",
- "@types/leaflet": "~1.9.3",
- "@types/markdown-it": "~12.2.3",
- "@types/quill": "~1.3.10",
- "@types/react-dom": "18.2.0"
+ "@types/babel__standalone": "7.1.7",
+ "@types/codemirror": "~5.60.15",
+ "@types/d3": "~7.4.3",
+ "@types/leaflet": "~1.9.8",
+ "@types/markdown-it": "~13.0.7",
+ "@types/quill": "~2.0.14",
+ "@types/react-dom": "18.2.17"
}
}
diff --git a/demos/resources/README.html b/demos/resources/README.html
index 0ec161290..49aac819f 100644
--- a/demos/resources/README.html
+++ b/demos/resources/README.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/resources/apply-local-storage-variables.js b/demos/resources/apply-local-storage-variables.js
index c2892ef72..5008a60ba 100644
--- a/demos/resources/apply-local-storage-variables.js
+++ b/demos/resources/apply-local-storage-variables.js
@@ -63,7 +63,7 @@ function getNumberItemFromLocalStorage(key) {
}
const size = parseFloat(storageItem)
- return isFinite(size) ? size : null
+ return Number.isFinite(size) ? size : null
}
applyLocalStorageVariables()
diff --git a/demos/resources/demo-error.js b/demos/resources/demo-error.js
index f190a86aa..7fa405681 100644
--- a/demos/resources/demo-error.js
+++ b/demos/resources/demo-error.js
@@ -74,7 +74,7 @@ export function registerErrorDialog() {
}
// Register a handler for unhandled errors
- window.addEventListener('error', e => {
+ window.addEventListener('error', (e) => {
e.preventDefault()
if (inErrorState()) {
return
@@ -86,7 +86,7 @@ export function registerErrorDialog() {
})
// Register a handler for unhandled promise rejections
- window.addEventListener('unhandledrejection', e => {
+ window.addEventListener('unhandledrejection', (e) => {
e.preventDefault()
if (inErrorState()) {
return
@@ -102,11 +102,11 @@ export function registerErrorDialog() {
// Forward errors occurring in internal event handlers of yFiles to the standard reportError function
// https://docs.yworks.com/yfileshtml/#/api/Exception
- Exception.handler = error => openErrorOverlay(error)
+ Exception.handler = (error) => openErrorOverlay(error)
// Forward errors occurring during require.js module loading to the standard reportError function
if (anyWindow.require != null) {
- anyWindow.onError = error => openErrorOverlay(error)
+ anyWindow.onError = (error) => openErrorOverlay(error)
}
}
@@ -140,8 +140,8 @@ function unwindStack(error) {
return !stack || stack.length === 0
? ''
: error.cause
- ? `${stack}\nCaused by:\n${unwindStack(error.cause)}`
- : stack
+ ? `${stack}\nCaused by:\n${unwindStack(error.cause)}`
+ : stack
}
/**
diff --git a/demos/resources/demo-error.ts b/demos/resources/demo-error.ts
index 824afaf66..a05c50b0f 100644
--- a/demos/resources/demo-error.ts
+++ b/demos/resources/demo-error.ts
@@ -133,8 +133,8 @@ function unwindStack(error: any): string | undefined {
return !stack || stack.length === 0
? ''
: error.cause
- ? `${stack}\nCaused by:\n${unwindStack(error.cause)}`
- : stack
+ ? `${stack}\nCaused by:\n${unwindStack(error.cause)}`
+ : stack
}
/**
diff --git a/demos/resources/demo-ui/element-utils.js b/demos/resources/demo-ui/element-utils.js
index b99b88672..9ed5a52d1 100644
--- a/demos/resources/demo-ui/element-utils.js
+++ b/demos/resources/demo-ui/element-utils.js
@@ -79,7 +79,7 @@ export function addNavigationButtons(
const prevButton = document.createElement('button')
prevButton.classList.add('demo-icon-yIconPrevious', 'navigation-button', ...classes)
prevButton.setAttribute('title', 'Previous')
- prevButton.addEventListener('click', _ => {
+ prevButton.addEventListener('click', (_) => {
const oldIndex = selectElement.selectedIndex
const newIndex = lastIndexOfEnabled(selectElement, oldIndex - 1, wrapAround)
if (oldIndex != newIndex && newIndex > -1) {
@@ -91,7 +91,7 @@ export function addNavigationButtons(
const nextButton = document.createElement('button')
nextButton.classList.add('demo-icon-yIconNext', 'navigation-button', ...classes)
nextButton.setAttribute('title', 'Next')
- nextButton.addEventListener('click', _ => {
+ nextButton.addEventListener('click', (_) => {
const oldIndex = selectElement.selectedIndex
const newIndex = indexOfEnabled(selectElement, oldIndex + 1, wrapAround)
if (oldIndex != newIndex && newIndex > -1) {
@@ -123,11 +123,11 @@ export function addNavigationButtons(
selectElement.disabled || (!wrapAround && selectElement.selectedIndex === lastIndex)
}
- selectElement.addEventListener('change', _ => {
+ selectElement.addEventListener('change', (_) => {
updateDisabled()
})
- const disabledObserver = new MutationObserver(mutations => {
+ const disabledObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.attributeName === 'disabled') {
updateDisabled()
@@ -284,7 +284,7 @@ export function bindYFilesCommand(selector, command, target, parameter, tooltip)
*/
export function disableUIElements(...elementSelectors) {
for (const selector of elementSelectors) {
- document.querySelectorAll(selector).forEach(element => {
+ document.querySelectorAll(selector).forEach((element) => {
if (!element || element.hasAttribute('disabled')) return
element.setAttribute('disabled', '')
@@ -297,7 +297,7 @@ export function disableUIElements(...elementSelectors) {
* Re-enables all elements which were previously disabled by {@see disableUIElements}.
*/
export function enableUIElements() {
- document.querySelectorAll('[data-disabled]').forEach(e => {
+ document.querySelectorAll('[data-disabled]').forEach((e) => {
e.removeAttribute('disabled')
})
}
@@ -315,5 +315,5 @@ export async function showLoadingIndicator(visible, message) {
if (message) {
loadingIndicator.innerText = message
}
- return new Promise(resolve => setTimeout(resolve, 0))
+ return new Promise((resolve) => setTimeout(resolve, 0))
}
diff --git a/demos/resources/demo-ui/element-utils.ts b/demos/resources/demo-ui/element-utils.ts
index a4e155313..374f3df6b 100644
--- a/demos/resources/demo-ui/element-utils.ts
+++ b/demos/resources/demo-ui/element-utils.ts
@@ -72,7 +72,7 @@ export function addNavigationButtons(
const prevButton = document.createElement('button')
prevButton.classList.add('demo-icon-yIconPrevious', 'navigation-button', ...classes)
prevButton.setAttribute('title', 'Previous')
- prevButton.addEventListener('click', _ => {
+ prevButton.addEventListener('click', (_) => {
const oldIndex = selectElement.selectedIndex
const newIndex = lastIndexOfEnabled(selectElement, oldIndex - 1, wrapAround)
if (oldIndex != newIndex && newIndex > -1) {
@@ -84,7 +84,7 @@ export function addNavigationButtons(
const nextButton = document.createElement('button')
nextButton.classList.add('demo-icon-yIconNext', 'navigation-button', ...classes)
nextButton.setAttribute('title', 'Next')
- nextButton.addEventListener('click', _ => {
+ nextButton.addEventListener('click', (_) => {
const oldIndex = selectElement.selectedIndex
const newIndex = indexOfEnabled(selectElement, oldIndex + 1, wrapAround)
if (oldIndex != newIndex && newIndex > -1) {
@@ -116,11 +116,11 @@ export function addNavigationButtons(
selectElement.disabled || (!wrapAround && selectElement.selectedIndex === lastIndex)
}
- selectElement.addEventListener('change', _ => {
+ selectElement.addEventListener('change', (_) => {
updateDisabled()
})
- const disabledObserver = new MutationObserver(mutations => {
+ const disabledObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.attributeName === 'disabled') {
updateDisabled()
@@ -281,7 +281,7 @@ export function bindYFilesCommand(
*/
export function disableUIElements(...elementSelectors: string[]): void {
for (const selector of elementSelectors) {
- document.querySelectorAll(selector).forEach(element => {
+ document.querySelectorAll(selector).forEach((element) => {
if (!element || element.hasAttribute('disabled')) return
element.setAttribute('disabled', '')
@@ -294,7 +294,7 @@ export function disableUIElements(...elementSelectors: string[]): void {
* Re-enables all elements which were previously disabled by {@see disableUIElements}.
*/
export function enableUIElements() {
- document.querySelectorAll('[data-disabled]').forEach(e => {
+ document.querySelectorAll('[data-disabled]').forEach((e) => {
e.removeAttribute('disabled')
})
}
@@ -310,5 +310,5 @@ export async function showLoadingIndicator(visible: boolean, message?: string):
if (message) {
loadingIndicator.innerText = message
}
- return new Promise(resolve => setTimeout(resolve, 0))
+ return new Promise((resolve) => setTimeout(resolve, 0))
}
diff --git a/demos/resources/demo-ui/sidebars.js b/demos/resources/demo-ui/sidebars.js
index 7feb1d8be..01b1386fd 100644
--- a/demos/resources/demo-ui/sidebars.js
+++ b/demos/resources/demo-ui/sidebars.js
@@ -91,7 +91,7 @@ function enableDraggableDescription(description) {
description.append(verticalDragArea, horizontalDragArea)
let resizingElement
- const resize = event => {
+ const resize = (event) => {
if (!resizingElement) return
const vertical = resizingElement.classList.contains('demo-description__drag-area--vertical')
@@ -102,10 +102,10 @@ function enableDraggableDescription(description) {
? event.pageX
: window.innerHeight - event.pageY
: event instanceof TouchEvent
- ? vertical
- ? event.touches.item(0).pageX
- : window.innerHeight - event.touches.item(0).pageY
- : null
+ ? vertical
+ ? event.touches.item(0).pageX
+ : window.innerHeight - event.touches.item(0).pageY
+ : null
if (eventPos == null) {
return
diff --git a/demos/resources/demo-ui/sidebars.ts b/demos/resources/demo-ui/sidebars.ts
index 7a1349e63..ae280e4a3 100644
--- a/demos/resources/demo-ui/sidebars.ts
+++ b/demos/resources/demo-ui/sidebars.ts
@@ -99,10 +99,10 @@ function enableDraggableDescription(description: Element) {
? event.pageX
: window.innerHeight - event.pageY
: event instanceof TouchEvent
- ? vertical
- ? event.touches.item(0)!.pageX
- : window.innerHeight - event.touches.item(0)!.pageY
- : null
+ ? vertical
+ ? event.touches.item(0)!.pageX
+ : window.innerHeight - event.touches.item(0)!.pageY
+ : null
if (eventPos == null) {
return
diff --git a/demos/resources/demo-ui/toolbar.js b/demos/resources/demo-ui/toolbar.js
index c20bceba3..c9725d431 100644
--- a/demos/resources/demo-ui/toolbar.js
+++ b/demos/resources/demo-ui/toolbar.js
@@ -60,7 +60,7 @@ function getToolbarWidthAndPadding(entry) {
// borderBoxSize and contentBoxSize are not supported by Safari < 15,
// fallback to contentRect
if (!entry.borderBoxSize || !entry.contentBoxSize) {
- toolbarWidth = entry.contentRect.width + 32 ?? 0
+ toolbarWidth = entry.contentRect.width ? entry.contentRect.width + 32 : 0
toolbarContentWidth = entry.contentRect.width ?? 0
}
// old Firefox implemented borderBoxSize and contentBoxSize as non array
@@ -81,7 +81,7 @@ function getToolbarWidthAndPadding(entry) {
*/
function toolbarSizeChanged(entries, observer) {
window.requestAnimationFrame(() => {
- entries.forEach(entry => {
+ entries.forEach((entry) => {
const { toolbarWidth, toolbarPadding } = getToolbarWidthAndPadding(entry)
if (toolbarWidth > 0) {
wrapToolbar(entry.target, toolbarWidth, toolbarPadding)
@@ -109,7 +109,7 @@ function initToolbarResponsiveness(toolbar) {
overflowButton.classList.add('overflow-button')
overflowButton.setAttribute('title', 'More...')
- const closeContainerHandler = e => {
+ const closeContainerHandler = (e) => {
let current = e.target
while (current !== overflowContainer && current.parentNode) {
current = current.parentNode
@@ -120,7 +120,7 @@ function initToolbarResponsiveness(toolbar) {
e.preventDefault()
}
}
- overflowButton.addEventListener('click', e => {
+ overflowButton.addEventListener('click', (e) => {
if (e.target !== overflowButton) return
overflowContainer.classList.toggle('overflow-container--open')
@@ -243,12 +243,12 @@ function pushBackOverflow(toolbar, overflowContainerContent, toolbarWidth) {
function initTutorialToolbar(toolbar) {
const dropdown = toolbar.querySelector('.demo-toolbar__tutorial-dropdown')
- const closeDropdown = e => {
+ const closeDropdown = (e) => {
dropdown.classList.remove('demo-toolbar__tutorial-dropdown--expanded')
document.body.removeEventListener('click', closeDropdown)
}
- dropdown?.addEventListener('click', e => {
+ dropdown?.addEventListener('click', (e) => {
if (dropdown.classList.contains('demo-toolbar__tutorial-dropdown--expanded')) {
closeDropdown(e)
} else {
diff --git a/demos/resources/demo-ui/toolbar.ts b/demos/resources/demo-ui/toolbar.ts
index 2937db55e..fe3df56b1 100644
--- a/demos/resources/demo-ui/toolbar.ts
+++ b/demos/resources/demo-ui/toolbar.ts
@@ -57,7 +57,7 @@ function getToolbarWidthAndPadding(entry: ResizeObserverEntry) {
// borderBoxSize and contentBoxSize are not supported by Safari < 15,
// fallback to contentRect
if (!entry.borderBoxSize || !entry.contentBoxSize) {
- toolbarWidth = entry.contentRect.width + 32 ?? 0
+ toolbarWidth = entry.contentRect.width ? entry.contentRect.width + 32 : 0
toolbarContentWidth = entry.contentRect.width ?? 0
}
// old Firefox implemented borderBoxSize and contentBoxSize as non array
@@ -76,7 +76,7 @@ function getToolbarWidthAndPadding(entry: ResizeObserverEntry) {
function toolbarSizeChanged(entries: ResizeObserverEntry[], observer: ResizeObserver) {
window.requestAnimationFrame(() => {
- entries.forEach(entry => {
+ entries.forEach((entry) => {
const { toolbarWidth, toolbarPadding } = getToolbarWidthAndPadding(entry)
if (toolbarWidth > 0) {
wrapToolbar(entry.target, toolbarWidth, toolbarPadding)
@@ -114,7 +114,7 @@ function initToolbarResponsiveness(toolbar: Element) {
e.preventDefault()
}
}
- overflowButton.addEventListener('click', e => {
+ overflowButton.addEventListener('click', (e) => {
if (e.target !== overflowButton) return
overflowContainer.classList.toggle('overflow-container--open')
@@ -230,7 +230,7 @@ function initTutorialToolbar(toolbar: Element) {
document.body.removeEventListener('click', closeDropdown)
}
- dropdown?.addEventListener('click', e => {
+ dropdown?.addEventListener('click', (e) => {
if (dropdown.classList.contains('demo-toolbar__tutorial-dropdown--expanded')) {
closeDropdown(e)
} else {
diff --git a/demos/resources/fetch-license.js b/demos/resources/fetch-license.js
index f7759e311..da6f27328 100644
--- a/demos/resources/fetch-license.js
+++ b/demos/resources/fetch-license.js
@@ -74,7 +74,7 @@ function checkLicense(licenseData) {
const g = new DefaultGraph()
g.createNode()
if (g.nodes.size === 1) {
- return new Promise(resolve => resolve(licenseData))
+ return new Promise((resolve) => resolve(licenseData))
}
window.setTimeout(() => {
@@ -107,7 +107,7 @@ function parseLicense(licenseString) {
}
/**
- * @returns {!Promise.<(Record.|void)>}
+ * @returns {!(Promise.>|Promise)}
*/
function loadLicenseFromLocalStorage() {
if (typeof window === 'undefined') {
@@ -125,10 +125,10 @@ function loadLicenseFromLocalStorage() {
}
/**
- * @returns {!Promise.<(Record.|void)>}
+ * @returns {!Promise.>}
*/
async function showLicenseDialog() {
- return new Promise(resolve => {
+ return new Promise((resolve) => {
window.setTimeout(function () {
const div = document.createElement('div')
div.setAttribute(
diff --git a/demos/resources/fetch-license.ts b/demos/resources/fetch-license.ts
index 5ccb24aeb..ba47d4778 100644
--- a/demos/resources/fetch-license.ts
+++ b/demos/resources/fetch-license.ts
@@ -71,7 +71,7 @@ function checkLicense(licenseData: Record): Promise {
const g = new DefaultGraph()
g.createNode()
if (g.nodes.size === 1) {
- return new Promise(resolve => resolve(licenseData))
+ return new Promise((resolve) => resolve(licenseData))
}
window.setTimeout(() => {
@@ -99,7 +99,9 @@ function parseLicense(licenseString: string | undefined): Record | void> {
+function loadLicenseFromLocalStorage():
+ | Promise | undefined>
+ | Promise {
if (typeof window === 'undefined') {
console.warn('yFiles demo app: No yFiles for HTML license included!')
return Promise.resolve()
@@ -114,8 +116,8 @@ function loadLicenseFromLocalStorage(): Promise | void>
return showLicenseDialog()
}
-async function showLicenseDialog(): Promise | void> {
- return new Promise(resolve => {
+async function showLicenseDialog(): Promise | undefined> {
+ return new Promise((resolve) => {
window.setTimeout(function () {
const div = document.createElement('div')
div.setAttribute(
diff --git a/demos/resources/filesystem-warning.js b/demos/resources/filesystem-warning.js
index e6cf554a4..9abc6ef5d 100644
--- a/demos/resources/filesystem-warning.js
+++ b/demos/resources/filesystem-warning.js
@@ -26,8 +26,7 @@
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***************************************************************************/
-/* eslint-disable no-eval */
-/* eslint-disable no-var */
+/* eslint-disable no-eval, no-var */
;(function () {
var demoRoot = window.location.toString().indexOf('/demos-ts/') > -1 ? 'demos-ts' : 'demos-js'
diff --git a/demos/resources/image/amdloading.png b/demos/resources/image/amdloading.png
deleted file mode 100644
index c65bc2862..000000000
Binary files a/demos/resources/image/amdloading.png and /dev/null differ
diff --git a/demos/resources/image/export-pdf.png b/demos/resources/image/export-pdf.png
deleted file mode 100644
index b13640e38..000000000
Binary files a/demos/resources/image/export-pdf.png and /dev/null differ
diff --git a/demos/resources/image/export-png.png b/demos/resources/image/export-png.png
deleted file mode 100644
index 0459aa320..000000000
Binary files a/demos/resources/image/export-png.png and /dev/null differ
diff --git a/demos/resources/image/export-print.png b/demos/resources/image/export-print.png
deleted file mode 100644
index 335636724..000000000
Binary files a/demos/resources/image/export-print.png and /dev/null differ
diff --git a/demos/resources/image/export-svg.png b/demos/resources/image/export-svg.png
deleted file mode 100644
index 4bba8a698..000000000
Binary files a/demos/resources/image/export-svg.png and /dev/null differ
diff --git a/demos/resources/image/export.png b/demos/resources/image/export.png
deleted file mode 100644
index cb4e3d5f1..000000000
Binary files a/demos/resources/image/export.png and /dev/null differ
diff --git a/demos/resources/image/home-automation.png b/demos/resources/image/home-automation.png
new file mode 100644
index 000000000..cb5d143d0
Binary files /dev/null and b/demos/resources/image/home-automation.png differ
diff --git a/demos/resources/image/imageexport.png b/demos/resources/image/imageexport.png
new file mode 100644
index 000000000..4c672669d
Binary files /dev/null and b/demos/resources/image/imageexport.png differ
diff --git a/demos/resources/image/pdfexport.png b/demos/resources/image/pdfexport.png
new file mode 100644
index 000000000..20fa5a586
Binary files /dev/null and b/demos/resources/image/pdfexport.png differ
diff --git a/demos/resources/image/printing.png b/demos/resources/image/printing.png
index e5f1d16ea..8b3e2a8fc 100644
Binary files a/demos/resources/image/printing.png and b/demos/resources/image/printing.png differ
diff --git a/demos/resources/image/scriptloading.png b/demos/resources/image/scriptloading.png
deleted file mode 100644
index d80ad59e4..000000000
Binary files a/demos/resources/image/scriptloading.png and /dev/null differ
diff --git a/demos/resources/image/svgexport.png b/demos/resources/image/svgexport.png
new file mode 100644
index 000000000..ef696fca8
Binary files /dev/null and b/demos/resources/image/svgexport.png differ
diff --git a/demos/resources/image/webworkerumd.png b/demos/resources/image/webworkerumd.png
deleted file mode 100644
index 84c0f5eb3..000000000
Binary files a/demos/resources/image/webworkerumd.png and /dev/null differ
diff --git a/demos/resources/package.json b/demos/resources/package.json
index 990e3a711..2d7832444 100644
--- a/demos/resources/package.json
+++ b/demos/resources/package.json
@@ -1,6 +1,6 @@
{
"name": "demo-resources-ts",
- "version": "26.0.2",
+ "version": "26.0.3",
"author": "yWorks GmbH ",
"license": "https://www.yworks.com/products/yfiles-for-html/sla",
"private": true,
@@ -12,7 +12,6 @@
"./tutorial.css": "./style/tutorial.css"
},
"dependencies": {
- "yfiles": "^26.0.0 || ^26.0.0-A",
- "yfiles-umd": "^26.0.0 || ^26.0.0-A"
+ "yfiles": "^26.0.0 || ^26.0.0-A"
}
}
diff --git a/demos/resources/readme-demo-data.js b/demos/resources/readme-demo-data.js
index 673feff53..8d2c37ac3 100644
--- a/demos/resources/readme-demo-data.js
+++ b/demos/resources/readme-demo-data.js
@@ -917,6 +917,18 @@ function getDemoData() {
'webgl2'
]
},
+ {
+ id: 'home-automation',
+ name: 'Home Automation',
+ demoPath: 'showcase/home-automation/',
+ summary: 'Demonstrates visual programming of a home automation network.',
+ description: `This demo simulates a tool for visually programming a home automation network. The nodes represent
+ various stages of data flow within the system.`,
+ category: 'showcase',
+ thumbnailPath: 'resources/image/home-automation.png',
+ tags: ['interaction', 'layout', 'drag and drop'],
+ keywords: ['v2.6.0.3', 'validation', 'grid']
+ },
{
id: 'tree-map',
name: 'Tree Map',
@@ -2650,7 +2662,7 @@ function getDemoData() {
demoPath: 'view/imageexport/',
summary: 'Shows how to export the whole diagram or a part of it to a PNG image.',
category: 'view',
- thumbnailPath: 'resources/image/export.png',
+ thumbnailPath: 'resources/image/imageexport.png',
tags: ['export', 'png', 'jpg'],
keywords: ['jpeg', 'bitmap', 'save', 'handles']
},
@@ -2660,7 +2672,7 @@ function getDemoData() {
demoPath: 'view/svgexport/',
summary: 'Shows how to export the whole diagram or a part of it to an SVG image.',
category: 'view',
- thumbnailPath: 'resources/image/export.png',
+ thumbnailPath: 'resources/image/svgexport.png',
tags: ['export', 'svg', 'vector graphics'],
keywords: ['scalable vector graphics', 'save', 'handles', 'curves', 'bezier']
},
@@ -2670,7 +2682,7 @@ function getDemoData() {
demoPath: 'view/pdfexport/',
summary: 'Shows how to export the whole diagram or a part of it to a PDF.',
category: 'view',
- thumbnailPath: 'resources/image/export.png',
+ thumbnailPath: 'resources/image/pdfexport.png',
tags: ['export', 'pdf'],
keywords: ['vector graphics', 'handles']
},
@@ -2680,7 +2692,7 @@ function getDemoData() {
demoPath: 'view/printing/',
summary: 'Shows how to print the whole diagram or a part of it.',
category: 'view',
- thumbnailPath: 'resources/image/export.png',
+ thumbnailPath: 'resources/image/printing.png',
tags: ['printing'],
keywords: ['posters', 'vector graphics', 'handles']
},
@@ -2900,17 +2912,6 @@ function getDemoData() {
thumbnailPath: 'resources/image/web_components.png',
tags: ['web components', 'shadow dom', 'html imports']
},
- {
- id: 'amd-loading',
- name: 'AMD Loading',
- demoPath: 'loading/amdloading/',
- summary: 'Loads the yFiles library modules with the AMD loading standard (require.js).',
- category: 'loading',
- languageType: 'js-only',
- thumbnailPath: 'resources/image/amdloading.png',
- tags: ['loader', 'modules'],
- keywords: ['requirejs', 'require.js', 'non-symbolic']
- },
{
id: 'basic-module-loading',
name: 'Basic Module Loading',
@@ -2933,17 +2934,6 @@ function getDemoData() {
tags: ['deployment', 'optimizer'],
keywords: ['v2.2.0.0', 'web worker', 'modules']
},
- {
- id: 'script-loading',
- name: 'Script Loading',
- demoPath: 'loading/scriptloading/',
- summary: 'Loads the yFiles modules using plain old <script> tags.',
- category: 'loading',
- languageType: 'js-only',
- thumbnailPath: 'resources/image/scriptloading.png',
- tags: ['loader', 'modules'],
- keywords: ['script loading', 'non-symbolic']
- },
{
id: 'web-worker-webpack',
name: 'Web Worker Webpack',
@@ -2976,27 +2966,6 @@ function getDemoData() {
tags: ['modules', 'web worker', 'layout'],
keywords: ['v2.4.0.0', 'threads', 'threading', 'background', 'async', 'modules', 'hierarchic']
},
- {
- id: 'web-worker-umd',
- name: 'Web Worker UMD',
- demoPath: 'loading/webworker-umd/',
- summary: 'Shows how to run a yFiles layout algorithm in a Web Worker task using AMD modules.',
- category: 'loading',
- languageType: 'js-only',
- thumbnailPath: 'resources/image/webworkerumd.png',
- tags: ['umd', 'web worker', 'layout'],
- keywords: [
- 'v2.4.0.0',
- 'threads',
- 'threading',
- 'background',
- 'json',
- 'folding',
- 'hierarchic',
- 'non-symbolic',
- 'umd'
- ]
- },
{
id: 'webpack',
name: 'webpack',
diff --git a/demos/resources/readme-demo-support.js b/demos/resources/readme-demo-support.js
index 3cbfb39ff..086430a8d 100644
--- a/demos/resources/readme-demo-support.js
+++ b/demos/resources/readme-demo-support.js
@@ -26,39 +26,37 @@
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***************************************************************************/
-/* eslint-disable no-var,no-eval */
-;(function () {
- var isTsReadme = location.pathname.includes('demos-ts')
- var isJsReadme = location.pathname.includes('demos-js')
+/* eslint-disable no-eval */
+;(() => {
+ const isTsReadme = location.pathname.includes('demos-ts')
+ const isJsReadme = location.pathname.includes('demos-js')
document.body.className += isTsReadme ? ' ts' : isJsReadme ? ' js' : ''
const demoData = window.getDemoData()
- var categoryNames = window.getCategoryNames()
- var layoutCategories = window.getLayoutCategories()
+ const categoryNames = window.getCategoryNames()
+ const layoutCategories = window.getLayoutCategories()
- var tutorialIds = demoData.filter(item => item.category === 'tutorial').map(item => item.id)
+ const tutorialIds = demoData.filter((item) => item.category === 'tutorial').map((item) => item.id)
- var isViewerPackage = document.title.indexOf('Viewer') > -1
- var isLayoutPackage = document.title.indexOf('Layout') > -1
- var isCompletePackage = !isViewerPackage && !isLayoutPackage
+ const isViewerPackage = document.title.indexOf('Viewer') > -1
+ const isLayoutPackage = document.title.indexOf('Layout') > -1
+ const isCompletePackage = !isViewerPackage && !isLayoutPackage
- var demos = demoData.filter(function (demo) {
- return !demo.hidden
- })
+ const demos = demoData.filter((demo) => !demo.hidden)
const accordionItems = []
if (isTsReadme) {
// Thumbnails are only in /demos-js/ directory
- demos.forEach(function (demo) {
+ demos.forEach((demo) => {
if (demo.thumbnailPath != null) {
demo.thumbnailPath = '../demos-js/' + demo.thumbnailPath
}
})
}
- demos.forEach(function (item) {
+ demos.forEach((item) => {
item.availableInPackage =
isCompletePackage ||
(isViewerPackage &&
@@ -67,16 +65,16 @@
(isLayoutPackage && item.distributionType === 'no-viewer')
})
- var gridItemTemplate = document.querySelector('#grid-item-template')
- var accordionItemTemplate = document.querySelector('#accordion-template')
- var demoHeaderTemplate = document.querySelector('#demo-header-template')
+ const gridItemTemplate = document.querySelector('#grid-item-template')
+ const accordionItemTemplate = document.querySelector('#accordion-template')
+ const demoHeaderTemplate = document.querySelector('#demo-header-template')
function createGridItem(demo, index) {
- var gridItem = document.createElement('div')
+ const gridItem = document.createElement('div')
gridItem.className = 'grid-item'
gridItem.innerHTML = gridItemTemplate.innerHTML.replace(
/{{([^}]+)}}/gi,
- function (match, propertyName) {
+ (match, propertyName) => {
if (propertyName === 'demoPath' && isTsReadme && demo.languageType === 'js-only') {
return '../demos-js/' + demo.demoPath
} else if (propertyName === 'demoPath' && isJsReadme && demo.languageType === 'ts-only') {
@@ -91,10 +89,10 @@
}
)
if (demo.tags) {
- var tagContainer = gridItem.querySelector('.tags')
- demo.tags.forEach(function (tag) {
- var tagItem = document.createElement('span')
- var anchor = document.createElement('a')
+ const tagContainer = gridItem.querySelector('.tags')
+ demo.tags.forEach((tag) => {
+ const tagItem = document.createElement('span')
+ const anchor = document.createElement('a')
anchor.setAttribute('href', '#' + encodeURIComponent(tag))
tagItem.className += ' tag'
anchor.textContent = tag
@@ -103,14 +101,14 @@
})
}
- var languageTypeBadge = createLanguageTypeBatch(demo)
+ const languageTypeBadge = createLanguageTypeBatch(demo)
if (languageTypeBadge != null) {
gridItem.querySelector('.thumbnail').appendChild(languageTypeBadge)
}
if (!demo.availableInPackage) {
gridItem.className += ' not-available'
- var notAvailableNotice = document.createElement('div')
+ const notAvailableNotice = document.createElement('div')
notAvailableNotice.className = 'not-available-notice'
notAvailableNotice.innerHTML = `Requires "${
isViewerPackage ? 'layout' : 'viewer'
@@ -123,10 +121,10 @@
}
function createDemoHeader(category) {
- var tmpDiv = document.createElement('div')
+ const tmpDiv = document.createElement('div')
tmpDiv.innerHTML = demoHeaderTemplate.innerHTML.replace(
/{{([^}]+)}}/gi,
- function (match, propertyName) {
+ (match, propertyName) => {
if (Object.prototype.hasOwnProperty.call(category, propertyName)) {
return category[propertyName]
} else {
@@ -139,10 +137,10 @@
}
function createAccordionItem(category) {
- var tmpDiv = document.createElement('div')
+ const tmpDiv = document.createElement('div')
tmpDiv.innerHTML = accordionItemTemplate.innerHTML.replace(
/{{([^}]+)}}/gi,
- function (match, propertyName) {
+ (match, propertyName) => {
if (Object.prototype.hasOwnProperty.call(category, propertyName)) {
return category[propertyName]
} else {
@@ -151,14 +149,14 @@
}
}
)
- var item = tmpDiv.firstElementChild
- item.querySelector('.accordion-title').addEventListener('click', function () {
+ const item = tmpDiv.firstElementChild
+ item.querySelector('.accordion-title').addEventListener('click', () => {
if (item.classList.contains('expanded')) {
item.classList.remove('expanded')
filterByCategory('')
changeTextContent('')
} else {
- accordionItems.forEach(accordion => accordion.classList.remove('expanded'))
+ accordionItems.forEach((accordion) => accordion.classList.remove('expanded'))
item.classList.add('expanded')
clearSearchBox()
filterByCategory(category.identifier)
@@ -169,17 +167,17 @@
}
function createSidebarItem(demo) {
- var sidebarItem = document.createElement('div')
+ const sidebarItem = document.createElement('div')
sidebarItem.className = 'demo-sidebar-item'
if (!demo.availableInPackage) {
sidebarItem.className += ' not-available'
sidebarItem.className += isViewerPackage ? ' viewer-package' : ' layout-package'
}
- var link = document.createElement('a')
+ const link = document.createElement('a')
link.textContent = demo.name
link.setAttribute('href', demo.demoPath)
- var languageTypeBadge = createLanguageTypeBatch(demo)
+ const languageTypeBadge = createLanguageTypeBatch(demo)
if (languageTypeBadge != null) {
link.appendChild(languageTypeBadge)
if (isTsReadme && demo.languageType === 'js-only')
@@ -203,7 +201,7 @@
) {
return null
}
- var badge = document.createElement('span')
+ const badge = document.createElement('span')
badge.className = 'js-badge'
if (demo.languageType === 'js-only') {
badge.textContent = 'JS'
@@ -216,10 +214,10 @@
}
function insertSortedChild(parent, newChild) {
- var children = parent.querySelectorAll('div')
+ const children = parent.querySelectorAll('div')
parent.appendChild(newChild)
- for (var i = 0; i < children.length; i++) {
- var child = children[i]
+ for (let i = 0; i < children.length; i++) {
+ const child = children[i]
if (child.textContent > newChild.textContent) {
parent.insertBefore(newChild, child)
break
@@ -238,12 +236,10 @@
if (categoryFilter && demo.category !== categoryFilter) {
return 0
}
- var words = needle.split(/[^.\w/]/)
+ const words = needle.split(/[^.\w/]/)
return words
- .map(function (word) {
- return matchWord(demo, word)
- })
- .reduce(function (prev, curr) {
+ .map((word) => matchWord(demo, word))
+ .reduce((prev, curr) => {
if (categoryFilter) {
// when filtering a specific demo category, avoid any priorities, but show demos in the given order
return prev > 0 || curr > 0 ? 1 : 0
@@ -262,23 +258,14 @@
* the value is 0 if the demo doesn't match at all.
*/
function matchWord(demo, word) {
- var regex = new RegExp(word, 'gi')
+ const regex = new RegExp(word, 'gi')
if (regex.test(demo.name)) {
return 100
}
- if (
- demo.tags.some(function (tag) {
- return regex.test(normalize(tag))
- })
- ) {
+ if (demo.tags.some((tag) => regex.test(normalize(tag)))) {
return 50
}
- if (
- demo.keywords &&
- demo.keywords.some(function (keyword) {
- return regex.test(normalize(keyword))
- })
- ) {
+ if (demo.keywords && demo.keywords.some((keyword) => regex.test(normalize(keyword)))) {
return 20
}
if (regex.test(demo.category)) {
@@ -291,26 +278,28 @@
return word.replaceAll(/\s|-/g, '')
}
- var demoGrid = document.getElementById('non-tutorial-grid')
- var tutBasicFeaturesGrid = document.getElementById('tutorial-basic-features-grid')
- var tutCustomNodeStyleGrid = document.getElementById('tutorial-node-style-implementation-grid')
- var tutCustomLabelStyleGrid = document.getElementById('tutorial-label-style-implementation-grid')
- var tutCustomEdgeStyleGrid = document.getElementById('tutorial-edge-style-implementation-grid')
- var tutCustomPortStyleGrid = document.getElementById('tutorial-port-style-implementation-grid')
- var tutGraphBuilderGrid = document.getElementById('tutorial-graph-builder-grid')
- var searchBox = document.querySelector('#search')
- var noSearchResultsElement = document.querySelector('#no-search-results')
- var resetSearchButton = document.querySelector('.reset-search')
- var unAvailableGrid = document.getElementById('unavailable-grid')
- var unAvailableGridHeader = document.getElementById('unavailable-header')
+ const demoGrid = document.getElementById('non-tutorial-grid')
+ const tutBasicFeaturesGrid = document.getElementById('tutorial-basic-features-grid')
+ const tutCustomNodeStyleGrid = document.getElementById('tutorial-node-style-implementation-grid')
+ const tutCustomLabelStyleGrid = document.getElementById(
+ 'tutorial-label-style-implementation-grid'
+ )
+ const tutCustomEdgeStyleGrid = document.getElementById('tutorial-edge-style-implementation-grid')
+ const tutCustomPortStyleGrid = document.getElementById('tutorial-port-style-implementation-grid')
+ const tutGraphBuilderGrid = document.getElementById('tutorial-graph-builder-grid')
+ const searchBox = document.querySelector('#search')
+ const noSearchResultsElement = document.querySelector('#no-search-results')
+ const resetSearchButton = document.querySelector('.reset-search')
+ const unAvailableGrid = document.getElementById('unavailable-grid')
+ const unAvailableGridHeader = document.getElementById('unavailable-header')
if (isViewerPackage || isLayoutPackage) {
unAvailableGrid.style.display = 'block'
unAvailableGridHeader.style.display = 'block'
}
- demos.forEach(function (demo, index) {
- var gridItem = createGridItem(demo, index)
+ demos.forEach((demo, index) => {
+ const gridItem = createGridItem(demo, index)
if (demo.category === 'tutorial-basic-features') {
tutBasicFeaturesGrid.appendChild(gridItem)
} else if (demo.category === 'tutorial-node-style-implementation') {
@@ -329,8 +318,8 @@
demoGrid.appendChild(gridItem)
}
demo.element = gridItem
- var sidebarItem = createSidebarItem(demo)
- var element = document.querySelector('.demo-items-' + demo.category)
+ const sidebarItem = createSidebarItem(demo)
+ let element = document.querySelector('.demo-items-' + demo.category)
if (!element) {
let categoryName = categoryNames[demo.category] || demo.category
if (categoryName.match(/^Tutorial:/)) {
@@ -338,7 +327,7 @@
.replace('Tutorial: ', '
Tutorial: ')
.replace(' Implementation', '')
}
- let accordionItem = createAccordionItem({
+ const accordionItem = createAccordionItem({
title: categoryName,
identifier: demo.category
})
@@ -347,7 +336,7 @@
element = document.querySelector('.demo-items-' + demo.category)
// insert demo-header
if (!demo.category.match(/tutorial-.*/)) {
- let demoHeader = createDemoHeader({
+ const demoHeader = createDemoHeader({
title: categoryName,
identifier: demo.category
})
@@ -362,7 +351,7 @@
searchBox.addEventListener(
'input',
debounce(
- function () {
+ () => {
searchBoxChanged()
updateHash()
},
@@ -371,10 +360,10 @@
)
)
searchBox.addEventListener('click', searchBoxClicked)
- searchBox.addEventListener('blur', function () {
+ searchBox.addEventListener('blur', () => {
searchBox.addEventListener('click', searchBoxClicked)
})
- resetSearchButton.addEventListener('click', function () {
+ resetSearchButton.addEventListener('click', () => {
searchBox.value = ''
})
@@ -394,7 +383,7 @@
// Don't care about IE 9
return
}
- var searchTerm = searchBox.value.trim()
+ const searchTerm = searchBox.value.trim()
history.replaceState({}, '', `#${searchTerm}`)
}
@@ -413,7 +402,7 @@
function showDemoCategoryHeader(categoryName) {
document
.querySelectorAll('.tutorial-header')
- .forEach(element => element.classList.add('hidden'))
+ .forEach((element) => element.classList.add('hidden'))
document.getElementById(categoryName + '-header')?.classList.remove('hidden')
}
@@ -428,20 +417,20 @@
const searchBoxEmpty = searchTerm === ''
// when the search term is a category, use category matching/sorting
- const matchedCategory = Object.keys(categoryNames).find(categoryId => categoryId === searchTerm)
+ const matchedCategory = Object.keys(categoryNames).find(
+ (categoryId) => categoryId === searchTerm
+ )
if (matchedCategory) {
categoryFilter = matchedCategory
searchTerm = ''
}
- const sortedDemos = demos.map(function (demo) {
- return {
- demo: demo,
- prio: matchDemo(demo, searchTerm, categoryFilter)
- }
- })
+ const sortedDemos = demos.map((demo) => ({
+ demo: demo,
+ prio: matchDemo(demo, searchTerm, categoryFilter)
+ }))
- sortedDemos.sort(function (i1, i2) {
+ sortedDemos.sort((i1, i2) => {
if (i1.prio === i2.prio) {
return 0
}
@@ -456,7 +445,7 @@
// The first indexes are reserved for other elements.
let baseTabIndex = 2
- sortedDemos.forEach(function (item, index) {
+ sortedDemos.forEach((item, index) => {
const demo = item.demo
// Reorder the nodes in each grid section
demo.element.parentElement.appendChild(demo.element)
@@ -492,14 +481,14 @@
})
baseTabIndex += sortedDemos.length
- tutorialIds.forEach(function (id) {
+ tutorialIds.forEach((id) => {
const gridElement = document.getElementById(id + '-grid')
if (!gridElement) {
return
}
const children = gridElement.children
let allHidden = true
- for (var i = 0; i < children.length; i++) {
+ for (let i = 0; i < children.length; i++) {
const demoCard = children[i]
if (demoCard.getAttribute('class').indexOf('filtered') === -1) {
allHidden = false
@@ -519,10 +508,10 @@
}
function searchBoxChanged() {
- var searchTerm = searchBox.value.trim()
+ const searchTerm = searchBox.value.trim()
showDemoCategoryHeader('')
- accordionItems.forEach(accordion => accordion.classList.remove('expanded'))
+ accordionItems.forEach((accordion) => accordion.classList.remove('expanded'))
filterDemos(searchTerm, '')
@@ -531,16 +520,16 @@
function getDemosWithDescriptionElement() {
return demoData
- .map(item => item.category)
- .map(category => document.getElementById(category))
- .filter(element => element != null)
+ .map((item) => item.category)
+ .map((category) => document.getElementById(category))
+ .filter((element) => element != null)
}
function changeTextContent(categoryName) {
- getDemosWithDescriptionElement().forEach(element => {
+ getDemosWithDescriptionElement().forEach((element) => {
element.style.display = 'none'
})
- var content = document.getElementById(categoryName)
+ const content = document.getElementById(categoryName)
if (content != null) {
content.style.display = 'block'
}
@@ -554,21 +543,20 @@
* @returns {(function(): void)|*}
*/
function debounce(func, delay, immediate) {
- var timeout
+ let timeout
return function () {
- var context = this,
- args = arguments
- var later = function () {
+ const args = arguments
+ const later = () => {
timeout = null
if (!immediate) {
- func.apply(context, args)
+ func.apply(this, args)
}
}
- var callNow = immediate && !timeout
+ const callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, delay)
if (callNow) {
- func.apply(context, args)
+ func.apply(this, args)
}
}
}
diff --git a/demos/resources/style/demo-option-editor.css b/demos/resources/style/demo-option-editor.css
index 891163926..301a51772 100644
--- a/demos/resources/style/demo-option-editor.css
+++ b/demos/resources/style/demo-option-editor.css
@@ -94,11 +94,15 @@
.option-ui-tab .tab-content {
text-align: center;
- -webkit-transition: opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s,
+ -webkit-transition:
+ opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s,
color 0.1s cubic-bezier(0.4, 0, 1, 1) 0s;
- -moz-transition: opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s,
+ -moz-transition:
+ opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s,
+ color 0.1s cubic-bezier(0.4, 0, 1, 1) 0s;
+ transition:
+ opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s,
color 0.1s cubic-bezier(0.4, 0, 1, 1) 0s;
- transition: opacity 0.1s cubic-bezier(0.4, 0, 1, 1) 0s, color 0.1s cubic-bezier(0.4, 0, 1, 1) 0s;
cursor: default;
pointer-events: none;
-ms-user-select: initial;
@@ -114,9 +118,15 @@
left: 0;
width: 0;
background-color: #efefef;
- -webkit-transition: width 0.15s ease-in-out 0.18s, left 0.15s ease-in-out 0.18s;
- -moz-transition: width 0.15s ease-in-out 0.18s, left 0.15s ease-in-out 0.18s;
- transition: width 0.15s ease-in-out 0.18s, left 0.15s ease-in-out 0.18s;
+ -webkit-transition:
+ width 0.15s ease-in-out 0.18s,
+ left 0.15s ease-in-out 0.18s;
+ -moz-transition:
+ width 0.15s ease-in-out 0.18s,
+ left 0.15s ease-in-out 0.18s;
+ transition:
+ width 0.15s ease-in-out 0.18s,
+ left 0.15s ease-in-out 0.18s;
}
.option-ui-tab:not(.active) .tab-content {
@@ -511,7 +521,8 @@ form.option-ui-spinner div.spinner-container label {
}
.option-ui-form-group .option-ui-button {
- transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ transition:
+ background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
font-family: Tahoma, Verdana, sans-serif;
font-size: 14px;
diff --git a/demos/resources/style/demo.css b/demos/resources/style/demo.css
index e6c278a88..428098d85 100644
--- a/demos/resources/style/demo.css
+++ b/demos/resources/style/demo.css
@@ -1537,33 +1537,57 @@ body.loaded .hide-before-loaded {
visibility: visible;
}
.elevation-1 {
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 1px 3px 0 rgba(0, 0, 0, 0.2),
+ 0 1px 1px 0 rgba(0, 0, 0, 0.14),
+ 0 2px 1px -1px rgba(0, 0, 0, 0.12);
}
/* Floating Buttons */
.elevation-2 {
- box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 1px 5px 0 rgba(0, 0, 0, 0.2),
+ 0 2px 2px 0 rgba(0, 0, 0, 0.14),
+ 0 3px 1px -2px rgba(0, 0, 0, 0.12);
}
.elevation-3 {
- box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 1px 8px 0 rgba(0, 0, 0, 0.2),
+ 0 3px 4px 0 rgba(0, 0, 0, 0.14),
+ 0 3px 3px -2px rgba(0, 0, 0, 0.12);
}
/* header */
.elevation-4 {
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0px 4px 5px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
}
/* Menu, Floating Buttons:hover */
.elevation-8 {
- box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 5px 5px -3px rgba(0, 0, 0, 0.2),
+ 0px 8px 10px 1px rgba(0, 0, 0, 0.14),
+ 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.elevation-12 {
- box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 12px 17px 2px rgba(0, 0, 0, 0.14), 0px 5px 22px 4px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 7px 8px -4px rgba(0, 0, 0, 0.2),
+ 0px 12px 17px 2px rgba(0, 0, 0, 0.14),
+ 0px 5px 22px 4px rgba(0, 0, 0, 0.12);
}
/* Nav Drawer */
.elevation-16 {
- box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0px 16px 24px 2px rgba(0, 0, 0, 0.14), 0px 6px 30px 5px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 8px 10px -5px rgba(0, 0, 0, 0.2),
+ 0px 16px 24px 2px rgba(0, 0, 0, 0.14),
+ 0px 6px 30px 5px rgba(0, 0, 0, 0.12);
}
/* Dialog */
.elevation-24 {
- box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 11px 15px -7px rgba(0, 0, 0, 0.2),
+ 0px 24px 38px 3px rgba(0, 0, 0, 0.14),
+ 0px 9px 46px 8px rgba(0, 0, 0, 0.12);
}
.layer-0 {
z-index: 0;
@@ -1614,7 +1638,9 @@ body {
- otherwise, event coordinates will be wrong if scrolling
is re-enabled later */
display: grid;
- grid-template-columns: clamp(var(--description-min-width), var(--description-width), var(--description-max-width)) 1fr;
+ grid-template-columns:
+ clamp(var(--description-min-width), var(--description-width), var(--description-max-width))
+ 1fr;
grid-template-rows: 60px auto 1fr;
grid-template-areas: 'sidebar header' 'sidebar toolbar' 'sidebar content';
transition: grid-template 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
@@ -1627,7 +1653,7 @@ body.demo-left-hidden {
grid-template-rows: 30px auto 1fr;
}
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
body {
grid-template-columns: 100% 100%;
}
@@ -1665,10 +1691,12 @@ body:not(.loaded) .demo-page__main:after {
top: 0;
left: 0;
z-index: 999;
- background: #fff url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMy42NCAyNS4wMiIgaWQ9InN2ZzUxMDUiPg0KICA8ZyBpZD0ibGF5ZXIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtOTMuODEgLTExMS4xMykiPg0KICAgIDxnIGlkPSJnNTczNiIgdHJhbnNmb3JtPSJtYXRyaXgoLjI2NDU4IDAgMCAuMjY0NTggOTAuNjMgMTA4LjY1KSI+DQogICAgICA8cGF0aCBpZD0icGF0aDU2NTIiIGQ9Ik0xMi4zOSA0Ny4yOWwuMSAxOS4zYTI3Ljc0IDI3Ljc0IDAgMCAwIDEzLjkgMjMuOGwxNi44IDkuNmEyNy4zMiAyNy4zMiAwIDAgMCAyNy41LS4yTDg3LjM5IDkwQTI3LjQ0IDI3LjQ0IDAgMCAwIDEwMSA2Ni4wOWwtLjEtMTkuNEEyNy44NiAyNy44NiAwIDAgMCA4NyAyMi44OWwtMTYuNy05LjVhMjcuMzIgMjcuMzIgMCAwIDAtMjcuNS4ybC0xNi43IDkuOGEyNy41IDI3LjUgMCAwIDAtMTMuNyAyMy45IiBmaWxsPSIjMjQyMjY1Ii8+DQogICAgICA8ZyBpZD0iZzU2NzYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1IDkpIj4NCiAgICAgICAgPGcgaWQ9Imc1Njc0IiB0cmFuc2Zvcm09InJvdGF0ZSg1NCkiPg0KICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY1NCIgZD0iTTY2Ljg5LTIwLjA0bC4xIDQuOGMuMiAyLjQuOCA0LjUgMi4zIDYuNSAxLjMgMS44IDMgMyA1IDRsMi41IDEuNWMyIDEuNSAxLjMgMy4yLTIuMyAxLjJsLTMtMS42YTExLjYgMTEuNiAwIDAgMC0xMC40LS4zbC0zLjkgMi4xYy00IDEtMi41LTEgMS0zLjEgMy0xLjUgNS4xLTQuMSA2LTcuMy40LTEuNS42LTMgLjUtNC42di0zLjdjLS41LTQgMi44LTQgMi4yLjV6IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgPGcgaWQ9Imc1NjYwIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY1OCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46NjdweCAwcHg7YW5pbWF0aW9uLWRlbGF5Oi4xMjVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjU2IiBkPSJNNjUuNjEtMzguMzRjLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2NjYiIHRyYW5zZm9ybT0icm90YXRlKDEyMCA0NS45IDQ4LjcpIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY2NCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46LTE0LjVweCA0OHB4O2FuaW1hdGlvbi1kZWxheTouNDVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjYyIiBkPSJNLTEzLjk4IDMwLjMyYy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjcyIiB0cmFuc2Zvcm09InJvdGF0ZSgtMTIwIDQ1LjkgNDguNykiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjcwIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjo4NnB4IDg5cHg7YW5pbWF0aW9uLWRlbGF5Oi43OXMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2NjgiIGQ9Ik04NC44NSA2NC43NWMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgICA8ZyBpZD0iZzU3MDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkgNikiPg0KICAgICAgICA8ZyBpZD0iZzU2OTgiIHRyYW5zZm9ybT0icm90YXRlKDEwKSI+DQogICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njc4IiBkPSJNNTQuMjMgMjguMzVsLjEgNC44Yy4yIDIuNC44IDQuNSAyLjMgNi41IDEuMyAxLjggMyAzIDUgNGwyLjUgMS41YzIgMS41IDEuMyAzLjItMi4zIDEuMmwtMy0xLjZhMTEuNiAxMS42IDAgMCAwLTEwLjQtLjNsLTMuOSAyLjFjLTQgMS0yLjUtMSAxLTMuMSAzLTEuNSA1LjEtNC4xIDYtNy4zLjQtMS41LjYtMyAuNS00LjZ2LTMuN2MtLjUtNCAyLjgtNCAyLjIuNXoiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICA8ZyBpZD0iZzU2ODQiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjgyIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTNweCAzM3B4OyI+DQogICAgICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY4MCIgZD0iTTUyLjcxIDEwLjA5Yy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjkwIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2ODgiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjM3cHggNTBweDthbmltYXRpb24tZGVsYXk6LjMzMzNzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njg2IiBkPSJNMzQuMzQgMTYuMzljLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2OTYiIHRyYW5zZm9ybT0icm90YXRlKC0xMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2OTQiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjQ5cHggNTNweDthbmltYXRpb24tZGVsYXk6LjY2NnMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2OTIiIGQ9Ik00OS4wMSAyOC45MmMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgPC9nPg0KICA8L2c+DQogIDxzdHlsZSBpZD0ic3R5bGU1NjUwIj4NCiAgICBAa2V5ZnJhbWVzIHdvYmJsZSB7DQogICAgMCUsDQogICAgMzMlLA0KICAgIHRvIHsNCiAgICB0cmFuc2Zvcm06IHNjYWxlKDEpOw0KICAgIH0NCiAgICA1MCUgew0KICAgIHRyYW5zZm9ybTogc2NhbGUoMC45NSk7DQogICAgfQ0KICAgIDY2JSB7DQogICAgdHJhbnNmb3JtOiBzY2FsZSgxLjE1KTsNCiAgICB9DQogICAgfQ0KICAgIC53b2JibGUgew0KICAgIGFuaW1hdGlvbjogd29iYmxlIDFzIGVhc2UtaW4tb3V0IGluZmluaXRlOw0KICAgIHRyYW5zZm9ybS1vcmlnaW46IDUyLjNweCAzNC40NXB4Ow0KICAgIH0NCiAgPC9zdHlsZT4NCjwvc3ZnPg==) no-repeat center;
+ background: #fff
+ url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMy42NCAyNS4wMiIgaWQ9InN2ZzUxMDUiPg0KICA8ZyBpZD0ibGF5ZXIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtOTMuODEgLTExMS4xMykiPg0KICAgIDxnIGlkPSJnNTczNiIgdHJhbnNmb3JtPSJtYXRyaXgoLjI2NDU4IDAgMCAuMjY0NTggOTAuNjMgMTA4LjY1KSI+DQogICAgICA8cGF0aCBpZD0icGF0aDU2NTIiIGQ9Ik0xMi4zOSA0Ny4yOWwuMSAxOS4zYTI3Ljc0IDI3Ljc0IDAgMCAwIDEzLjkgMjMuOGwxNi44IDkuNmEyNy4zMiAyNy4zMiAwIDAgMCAyNy41LS4yTDg3LjM5IDkwQTI3LjQ0IDI3LjQ0IDAgMCAwIDEwMSA2Ni4wOWwtLjEtMTkuNEEyNy44NiAyNy44NiAwIDAgMCA4NyAyMi44OWwtMTYuNy05LjVhMjcuMzIgMjcuMzIgMCAwIDAtMjcuNS4ybC0xNi43IDkuOGEyNy41IDI3LjUgMCAwIDAtMTMuNyAyMy45IiBmaWxsPSIjMjQyMjY1Ii8+DQogICAgICA8ZyBpZD0iZzU2NzYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1IDkpIj4NCiAgICAgICAgPGcgaWQ9Imc1Njc0IiB0cmFuc2Zvcm09InJvdGF0ZSg1NCkiPg0KICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY1NCIgZD0iTTY2Ljg5LTIwLjA0bC4xIDQuOGMuMiAyLjQuOCA0LjUgMi4zIDYuNSAxLjMgMS44IDMgMyA1IDRsMi41IDEuNWMyIDEuNSAxLjMgMy4yLTIuMyAxLjJsLTMtMS42YTExLjYgMTEuNiAwIDAgMC0xMC40LS4zbC0zLjkgMi4xYy00IDEtMi41LTEgMS0zLjEgMy0xLjUgNS4xLTQuMSA2LTcuMy40LTEuNS42LTMgLjUtNC42di0zLjdjLS41LTQgMi44LTQgMi4yLjV6IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgPGcgaWQ9Imc1NjYwIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY1OCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46NjdweCAwcHg7YW5pbWF0aW9uLWRlbGF5Oi4xMjVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjU2IiBkPSJNNjUuNjEtMzguMzRjLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2NjYiIHRyYW5zZm9ybT0icm90YXRlKDEyMCA0NS45IDQ4LjcpIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY2NCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46LTE0LjVweCA0OHB4O2FuaW1hdGlvbi1kZWxheTouNDVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjYyIiBkPSJNLTEzLjk4IDMwLjMyYy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjcyIiB0cmFuc2Zvcm09InJvdGF0ZSgtMTIwIDQ1LjkgNDguNykiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjcwIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjo4NnB4IDg5cHg7YW5pbWF0aW9uLWRlbGF5Oi43OXMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2NjgiIGQ9Ik04NC44NSA2NC43NWMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgICA8ZyBpZD0iZzU3MDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkgNikiPg0KICAgICAgICA8ZyBpZD0iZzU2OTgiIHRyYW5zZm9ybT0icm90YXRlKDEwKSI+DQogICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njc4IiBkPSJNNTQuMjMgMjguMzVsLjEgNC44Yy4yIDIuNC44IDQuNSAyLjMgNi41IDEuMyAxLjggMyAzIDUgNGwyLjUgMS41YzIgMS41IDEuMyAzLjItMi4zIDEuMmwtMy0xLjZhMTEuNiAxMS42IDAgMCAwLTEwLjQtLjNsLTMuOSAyLjFjLTQgMS0yLjUtMSAxLTMuMSAzLTEuNSA1LjEtNC4xIDYtNy4zLjQtMS41LjYtMyAuNS00LjZ2LTMuN2MtLjUtNCAyLjgtNCAyLjIuNXoiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICA8ZyBpZD0iZzU2ODQiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjgyIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTNweCAzM3B4OyI+DQogICAgICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY4MCIgZD0iTTUyLjcxIDEwLjA5Yy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjkwIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2ODgiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjM3cHggNTBweDthbmltYXRpb24tZGVsYXk6LjMzMzNzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njg2IiBkPSJNMzQuMzQgMTYuMzljLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2OTYiIHRyYW5zZm9ybT0icm90YXRlKC0xMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2OTQiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjQ5cHggNTNweDthbmltYXRpb24tZGVsYXk6LjY2NnMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2OTIiIGQ9Ik00OS4wMSAyOC45MmMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgPC9nPg0KICA8L2c+DQogIDxzdHlsZSBpZD0ic3R5bGU1NjUwIj4NCiAgICBAa2V5ZnJhbWVzIHdvYmJsZSB7DQogICAgMCUsDQogICAgMzMlLA0KICAgIHRvIHsNCiAgICB0cmFuc2Zvcm06IHNjYWxlKDEpOw0KICAgIH0NCiAgICA1MCUgew0KICAgIHRyYW5zZm9ybTogc2NhbGUoMC45NSk7DQogICAgfQ0KICAgIDY2JSB7DQogICAgdHJhbnNmb3JtOiBzY2FsZSgxLjE1KTsNCiAgICB9DQogICAgfQ0KICAgIC53b2JibGUgew0KICAgIGFuaW1hdGlvbjogd29iYmxlIDFzIGVhc2UtaW4tb3V0IGluZmluaXRlOw0KICAgIHRyYW5zZm9ybS1vcmlnaW46IDUyLjNweCAzNC40NXB4Ow0KICAgIH0NCiAgPC9zdHlsZT4NCjwvc3ZnPg==)
+ no-repeat center;
background-size: 200px;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-page__main {
min-width: 100vw;
}
@@ -1688,7 +1716,10 @@ body:not(.loaded) .demo-page__main:after {
font-family: Tahoma, Verdana, sans-serif;
font-size: 14px;
letter-spacing: 1px;
- transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ transition:
+ background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.flat-button.secondary {
border: thin solid #4caf50;
@@ -1710,11 +1741,14 @@ body:not(.loaded) .demo-page__main:after {
height: 230px;
background: #f7f7f7;
overflow: hidden;
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0px 4px 5px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
z-index: 4;
transition: height 1s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-overlay {
visibility: hidden;
}
@@ -1866,7 +1900,9 @@ body:not(.loaded) .demo-page__main:after {
bottom: 0;
right: 0;
width: 320px;
- font: 20px Tahoma, sans-serif;
+ font:
+ 20px Tahoma,
+ sans-serif;
padding: 1em;
box-sizing: border-box;
}
@@ -2070,7 +2106,7 @@ rect:not(.yfiles-node-highlight-inner-template):not(.yfiles-node-highlight-middl
width: 60px;
height: 60px;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-header__right > * {
margin: 0 5px;
width: 30px;
@@ -2273,7 +2309,7 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-page__toolbar .demo-toggle-button:checked:active + label {
background-color: #b2b2b2;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-page__toolbar button.demo-unimportant {
display: none;
}
@@ -2308,7 +2344,9 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-page__toolbar .overflow-button {
position: absolute;
right: 4px;
- background: #ebeef0 url("data:image/svg+xml,%3Csvg fill='%23666' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E") no-repeat center 4px;
+ background: #ebeef0
+ url("data:image/svg+xml,%3Csvg fill='%23666' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E")
+ no-repeat center 4px;
}
.demo-page__toolbar .overflow-button.hidden {
display: none;
@@ -2327,7 +2365,10 @@ body:not(.loaded) .demo-page__toolbar:after {
right: 0;
width: 200px;
background-color: #f7f7f7;
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0px 4px 5px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
visibility: collapse;
z-index: 1000;
}
@@ -2372,26 +2413,54 @@ body:not(.loaded) .demo-page__toolbar:after {
line-height: 24px;
}
}
-.demo-page__toolbar .overflow-container__content > *:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > button:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > label:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button + label:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button.labeled + label:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > button.labeled:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > *:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > button:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > label:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button
+ + label:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button.labeled
+ + label:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > button.labeled:not(.labeled)[class^='demo-icon-'][title]::after,
.demo-page__toolbar .overflow-container__content > *:not(.labeled)[data-command][title]::after,
.demo-page__toolbar .overflow-container__content > button:not(.labeled)[data-command][title]::after,
.demo-page__toolbar .overflow-container__content > label:not(.labeled)[data-command][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button + label:not(.labeled)[data-command][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button.labeled + label:not(.labeled)[data-command][title]::after,
-.demo-page__toolbar .overflow-container__content > button.labeled:not(.labeled)[data-command][title]::after {
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button
+ + label:not(.labeled)[data-command][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button.labeled
+ + label:not(.labeled)[data-command][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > button.labeled:not(.labeled)[data-command][title]::after {
content: attr(title);
display: block;
}
.demo-page__toolbar .overflow-container__content > *:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > button:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > label:not(.labeled)[title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button + label:not(.labeled)[title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button.labeled + label:not(.labeled)[title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button
+ + label:not(.labeled)[title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button.labeled
+ + label:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > button.labeled:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > *.labeled,
.demo-page__toolbar .overflow-container__content > button.labeled,
@@ -2422,7 +2491,10 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-page__toolbar .overflow-container__content input[type='checkbox']:focus {
outline: none;
}
-.demo-page__toolbar .overflow-container__content input[type='checkbox'].demo-toggle-button.labeled + label {
+.demo-page__toolbar
+ .overflow-container__content
+ input[type='checkbox'].demo-toggle-button.labeled
+ + label {
padding-left: 45px !important;
line-height: 32px;
white-space: nowrap;
@@ -2431,7 +2503,10 @@ body:not(.loaded) .demo-page__toolbar:after {
text-align: left;
}
@media screen and (max-height: 500px) {
- .demo-page__toolbar .overflow-container__content input[type='checkbox'].demo-toggle-button.labeled + label {
+ .demo-page__toolbar
+ .overflow-container__content
+ input[type='checkbox'].demo-toggle-button.labeled
+ + label {
line-height: 24px;
}
}
@@ -2461,11 +2536,15 @@ body:not(.loaded) .demo-page__toolbar:after {
height: 100%;
width: 100%;
line-height: 140%;
- min-width: clamp(var(--description-min-width), var(--description-width), var(--description-max-width));
+ min-width: clamp(
+ var(--description-min-width),
+ var(--description-width),
+ var(--description-max-width)
+ );
background-color: var(--description-color);
z-index: 16;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-page__description {
--description-width: 100vw;
}
@@ -2556,14 +2635,15 @@ body:not(.loaded) .demo-page__toolbar:after {
right: 0;
top: 0;
cursor: pointer;
- background: url("data:image/svg+xml,%3Csvg fill='%23343f4a' height='24' viewBox='2 2 20 20' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 7h10v10H7z' fill='%2300d8ff'/%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z'/%3E%3C/svg%3E") no-repeat calc(100% - 15px);
+ background: url("data:image/svg+xml,%3Csvg fill='%23343f4a' height='24' viewBox='2 2 20 20' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 7h10v10H7z' fill='%2300d8ff'/%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z'/%3E%3C/svg%3E")
+ no-repeat calc(100% - 15px);
background-size: 35px;
font-size: 1.1rem;
line-height: 60px;
text-align: right;
padding-right: 60px;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-description__play-button {
display: block;
}
@@ -2597,7 +2677,7 @@ body:not(.loaded) .demo-page__toolbar:after {
top: 50%;
line-height: 7px;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-description__drag-area--vertical {
display: none;
}
@@ -2613,7 +2693,7 @@ body:not(.loaded) .demo-page__toolbar:after {
top: 0;
line-height: 9px;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-description__drag-area--horizontal {
display: block;
}
@@ -2625,7 +2705,7 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-description--draggable .demo-description__play-button {
display: none;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-description--draggable {
border-right: none;
border-top: 9px solid #d5d7d8;
@@ -2656,7 +2736,9 @@ body:not(.loaded) .demo-page__toolbar:after {
line-height: 140%;
width: var(--sidebar-width);
border-left: 1px solid #d5d7d8;
- transition: width 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, padding-left 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ width 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ padding-left 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-main__sidebar--hidden {
padding-left: 24px;
@@ -2696,7 +2778,10 @@ body:not(.loaded) .demo-page__toolbar:after {
background-image: url('../icons/single-arrow-right.svg');
background-size: 8px;
background-repeat: no-repeat;
- transition: top 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, background-color 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ top 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ background-color 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-sidebar__toggle__button:hover {
background-color: #dedede;
@@ -2738,7 +2823,9 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-main__sidebar--hidden .demo-sidebar__toggle__title {
opacity: 1;
transform: translateX(0);
- transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0.1s, opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0.1s,
+ opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-properties__settings fieldset {
border: 1px solid #888;
diff --git a/demos/resources/style/tutorial.css b/demos/resources/style/tutorial.css
index 50ab37fd0..67098694b 100644
--- a/demos/resources/style/tutorial.css
+++ b/demos/resources/style/tutorial.css
@@ -1537,33 +1537,57 @@ body.loaded .hide-before-loaded {
visibility: visible;
}
.elevation-1 {
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 1px 3px 0 rgba(0, 0, 0, 0.2),
+ 0 1px 1px 0 rgba(0, 0, 0, 0.14),
+ 0 2px 1px -1px rgba(0, 0, 0, 0.12);
}
/* Floating Buttons */
.elevation-2 {
- box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 1px 5px 0 rgba(0, 0, 0, 0.2),
+ 0 2px 2px 0 rgba(0, 0, 0, 0.14),
+ 0 3px 1px -2px rgba(0, 0, 0, 0.12);
}
.elevation-3 {
- box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 1px 8px 0 rgba(0, 0, 0, 0.2),
+ 0 3px 4px 0 rgba(0, 0, 0, 0.14),
+ 0 3px 3px -2px rgba(0, 0, 0, 0.12);
}
/* header */
.elevation-4 {
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0px 4px 5px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
}
/* Menu, Floating Buttons:hover */
.elevation-8 {
- box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 5px 5px -3px rgba(0, 0, 0, 0.2),
+ 0px 8px 10px 1px rgba(0, 0, 0, 0.14),
+ 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.elevation-12 {
- box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 12px 17px 2px rgba(0, 0, 0, 0.14), 0px 5px 22px 4px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 7px 8px -4px rgba(0, 0, 0, 0.2),
+ 0px 12px 17px 2px rgba(0, 0, 0, 0.14),
+ 0px 5px 22px 4px rgba(0, 0, 0, 0.12);
}
/* Nav Drawer */
.elevation-16 {
- box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0px 16px 24px 2px rgba(0, 0, 0, 0.14), 0px 6px 30px 5px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 8px 10px -5px rgba(0, 0, 0, 0.2),
+ 0px 16px 24px 2px rgba(0, 0, 0, 0.14),
+ 0px 6px 30px 5px rgba(0, 0, 0, 0.12);
}
/* Dialog */
.elevation-24 {
- box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 11px 15px -7px rgba(0, 0, 0, 0.2),
+ 0px 24px 38px 3px rgba(0, 0, 0, 0.14),
+ 0px 9px 46px 8px rgba(0, 0, 0, 0.12);
}
.layer-0 {
z-index: 0;
@@ -1614,7 +1638,9 @@ body {
- otherwise, event coordinates will be wrong if scrolling
is re-enabled later */
display: grid;
- grid-template-columns: clamp(var(--description-min-width), var(--description-width), var(--description-max-width)) 1fr;
+ grid-template-columns:
+ clamp(var(--description-min-width), var(--description-width), var(--description-max-width))
+ 1fr;
grid-template-rows: 60px auto 1fr;
grid-template-areas: 'sidebar header' 'sidebar toolbar' 'sidebar content';
transition: grid-template 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
@@ -1627,7 +1653,7 @@ body.demo-left-hidden {
grid-template-rows: 30px auto 1fr;
}
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
body {
grid-template-columns: 100% 100%;
}
@@ -1665,10 +1691,12 @@ body:not(.loaded) .demo-page__main:after {
top: 0;
left: 0;
z-index: 999;
- background: #fff url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMy42NCAyNS4wMiIgaWQ9InN2ZzUxMDUiPg0KICA8ZyBpZD0ibGF5ZXIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtOTMuODEgLTExMS4xMykiPg0KICAgIDxnIGlkPSJnNTczNiIgdHJhbnNmb3JtPSJtYXRyaXgoLjI2NDU4IDAgMCAuMjY0NTggOTAuNjMgMTA4LjY1KSI+DQogICAgICA8cGF0aCBpZD0icGF0aDU2NTIiIGQ9Ik0xMi4zOSA0Ny4yOWwuMSAxOS4zYTI3Ljc0IDI3Ljc0IDAgMCAwIDEzLjkgMjMuOGwxNi44IDkuNmEyNy4zMiAyNy4zMiAwIDAgMCAyNy41LS4yTDg3LjM5IDkwQTI3LjQ0IDI3LjQ0IDAgMCAwIDEwMSA2Ni4wOWwtLjEtMTkuNEEyNy44NiAyNy44NiAwIDAgMCA4NyAyMi44OWwtMTYuNy05LjVhMjcuMzIgMjcuMzIgMCAwIDAtMjcuNS4ybC0xNi43IDkuOGEyNy41IDI3LjUgMCAwIDAtMTMuNyAyMy45IiBmaWxsPSIjMjQyMjY1Ii8+DQogICAgICA8ZyBpZD0iZzU2NzYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1IDkpIj4NCiAgICAgICAgPGcgaWQ9Imc1Njc0IiB0cmFuc2Zvcm09InJvdGF0ZSg1NCkiPg0KICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY1NCIgZD0iTTY2Ljg5LTIwLjA0bC4xIDQuOGMuMiAyLjQuOCA0LjUgMi4zIDYuNSAxLjMgMS44IDMgMyA1IDRsMi41IDEuNWMyIDEuNSAxLjMgMy4yLTIuMyAxLjJsLTMtMS42YTExLjYgMTEuNiAwIDAgMC0xMC40LS4zbC0zLjkgMi4xYy00IDEtMi41LTEgMS0zLjEgMy0xLjUgNS4xLTQuMSA2LTcuMy40LTEuNS42LTMgLjUtNC42di0zLjdjLS41LTQgMi44LTQgMi4yLjV6IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgPGcgaWQ9Imc1NjYwIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY1OCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46NjdweCAwcHg7YW5pbWF0aW9uLWRlbGF5Oi4xMjVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjU2IiBkPSJNNjUuNjEtMzguMzRjLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2NjYiIHRyYW5zZm9ybT0icm90YXRlKDEyMCA0NS45IDQ4LjcpIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY2NCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46LTE0LjVweCA0OHB4O2FuaW1hdGlvbi1kZWxheTouNDVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjYyIiBkPSJNLTEzLjk4IDMwLjMyYy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjcyIiB0cmFuc2Zvcm09InJvdGF0ZSgtMTIwIDQ1LjkgNDguNykiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjcwIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjo4NnB4IDg5cHg7YW5pbWF0aW9uLWRlbGF5Oi43OXMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2NjgiIGQ9Ik04NC44NSA2NC43NWMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgICA8ZyBpZD0iZzU3MDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkgNikiPg0KICAgICAgICA8ZyBpZD0iZzU2OTgiIHRyYW5zZm9ybT0icm90YXRlKDEwKSI+DQogICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njc4IiBkPSJNNTQuMjMgMjguMzVsLjEgNC44Yy4yIDIuNC44IDQuNSAyLjMgNi41IDEuMyAxLjggMyAzIDUgNGwyLjUgMS41YzIgMS41IDEuMyAzLjItMi4zIDEuMmwtMy0xLjZhMTEuNiAxMS42IDAgMCAwLTEwLjQtLjNsLTMuOSAyLjFjLTQgMS0yLjUtMSAxLTMuMSAzLTEuNSA1LjEtNC4xIDYtNy4zLjQtMS41LjYtMyAuNS00LjZ2LTMuN2MtLjUtNCAyLjgtNCAyLjIuNXoiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICA8ZyBpZD0iZzU2ODQiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjgyIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTNweCAzM3B4OyI+DQogICAgICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY4MCIgZD0iTTUyLjcxIDEwLjA5Yy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjkwIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2ODgiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjM3cHggNTBweDthbmltYXRpb24tZGVsYXk6LjMzMzNzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njg2IiBkPSJNMzQuMzQgMTYuMzljLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2OTYiIHRyYW5zZm9ybT0icm90YXRlKC0xMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2OTQiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjQ5cHggNTNweDthbmltYXRpb24tZGVsYXk6LjY2NnMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2OTIiIGQ9Ik00OS4wMSAyOC45MmMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgPC9nPg0KICA8L2c+DQogIDxzdHlsZSBpZD0ic3R5bGU1NjUwIj4NCiAgICBAa2V5ZnJhbWVzIHdvYmJsZSB7DQogICAgMCUsDQogICAgMzMlLA0KICAgIHRvIHsNCiAgICB0cmFuc2Zvcm06IHNjYWxlKDEpOw0KICAgIH0NCiAgICA1MCUgew0KICAgIHRyYW5zZm9ybTogc2NhbGUoMC45NSk7DQogICAgfQ0KICAgIDY2JSB7DQogICAgdHJhbnNmb3JtOiBzY2FsZSgxLjE1KTsNCiAgICB9DQogICAgfQ0KICAgIC53b2JibGUgew0KICAgIGFuaW1hdGlvbjogd29iYmxlIDFzIGVhc2UtaW4tb3V0IGluZmluaXRlOw0KICAgIHRyYW5zZm9ybS1vcmlnaW46IDUyLjNweCAzNC40NXB4Ow0KICAgIH0NCiAgPC9zdHlsZT4NCjwvc3ZnPg==) no-repeat center;
+ background: #fff
+ url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMy42NCAyNS4wMiIgaWQ9InN2ZzUxMDUiPg0KICA8ZyBpZD0ibGF5ZXIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtOTMuODEgLTExMS4xMykiPg0KICAgIDxnIGlkPSJnNTczNiIgdHJhbnNmb3JtPSJtYXRyaXgoLjI2NDU4IDAgMCAuMjY0NTggOTAuNjMgMTA4LjY1KSI+DQogICAgICA8cGF0aCBpZD0icGF0aDU2NTIiIGQ9Ik0xMi4zOSA0Ny4yOWwuMSAxOS4zYTI3Ljc0IDI3Ljc0IDAgMCAwIDEzLjkgMjMuOGwxNi44IDkuNmEyNy4zMiAyNy4zMiAwIDAgMCAyNy41LS4yTDg3LjM5IDkwQTI3LjQ0IDI3LjQ0IDAgMCAwIDEwMSA2Ni4wOWwtLjEtMTkuNEEyNy44NiAyNy44NiAwIDAgMCA4NyAyMi44OWwtMTYuNy05LjVhMjcuMzIgMjcuMzIgMCAwIDAtMjcuNS4ybC0xNi43IDkuOGEyNy41IDI3LjUgMCAwIDAtMTMuNyAyMy45IiBmaWxsPSIjMjQyMjY1Ii8+DQogICAgICA8ZyBpZD0iZzU2NzYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE1IDkpIj4NCiAgICAgICAgPGcgaWQ9Imc1Njc0IiB0cmFuc2Zvcm09InJvdGF0ZSg1NCkiPg0KICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY1NCIgZD0iTTY2Ljg5LTIwLjA0bC4xIDQuOGMuMiAyLjQuOCA0LjUgMi4zIDYuNSAxLjMgMS44IDMgMyA1IDRsMi41IDEuNWMyIDEuNSAxLjMgMy4yLTIuMyAxLjJsLTMtMS42YTExLjYgMTEuNiAwIDAgMC0xMC40LS4zbC0zLjkgMi4xYy00IDEtMi41LTEgMS0zLjEgMy0xLjUgNS4xLTQuMSA2LTcuMy40LTEuNS42LTMgLjUtNC42di0zLjdjLS41LTQgMi44LTQgMi4yLjV6IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgPGcgaWQ9Imc1NjYwIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY1OCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46NjdweCAwcHg7YW5pbWF0aW9uLWRlbGF5Oi4xMjVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjU2IiBkPSJNNjUuNjEtMzguMzRjLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2NjYiIHRyYW5zZm9ybT0icm90YXRlKDEyMCA0NS45IDQ4LjcpIj4NCiAgICAgICAgICAgIDxnIGlkPSJnNTY2NCIgY2xhc3M9IndvYmJsZSIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46LTE0LjVweCA0OHB4O2FuaW1hdGlvbi1kZWxheTouNDVzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1NjYyIiBkPSJNLTEzLjk4IDMwLjMyYy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjcyIiB0cmFuc2Zvcm09InJvdGF0ZSgtMTIwIDQ1LjkgNDguNykiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjcwIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjo4NnB4IDg5cHg7YW5pbWF0aW9uLWRlbGF5Oi43OXMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2NjgiIGQ9Ik04NC44NSA2NC43NWMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgICA8ZyBpZD0iZzU3MDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkgNikiPg0KICAgICAgICA8ZyBpZD0iZzU2OTgiIHRyYW5zZm9ybT0icm90YXRlKDEwKSI+DQogICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njc4IiBkPSJNNTQuMjMgMjguMzVsLjEgNC44Yy4yIDIuNC44IDQuNSAyLjMgNi41IDEuMyAxLjggMyAzIDUgNGwyLjUgMS41YzIgMS41IDEuMyAzLjItMi4zIDEuMmwtMy0xLjZhMTEuNiAxMS42IDAgMCAwLTEwLjQtLjNsLTMuOSAyLjFjLTQgMS0yLjUtMSAxLTMuMSAzLTEuNSA1LjEtNC4xIDYtNy4zLjQtMS41LjYtMyAuNS00LjZ2LTMuN2MtLjUtNCAyLjgtNCAyLjIuNXoiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICA8ZyBpZD0iZzU2ODQiPg0KICAgICAgICAgICAgPGcgaWQ9Imc1NjgyIiBjbGFzcz0id29iYmxlIiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTNweCAzM3B4OyI+DQogICAgICAgICAgICAgIDxwYXRoIGlkPSJwYXRoNTY4MCIgZD0iTTUyLjcxIDEwLjA5Yy0xLjMgMC0yLjUuNi0zLjUgMS41YTYgNiAwIDAgMC0xLjYgNi4zYy40IDEuMiAxIDIuMyAxLjggMy40bDEuMiAyLjJjLjggMS42IDEuMiAzLjMgMS40IDV2My4xYzAgMS0uMyA0LjkgMSA0LjkgMS40IDAgMS4zLTMuOCAxLjItNC45di0yLjZjMC0xLjYuNC0zLjIgMS00LjcuNS0xLjIgMS4yLTIuMyAxLjgtMy40LjctMS4yIDEuNC0yLjUgMS42LTMuOWE2IDYgMCAwIDAtMS43LTUuNCA1LjYgNS42IDAgMCAwLTQuMi0xLjUiIGZpbGw9IiMwMGQ4ZmYiLz4NCiAgICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8L2c+DQogICAgICAgICAgPGcgaWQ9Imc1NjkwIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2ODgiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjM3cHggNTBweDthbmltYXRpb24tZGVsYXk6LjMzMzNzIj4NCiAgICAgICAgICAgICAgPHBhdGggaWQ9InBhdGg1Njg2IiBkPSJNMzQuMzQgMTYuMzljLTEuMyAwLTIuNS42LTMuNSAxLjVhNiA2IDAgMCAwLTEuNiA2LjNjLjQgMS4yIDEgMi4zIDEuOCAzLjRsMS4yIDIuMmMuOCAxLjYgMS4yIDMuMyAxLjQgNXYzLjFjMCAxLS4zIDQuOSAxIDQuOSAxLjQgMCAxLjMtMy44IDEuMi00Ljl2LTIuNmMwLTEuNi40LTMuMiAxLTQuNy41LTEuMiAxLjItMi4zIDEuOC0zLjQuNy0xLjIgMS40LTIuNSAxLjYtMy45YTYgNiAwIDAgMC0xLjctNS40IDUuNiA1LjYgMCAwIDAtNC4yLTEuNSIgZmlsbD0iIzAwZDhmZiIvPg0KICAgICAgICAgICAgPC9nPg0KICAgICAgICAgIDwvZz4NCiAgICAgICAgICA8ZyBpZD0iZzU2OTYiIHRyYW5zZm9ybT0icm90YXRlKC0xMjAgNDUuOSA0OC43KSI+DQogICAgICAgICAgICA8ZyBpZD0iZzU2OTQiIGNsYXNzPSJ3b2JibGUiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOjQ5cHggNTNweDthbmltYXRpb24tZGVsYXk6LjY2NnMiPg0KICAgICAgICAgICAgICA8cGF0aCBpZD0icGF0aDU2OTIiIGQ9Ik00OS4wMSAyOC45MmMtMS4zIDAtMi41LjYtMy41IDEuNWE2IDYgMCAwIDAtMS42IDYuM2MuNCAxLjIgMSAyLjMgMS44IDMuNGwxLjIgMi4yYy44IDEuNiAxLjIgMy4zIDEuNCA1djMuMWMwIDEtLjMgNC45IDEgNC45IDEuNCAwIDEuMy0zLjggMS4yLTQuOXYtMi42YzAtMS42LjQtMy4yIDEtNC43LjUtMS4yIDEuMi0yLjMgMS44LTMuNC43LTEuMiAxLjQtMi41IDEuNi0zLjlhNiA2IDAgMCAwLTEuNy01LjQgNS42IDUuNiAwIDAgMC00LjItMS41IiBmaWxsPSIjMDBkOGZmIi8+DQogICAgICAgICAgICA8L2c+DQogICAgICAgICAgPC9nPg0KICAgICAgICA8L2c+DQogICAgICA8L2c+DQogICAgPC9nPg0KICA8L2c+DQogIDxzdHlsZSBpZD0ic3R5bGU1NjUwIj4NCiAgICBAa2V5ZnJhbWVzIHdvYmJsZSB7DQogICAgMCUsDQogICAgMzMlLA0KICAgIHRvIHsNCiAgICB0cmFuc2Zvcm06IHNjYWxlKDEpOw0KICAgIH0NCiAgICA1MCUgew0KICAgIHRyYW5zZm9ybTogc2NhbGUoMC45NSk7DQogICAgfQ0KICAgIDY2JSB7DQogICAgdHJhbnNmb3JtOiBzY2FsZSgxLjE1KTsNCiAgICB9DQogICAgfQ0KICAgIC53b2JibGUgew0KICAgIGFuaW1hdGlvbjogd29iYmxlIDFzIGVhc2UtaW4tb3V0IGluZmluaXRlOw0KICAgIHRyYW5zZm9ybS1vcmlnaW46IDUyLjNweCAzNC40NXB4Ow0KICAgIH0NCiAgPC9zdHlsZT4NCjwvc3ZnPg==)
+ no-repeat center;
background-size: 200px;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-page__main {
min-width: 100vw;
}
@@ -1688,7 +1716,10 @@ body:not(.loaded) .demo-page__main:after {
font-family: Tahoma, Verdana, sans-serif;
font-size: 14px;
letter-spacing: 1px;
- transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ transition:
+ background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.flat-button.secondary {
border: thin solid #4caf50;
@@ -1710,11 +1741,14 @@ body:not(.loaded) .demo-page__main:after {
height: 230px;
background: #f7f7f7;
overflow: hidden;
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0px 4px 5px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
z-index: 4;
transition: height 1s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-overlay {
visibility: hidden;
}
@@ -1866,7 +1900,9 @@ body:not(.loaded) .demo-page__main:after {
bottom: 0;
right: 0;
width: 320px;
- font: 20px Tahoma, sans-serif;
+ font:
+ 20px Tahoma,
+ sans-serif;
padding: 1em;
box-sizing: border-box;
}
@@ -2070,7 +2106,7 @@ rect:not(.yfiles-node-highlight-inner-template):not(.yfiles-node-highlight-middl
width: 60px;
height: 60px;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-header__right > * {
margin: 0 5px;
width: 30px;
@@ -2273,7 +2309,7 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-page__toolbar .demo-toggle-button:checked:active + label {
background-color: #b2b2b2;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-page__toolbar button.demo-unimportant {
display: none;
}
@@ -2308,7 +2344,9 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-page__toolbar .overflow-button {
position: absolute;
right: 4px;
- background: #ebeef0 url("data:image/svg+xml,%3Csvg fill='%23666' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E") no-repeat center 4px;
+ background: #ebeef0
+ url("data:image/svg+xml,%3Csvg fill='%23666' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E")
+ no-repeat center 4px;
}
.demo-page__toolbar .overflow-button.hidden {
display: none;
@@ -2327,7 +2365,10 @@ body:not(.loaded) .demo-page__toolbar:after {
right: 0;
width: 200px;
background-color: #f7f7f7;
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0px 4px 5px 0px rgba(0, 0, 0, 0.14),
+ 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
visibility: collapse;
z-index: 1000;
}
@@ -2372,26 +2413,54 @@ body:not(.loaded) .demo-page__toolbar:after {
line-height: 24px;
}
}
-.demo-page__toolbar .overflow-container__content > *:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > button:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > label:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button + label:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button.labeled + label:not(.labeled)[class^='demo-icon-'][title]::after,
-.demo-page__toolbar .overflow-container__content > button.labeled:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > *:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > button:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > label:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button
+ + label:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button.labeled
+ + label:not(.labeled)[class^='demo-icon-'][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > button.labeled:not(.labeled)[class^='demo-icon-'][title]::after,
.demo-page__toolbar .overflow-container__content > *:not(.labeled)[data-command][title]::after,
.demo-page__toolbar .overflow-container__content > button:not(.labeled)[data-command][title]::after,
.demo-page__toolbar .overflow-container__content > label:not(.labeled)[data-command][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button + label:not(.labeled)[data-command][title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button.labeled + label:not(.labeled)[data-command][title]::after,
-.demo-page__toolbar .overflow-container__content > button.labeled:not(.labeled)[data-command][title]::after {
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button
+ + label:not(.labeled)[data-command][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button.labeled
+ + label:not(.labeled)[data-command][title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > button.labeled:not(.labeled)[data-command][title]::after {
content: attr(title);
display: block;
}
.demo-page__toolbar .overflow-container__content > *:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > button:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > label:not(.labeled)[title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button + label:not(.labeled)[title]::after,
-.demo-page__toolbar .overflow-container__content > .demo-toggle-button.labeled + label:not(.labeled)[title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button
+ + label:not(.labeled)[title]::after,
+.demo-page__toolbar
+ .overflow-container__content
+ > .demo-toggle-button.labeled
+ + label:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > button.labeled:not(.labeled)[title]::after,
.demo-page__toolbar .overflow-container__content > *.labeled,
.demo-page__toolbar .overflow-container__content > button.labeled,
@@ -2422,7 +2491,10 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-page__toolbar .overflow-container__content input[type='checkbox']:focus {
outline: none;
}
-.demo-page__toolbar .overflow-container__content input[type='checkbox'].demo-toggle-button.labeled + label {
+.demo-page__toolbar
+ .overflow-container__content
+ input[type='checkbox'].demo-toggle-button.labeled
+ + label {
padding-left: 45px !important;
line-height: 32px;
white-space: nowrap;
@@ -2431,7 +2503,10 @@ body:not(.loaded) .demo-page__toolbar:after {
text-align: left;
}
@media screen and (max-height: 500px) {
- .demo-page__toolbar .overflow-container__content input[type='checkbox'].demo-toggle-button.labeled + label {
+ .demo-page__toolbar
+ .overflow-container__content
+ input[type='checkbox'].demo-toggle-button.labeled
+ + label {
line-height: 24px;
}
}
@@ -2461,11 +2536,15 @@ body:not(.loaded) .demo-page__toolbar:after {
height: 100%;
width: 100%;
line-height: 140%;
- min-width: clamp(var(--description-min-width), var(--description-width), var(--description-max-width));
+ min-width: clamp(
+ var(--description-min-width),
+ var(--description-width),
+ var(--description-max-width)
+ );
background-color: var(--description-color);
z-index: 16;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-page__description {
--description-width: 100vw;
}
@@ -2556,14 +2635,15 @@ body:not(.loaded) .demo-page__toolbar:after {
right: 0;
top: 0;
cursor: pointer;
- background: url("data:image/svg+xml,%3Csvg fill='%23343f4a' height='24' viewBox='2 2 20 20' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 7h10v10H7z' fill='%2300d8ff'/%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z'/%3E%3C/svg%3E") no-repeat calc(100% - 15px);
+ background: url("data:image/svg+xml,%3Csvg fill='%23343f4a' height='24' viewBox='2 2 20 20' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 7h10v10H7z' fill='%2300d8ff'/%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z'/%3E%3C/svg%3E")
+ no-repeat calc(100% - 15px);
background-size: 35px;
font-size: 1.1rem;
line-height: 60px;
text-align: right;
padding-right: 60px;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-description__play-button {
display: block;
}
@@ -2597,7 +2677,7 @@ body:not(.loaded) .demo-page__toolbar:after {
top: 50%;
line-height: 7px;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-description__drag-area--vertical {
display: none;
}
@@ -2613,7 +2693,7 @@ body:not(.loaded) .demo-page__toolbar:after {
top: 0;
line-height: 9px;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-description__drag-area--horizontal {
display: block;
}
@@ -2625,7 +2705,7 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-description--draggable .demo-description__play-button {
display: none;
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-description--draggable {
border-right: none;
border-top: 9px solid #d5d7d8;
@@ -2656,7 +2736,9 @@ body:not(.loaded) .demo-page__toolbar:after {
line-height: 140%;
width: var(--sidebar-width);
border-left: 1px solid #d5d7d8;
- transition: width 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, padding-left 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ width 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ padding-left 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-main__sidebar--hidden {
padding-left: 24px;
@@ -2696,7 +2778,10 @@ body:not(.loaded) .demo-page__toolbar:after {
background-image: url('../icons/single-arrow-right.svg');
background-size: 8px;
background-repeat: no-repeat;
- transition: top 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, background-color 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ top 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ background-color 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-sidebar__toggle__button:hover {
background-color: #dedede;
@@ -2738,7 +2823,9 @@ body:not(.loaded) .demo-page__toolbar:after {
.demo-main__sidebar--hidden .demo-sidebar__toggle__title {
opacity: 1;
transform: translateX(0);
- transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0.1s, opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0.1s,
+ opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-properties__settings fieldset {
border: 1px solid #888;
@@ -3069,14 +3156,14 @@ body.demo-tutorial {
--description-color: none;
grid-template-areas: 'header header' 'toolbar toolbar' 'sidebar content';
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
body.demo-tutorial {
grid-template-columns: 1fr;
grid-template-rows: 60px auto 1fr clamp(25%, var(--description-drag-height), 65%);
grid-template-areas: 'header' 'toolbar' 'content' 'sidebar';
}
}
-@media screen and (max-width: 960px ) and (max-height: 500px) {
+@media screen and (max-width: 960px) and (max-height: 500px) {
body.demo-tutorial {
grid-template-rows: 30px auto 1fr clamp(25%, var(--description-drag-height), 65%);
}
@@ -3158,7 +3245,7 @@ body.demo-tutorial {
.demo-toolbar__button--forward:after {
border-width: 2px 2px 0 0;
}
-@media screen and (max-width: 640px ) {
+@media screen and (max-width: 640px) {
.demo-toolbar__button--back,
.demo-toolbar__button--forward {
padding: 0;
@@ -3174,7 +3261,7 @@ body.demo-tutorial {
padding-right: 4px;
}
}
-@media screen and (max-width: 960px ) {
+@media screen and (max-width: 960px) {
.demo-toolbar__tutorial-step-title {
display: none;
}
@@ -3215,8 +3302,13 @@ body.demo-tutorial {
border-radius: 6px;
background-color: var(--toolbar-color);
overflow-y: hidden;
- box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
- transition: opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, max-height 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ box-shadow:
+ 0 5px 5px -3px rgba(0, 0, 0, 0.2),
+ 0px 8px 10px 1px rgba(0, 0, 0, 0.14),
+ 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
+ transition:
+ opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ max-height 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-toolbar__tutorial-dropdown .tutorial-dropdown__item {
display: block;
@@ -3242,7 +3334,9 @@ body.demo-tutorial {
margin-bottom: 1px;
transform: translateX(-10px) rotate(45deg);
opacity: 0;
- transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s, opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
+ transition:
+ transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s,
+ opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0s;
}
.demo-toolbar__tutorial-dropdown .tutorial-dropdown__item:hover {
background-color: #29323c;
@@ -3275,7 +3369,9 @@ body.demo-tutorial.theme-dark .demo-description__content .paragraph code {
background: var(--description-kbd-background);
border: 1px solid var(--description-kbd-border-color);
border-radius: 0.25em;
- box-shadow: 0 1px 0 var(--description-kbd-border-color), 0 0 0 0.1em var(--description-kbd-background) inset;
+ box-shadow:
+ 0 1px 0 var(--description-kbd-border-color),
+ 0 0 0 0.1em var(--description-kbd-background) inset;
display: inline-block;
font-size: 80%;
padding: 0.1em 0.5em;
diff --git a/demos/showcase/bpmn/BpmnEditorDemo.js b/demos/showcase/bpmn/BpmnEditorDemo.js
index 6a19f9cb6..e3970a17d 100644
--- a/demos/showcase/bpmn/BpmnEditorDemo.js
+++ b/demos/showcase/bpmn/BpmnEditorDemo.js
@@ -214,7 +214,7 @@ function initializeGraphComponent() {
graphComponent.clipboard = graphClipboard
const decorator = graphComponent.graph.decorator
- decorator.nodeDecorator.editLabelHelperDecorator.setFactory(node => {
+ decorator.nodeDecorator.editLabelHelperDecorator.setFactory((node) => {
const style = node.style
if (style.lookup && style.lookup(node, IEditLabelHelper.$class)) {
return style.lookup(node, IEditLabelHelper.$class)
@@ -266,7 +266,7 @@ function initializeInputMode() {
const nodeDropInputMode = new NoNestedTablesDropInputMode()
nodeDropInputMode.showPreview = true
nodeDropInputMode.enabled = true
- nodeDropInputMode.isGroupNodePredicate = draggedNode =>
+ nodeDropInputMode.isGroupNodePredicate = (draggedNode) =>
!!draggedNode.lookup(ITable.$class) || draggedNode.tag === 'GroupNode'
graphEditorInputMode.nodeDropInputMode = nodeDropInputMode
@@ -347,7 +347,7 @@ function enableFolding() {
graphComponent.graph.nodeDefaults.labels.layoutParameter =
compositeLabelModel.createDefaultParameter()
- manager.masterGraph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(node => {
+ manager.masterGraph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory((node) => {
if (node.lookup(ITable.$class)) {
// Pool only have a dynamic PortCandidate
return IPortCandidateProvider.fromCandidates([
@@ -528,7 +528,7 @@ function onFileSelected(e) {
const isGraphML = file.name.toLowerCase().endsWith('.graphml')
if (isBPMN || isGraphML) {
const reader = new FileReader()
- reader.onload = async ev => {
+ reader.onload = async (ev) => {
// get the file content that shall be parsed by a BpmnDiParser or a GraphMLIOHandler
const content = ev.target.result
if (isBPMN) {
@@ -563,7 +563,7 @@ function initializeContextMenu() {
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
@@ -920,8 +920,8 @@ class AdditionalEditLabelHelper extends EditLabelHelper {
return InteriorLabelModel.NORTH
}
// eslint-disable-next-line arrow-body-style
- const validParameters = parameters.filter(parameter =>
- owner.labels.every(label => {
+ const validParameters = parameters.filter((parameter) =>
+ owner.labels.every((label) => {
const bounds = label.layoutParameter.model.getGeometry(label, label.layoutParameter)
return !parameter.model.getGeometry(label, parameter).bounds.intersects(bounds)
})
diff --git a/demos/showcase/bpmn/BpmnEditorDemo.ts b/demos/showcase/bpmn/BpmnEditorDemo.ts
index ae335d390..2ca77a05e 100644
--- a/demos/showcase/bpmn/BpmnEditorDemo.ts
+++ b/demos/showcase/bpmn/BpmnEditorDemo.ts
@@ -208,7 +208,7 @@ function initializeGraphComponent(): void {
graphComponent.clipboard = graphClipboard
const decorator = graphComponent.graph.decorator
- decorator.nodeDecorator.editLabelHelperDecorator.setFactory(node => {
+ decorator.nodeDecorator.editLabelHelperDecorator.setFactory((node) => {
const style = node.style as BpmnNodeStyle
if (style.lookup && style.lookup(node, IEditLabelHelper.$class)) {
return style.lookup(node, IEditLabelHelper.$class) as IEditLabelHelper
@@ -341,7 +341,7 @@ function enableFolding(): void {
graphComponent.graph.nodeDefaults.labels.layoutParameter =
compositeLabelModel.createDefaultParameter()
- manager.masterGraph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(node => {
+ manager.masterGraph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory((node) => {
if (node.lookup(ITable.$class)) {
// Pool only have a dynamic PortCandidate
return IPortCandidateProvider.fromCandidates([
@@ -516,7 +516,7 @@ function onFileSelected(e: Event): void {
const isGraphML = file.name.toLowerCase().endsWith('.graphml')
if (isBPMN || isGraphML) {
const reader = new FileReader()
- reader.onload = async ev => {
+ reader.onload = async (ev) => {
// get the file content that shall be parsed by a BpmnDiParser or a GraphMLIOHandler
const content = ev.target!.result as string
if (isBPMN) {
@@ -894,8 +894,8 @@ class AdditionalEditLabelHelper extends EditLabelHelper {
return InteriorLabelModel.NORTH
}
// eslint-disable-next-line arrow-body-style
- const validParameters = parameters.filter(parameter =>
- owner.labels.every(label => {
+ const validParameters = parameters.filter((parameter) =>
+ owner.labels.every((label) => {
const bounds = label.layoutParameter.model.getGeometry(label, label.layoutParameter)
return !parameter.model.getGeometry(label, parameter).bounds.intersects(bounds)
})
diff --git a/demos/showcase/bpmn/BpmnLayout.js b/demos/showcase/bpmn/BpmnLayout.js
index 34a5a3afe..65318e742 100644
--- a/demos/showcase/bpmn/BpmnLayout.js
+++ b/demos/showcase/bpmn/BpmnLayout.js
@@ -200,12 +200,12 @@ export default class BpmnLayout extends BaseClass(ILayoutAlgorithm) {
configurePartitionGrid(graph) {
const grid = PartitionGrid.getPartitionGrid(graph)
if (grid != null) {
- grid.columns.forEach(columnObject => {
+ grid.columns.forEach((columnObject) => {
const column = columnObject
column.leftInset += this.laneInsets
column.rightInset += this.laneInsets
})
- grid.rows.forEach(rowObject => {
+ grid.rows.forEach((rowObject) => {
const row = rowObject
row.topInset += this.laneInsets
row.bottomInset += this.laneInsets
@@ -586,7 +586,7 @@ class BalancingPortOptimizer extends PortConstraintOptimizerBase {
const criticalEdges = Maps.createHashedEdgeMap()
// determine whether an edge crosses a swim-lane border and if so in which direction
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const originalEdge = this.getOriginalEdge(edge, ldp)
// now we have a 'real' edge with valid source and target nodes
@@ -605,12 +605,12 @@ class BalancingPortOptimizer extends PortConstraintOptimizerBase {
})
// determine basic node alignment
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
const alignment = this.calculateLaneAlignment(n)
this.node2LaneAlignment.set(n, alignment)
})
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
// sort the edges with the provided comparer
n.sortInEdges(inEdgeOrder)
n.sortOutEdges(outEdgeOrder)
@@ -907,7 +907,7 @@ class BalancingPortOptimizer extends PortConstraintOptimizerBase {
calculateLaneAlignment(n) {
let toRightCount = 0
let toLeftCount = 0
- n.edges.forEach(edge => {
+ n.edges.forEach((edge) => {
const crossing = this.edge2LaneCrossing.get(edge)
if (n === edge.source) {
if (crossing === LaneCrossing.TO_EAST) {
@@ -1061,7 +1061,7 @@ class BpmnLabelProfitModel extends BaseClass(IProfitModel) {
// diagonal candidates get a bit less profit
profit = 0.9
}
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
const portLocation =
edge.source === node
? this.graph.getSourcePointRel(edge)
diff --git a/demos/showcase/bpmn/BpmnLayout.ts b/demos/showcase/bpmn/BpmnLayout.ts
index 96ab7ba50..06de5310f 100644
--- a/demos/showcase/bpmn/BpmnLayout.ts
+++ b/demos/showcase/bpmn/BpmnLayout.ts
@@ -196,12 +196,12 @@ export default class BpmnLayout extends BaseClass(ILayoutAlgorithm) {
configurePartitionGrid(graph: LayoutGraph): void {
const grid = PartitionGrid.getPartitionGrid(graph)
if (grid != null) {
- grid.columns.forEach(columnObject => {
+ grid.columns.forEach((columnObject) => {
const column = columnObject
column.leftInset += this.laneInsets
column.rightInset += this.laneInsets
})
- grid.rows.forEach(rowObject => {
+ grid.rows.forEach((rowObject) => {
const row = rowObject
row.topInset += this.laneInsets
row.bottomInset += this.laneInsets
@@ -543,7 +543,7 @@ class BalancingPortOptimizer extends PortConstraintOptimizerBase {
const criticalEdges = Maps.createHashedEdgeMap()
// determine whether an edge crosses a swim-lane border and if so in which direction
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const originalEdge = this.getOriginalEdge(edge, ldp)
// now we have a 'real' edge with valid source and target nodes
@@ -562,12 +562,12 @@ class BalancingPortOptimizer extends PortConstraintOptimizerBase {
})
// determine basic node alignment
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
const alignment = this.calculateLaneAlignment(n)
this.node2LaneAlignment!.set(n, alignment)
})
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
// sort the edges with the provided comparer
n.sortInEdges(inEdgeOrder)
n.sortOutEdges(outEdgeOrder)
@@ -846,7 +846,7 @@ class BalancingPortOptimizer extends PortConstraintOptimizerBase {
calculateLaneAlignment(n: YNode): LaneAlignment {
let toRightCount = 0
let toLeftCount = 0
- n.edges.forEach(edge => {
+ n.edges.forEach((edge) => {
const crossing = this.edge2LaneCrossing!.get(edge)
if (n === edge.source) {
if (crossing === LaneCrossing.TO_EAST) {
@@ -999,7 +999,7 @@ class BpmnLabelProfitModel extends BaseClass(IProfitModel) {
// diagonal candidates get a bit less profit
profit = 0.9
}
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
const portLocation =
edge.source === node
? this.graph.getSourcePointRel(edge)
diff --git a/demos/showcase/bpmn/BpmnLayoutData.js b/demos/showcase/bpmn/BpmnLayoutData.js
index 55322b96c..4bd176a06 100644
--- a/demos/showcase/bpmn/BpmnLayoutData.js
+++ b/demos/showcase/bpmn/BpmnLayoutData.js
@@ -147,11 +147,11 @@ export default class BpmnLayoutData {
data.addEdgeItemCollection(BpmnLayout.SEQUENCE_FLOW_EDGES_DP_KEY).delegate = isSequenceFlow
// mark boundary interrupting edges for the BalancingPortOptimizer
- data.addEdgeItemCollection(BpmnLayout.BOUNDARY_INTERRUPTING_EDGES_DP_KEY).delegate = edge =>
+ data.addEdgeItemCollection(BpmnLayout.BOUNDARY_INTERRUPTING_EDGES_DP_KEY).delegate = (edge) =>
edge.sourcePort.style instanceof EventPortStyle
// mark conversations, events and gateways so their port locations are adjusted
- data.addNodeItemCollection(BpmnLayout.ADJUST_PORT_LOCATION_NODES_DP_KEY).delegate = node =>
+ data.addNodeItemCollection(BpmnLayout.ADJUST_PORT_LOCATION_NODES_DP_KEY).delegate = (node) =>
node.style instanceof ConversationNodeStyle ||
node.style instanceof EventNodeStyle ||
node.style instanceof GatewayNodeStyle
@@ -169,7 +169,7 @@ export default class BpmnLayoutData {
markFixedAndAffectedItems(data, hierarchicLayoutData, selection, layoutOnlySelection)
// mark associations and message flows as undirected so they have less impact on layering
- hierarchicLayoutData.edgeDirectedness.delegate = edge =>
+ hierarchicLayoutData.edgeDirectedness.delegate = (edge) =>
isMessageFlow(edge) || isAssociation(edge) ? 0 : 1
// add layer constraints for start events, sub processes and message flows
@@ -197,7 +197,7 @@ const addLayerConstraints = (
// use layer constraints via HierarchicLayoutData
const layerConstraints = hierarchicLayoutData.layerConstraints
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (isMessageFlow(edge) && !compactMessageFlowLayering) {
// message flow layering compaction is disabled, we add a 'weak' same layer constraint, i.e. source node shall
// be placed at least 0 layers above target node
@@ -217,7 +217,7 @@ const addLayerConstraints = (
// if start events should be pulled to the first layer, add PlaceNodeAtTop constraint.
if (startNodesFirst) {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (
node.style instanceof EventNodeStyle &&
node.style.characteristic === EventCharacteristic.START &&
@@ -244,8 +244,8 @@ function addAboveLayerConstraint(layerConstraints, edge, graph) {
const targetNodes = []
collectLeafNodes(graph, sourceNode, sourceNodes)
collectLeafNodes(graph, targetNode, targetNodes)
- sourceNodes.forEach(source => {
- targetNodes.forEach(target => {
+ sourceNodes.forEach((source) => {
+ targetNodes.forEach((target) => {
layerConstraints.placeAbove(target, source)
})
})
@@ -260,7 +260,7 @@ function addAboveLayerConstraint(layerConstraints, edge, graph) {
function collectLeafNodes(graph, node, leafNodes) {
const children = graph.getChildren(node)
if (children.size > 0) {
- children.forEach(child => {
+ children.forEach((child) => {
collectLeafNodes(graph, child, leafNodes)
})
} else {
@@ -277,9 +277,9 @@ function addMinimumEdgeLength(hierarchicLayoutData, minimumEdgeLength) {
// each edge should have a minimum length so that all its labels can be placed on it one
// after another with a minimum label-to-label distance
const minLabelToLabelDistance = 5
- hierarchicLayoutData.edgeLayoutDescriptors.delegate = edge => {
+ hierarchicLayoutData.edgeLayoutDescriptors.delegate = (edge) => {
let minLength = 0
- edge.labels.forEach(label => {
+ edge.labels.forEach((label) => {
const labelSize = label.layout.bounds
minLength += Math.max(labelSize.width, labelSize.height)
})
@@ -361,14 +361,14 @@ function isAssociation(edge) {
*/
function addNodeHalos(data, graph, selection, layoutOnlySelection) {
const nodeHalos = new Mapper()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let top = 0.0
let left = 0.0
let bottom = 0.0
let right = 0.0
// for each port with an EventPortStyle extend the node halo to cover the ports render size
- node.ports.forEach(port => {
+ node.ports.forEach((port) => {
if (port.style instanceof EventPortStyle) {
const eventPortStyle = port.style
const renderSize = eventPortStyle.renderSize
@@ -383,7 +383,7 @@ function addNodeHalos(data, graph, selection, layoutOnlySelection) {
// for each node without incoming or outgoing edges reserve space for laid out exterior labels
if (graph.inDegree(node) === 0 || graph.outDegree(node) === 0) {
const margin = 15
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
if (isNodeLabelAffected(graph, selection, label, layoutOnlySelection)) {
const labelBounds = label.layout.bounds
if (graph.inDegree(node) === 0) {
@@ -444,7 +444,7 @@ function addEdgeLabelPlacementDescriptors(data) {
})
data.addLabelItemMapping(
LayoutGraphAdapter.EDGE_LABEL_LAYOUT_PREFERRED_PLACEMENT_DESCRIPTOR_DP_KEY
- ).delegate = label => {
+ ).delegate = (label) => {
const labelOwner = label.owner
const edgeType = labelOwner.style.type
if (
@@ -469,7 +469,7 @@ function addEdgeLabelPlacementDescriptors(data) {
function markFixedAndAffectedItems(data, hierarchicLayoutData, selection, layoutOnlySelection) {
if (layoutOnlySelection) {
const affectedEdges = IMapper.fromDelegate(
- edge =>
+ (edge) =>
selection.isSelected(edge) ||
selection.isSelected(edge.sourceNode) ||
selection.isSelected(edge.targetNode)
@@ -478,13 +478,13 @@ function markFixedAndAffectedItems(data, hierarchicLayoutData, selection, layout
data.addEdgeItemCollection(LayoutKeys.AFFECTED_EDGES_DP_KEY).mapper = affectedEdges
// fix ports of unselected edges and edges at event ports
- data.addEdgeItemMapping(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_DP_KEY).delegate = edge => {
+ data.addEdgeItemMapping(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_DP_KEY).delegate = (edge) => {
if (!affectedEdges.get(edge) || edge.sourcePort.style instanceof EventPortStyle) {
return PortConstraint.create(getSide(edge, true))
}
return null
}
- data.addEdgeItemMapping(PortConstraintKeys.TARGET_PORT_CONSTRAINT_DP_KEY).delegate = edge => {
+ data.addEdgeItemMapping(PortConstraintKeys.TARGET_PORT_CONSTRAINT_DP_KEY).delegate = (edge) => {
if (!affectedEdges.get(edge)) {
return PortConstraint.create(getSide(edge, false))
}
@@ -500,7 +500,7 @@ function markFixedAndAffectedItems(data, hierarchicLayoutData, selection, layout
}
return null
}
- data.addLabelItemCollection(BpmnLayout.AFFECTED_LABELS_DP_KEY).delegate = label => {
+ data.addLabelItemCollection(BpmnLayout.AFFECTED_LABELS_DP_KEY).delegate = (label) => {
if (label.owner instanceof IEdge) {
return affectedEdges.get(label.owner)
}
@@ -515,14 +515,14 @@ function markFixedAndAffectedItems(data, hierarchicLayoutData, selection, layout
}
} else {
// fix source port of edges at event ports
- data.addEdgeItemMapping(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_DP_KEY).delegate = edge => {
+ data.addEdgeItemMapping(PortConstraintKeys.SOURCE_PORT_CONSTRAINT_DP_KEY).delegate = (edge) => {
if (edge.sourcePort.style instanceof EventPortStyle) {
return PortConstraint.create(getSide(edge, true))
}
return null
}
- data.addLabelItemCollection(BpmnLayout.AFFECTED_LABELS_DP_KEY).delegate = label => {
+ data.addLabelItemCollection(BpmnLayout.AFFECTED_LABELS_DP_KEY).delegate = (label) => {
if (label.owner instanceof IEdge) {
return true
}
diff --git a/demos/showcase/bpmn/BpmnLayoutData.ts b/demos/showcase/bpmn/BpmnLayoutData.ts
index 7d27547f3..bf07370b1 100644
--- a/demos/showcase/bpmn/BpmnLayoutData.ts
+++ b/demos/showcase/bpmn/BpmnLayoutData.ts
@@ -188,7 +188,7 @@ const addLayerConstraints = (
// use layer constraints via HierarchicLayoutData
const layerConstraints = hierarchicLayoutData.layerConstraints
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (isMessageFlow(edge) && !compactMessageFlowLayering) {
// message flow layering compaction is disabled, we add a 'weak' same layer constraint, i.e. source node shall
// be placed at least 0 layers above target node
@@ -208,7 +208,7 @@ const addLayerConstraints = (
// if start events should be pulled to the first layer, add PlaceNodeAtTop constraint.
if (startNodesFirst) {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (
node.style instanceof EventNodeStyle &&
node.style.characteristic === EventCharacteristic.START &&
@@ -236,8 +236,8 @@ function addAboveLayerConstraint(
const targetNodes: INode[] = []
collectLeafNodes(graph, sourceNode, sourceNodes)
collectLeafNodes(graph, targetNode, targetNodes)
- sourceNodes.forEach(source => {
- targetNodes.forEach(target => {
+ sourceNodes.forEach((source) => {
+ targetNodes.forEach((target) => {
layerConstraints.placeAbove(target, source)
})
})
@@ -249,7 +249,7 @@ function addAboveLayerConstraint(
function collectLeafNodes(graph: IGraph, node: INode, leafNodes: INode[]): void {
const children = graph.getChildren(node)
if (children.size > 0) {
- children.forEach(child => {
+ children.forEach((child) => {
collectLeafNodes(graph, child, leafNodes)
})
} else {
@@ -269,7 +269,7 @@ function addMinimumEdgeLength(
const minLabelToLabelDistance = 5
hierarchicLayoutData.edgeLayoutDescriptors.delegate = (edge: IEdge) => {
let minLength = 0
- edge.labels.forEach(label => {
+ edge.labels.forEach((label) => {
const labelSize = label.layout.bounds
minLength += Math.max(labelSize.width, labelSize.height)
})
@@ -344,14 +344,14 @@ function addNodeHalos(
layoutOnlySelection: boolean
): void {
const nodeHalos: Mapper
= new Mapper()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let top = 0.0
let left = 0.0
let bottom = 0.0
let right = 0.0
// for each port with an EventPortStyle extend the node halo to cover the ports render size
- node.ports.forEach(port => {
+ node.ports.forEach((port) => {
if (port.style instanceof EventPortStyle) {
const eventPortStyle = port.style
const renderSize = eventPortStyle.renderSize
@@ -366,7 +366,7 @@ function addNodeHalos(
// for each node without incoming or outgoing edges reserve space for laid out exterior labels
if (graph.inDegree(node) === 0 || graph.outDegree(node) === 0) {
const margin = 15
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
if (isNodeLabelAffected(graph, selection, label, layoutOnlySelection)) {
const labelBounds = label.layout.bounds
if (graph.inDegree(node) === 0) {
diff --git a/demos/showcase/bpmn/BpmnPopupSupport.js b/demos/showcase/bpmn/BpmnPopupSupport.js
index 51bd31894..c1125f9ce 100644
--- a/demos/showcase/bpmn/BpmnPopupSupport.js
+++ b/demos/showcase/bpmn/BpmnPopupSupport.js
@@ -777,7 +777,7 @@ export default class BpmnPopupSupport {
)
})
- document.querySelectorAll('.close-popup-button').forEach(btn =>
+ document.querySelectorAll('.close-popup-button').forEach((btn) =>
btn.addEventListener('click', () => {
this.hidePropertyPopup()
})
@@ -854,7 +854,7 @@ export default class BpmnPopupSupport {
* @param {!Class} enumType
*/
function populateComboBox(comboBox, enumType) {
- Enum.getValueNames(enumType).forEach(name => {
+ Enum.getValueNames(enumType).forEach((name) => {
const option = document.createElement('option')
option.innerText = getFriendlyName(name)
option.value = name
diff --git a/demos/showcase/bpmn/BpmnPopupSupport.ts b/demos/showcase/bpmn/BpmnPopupSupport.ts
index 59de319dd..4f4071421 100644
--- a/demos/showcase/bpmn/BpmnPopupSupport.ts
+++ b/demos/showcase/bpmn/BpmnPopupSupport.ts
@@ -785,7 +785,7 @@ export default class BpmnPopupSupport {
)
})
- document.querySelectorAll('.close-popup-button').forEach(btn =>
+ document.querySelectorAll('.close-popup-button').forEach((btn) =>
btn.addEventListener('click', () => {
this.hidePropertyPopup()
})
@@ -863,7 +863,7 @@ export default class BpmnPopupSupport {
* Adds options to the given combo box for the content of the enum type.
*/
function populateComboBox(comboBox: HTMLSelectElement, enumType: Class): void {
- Enum.getValueNames(enumType).forEach(name => {
+ Enum.getValueNames(enumType).forEach((name) => {
const option = document.createElement('option')
option.innerText = getFriendlyName(name)
option.value = name
diff --git a/demos/showcase/bpmn/bpmn-di.js b/demos/showcase/bpmn/bpmn-di.js
index ab7256280..6dba977a0 100644
--- a/demos/showcase/bpmn/bpmn-di.js
+++ b/demos/showcase/bpmn/bpmn-di.js
@@ -288,23 +288,23 @@ export class BpmnDiParser {
// Get the Diagram to load
let diaToLoad
- return new Promise(resolve => {
+ return new Promise((resolve) => {
if (selectDiagramCallback) {
selectDiagramCallback(
- topLevelDiagrams.map(d => ({
+ topLevelDiagrams.map((d) => ({
name: d.name,
nodeCount: d.plane.listOfShapes.size,
edgeCount: d.plane.listOfEdges.size
}))
- ).then(chosenName => {
- diaToLoad = topLevelDiagrams.find(d => d.name === chosenName)
+ ).then((chosenName) => {
+ diaToLoad = topLevelDiagrams.find((d) => d.name === chosenName)
resolve(diaToLoad)
})
} else {
diaToLoad = topLevelDiagrams.at(0) ?? null
resolve(diaToLoad)
}
- }).then(diaToLoad => {
+ }).then((diaToLoad) => {
// Loads the selected Diagram into the supplied Graph
if (diaToLoad) {
this.loadDiagram(diaToLoad, null)
@@ -595,14 +595,14 @@ export class BpmnDiParser {
}
const groupNodes = this.masterGraph.nodes
- .filter(node => node.style instanceof GroupNodeStyle)
+ .filter((node) => node.style instanceof GroupNodeStyle)
.toList()
for (const groupNode of groupNodes) {
if (this.masterGraph.getChildren(groupNode).size === 0) {
const newChildren = this.masterGraph
.getChildren(this.masterGraph.getParent(groupNode))
.filter(
- child =>
+ (child) =>
child !== groupNode &&
groupNode.layout.contains(child.layout.topLeft) &&
groupNode.layout.contains(child.layout.bottomRight)
@@ -769,7 +769,7 @@ export class BpmnDiParser {
return
}
const labelingData = new LabelingData()
- labelingData.edgeLabelPreferredPlacement.delegate = label => {
+ labelingData.edgeLabelPreferredPlacement.delegate = (label) => {
if (/yes|no/i.test(label.text)) {
const preferredPlacementDescriptor = new PreferredPlacementDescriptor()
preferredPlacementDescriptor.placeAlongEdge = LabelPlacements.AT_SOURCE
@@ -1433,7 +1433,7 @@ export class BpmnDiParser {
this.masterGraph.setStyle(node, partStyle)
const table = partStyle.tableNodeStyle.table
- if (shape.isHorizontal) {
+ if (shape.isHorizontal ?? false) {
const row = table.rootRow.childRows.first()
BpmnDiParser.addTableLabel(table, row, shape)
} else {
@@ -2148,7 +2148,7 @@ export class BpmnDiParser {
}
let layout = Rect.EMPTY
- let isHorizontal = false
+ let isHorizontal = null
let multipleInstance = false
let tableShape = this.getShape(element, plane)
@@ -2171,20 +2171,30 @@ export class BpmnDiParser {
if (tableShape) {
// table has a shape itself so we use its layout to initialize the table
layout = new Rect(tableShape.x, tableShape.y, tableShape.width, tableShape.height)
- isHorizontal = tableShape.isHorizontal
- } else {
+ if (tableShape.isHorizontal != null) {
+ isHorizontal = tableShape.isHorizontal
+ }
+ }
+ const calculateRect = layout.isEmpty
+ if (calculateRect || isHorizontal == null) {
// check the child lanes for their shapes
for (const lane of element.getChildren('lane')) {
const laneShape = this.getShape(lane, plane)
if (laneShape) {
- layout = Rect.add(
- layout,
- new Rect(laneShape.x, laneShape.y, laneShape.width, laneShape.height)
- )
- isHorizontal = laneShape.isHorizontal
+ if (calculateRect) {
+ layout = Rect.add(
+ layout,
+ new Rect(laneShape.x, laneShape.y, laneShape.width, laneShape.height)
+ )
+ }
+ if (isHorizontal == null && laneShape.isHorizontal != null) {
+ isHorizontal = laneShape.isHorizontal
+ }
}
}
}
+ // fallback
+ isHorizontal = isHorizontal ?? false
let node
if (!layout.isEmpty) {
let table
@@ -2227,7 +2237,7 @@ export class BpmnDiParser {
? table.rootRow.childRows.at(0) ?? table.rootRow
: table.rootColumn.childColumns.at(0) ?? table.rootColumn
if (tableShape) {
- parentStripe = this.addToTable(tableShape, table, node, parentStripe)
+ parentStripe = this.addToTable(tableShape, table, node, parentStripe, isHorizontal)
}
element.node = node
@@ -2235,17 +2245,17 @@ export class BpmnDiParser {
parent.node = node
}
- this.addChildLanes(element, table, parentStripe, plane, node)
+ this.addChildLanes(element, table, parentStripe, plane, node, isHorizontal)
// Resize the root row/column after adding a column/row with insets
if (isHorizontal) {
const max = table.rootRow.leaves
- .map(s => s.layout.x - table.layout.x + s.insets.left)
+ .map((s) => s.layout.x - table.layout.x + s.insets.left)
.reduce((acc, val) => Math.max(acc, val), Number.MIN_VALUE)
table.setSize(table.rootColumn.childColumns.first(), node.layout.width - max)
} else {
const max = table.rootColumn.leaves
- .map(s => s.layout.y - table.layout.y + s.insets.top)
+ .map((s) => s.layout.y - table.layout.y + s.insets.top)
.reduce((acc, val) => Math.max(acc, val), Number.MIN_VALUE)
table.setSize(table.rootRow.childRows.first(), node.layout.height - max)
}
@@ -2276,12 +2286,13 @@ export class BpmnDiParser {
* @param {!IStripe} parentStripe
* @param {!BpmnPlane} plane
* @param {!INode} node
+ * @param {boolean} isHorizontal
*/
- addChildLanes(element, table, parentStripe, plane, node) {
+ addChildLanes(element, table, parentStripe, plane, node, isHorizontal) {
for (const lane of element.getChildren('lane')) {
const laneShape = this.getShape(lane, plane)
if (laneShape) {
- const addedStripe = this.addToTable(laneShape, table, node, parentStripe)
+ const addedStripe = this.addToTable(laneShape, table, node, parentStripe, isHorizontal)
for (const refElement of lane.getChildren('flowNodeRef')) {
const bpmnElement = { value: null }
if (refElement.value && this.tryGetElementForId(refElement.value, bpmnElement)) {
@@ -2290,7 +2301,7 @@ export class BpmnDiParser {
}
const childLaneSet = lane.getChild('childLaneSet')
if (childLaneSet) {
- this.addChildLanes(childLaneSet, table, addedStripe, plane, node)
+ this.addChildLanes(childLaneSet, table, addedStripe, plane, node, isHorizontal)
}
}
}
@@ -2302,20 +2313,21 @@ export class BpmnDiParser {
* @param {!ITable} table
* @param {!INode} node
* @param {!IStripe} parentStripe
+ * @param {boolean} isHorizontal
* @returns {!IStripe}
*/
- addToTable(shape, table, node, parentStripe) {
+ addToTable(shape, table, node, parentStripe, isHorizontal) {
// lane element
const element = shape.element
// Link the node to the BpmnElement of the lane
element.node = node
- if (shape.isHorizontal) {
+ if (isHorizontal) {
const parentRow = parentStripe instanceof IRow ? parentStripe : null
// getIndex
const index = parentRow
- ? parentRow.childRows.filter(siblingRow => siblingRow.tag.y < shape.y).size
+ ? parentRow.childRows.filter((siblingRow) => siblingRow.tag.y < shape.y).size
: -1
const row = table.createChildRow(parentRow, shape.height, null, null, null, null, index)
@@ -2327,7 +2339,7 @@ export class BpmnDiParser {
const parentCol = IColumn.isInstance(parentStripe) ? parentStripe : null
// getIndex
const index = parentCol
- ? parentCol.childColumns.filter(siblingCol => siblingCol.tag.x < shape.x).size
+ ? parentCol.childColumns.filter((siblingCol) => siblingCol.tag.x < shape.x).size
: -1
const col = table.createChildColumn(parentCol, shape.width, null, null, null, null, index)
@@ -2343,7 +2355,7 @@ export class BpmnDiParser {
* @returns {!PoolNodeStyle}
*/
static createTable(shape) {
- const poolNodeStyle = BpmnDiParser.createPoolNodeStyle(shape.isHorizontal)
+ const poolNodeStyle = BpmnDiParser.createPoolNodeStyle(shape.isHorizontal ?? false)
const table = poolNodeStyle.tableNodeStyle.table
// Create first row & column
@@ -3500,7 +3512,7 @@ export class BpmnNamespaceManager {
*/
static attributesInNamespace(list, nameSpace) {
// Some Attributes do not have a namespace declared explicitly. Since we test the parent for the correct namespace this is ok.
- return list.filter(el => !el.namespaceURI || el.namespaceURI === nameSpace)
+ return list.filter((el) => !el.namespaceURI || el.namespaceURI === nameSpace)
}
/**
@@ -3635,7 +3647,7 @@ export class BpmnShape {
id = null
// Get all additional Attributes
// Attribute which indicates the orientation if this is a pool or lane
- isHorizontal = false
+ isHorizontal = null
// String id of the expansion state of this shape
isExpanded = null
// Determines, if a marker should be depicted on the shape for exclusive Gateways.
@@ -3666,9 +3678,12 @@ export class BpmnShape {
this.id = BpmnNamespaceManager.getAttributeValue(xShape, BpmnNamespaceManager.BPMN_DI, 'id')
- this.isHorizontal = convertToBoolean(
- BpmnNamespaceManager.getAttributeValue(xShape, BpmnNamespaceManager.BPMN_DI, 'isHorizontal')
+ const isHorizontalString = BpmnNamespaceManager.getAttributeValue(
+ xShape,
+ BpmnNamespaceManager.BPMN_DI,
+ 'isHorizontal'
)
+ this.isHorizontal = isHorizontalString != null ? convertToBoolean(isHorizontalString) : null
this.isExpanded = BpmnNamespaceManager.getAttributeValue(
xShape,
BpmnNamespaceManager.BPMN_DI,
@@ -3843,10 +3858,6 @@ export class MultiLabelFolderNodeConverter extends DefaultFolderNodeConverter {
*/
copyLabels = false
- constructor() {
- super()
- }
-
/**
* @param {!FolderNodeState} state
* @param {!IFoldingView} foldingView
diff --git a/demos/showcase/bpmn/bpmn-di.ts b/demos/showcase/bpmn/bpmn-di.ts
index aca8715ad..b2467a57d 100644
--- a/demos/showcase/bpmn/bpmn-di.ts
+++ b/demos/showcase/bpmn/bpmn-di.ts
@@ -282,20 +282,20 @@ export class BpmnDiParser {
return new Promise((resolve: (value?: BpmnDiagram | null) => void): void => {
if (selectDiagramCallback) {
selectDiagramCallback(
- topLevelDiagrams.map(d => ({
+ topLevelDiagrams.map((d) => ({
name: d.name,
nodeCount: d.plane!.listOfShapes.size,
edgeCount: d.plane!.listOfEdges.size
}))
).then((chosenName: string) => {
- diaToLoad = topLevelDiagrams.find(d => d.name === chosenName)
+ diaToLoad = topLevelDiagrams.find((d) => d.name === chosenName)
resolve(diaToLoad)
})
} else {
diaToLoad = topLevelDiagrams.at(0) ?? null
resolve(diaToLoad)
}
- }).then(diaToLoad => {
+ }).then((diaToLoad) => {
// Loads the selected Diagram into the supplied Graph
if (diaToLoad) {
this.loadDiagram(diaToLoad, null)
@@ -586,14 +586,14 @@ export class BpmnDiParser {
}
const groupNodes = this.masterGraph.nodes
- .filter(node => node.style instanceof GroupNodeStyle)
+ .filter((node) => node.style instanceof GroupNodeStyle)
.toList()
for (const groupNode of groupNodes) {
if (this.masterGraph.getChildren(groupNode).size === 0) {
const newChildren = this.masterGraph
.getChildren(this.masterGraph.getParent(groupNode))
.filter(
- child =>
+ (child) =>
child !== groupNode &&
groupNode.layout.contains(child.layout.topLeft) &&
groupNode.layout.contains(child.layout.bottomRight)
@@ -1417,7 +1417,7 @@ export class BpmnDiParser {
this.masterGraph.setStyle(node, partStyle)
const table = partStyle.tableNodeStyle.table
- if (shape.isHorizontal) {
+ if (shape.isHorizontal ?? false) {
const row = table.rootRow.childRows.first()
BpmnDiParser.addTableLabel(table, row, shape)
} else {
@@ -2091,7 +2091,7 @@ export class BpmnDiParser {
}
let layout: Rect = Rect.EMPTY
- let isHorizontal = false
+ let isHorizontal: boolean | null = null
let multipleInstance = false
let tableShape: BpmnShape | null = this.getShape(element, plane)
@@ -2115,20 +2115,30 @@ export class BpmnDiParser {
if (tableShape) {
// table has a shape itself so we use its layout to initialize the table
layout = new Rect(tableShape.x, tableShape.y, tableShape.width, tableShape.height)
- isHorizontal = tableShape.isHorizontal
- } else {
+ if (tableShape.isHorizontal != null) {
+ isHorizontal = tableShape.isHorizontal
+ }
+ }
+ const calculateRect = layout.isEmpty
+ if (calculateRect || isHorizontal == null) {
// check the child lanes for their shapes
for (const lane of element.getChildren('lane')) {
const laneShape = this.getShape(lane, plane)
if (laneShape) {
- layout = Rect.add(
- layout,
- new Rect(laneShape.x, laneShape.y, laneShape.width, laneShape.height)
- )
- isHorizontal = laneShape.isHorizontal
+ if (calculateRect) {
+ layout = Rect.add(
+ layout,
+ new Rect(laneShape.x, laneShape.y, laneShape.width, laneShape.height)
+ )
+ }
+ if (isHorizontal == null && laneShape.isHorizontal != null) {
+ isHorizontal = laneShape.isHorizontal
+ }
}
}
}
+ // fallback
+ isHorizontal = isHorizontal ?? false
let node: INode
if (!layout.isEmpty) {
let table: ITable
@@ -2171,7 +2181,7 @@ export class BpmnDiParser {
? table.rootRow.childRows.at(0) ?? table.rootRow
: table.rootColumn.childColumns.at(0) ?? table.rootColumn
if (tableShape) {
- parentStripe = this.addToTable(tableShape, table, node, parentStripe)
+ parentStripe = this.addToTable(tableShape, table, node, parentStripe, isHorizontal)
}
element.node = node
@@ -2179,7 +2189,7 @@ export class BpmnDiParser {
parent.node = node
}
- this.addChildLanes(element, table, parentStripe, plane, node)
+ this.addChildLanes(element, table, parentStripe, plane, node, isHorizontal)
// Resize the root row/column after adding a column/row with insets
if (isHorizontal) {
@@ -2219,12 +2229,13 @@ export class BpmnDiParser {
table: ITable,
parentStripe: IStripe,
plane: BpmnPlane,
- node: INode
+ node: INode,
+ isHorizontal: boolean
): void {
for (const lane of element.getChildren('lane')) {
const laneShape = this.getShape(lane, plane)
if (laneShape) {
- const addedStripe = this.addToTable(laneShape, table, node, parentStripe)
+ const addedStripe = this.addToTable(laneShape, table, node, parentStripe, isHorizontal)
for (const refElement of lane.getChildren('flowNodeRef')) {
const bpmnElement = { value: null }
if (refElement.value && this.tryGetElementForId(refElement.value, bpmnElement)) {
@@ -2233,7 +2244,7 @@ export class BpmnDiParser {
}
const childLaneSet = lane.getChild('childLaneSet')
if (childLaneSet) {
- this.addChildLanes(childLaneSet, table, addedStripe, plane, node)
+ this.addChildLanes(childLaneSet, table, addedStripe, plane, node, isHorizontal)
}
}
}
@@ -2242,18 +2253,24 @@ export class BpmnDiParser {
/**
* Adds the given lane to the appropriate table (pool), or creates a new one
*/
- private addToTable(shape: BpmnShape, table: ITable, node: INode, parentStripe: IStripe): IStripe {
+ private addToTable(
+ shape: BpmnShape,
+ table: ITable,
+ node: INode,
+ parentStripe: IStripe,
+ isHorizontal: boolean
+ ): IStripe {
// lane element
const element = shape.element!
// Link the node to the BpmnElement of the lane
element.node = node
- if (shape.isHorizontal) {
+ if (isHorizontal) {
const parentRow = parentStripe instanceof IRow ? parentStripe : null
// getIndex
const index = parentRow
- ? parentRow.childRows.filter(siblingRow => siblingRow.tag.y < shape.y).size
+ ? parentRow.childRows.filter((siblingRow) => siblingRow.tag.y < shape.y).size
: -1
const row = table.createChildRow(parentRow, shape.height, null, null, null, null, index)
@@ -2265,7 +2282,7 @@ export class BpmnDiParser {
const parentCol = IColumn.isInstance(parentStripe) ? parentStripe : null
// getIndex
const index = parentCol
- ? parentCol.childColumns.filter(siblingCol => siblingCol.tag.x < shape.x).size
+ ? parentCol.childColumns.filter((siblingCol) => siblingCol.tag.x < shape.x).size
: -1
const col = table.createChildColumn(parentCol, shape.width, null, null, null, null, index)
@@ -2279,7 +2296,7 @@ export class BpmnDiParser {
* Creates table (participant/pool)
*/
private static createTable(shape: BpmnShape): PoolNodeStyle {
- const poolNodeStyle = BpmnDiParser.createPoolNodeStyle(shape.isHorizontal)
+ const poolNodeStyle = BpmnDiParser.createPoolNodeStyle(shape.isHorizontal ?? false)
const table = poolNodeStyle.tableNodeStyle.table
// Create first row & column
@@ -3419,7 +3436,7 @@ export class BpmnNamespaceManager {
*/
static attributesInNamespace(list: IEnumerable, nameSpace: string): IEnumerable {
// Some Attributes do not have a namespace declared explicitly. Since we test the parent for the correct namespace this is ok.
- return list.filter(el => !el.namespaceURI || el.namespaceURI === nameSpace)
+ return list.filter((el) => !el.namespaceURI || el.namespaceURI === nameSpace)
}
/**
@@ -3556,7 +3573,7 @@ export class BpmnShape {
id: string = null!
// Get all additional Attributes
// Attribute which indicates the orientation if this is a pool or lane
- isHorizontal = false
+ isHorizontal: boolean | null = null
// String id of the expansion state of this shape
isExpanded: string = null!
// Determines, if a marker should be depicted on the shape for exclusive Gateways.
@@ -3587,9 +3604,12 @@ export class BpmnShape {
this.id = BpmnNamespaceManager.getAttributeValue(xShape, BpmnNamespaceManager.BPMN_DI, 'id')
- this.isHorizontal = convertToBoolean(
- BpmnNamespaceManager.getAttributeValue(xShape, BpmnNamespaceManager.BPMN_DI, 'isHorizontal')
+ const isHorizontalString = BpmnNamespaceManager.getAttributeValue(
+ xShape,
+ BpmnNamespaceManager.BPMN_DI,
+ 'isHorizontal'
)
+ this.isHorizontal = isHorizontalString != null ? convertToBoolean(isHorizontalString) : null
this.isExpanded = BpmnNamespaceManager.getAttributeValue(
xShape,
BpmnNamespaceManager.BPMN_DI,
@@ -3762,10 +3782,6 @@ export class MultiLabelFolderNodeConverter extends DefaultFolderNodeConverter {
*/
copyLabels = false
- constructor() {
- super()
- }
-
updateFolderNodeState(
state: FolderNodeState,
foldingView: IFoldingView,
diff --git a/demos/showcase/bpmn/bpmn-view.js b/demos/showcase/bpmn/bpmn-view.js
index cfc7f87cd..15a83a6d5 100644
--- a/demos/showcase/bpmn/bpmn-view.js
+++ b/demos/showcase/bpmn/bpmn-view.js
@@ -505,7 +505,7 @@ class ScalingLabelModel extends BaseClass(ILabelModel) {
* @param {!Class.} type the type for which an instance shall be returned
* @returns {?T} an instance that is assignable to type or `null`
* @see Specified by {@link ILookup.lookup}.
- * @template {*} T
+ * @template T
*/
lookup(type) {
return ScalingLabelModel.STRETCH_MODEL.lookup(type)
@@ -743,7 +743,7 @@ export class BpmnPortCandidateProvider extends PortCandidateProviderBase {
const portCandidates = new List()
// provide existing ports as candidates only if they use EventPortStyle and have no edges attached to them.
- node.ports.forEach(port => {
+ node.ports.forEach((port) => {
if (port.style instanceof EventPortStyle && context.graph.edgesAt(port).size === 0) {
portCandidates.add(new DefaultPortCandidate(port))
}
@@ -920,7 +920,7 @@ class AspectRatioHandle extends BaseClass(IHandle) {
let deltaDragY = newLocation.y - originalLocation.y
if (this.ratio === 0) {
deltaDragX = 0
- } else if (!isFinite(this.ratio)) {
+ } else if (!Number.isFinite(this.ratio)) {
deltaDragY = 0
} else if (Math.abs(this.ratio) > 1) {
const sign =
@@ -1361,7 +1361,7 @@ export class ChoreographyLabelModel extends BaseClass(ILabelModel, ILabelModelPa
* @param {!Class.} type the type for which an instance shall be returned
* @returns {?T} an instance that is assignable to type or `null`
* @see Specified by {@link ILookup.lookup}.
- * @template {*} T
+ * @template T
*/
lookup(type) {
if (type === ILabelModelParameterProvider.$class) {
@@ -1429,7 +1429,7 @@ export class ChoreographyLabelModel extends BaseClass(ILabelModel, ILabelModelPa
)
// check which label positions are already taken
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
if (label.layoutParameter instanceof ChoreographyParameter) {
let index = 0
const parameter = label.layoutParameter
@@ -1932,7 +1932,7 @@ class LineUpIcon extends Icon {
const container = new SvgVisualGroup()
let offset = 0
- this.icons.forEach(pathIcon => {
+ this.icons.forEach((pathIcon) => {
pathIcon.setBounds(new Rect(offset, 0, this.innerIconSize.width, this.innerIconSize.height))
const pathIconVisual = pathIcon.createVisual(context)
container.add(pathIconVisual)
@@ -2126,7 +2126,7 @@ class CombinedIcon extends Icon {
const container = new SvgVisualGroup()
const iconBounds = new Rect(Point.ORIGIN, this.bounds.toSize())
- this.icons.forEach(icon => {
+ this.icons.forEach((icon) => {
icon.setBounds(iconBounds)
const iconVisual = icon.createVisual(context)
container.add(iconVisual)
@@ -4665,7 +4665,7 @@ class ParticipantList extends BaseClass(IList) {
*/
getHeight() {
let height = 0
- this.innerList.forEach(participant => {
+ this.innerList.forEach((participant) => {
height += participant.getSize()
})
return height
@@ -4676,7 +4676,7 @@ class ParticipantList extends BaseClass(IList) {
*/
getParticipantModCount() {
let participantCount = 0
- this.innerList.forEach(participant => {
+ this.innerList.forEach((participant) => {
participantCount += participant.modCount
})
return participantCount
@@ -5303,7 +5303,7 @@ export class ChoreographyNodeStyle extends BpmnNodeStyle {
// top participants
let topOffset = 0
let first = true
- this._topParticipants.forEach(participant => {
+ this._topParticipants.forEach((participant) => {
const participantIcon = this.createParticipantIcon(participant, true, first)
tpi.add(participantIcon)
const height = participant.getSize()
@@ -5318,7 +5318,7 @@ export class ChoreographyNodeStyle extends BpmnNodeStyle {
// bottom participants
let bottomOffset = bounds.height
first = true
- this._bottomParticipants.forEach(participant => {
+ this._bottomParticipants.forEach((participant) => {
const participantIcon = this.createParticipantIcon(participant, false, first)
bpi.add(participantIcon)
const height = participant.getSize()
@@ -5813,10 +5813,10 @@ export class ChoreographyNodeStyle extends BpmnNodeStyle {
clone.background = this.background
clone.messageOutline = this.messageOutline
- this.topParticipants.forEach(participant => {
+ this.topParticipants.forEach((participant) => {
clone.topParticipants.add(participant.clone())
})
- this.bottomParticipants.forEach(participant => {
+ this.bottomParticipants.forEach((participant) => {
clone.bottomParticipants.add(participant.clone())
})
return clone
@@ -7527,14 +7527,14 @@ export class AlternatingLeafStripeStyle extends StripeStyleBase {
// Get all leaf columns
const leaves = col.table.rootColumn.leaves.toList()
// Determine the index
- index = leaves.findIndex(curr => col === curr)
+ index = leaves.findIndex((curr) => col === curr)
// Use the correct descriptor
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
} else {
const row = stripe
const leaves = row.table.rootRow.leaves.toList()
- index = leaves.findIndex(curr => row === curr)
+ index = leaves.findIndex((curr) => row === curr)
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
}
@@ -7595,13 +7595,13 @@ export class AlternatingLeafStripeStyle extends StripeStyleBase {
if (stripe instanceof IColumn) {
const col = stripe
const leaves = col.table.rootColumn.leaves.toList()
- index = leaves.findIndex(curr => col === curr)
+ index = leaves.findIndex((curr) => col === curr)
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
} else {
const row = stripe
const leaves = row.table.rootRow.leaves.toList()
- index = leaves.findIndex(curr => row === curr)
+ index = leaves.findIndex((curr) => row === curr)
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
}
@@ -9013,7 +9013,7 @@ export class PoolHeaderLabelModel extends BaseClass(ILabelModel, ILabelModelPara
* @param {!Class.} type the type for which an instance shall be returned
* @returns {?T} an instance that is assignable to type or `null`
* @see Specified by {@link ILookup.lookup}.
- * @template {*} T
+ * @template T
*/
lookup(type) {
if (type === ILabelModelParameterProvider.$class) {
@@ -10312,10 +10312,6 @@ export class GroupNodeStyle extends BaseClass(INodeStyle) {
_insets = new Insets(15)
_renderer = new GroupNodeStyleRenderer()
- constructor() {
- super()
- }
-
/**
* Gets the insets for the node.
* These insets are returned via an {@link INodeInsetsProvider} if such an instance is queried
@@ -10581,7 +10577,7 @@ class GroupNodeStyleRenderer extends BaseClass(INodeStyleRenderer, ILookup) {
* @param {!Class.} type the type for which an instance shall be returned
* @returns {?T} an instance that is assignable to type or `null`
* @see Specified by {@link ILookup.lookup}.
- * @template {*} T
+ * @template T
*/
lookup(type) {
if (type === INodeInsetsProvider.$class && this.lastStyle != null) {
@@ -11100,7 +11096,7 @@ class EventPortStyleRenderer extends BaseClass(IPortStyleRenderer, ILookup) {
* @param {!Class.} type the type for which an instance shall be returned
* @returns {?T} an instance that is assignable to type or `null`
* @see Specified by {@link ILookup.lookup}.
- * @template {*} T
+ * @template T
*/
lookup(type) {
if (type === IEdgePathCropper.$class) {
@@ -11222,10 +11218,6 @@ class DataObjectIcon extends Icon {
fill = null
stroke = null
- constructor() {
- super()
- }
-
/**
* @param {!IRenderContext} context
* @returns {!SvgVisual}
@@ -11435,7 +11427,7 @@ class CollapseButtonIcon extends Icon {
false
)
- this.onTouchEndDelegate = event => {
+ this.onTouchEndDelegate = (event) => {
// prevent click event
event.preventDefault()
this.onTouchEnd(button, currentItem, context)
@@ -12701,10 +12693,10 @@ export class ChoreographyNodeStyleExtension extends MarkupExtension {
const style = new ChoreographyNodeStyle()
style.loopCharacteristic = this.loopCharacteristic
style.subState = this.subState
- this.topParticipants.forEach(participant => {
+ this.topParticipants.forEach((participant) => {
style.topParticipants.add(participant)
})
- this.bottomParticipants.forEach(participant => {
+ this.bottomParticipants.forEach((participant) => {
style.bottomParticipants.add(participant)
})
style.initiatingMessage = this.initiatingMessage
@@ -13051,10 +13043,10 @@ export class LegacyChoreographyNodeStyleExtension extends MarkupExtension {
const style = new ChoreographyNodeStyle()
style.loopCharacteristic = this.loopCharacteristic
style.subState = this.subState
- this.topParticipants.forEach(participant => {
+ this.topParticipants.forEach((participant) => {
style.topParticipants.add(participant)
})
- this.bottomParticipants.forEach(participant => {
+ this.bottomParticipants.forEach((participant) => {
style.bottomParticipants.add(participant)
})
style.initiatingMessage = this.initiatingMessage
@@ -14351,10 +14343,10 @@ export const BpmnHandleSerializationListener = (source, args) => {
markupExtension = new ChoreographyNodeStyleExtension()
markupExtension.loopCharacteristic = item.loopCharacteristic
markupExtension.subState = item.subState
- item.topParticipants.forEach(participant => {
+ item.topParticipants.forEach((participant) => {
markupExtension.topParticipants.add(participant)
})
- item.bottomParticipants.forEach(participant => {
+ item.bottomParticipants.forEach((participant) => {
markupExtension.bottomParticipants.add(participant)
})
markupExtension.initiatingMessage = item.initiatingMessage
diff --git a/demos/showcase/bpmn/bpmn-view.ts b/demos/showcase/bpmn/bpmn-view.ts
index fd6b31c52..6776a44ab 100644
--- a/demos/showcase/bpmn/bpmn-view.ts
+++ b/demos/showcase/bpmn/bpmn-view.ts
@@ -499,7 +499,7 @@ class ScalingLabelModel extends BaseClass(ILabelModel) {
* @see Specified by {@link ILookup.lookup}.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
return ScalingLabelModel.STRETCH_MODEL.lookup(type)
}
@@ -694,7 +694,7 @@ export class BpmnPortCandidateProvider extends PortCandidateProviderBase {
const portCandidates = new List()
// provide existing ports as candidates only if they use EventPortStyle and have no edges attached to them.
- node.ports.forEach(port => {
+ node.ports.forEach((port) => {
if (port.style instanceof EventPortStyle && context.graph!.edgesAt(port).size === 0) {
portCandidates.add(new DefaultPortCandidate(port))
}
@@ -854,7 +854,7 @@ class AspectRatioHandle extends BaseClass(IHandle) {
let deltaDragY = newLocation.y - originalLocation.y
if (this.ratio === 0) {
deltaDragX = 0
- } else if (!isFinite(this.ratio)) {
+ } else if (!Number.isFinite(this.ratio)) {
deltaDragY = 0
} else if (Math.abs(this.ratio) > 1) {
const sign =
@@ -1256,7 +1256,7 @@ export class ChoreographyLabelModel extends BaseClass(ILabelModel, ILabelModelPa
* @see Specified by {@link ILookup.lookup}.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
if (type === ILabelModelParameterProvider.$class) {
return this as unknown as T
}
@@ -1320,7 +1320,7 @@ export class ChoreographyLabelModel extends BaseClass(ILabelModel, ILabelModelPa
)
// check which label positions are already taken
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
if (label.layoutParameter instanceof ChoreographyParameter) {
let index = 0
const parameter = label.layoutParameter
@@ -1753,7 +1753,7 @@ class LineUpIcon extends Icon {
const container = new SvgVisualGroup()
let offset = 0
- this.icons.forEach(pathIcon => {
+ this.icons.forEach((pathIcon) => {
pathIcon.setBounds(new Rect(offset, 0, this.innerIconSize.width, this.innerIconSize.height))
const pathIconVisual = pathIcon.createVisual(context)!
container.add(pathIconVisual)
@@ -1903,7 +1903,7 @@ class CombinedIcon extends Icon {
const container = new SvgVisualGroup()
const iconBounds = new Rect(Point.ORIGIN, this.bounds.toSize())
- this.icons.forEach(icon => {
+ this.icons.forEach((icon) => {
icon.setBounds(iconBounds)
const iconVisual = icon.createVisual(context)!
container.add(iconVisual)
@@ -4113,7 +4113,7 @@ class ParticipantList extends BaseClass(IList) {
getHeight(): number {
let height = 0
- this.innerList.forEach(participant => {
+ this.innerList.forEach((participant) => {
height += participant.getSize()
})
return height
@@ -4121,7 +4121,7 @@ class ParticipantList extends BaseClass(IList) {
getParticipantModCount(): number {
let participantCount = 0
- this.innerList.forEach(participant => {
+ this.innerList.forEach((participant) => {
participantCount += participant.modCount
})
return participantCount
@@ -4668,7 +4668,7 @@ export class ChoreographyNodeStyle extends BpmnNodeStyle {
// top participants
let topOffset = 0
let first = true
- this._topParticipants.forEach(participant => {
+ this._topParticipants.forEach((participant) => {
const participantIcon = this.createParticipantIcon(participant, true, first)
tpi.add(participantIcon)
const height = participant.getSize()
@@ -4683,7 +4683,7 @@ export class ChoreographyNodeStyle extends BpmnNodeStyle {
// bottom participants
let bottomOffset = bounds.height
first = true
- this._bottomParticipants.forEach(participant => {
+ this._bottomParticipants.forEach((participant) => {
const participantIcon = this.createParticipantIcon(participant, false, first)
bpi.add(participantIcon)
const height = participant.getSize()
@@ -5169,10 +5169,10 @@ export class ChoreographyNodeStyle extends BpmnNodeStyle {
clone.background = this.background
clone.messageOutline = this.messageOutline
- this.topParticipants.forEach(participant => {
+ this.topParticipants.forEach((participant) => {
clone.topParticipants.add(participant.clone())
})
- this.bottomParticipants.forEach(participant => {
+ this.bottomParticipants.forEach((participant) => {
clone.bottomParticipants.add(participant.clone())
})
return clone as this
@@ -6748,14 +6748,14 @@ export class AlternatingLeafStripeStyle extends StripeStyleBase {
// Get all leaf columns
const leaves = col.table!.rootColumn.leaves.toList()
// Determine the index
- index = leaves.findIndex(curr => col === curr)
+ index = leaves.findIndex((curr) => col === curr)
// Use the correct descriptor
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
} else {
const row = stripe as IRow
const leaves = row.table!.rootRow.leaves.toList()
- index = leaves.findIndex(curr => row === curr)
+ index = leaves.findIndex((curr) => row === curr)
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
}
@@ -6824,13 +6824,13 @@ export class AlternatingLeafStripeStyle extends StripeStyleBase {
if (stripe instanceof IColumn) {
const col = stripe
const leaves = col.table!.rootColumn.leaves.toList()
- index = leaves.findIndex(curr => col === curr)
+ index = leaves.findIndex((curr) => col === curr)
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
} else {
const row = stripe as IRow
const leaves = row.table!.rootRow.leaves.toList()
- index = leaves.findIndex(curr => row === curr)
+ index = leaves.findIndex((curr) => row === curr)
descriptor = index % 2 === 0 ? this.evenLeafDescriptor : this.oddLeafDescriptor
actualBorderThickness = descriptor.borderThickness
}
@@ -8155,7 +8155,7 @@ export class PoolHeaderLabelModel extends BaseClass(ILabelModel, ILabelModelPara
* @see Specified by {@link ILookup.lookup}.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
if (type === ILabelModelParameterProvider.$class) {
return this as unknown as T
}
@@ -9324,10 +9324,6 @@ export class GroupNodeStyle extends BaseClass(INodeStyle) {
private _insets: Insets = new Insets(15)
private _renderer: GroupNodeStyleRenderer = new GroupNodeStyleRenderer()
- constructor() {
- super()
- }
-
/**
* Gets the insets for the node.
* These insets are returned via an {@link INodeInsetsProvider} if such an instance is queried
@@ -9584,7 +9580,7 @@ class GroupNodeStyleRenderer extends BaseClass(INodeStyleRenderer, ILookup) {
* @see Specified by {@link ILookup.lookup}.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
if (type === INodeInsetsProvider.$class && this.lastStyle != null) {
return new GroupInsetsProvider(this.lastStyle) as T
}
@@ -10064,7 +10060,7 @@ class EventPortStyleRenderer extends BaseClass(IPortStyleRenderer, ILookup) {
* @see Specified by {@link ILookup.lookup}.
*/
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
- lookup(type: Class): T | null {
+ lookup(type: Class): T | null {
if (type === IEdgePathCropper.$class) {
return EventPortEdgeIntersectionCalculator.CalculatorInstance as T
}
@@ -10164,10 +10160,6 @@ class DataObjectIcon extends Icon {
fill: Fill | null = null
stroke: Stroke | null = null
- constructor() {
- super()
- }
-
createVisual(context: IRenderContext): SvgVisual {
const container = document.createElementNS('http://www.w3.org/2000/svg', 'g')
@@ -11317,10 +11309,10 @@ export class ChoreographyNodeStyleExtension extends MarkupExtension {
const style = new ChoreographyNodeStyle()
style.loopCharacteristic = this.loopCharacteristic
style.subState = this.subState
- this.topParticipants.forEach(participant => {
+ this.topParticipants.forEach((participant) => {
style.topParticipants.add(participant)
})
- this.bottomParticipants.forEach(participant => {
+ this.bottomParticipants.forEach((participant) => {
style.bottomParticipants.add(participant)
})
style.initiatingMessage = this.initiatingMessage
@@ -11581,10 +11573,10 @@ export class LegacyChoreographyNodeStyleExtension extends MarkupExtension {
const style = new ChoreographyNodeStyle()
style.loopCharacteristic = this.loopCharacteristic
style.subState = this.subState
- this.topParticipants.forEach(participant => {
+ this.topParticipants.forEach((participant) => {
style.topParticipants.add(participant)
})
- this.bottomParticipants.forEach(participant => {
+ this.bottomParticipants.forEach((participant) => {
style.bottomParticipants.add(participant)
})
style.initiatingMessage = this.initiatingMessage
@@ -12566,10 +12558,10 @@ export const BpmnHandleSerializationListener = (
markupExtension = new ChoreographyNodeStyleExtension()
markupExtension.loopCharacteristic = item.loopCharacteristic
markupExtension.subState = item.subState
- item.topParticipants.forEach(participant => {
+ item.topParticipants.forEach((participant) => {
markupExtension.topParticipants.add(participant)
})
- item.bottomParticipants.forEach(participant => {
+ item.bottomParticipants.forEach((participant) => {
markupExtension.bottomParticipants.add(participant)
})
markupExtension.initiatingMessage = item.initiatingMessage
diff --git a/demos/showcase/bpmn/index.html b/demos/showcase/bpmn/index.html
index 3ae6e3960..a18d99885 100644
--- a/demos/showcase/bpmn/index.html
+++ b/demos/showcase/bpmn/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.js b/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.js
index 82d086529..16c7d3a48 100644
--- a/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.js
+++ b/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.js
@@ -167,7 +167,7 @@ export function configureHighlight(graphComponent) {
// highlight the node, its adjacent edges and the node labels
const node = item
highlightNode(node, highlightIndicatorManager)
- graphComponent.graph.edgesAt(node).forEach(edge => {
+ graphComponent.graph.edgesAt(node).forEach((edge) => {
highlightIndicatorManager.addHighlight(edge)
})
} else if (item instanceof IEdge) {
@@ -187,7 +187,7 @@ export function configureHighlight(graphComponent) {
*/
function highlightNode(node, highlightIndicatorManager) {
highlightIndicatorManager.addHighlight(node)
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
highlightIndicatorManager.addHighlight(label)
})
}
diff --git a/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.ts b/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.ts
index ff6576cb4..9c37d9c77 100644
--- a/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.ts
+++ b/demos/showcase/chord-diagram-non-ribbon/HighlightSupport.ts
@@ -165,7 +165,7 @@ export function configureHighlight(graphComponent: GraphComponent) {
// highlight the node, its adjacent edges and the node labels
const node = item
highlightNode(node, highlightIndicatorManager)
- graphComponent.graph.edgesAt(node).forEach(edge => {
+ graphComponent.graph.edgesAt(node).forEach((edge) => {
highlightIndicatorManager.addHighlight(edge)
})
} else if (item instanceof IEdge) {
@@ -188,7 +188,7 @@ function highlightNode(
highlightIndicatorManager: HighlightIndicatorManager
) {
highlightIndicatorManager.addHighlight(node)
- node.labels.forEach(label => {
+ node.labels.forEach((label) => {
highlightIndicatorManager.addHighlight(label)
})
}
diff --git a/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.js b/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.js
index 0ed44c9cf..f21ad6928 100644
--- a/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.js
+++ b/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.js
@@ -165,7 +165,7 @@ async function initializeGraph(graphComponent) {
nodeStyle: VoidNodeStyle.INSTANCE,
edgeStyle: VoidEdgeStyle.INSTANCE
})
- const graphData = await fetch('resources/GraphData.json').then(response => response.json())
+ const graphData = await fetch('resources/GraphData.json').then((response) => response.json())
const builder = new GraphBuilder(graph)
const nodesSource = builder.createNodesSource({
@@ -176,7 +176,7 @@ async function initializeGraph(graphComponent) {
tag: 'tag'
})
- nodesSource.nodeCreator.styleProvider = data => {
+ nodesSource.nodeCreator.styleProvider = (data) => {
const colorSet = colorSets[predefinedColorSets.get(data.tag?.department) || 'demo-palette-41']
return new ShapeNodeStyle({
shape: 'ellipse',
@@ -196,7 +196,7 @@ async function initializeGraph(graphComponent) {
builder.buildGraph()
// sets the style for the labels
- graph.labels.forEach(label => {
+ graph.labels.forEach((label) => {
const colorSet =
colorSets[predefinedColorSets.get(label.owner.tag?.department) || 'demo-palette-41']
graph.setStyle(
@@ -213,7 +213,7 @@ async function initializeGraph(graphComponent) {
// normalizes the nodes based on the number of connections stored in the tag
let minConnections = Number.MAX_VALUE
let maxConnections = -Number.MAX_VALUE
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const connections = node.tag?.connections || 1
minConnections = Math.min(minConnections, connections)
maxConnections = Math.max(maxConnections, connections)
@@ -222,7 +222,7 @@ async function initializeGraph(graphComponent) {
const largest = 100
const smallest = 40
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const connections = node.tag?.connections || 1
const sizeScale = (largest - smallest) / connectionsDelta
const size = Math.floor(smallest + (connections - minConnections) * sizeScale)
@@ -235,7 +235,7 @@ async function initializeGraph(graphComponent) {
* @param {!GraphComponent} graphComponent The given graphComponent
*/
function initializeUI(graphComponent) {
- document.querySelector('#labelStyleSelect').addEventListener('change', async evt => {
+ document.querySelector('#labelStyleSelect').addEventListener('change', async (evt) => {
await configureAndRunChordLayout(graphComponent, evt.target.value)
})
document.querySelector('#labelStyleRayLike').addEventListener('click', async () => {
@@ -279,7 +279,7 @@ async function configureAndRunChordLayout(graphComponent, labelingPolicy) {
// creates the layout data needed in order to sort the edges based on their type
const chordLayoutData = new CircularLayoutData({
- nodeTypes: node => node.tag?.department
+ nodeTypes: (node) => node.tag?.department
})
// apply the layout
diff --git a/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.ts b/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.ts
index 933c24e27..d6498847c 100644
--- a/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.ts
+++ b/demos/showcase/chord-diagram-non-ribbon/NonRibbonChordDiagramDemo.ts
@@ -164,7 +164,7 @@ async function initializeGraph(graphComponent: GraphComponent): Promise {
nodeStyle: VoidNodeStyle.INSTANCE,
edgeStyle: VoidEdgeStyle.INSTANCE
})
- const graphData = await fetch('resources/GraphData.json').then(response => response.json())
+ const graphData = await fetch('resources/GraphData.json').then((response) => response.json())
const builder = new GraphBuilder(graph)
const nodesSource = builder.createNodesSource({
@@ -195,7 +195,7 @@ async function initializeGraph(graphComponent: GraphComponent): Promise {
builder.buildGraph()
// sets the style for the labels
- graph.labels.forEach(label => {
+ graph.labels.forEach((label) => {
const colorSet =
colorSets[predefinedColorSets.get(label.owner!.tag?.department) || 'demo-palette-41']
graph.setStyle(
@@ -212,7 +212,7 @@ async function initializeGraph(graphComponent: GraphComponent): Promise {
// normalizes the nodes based on the number of connections stored in the tag
let minConnections = Number.MAX_VALUE
let maxConnections = -Number.MAX_VALUE
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const connections = node.tag?.connections || 1
minConnections = Math.min(minConnections, connections)
maxConnections = Math.max(maxConnections, connections)
@@ -221,7 +221,7 @@ async function initializeGraph(graphComponent: GraphComponent): Promise {
const largest = 100
const smallest = 40
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const connections = node.tag?.connections || 1
const sizeScale = (largest - smallest) / connectionsDelta
const size = Math.floor(smallest + (connections - minConnections) * sizeScale)
@@ -236,7 +236,7 @@ async function initializeGraph(graphComponent: GraphComponent): Promise {
function initializeUI(graphComponent: GraphComponent): void {
document
.querySelector('#labelStyleSelect')!
- .addEventListener('change', async evt => {
+ .addEventListener('change', async (evt) => {
await configureAndRunChordLayout(
graphComponent,
(evt.target as HTMLSelectElement).value as NodeLabelingPolicyStringValues
diff --git a/demos/showcase/chord-diagram-non-ribbon/index.html b/demos/showcase/chord-diagram-non-ribbon/index.html
index d8eacc029..001288bdb 100644
--- a/demos/showcase/chord-diagram-non-ribbon/index.html
+++ b/demos/showcase/chord-diagram-non-ribbon/index.html
@@ -1,4 +1,4 @@
-
+
@@ -42,7 +42,9 @@
.yfiles-tooltip {
background: #ebeef0;
color: #29323c;
- box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
+ box-shadow:
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2),
+ 0 4px 5px 0 rgba(0, 0, 0, 0.14),
0 1px 10px 0 rgba(0, 0, 0, 0.12);
padding: 6px;
border-radius: 4px;
diff --git a/demos/showcase/chord-diagram/ChordDiagramDemo.js b/demos/showcase/chord-diagram/ChordDiagramDemo.js
index 197da22e8..452a1a6a4 100644
--- a/demos/showcase/chord-diagram/ChordDiagramDemo.js
+++ b/demos/showcase/chord-diagram/ChordDiagramDemo.js
@@ -108,14 +108,14 @@ function configureUserInteraction(graphComponent) {
gvim.itemHoverInputMode.addHoveredItemChangedListener((_, evt) => {
// reset opacities of all edges
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge.tag.opacity = ChordEdgeStyle.defaultOpacity
})
// if hovered on a node, highlight all edges of this node
if (evt.item instanceof INode) {
const node = evt.item
- graph.edgesAt(node).forEach(edge => {
+ graph.edgesAt(node).forEach((edge) => {
edge.tag.opacity = 1.0
manager.toFront(edge)
})
@@ -145,9 +145,9 @@ function configureUserInteraction(graphComponent) {
// deselect all other edges
graphComponent.selection.selectedEdges
- .filter(e => e != edge)
+ .filter((e) => e != edge)
.toList()
- .forEach(e => graphComponent.selection.setSelected(e, false))
+ .forEach((e) => graphComponent.selection.setSelected(e, false))
} else {
edge.tag.highlighted = false
slider.disabled = graphComponent.selection.selectedEdges.size == 0
@@ -189,7 +189,7 @@ function createSampleGraph(graph) {
builder.createNodesSource({
data: SampleData.nodes,
id: 'id',
- layout: data => new Rect(data.x, data.y, defaultNodeSize.width, defaultNodeSize.height)
+ layout: (data) => new Rect(data.x, data.y, defaultNodeSize.width, defaultNodeSize.height)
})
builder.createEdgesSource({
data: SampleData.edges,
@@ -204,7 +204,7 @@ function createSampleGraph(graph) {
ChordDiagramLayout.EDGE_WEIGHT_KEY
).mapper
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
// create initial weights for the edges, these are relative and will be normalized by the layout
weightMapping.set(edge, parseFloat(edge.tag.thickness))
})
@@ -268,15 +268,17 @@ function updateGapRatio(graphComponent, gapRatio) {
function initializeUI(graphComponent) {
document
.querySelector('#toggle-actual-graph')
- .addEventListener('change', evt => showGraph(graphComponent, evt.target.checked))
+ .addEventListener('change', (evt) => showGraph(graphComponent, evt.target.checked))
// when the slider is moved, increase/decrease the weight of the edge and update the chord layout
document
.querySelector('#thickness')
- .addEventListener('input', evt => updateDiagram(graphComponent, parseFloat(evt.target.value)))
+ .addEventListener('input', (evt) => updateDiagram(graphComponent, parseFloat(evt.target.value)))
// when the gap slider is moved increase/decrease the gaps between the nodes
document
.querySelector('#gap-ratio')
- .addEventListener('input', evt => updateGapRatio(graphComponent, parseFloat(evt.target.value)))
+ .addEventListener('input', (evt) =>
+ updateGapRatio(graphComponent, parseFloat(evt.target.value))
+ )
}
run().then(finishLoading)
diff --git a/demos/showcase/chord-diagram/ChordDiagramDemo.ts b/demos/showcase/chord-diagram/ChordDiagramDemo.ts
index 205796747..7d82060a3 100644
--- a/demos/showcase/chord-diagram/ChordDiagramDemo.ts
+++ b/demos/showcase/chord-diagram/ChordDiagramDemo.ts
@@ -105,14 +105,14 @@ function configureUserInteraction(graphComponent: GraphComponent): void {
gvim.itemHoverInputMode.addHoveredItemChangedListener((_, evt) => {
// reset opacities of all edges
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge.tag.opacity = ChordEdgeStyle.defaultOpacity
})
// if hovered on a node, highlight all edges of this node
if (evt.item instanceof INode) {
const node = evt.item
- graph.edgesAt(node).forEach(edge => {
+ graph.edgesAt(node).forEach((edge) => {
edge.tag.opacity = 1.0
manager.toFront(edge)
})
@@ -142,9 +142,9 @@ function configureUserInteraction(graphComponent: GraphComponent): void {
// deselect all other edges
graphComponent.selection.selectedEdges
- .filter(e => e != edge)
+ .filter((e) => e != edge)
.toList()
- .forEach(e => graphComponent.selection.setSelected(e, false))
+ .forEach((e) => graphComponent.selection.setSelected(e, false))
} else {
edge.tag.highlighted = false
slider.disabled = graphComponent.selection.selectedEdges.size == 0
@@ -185,7 +185,7 @@ function createSampleGraph(graph: IGraph): void {
builder.createNodesSource({
data: SampleData.nodes,
id: 'id',
- layout: data => new Rect(data.x, data.y, defaultNodeSize.width, defaultNodeSize.height)
+ layout: (data) => new Rect(data.x, data.y, defaultNodeSize.width, defaultNodeSize.height)
})
builder.createEdgesSource({
data: SampleData.edges,
@@ -200,7 +200,7 @@ function createSampleGraph(graph: IGraph): void {
ChordDiagramLayout.EDGE_WEIGHT_KEY
).mapper
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
// create initial weights for the edges, these are relative and will be normalized by the layout
weightMapping.set(edge, parseFloat(edge.tag.thickness))
})
@@ -261,19 +261,19 @@ function updateGapRatio(graphComponent: GraphComponent, gapRatio: number) {
function initializeUI(graphComponent: GraphComponent): void {
document
.querySelector('#toggle-actual-graph')!
- .addEventListener('change', evt =>
+ .addEventListener('change', (evt) =>
showGraph(graphComponent, (evt.target as HTMLInputElement).checked)
)
// when the slider is moved, increase/decrease the weight of the edge and update the chord layout
document
.querySelector('#thickness')!
- .addEventListener('input', evt =>
+ .addEventListener('input', (evt) =>
updateDiagram(graphComponent, parseFloat((evt.target as HTMLInputElement).value))
)
// when the gap slider is moved increase/decrease the gaps between the nodes
document
.querySelector('#gap-ratio')!
- .addEventListener('input', evt =>
+ .addEventListener('input', (evt) =>
updateGapRatio(graphComponent, parseFloat((evt.target as HTMLInputElement).value))
)
}
diff --git a/demos/showcase/chord-diagram/ChordDiagramLayout.js b/demos/showcase/chord-diagram/ChordDiagramLayout.js
index 69bb2e035..74976401e 100644
--- a/demos/showcase/chord-diagram/ChordDiagramLayout.js
+++ b/demos/showcase/chord-diagram/ChordDiagramLayout.js
@@ -128,7 +128,7 @@ export class ChordDiagramLayout extends LayoutStageBase {
)
// normalize the edge weights
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const votesOnEdge = edgeThicknessProvider.getNumber(edge)
const normalizedThickness = (votesOnEdge / totalEdgeWeights) * (Math.PI * (1 - this.gapRatio)) // reserve half the circle for gaps between nodes
edgeThicknessProvider.setNumber(edge, normalizedThickness)
@@ -143,21 +143,23 @@ export class ChordDiagramLayout extends LayoutStageBase {
// compute a map of node sizes. The node size is equal to the compound size of all edges at the node
const nodeSizes = graph.nodes
- .map(node => node.edges.reduce((acc, curr) => acc + edgeThicknessProvider.getNumber(curr), 0))
+ .map((node) =>
+ node.edges.reduce((acc, curr) => acc + edgeThicknessProvider.getNumber(curr), 0)
+ )
.toArray()
// sort edges to prevent intra-node crossings
graph.nodes.forEach((n, idx) => {
const outComparer = IComparer.create((edge0, edge1) => {
- const targetIndex0 = graph.nodes.findIndex(node => node == edge0.target)
- const targetIndex1 = graph.nodes.findIndex(node => node == edge1.target)
+ const targetIndex0 = graph.nodes.findIndex((node) => node == edge0.target)
+ const targetIndex1 = graph.nodes.findIndex((node) => node == edge1.target)
return compareEdges(idx, targetIndex0, targetIndex1, nodeSizes, gap)
})
n.sortOutEdges(outComparer)
const inComparer = IComparer.create((edge0, edge1) => {
- const targetIndex0 = graph.nodes.findIndex(node => node == edge0.source)
- const targetIndex1 = graph.nodes.findIndex(node => node == edge1.source)
+ const targetIndex0 = graph.nodes.findIndex((node) => node == edge0.source)
+ const targetIndex1 = graph.nodes.findIndex((node) => node == edge1.source)
return compareEdges(idx, targetIndex0, targetIndex1, nodeSizes, gap)
})
n.sortInEdges(inComparer)
diff --git a/demos/showcase/chord-diagram/ChordDiagramLayout.ts b/demos/showcase/chord-diagram/ChordDiagramLayout.ts
index 9f00b3a64..73013fb3f 100644
--- a/demos/showcase/chord-diagram/ChordDiagramLayout.ts
+++ b/demos/showcase/chord-diagram/ChordDiagramLayout.ts
@@ -102,7 +102,7 @@ export class ChordDiagramLayout extends LayoutStageBase {
)
// normalize the edge weights
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const votesOnEdge = edgeThicknessProvider.getNumber(edge)
const normalizedThickness = (votesOnEdge / totalEdgeWeights) * (Math.PI * (1 - this.gapRatio)) // reserve half the circle for gaps between nodes
edgeThicknessProvider.setNumber(edge, normalizedThickness)
@@ -117,21 +117,23 @@ export class ChordDiagramLayout extends LayoutStageBase {
// compute a map of node sizes. The node size is equal to the compound size of all edges at the node
const nodeSizes = graph.nodes
- .map(node => node.edges.reduce((acc, curr) => acc + edgeThicknessProvider.getNumber(curr), 0))
+ .map((node) =>
+ node.edges.reduce((acc, curr) => acc + edgeThicknessProvider.getNumber(curr), 0)
+ )
.toArray()
// sort edges to prevent intra-node crossings
graph.nodes.forEach((n, idx) => {
const outComparer = IComparer.create((edge0: Edge, edge1: Edge) => {
- const targetIndex0 = graph.nodes.findIndex(node => node == edge0.target)
- const targetIndex1 = graph.nodes.findIndex(node => node == edge1.target)
+ const targetIndex0 = graph.nodes.findIndex((node) => node == edge0.target)
+ const targetIndex1 = graph.nodes.findIndex((node) => node == edge1.target)
return compareEdges(idx, targetIndex0, targetIndex1, nodeSizes, gap)
})
n.sortOutEdges(outComparer)
const inComparer = IComparer.create((edge0: Edge, edge1: Edge) => {
- const targetIndex0 = graph.nodes.findIndex(node => node == edge0.source)
- const targetIndex1 = graph.nodes.findIndex(node => node == edge1.source)
+ const targetIndex0 = graph.nodes.findIndex((node) => node == edge0.source)
+ const targetIndex1 = graph.nodes.findIndex((node) => node == edge1.source)
return compareEdges(idx, targetIndex0, targetIndex1, nodeSizes, gap)
})
n.sortInEdges(inComparer)
diff --git a/demos/showcase/chord-diagram/CircleSegmentNodeStyle.ts b/demos/showcase/chord-diagram/CircleSegmentNodeStyle.ts
index 044fef29b..98641023d 100644
--- a/demos/showcase/chord-diagram/CircleSegmentNodeStyle.ts
+++ b/demos/showcase/chord-diagram/CircleSegmentNodeStyle.ts
@@ -356,7 +356,10 @@ type NodeData = {
}
class NodeRenderDataCache {
- constructor(public readonly nodeData: NodeData, public readonly showStyleHints: boolean) {}
+ constructor(
+ public readonly nodeData: NodeData,
+ public readonly showStyleHints: boolean
+ ) {}
equals(other?: NodeRenderDataCache): boolean {
if (!other) {
diff --git a/demos/showcase/chord-diagram/index.html b/demos/showcase/chord-diagram/index.html
index 1092f50bc..5fd6d3346 100644
--- a/demos/showcase/chord-diagram/index.html
+++ b/demos/showcase/chord-diagram/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/company-ownership/CompanyOwnershipDemo.js b/demos/showcase/company-ownership/CompanyOwnershipDemo.js
index 598a2e0d6..42e2e14f7 100644
--- a/demos/showcase/company-ownership/CompanyOwnershipDemo.js
+++ b/demos/showcase/company-ownership/CompanyOwnershipDemo.js
@@ -64,8 +64,8 @@ async function run() {
applyDemoTheme(graphComponent)
// add the listeners for the companyStructureView
- companyStructureView.addNodeClickedListener(node => propertiesView.showNodeProperties(node))
- companyStructureView.addEdgeClickedListener(edge => propertiesView.showEdgeProperties(edge))
+ companyStructureView.addNodeClickedListener((node) => propertiesView.showNodeProperties(node))
+ companyStructureView.addEdgeClickedListener((edge) => propertiesView.showEdgeProperties(edge))
// initialize graph search
graphSearch = new CompanyOwnershipSearch(graphComponent)
@@ -100,20 +100,20 @@ function createPropertiesView() {
* @param {!GraphComponent} graphComponent
*/
function initializeUI(graphComponent) {
- document.querySelector('#styles').addEventListener('change', async event => {
+ document.querySelector('#styles').addEventListener('change', async (event) => {
const select = event.target
companyStructureView.useShapeNodeStyle = select.value === 'shapes'
await loadGraph(graphComponent)
})
- document.querySelectorAll('[data-command="Shapes"]').forEach(element => {
+ document.querySelectorAll('[data-command="Shapes"]').forEach((element) => {
element.addEventListener('click', async () => {
document.querySelector('#styles').value = 'shapes'
companyStructureView.useShapeNodeStyle = true
await loadGraph(graphComponent)
})
})
- document.querySelectorAll('[data-command="Tables"]').forEach(element => {
+ document.querySelectorAll('[data-command="Tables"]').forEach((element) => {
element.addEventListener('click', async () => {
document.querySelector('#styles').value = 'tables'
companyStructureView.useShapeNodeStyle = false
@@ -147,10 +147,10 @@ async function loadGraph(graphComponent, animate = true) {
*/
function setUIDisabled(disabled) {
document.querySelector('#styles').disabled = disabled
- document.querySelectorAll('[data-command="Shapes"]').forEach(element => {
+ document.querySelectorAll('[data-command="Shapes"]').forEach((element) => {
element.disabled = disabled
})
- document.querySelectorAll('[data-command="Tables"]').forEach(element => {
+ document.querySelectorAll('[data-command="Tables"]').forEach((element) => {
element.disabled = disabled
})
}
diff --git a/demos/showcase/company-ownership/CompanyOwnershipDemo.ts b/demos/showcase/company-ownership/CompanyOwnershipDemo.ts
index 356d32a54..c380641ee 100644
--- a/demos/showcase/company-ownership/CompanyOwnershipDemo.ts
+++ b/demos/showcase/company-ownership/CompanyOwnershipDemo.ts
@@ -60,8 +60,8 @@ async function run(): Promise {
applyDemoTheme(graphComponent)
// add the listeners for the companyStructureView
- companyStructureView.addNodeClickedListener(node => propertiesView.showNodeProperties(node))
- companyStructureView.addEdgeClickedListener(edge => propertiesView.showEdgeProperties(edge))
+ companyStructureView.addNodeClickedListener((node) => propertiesView.showNodeProperties(node))
+ companyStructureView.addEdgeClickedListener((edge) => propertiesView.showEdgeProperties(edge))
// initialize graph search
graphSearch = new CompanyOwnershipSearch(graphComponent)
@@ -98,20 +98,22 @@ function createPropertiesView(): void {
* Binds actions to the buttons in the toolbar.
*/
function initializeUI(graphComponent: GraphComponent): void {
- document.querySelector('#styles')!.addEventListener('change', async event => {
- const select = event.target as HTMLSelectElement
- companyStructureView.useShapeNodeStyle = select.value === 'shapes'
- await loadGraph(graphComponent)
- })
+ document
+ .querySelector('#styles')!
+ .addEventListener('change', async (event) => {
+ const select = event.target as HTMLSelectElement
+ companyStructureView.useShapeNodeStyle = select.value === 'shapes'
+ await loadGraph(graphComponent)
+ })
- document.querySelectorAll('[data-command="Shapes"]').forEach(element => {
+ document.querySelectorAll('[data-command="Shapes"]').forEach((element) => {
element.addEventListener('click', async () => {
document.querySelector('#styles')!.value = 'shapes'
companyStructureView.useShapeNodeStyle = true
await loadGraph(graphComponent)
})
})
- document.querySelectorAll('[data-command="Tables"]').forEach(element => {
+ document.querySelectorAll('[data-command="Tables"]').forEach((element) => {
element.addEventListener('click', async () => {
document.querySelector('#styles')!.value = 'tables'
companyStructureView.useShapeNodeStyle = false
@@ -143,10 +145,10 @@ async function loadGraph(graphComponent: GraphComponent, animate = true): Promis
*/
function setUIDisabled(disabled: boolean): void {
document.querySelector('#styles')!.disabled = disabled
- document.querySelectorAll('[data-command="Shapes"]').forEach(element => {
+ document.querySelectorAll('[data-command="Shapes"]').forEach((element) => {
element.disabled = disabled
})
- document.querySelectorAll('[data-command="Tables"]').forEach(element => {
+ document.querySelectorAll('[data-command="Tables"]').forEach((element) => {
element.disabled = disabled
})
}
diff --git a/demos/showcase/company-ownership/CompanyOwnershipSearch.js b/demos/showcase/company-ownership/CompanyOwnershipSearch.js
index e1adc7712..72b53ccdd 100644
--- a/demos/showcase/company-ownership/CompanyOwnershipSearch.js
+++ b/demos/showcase/company-ownership/CompanyOwnershipSearch.js
@@ -26,7 +26,7 @@
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***************************************************************************/
-import GraphSearch from 'demo-utils/GraphSearch'
+import { GraphSearch } from 'demo-utils/GraphSearch'
import { getEntityData } from '../frauddetection/entity-data.js'
/**
@@ -51,6 +51,6 @@ export class CompanyOwnershipSearch extends GraphSearch {
) {
return true
}
- return node.labels.some(label => label.text.toLowerCase().indexOf(lowercaseText) !== -1)
+ return node.labels.some((label) => label.text.toLowerCase().indexOf(lowercaseText) !== -1)
}
}
diff --git a/demos/showcase/company-ownership/CompanyOwnershipSearch.ts b/demos/showcase/company-ownership/CompanyOwnershipSearch.ts
index 64baf9fa4..d10a81222 100644
--- a/demos/showcase/company-ownership/CompanyOwnershipSearch.ts
+++ b/demos/showcase/company-ownership/CompanyOwnershipSearch.ts
@@ -26,7 +26,7 @@
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***************************************************************************/
-import GraphSearch from 'demo-utils/GraphSearch'
+import { GraphSearch } from 'demo-utils/GraphSearch'
import type { INode } from 'yfiles'
import { getEntityData } from '../frauddetection/entity-data'
@@ -52,6 +52,6 @@ export class CompanyOwnershipSearch extends GraphSearch {
) {
return true
}
- return node.labels.some(label => label.text.toLowerCase().indexOf(lowercaseText) !== -1)
+ return node.labels.some((label) => label.text.toLowerCase().indexOf(lowercaseText) !== -1)
}
}
diff --git a/demos/showcase/company-ownership/CompanyStructureView.js b/demos/showcase/company-ownership/CompanyStructureView.js
index c7f4a270a..79f51cefb 100644
--- a/demos/showcase/company-ownership/CompanyStructureView.js
+++ b/demos/showcase/company-ownership/CompanyStructureView.js
@@ -63,13 +63,13 @@ import { modifyGraph } from './prepare-smooth-animation.js'
* Returns whether the edge is a hierarchy edge.
* @param edge The edge to be checked
*/
-const isHierarchyEdge = edge => getRelationship(edge).type === EdgeTypeEnum.Hierarchy
+const isHierarchyEdge = (edge) => getRelationship(edge).type === EdgeTypeEnum.Hierarchy
/**
* Returns the ownership percentage for the given edge.
* @param edge The edge to be checked
*/
-const ownershipPercentage = edge => {
+const ownershipPercentage = (edge) => {
const relationship = getRelationship(edge)
if (relationship.type === EdgeTypeEnum.Hierarchy) {
return relationship.ownership
@@ -82,7 +82,7 @@ const ownershipPercentage = edge => {
* Checks whether the given node should be visible.
* @param node The node to be checked
*/
-const isVisible = node => !getCompany(node).invisible
+const isVisible = (node) => !getCompany(node).invisible
/**
* Sets the visibility of the given node.
* @param node The given node
@@ -103,7 +103,7 @@ const collapseInput = (node, collapse) => {
/**
* Checks whether the node has collapsed neighbors (from the outgoing edges)
*/
-const isOutputCollapsed = node => getCompany(node).outputCollapsed
+const isOutputCollapsed = (node) => getCompany(node).outputCollapsed
/**
* Collapses/expands the neighbors of the given node (from the outgoing edges)
* @param node The given node
@@ -123,12 +123,12 @@ const setDominantHierarchyEdge = (edge, dominant) => {
/**
* Returns the node id needed for the `NormalizeGraphElementOrderStage`.
*/
-const getNodeId = node => 'node-' + getCompany(node).id.toString()
+const getNodeId = (node) => 'node-' + getCompany(node).id.toString()
/**
* Returns the edge id needed for the `NormalizeGraphElementOrderStage`.
*/
-const getEdgeId = edge => getRelationship(edge).id
+const getEdgeId = (edge) => getRelationship(edge).id
/**
* Central class of the application that manages the graph component and the handling of the data.
@@ -160,9 +160,9 @@ export class CompanyStructureView {
enableBridgeRendering(graphComponent)
graphComponent.graph = new FilteredGraphWrapper(
(this.completeGraph = graphComponent.graph),
- node =>
+ (node) =>
this.completeGraph.isGroupNode(node)
- ? !this.completeGraph.getChildren(node).every(child => !isVisible(child))
+ ? !this.completeGraph.getChildren(node).every((child) => !isVisible(child))
: isVisible(node)
)
configureLayoutNormalizationIds(graphComponent.graph, getNodeId, getEdgeId)
@@ -268,13 +268,13 @@ export class CompanyStructureView {
* @param {!function} collapse The collapse function
*/
addToggleButtonPorts(graph, nodes, expand, collapse) {
- nodes.forEach(n => {
+ nodes.forEach((n) => {
if (graph.outDegree(n) > 0) {
this.toggleButtonSupport.addPort(
graph,
n,
FreeNodePortLocationModel.NODE_BOTTOM_ANCHORED,
- collapsed => (collapsed ? collapse(n, false) : expand(n, false))
+ (collapsed) => (collapsed ? collapse(n, false) : expand(n, false))
)
}
})
@@ -308,7 +308,7 @@ export class CompanyStructureView {
*/
async adjustVisibility() {
this.updateVisibility(this.completeGraph)
- modifyGraph(graph => graph.nodePredicateChanged(), this.graphComponent.graph)
+ modifyGraph((graph) => graph.nodePredicateChanged(), this.graphComponent.graph)
await this.layout()
}
@@ -319,9 +319,9 @@ export class CompanyStructureView {
calculateHierarchy(graph) {
const treeResult = new SpanningTree({
subgraphEdges: isHierarchyEdge,
- costs: item => 1 - ownershipPercentage(item)
+ costs: (item) => 1 - ownershipPercentage(item)
}).run(graph)
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
setDominantHierarchyEdge(e, treeResult.edges.contains(e))
})
}
@@ -332,11 +332,11 @@ export class CompanyStructureView {
*/
updateVisibility(graph) {
if (graph.nodes.some(isOutputCollapsed)) {
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
setVisible(n, this.shouldBeShown(graph, n))
})
} else {
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
setVisible(n, true)
})
}
@@ -354,8 +354,8 @@ export class CompanyStructureView {
graph.inDegree(node) === 0 ||
graph
.inEdgesAt(node)
- .map(e => e.sourceNode)
- .some(parent => !isOutputCollapsed(parent) && this.shouldBeShown(graph, parent))
+ .map((e) => e.sourceNode)
+ .some((parent) => !isOutputCollapsed(parent) && this.shouldBeShown(graph, parent))
)
}
@@ -402,8 +402,8 @@ export class CompanyStructureView {
const nodeSource = builder.createNodesSource({
data: filteredNodes,
- id: dataItem => dataItem.id,
- style: dataItem => getNodeStyle(dataItem, this.useShapeNodeStyle),
+ id: (dataItem) => dataItem.id,
+ style: (dataItem) => getNodeStyle(dataItem, this.useShapeNodeStyle),
layout: () => getNodeLayout(this.useShapeNodeStyle)
})
@@ -416,7 +416,7 @@ export class CompanyStructureView {
// adds the node labels if the shape node style is selected
if (this.useShapeNodeStyle) {
const nameLabel = nodeSource.nodeCreator.createLabelBinding({
- text: dataItem => dataItem.name,
+ text: (dataItem) => dataItem.name,
defaults: nameLabelDefaults,
preferredSize: () => labelSizeDefaults
})
@@ -429,14 +429,15 @@ export class CompanyStructureView {
const filteredEdges = graphData.edges.filter(edgePredicate)
const edgeSource = builder.createEdgesSource({
data: filteredEdges,
- id: data => data.id,
- sourceId: data => data.sourceId,
- targetId: data => data.targetId,
+ id: (data) => data.id,
+ sourceId: (data) => data.sourceId,
+ targetId: (data) => data.targetId,
style: getEdgeStyle
})
const edgeLabel = edgeSource.edgeCreator.createLabelBinding({
- text: dataItem => (dataItem.type === EdgeTypeEnum.Hierarchy ? `${dataItem.ownership}` : null),
+ text: (dataItem) =>
+ dataItem.type === EdgeTypeEnum.Hierarchy ? `${dataItem.ownership}` : null,
defaults: edgeLabelDefaults
})
edgeSource.edgeCreator.addEdgeUpdatedListener((_, evt) => {
diff --git a/demos/showcase/company-ownership/CompanyStructureView.ts b/demos/showcase/company-ownership/CompanyStructureView.ts
index 850ef78eb..54c061942 100644
--- a/demos/showcase/company-ownership/CompanyStructureView.ts
+++ b/demos/showcase/company-ownership/CompanyStructureView.ts
@@ -170,9 +170,9 @@ export class CompanyStructureView {
enableBridgeRendering(graphComponent)
graphComponent.graph = new FilteredGraphWrapper(
(this.completeGraph = graphComponent.graph),
- node =>
+ (node) =>
this.completeGraph.isGroupNode(node)
- ? !this.completeGraph.getChildren(node).every(child => !isVisible(child))
+ ? !this.completeGraph.getChildren(node).every((child) => !isVisible(child))
: isVisible(node)
)
configureLayoutNormalizationIds(graphComponent.graph, getNodeId, getEdgeId)
@@ -285,13 +285,13 @@ export class CompanyStructureView {
expand: (node: INode, incoming: boolean) => void,
collapse: (node: INode, incoming: boolean) => void
): void {
- nodes.forEach(n => {
+ nodes.forEach((n) => {
if (graph.outDegree(n) > 0) {
this.toggleButtonSupport.addPort(
graph,
n,
FreeNodePortLocationModel.NODE_BOTTOM_ANCHORED,
- collapsed => (collapsed ? collapse(n, false) : expand(n, false))
+ (collapsed) => (collapsed ? collapse(n, false) : expand(n, false))
)
}
})
@@ -323,7 +323,7 @@ export class CompanyStructureView {
private async adjustVisibility(): Promise {
this.updateVisibility(this.completeGraph)
modifyGraph(
- graph => (graph as FilteredGraphWrapper).nodePredicateChanged(),
+ (graph) => (graph as FilteredGraphWrapper).nodePredicateChanged(),
this.graphComponent.graph
)
await this.layout()
@@ -336,9 +336,9 @@ export class CompanyStructureView {
private calculateHierarchy(graph: IGraph): void {
const treeResult = new SpanningTree({
subgraphEdges: isHierarchyEdge,
- costs: item => 1 - ownershipPercentage(item)
+ costs: (item) => 1 - ownershipPercentage(item)
}).run(graph)
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
setDominantHierarchyEdge(e, treeResult.edges.contains(e))
})
}
@@ -349,11 +349,11 @@ export class CompanyStructureView {
*/
private updateVisibility(graph: IGraph): void {
if (graph.nodes.some(isOutputCollapsed)) {
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
setVisible(n, this.shouldBeShown(graph, n))
})
} else {
- graph.nodes.forEach(n => {
+ graph.nodes.forEach((n) => {
setVisible(n, true)
})
}
@@ -368,7 +368,7 @@ export class CompanyStructureView {
graph.inDegree(node) === 0 ||
graph
.inEdgesAt(node)
- .map(e => e.sourceNode!)
+ .map((e) => e.sourceNode!)
.some((parent: INode) => !isOutputCollapsed(parent) && this.shouldBeShown(graph, parent))
)
}
@@ -414,8 +414,8 @@ export class CompanyStructureView {
const nodeSource = builder.createNodesSource({
data: filteredNodes,
- id: dataItem => dataItem.id,
- style: dataItem => getNodeStyle(dataItem, this.useShapeNodeStyle),
+ id: (dataItem) => dataItem.id,
+ style: (dataItem) => getNodeStyle(dataItem, this.useShapeNodeStyle),
layout: () => getNodeLayout(this.useShapeNodeStyle)
})
@@ -428,7 +428,7 @@ export class CompanyStructureView {
// adds the node labels if the shape node style is selected
if (this.useShapeNodeStyle) {
const nameLabel = nodeSource.nodeCreator.createLabelBinding({
- text: dataItem => dataItem.name,
+ text: (dataItem) => dataItem.name,
defaults: nameLabelDefaults,
preferredSize: () => labelSizeDefaults
})
@@ -441,14 +441,15 @@ export class CompanyStructureView {
const filteredEdges = graphData.edges.filter(edgePredicate)
const edgeSource = builder.createEdgesSource({
data: filteredEdges,
- id: data => data.id,
- sourceId: data => data.sourceId,
- targetId: data => data.targetId,
+ id: (data) => data.id,
+ sourceId: (data) => data.sourceId,
+ targetId: (data) => data.targetId,
style: getEdgeStyle
})
const edgeLabel = edgeSource.edgeCreator.createLabelBinding({
- text: dataItem => (dataItem.type === EdgeTypeEnum.Hierarchy ? `${dataItem.ownership}` : null),
+ text: (dataItem) =>
+ dataItem.type === EdgeTypeEnum.Hierarchy ? `${dataItem.ownership}` : null,
defaults: edgeLabelDefaults
})
edgeSource.edgeCreator.addEdgeUpdatedListener((_, evt) => {
diff --git a/demos/showcase/company-ownership/TogglePortButtonSupport.js b/demos/showcase/company-ownership/TogglePortButtonSupport.js
index 5b9951917..0c5d2679a 100644
--- a/demos/showcase/company-ownership/TogglePortButtonSupport.js
+++ b/demos/showcase/company-ownership/TogglePortButtonSupport.js
@@ -65,7 +65,7 @@ export default class TogglePortButtonSupport {
constructor() {
// initialize converter
StringTemplatePortStyle.CONVERTERS.companyOwnershipConverters = {
- portIconStateConverter: val =>
+ portIconStateConverter: (val) =>
'port-icon ' + (val.collapsed ?? false ? 'port-icon-expand' : 'port-icon-collapse')
}
}
diff --git a/demos/showcase/company-ownership/configure-highlight.js b/demos/showcase/company-ownership/configure-highlight.js
index 551f11f73..7b1aceb68 100644
--- a/demos/showcase/company-ownership/configure-highlight.js
+++ b/demos/showcase/company-ownership/configure-highlight.js
@@ -56,7 +56,7 @@ export function enableHoverHighlights(viewerInputMode, graphComponent) {
// configures the highlighting style for the edges
const decorator = graphComponent.graph.decorator
- decorator.nodeDecorator.highlightDecorator.setFactory(node => {
+ decorator.nodeDecorator.highlightDecorator.setFactory((node) => {
const shape =
node.style instanceof CustomShapeNodeStyle
? highlightShapes.get(getCompany(node).nodeType)
@@ -72,7 +72,7 @@ export function enableHoverHighlights(viewerInputMode, graphComponent) {
})
})
decorator.edgeDecorator.highlightDecorator.setFactory(
- edge =>
+ (edge) =>
new EdgeStyleDecorationInstaller({
edgeStyle: new PolylineEdgeStyle({
stroke: '3px #ab2346',
@@ -112,14 +112,14 @@ export function enableHoverHighlights(viewerInputMode, graphComponent) {
if (evt.item) {
highlightIndicatorManager.addHighlight(evt.item)
if (evt.item instanceof INode) {
- graphComponent.graph.edgesAt(evt.item).forEach(edge => {
+ graphComponent.graph.edgesAt(evt.item).forEach((edge) => {
highlightIndicatorManager.addHighlight(edge)
- edge.labels.forEach(label => {
+ edge.labels.forEach((label) => {
highlightIndicatorManager.addHighlight(label)
})
})
} else if (evt.item instanceof IEdge) {
- evt.item.labels.forEach(label => {
+ evt.item.labels.forEach((label) => {
highlightIndicatorManager.addHighlight(label)
})
} else if (evt.item instanceof ILabel) {
diff --git a/demos/showcase/company-ownership/configure-highlight.ts b/demos/showcase/company-ownership/configure-highlight.ts
index 9e2148991..0aa394d64 100644
--- a/demos/showcase/company-ownership/configure-highlight.ts
+++ b/demos/showcase/company-ownership/configure-highlight.ts
@@ -61,7 +61,7 @@ export function enableHoverHighlights(
// configures the highlighting style for the edges
const decorator = graphComponent.graph.decorator
- decorator.nodeDecorator.highlightDecorator.setFactory(node => {
+ decorator.nodeDecorator.highlightDecorator.setFactory((node) => {
const shape =
node.style instanceof CustomShapeNodeStyle
? highlightShapes.get(getCompany(node).nodeType)
@@ -77,7 +77,7 @@ export function enableHoverHighlights(
})
})
decorator.edgeDecorator.highlightDecorator.setFactory(
- edge =>
+ (edge) =>
new EdgeStyleDecorationInstaller({
edgeStyle: new PolylineEdgeStyle({
stroke: '3px #ab2346',
@@ -117,14 +117,14 @@ export function enableHoverHighlights(
if (evt.item) {
highlightIndicatorManager.addHighlight(evt.item)
if (evt.item instanceof INode) {
- graphComponent.graph.edgesAt(evt.item).forEach(edge => {
+ graphComponent.graph.edgesAt(evt.item).forEach((edge) => {
highlightIndicatorManager.addHighlight(edge)
- edge.labels.forEach(label => {
+ edge.labels.forEach((label) => {
highlightIndicatorManager.addHighlight(label)
})
})
} else if (evt.item instanceof IEdge) {
- evt.item.labels.forEach(label => {
+ evt.item.labels.forEach((label) => {
highlightIndicatorManager.addHighlight(label)
})
} else if (evt.item instanceof ILabel) {
diff --git a/demos/showcase/company-ownership/configure-layout.js b/demos/showcase/company-ownership/configure-layout.js
index 088cb2c64..4aebfbefb 100644
--- a/demos/showcase/company-ownership/configure-layout.js
+++ b/demos/showcase/company-ownership/configure-layout.js
@@ -85,10 +85,10 @@ export function createLayoutData(graph, isHierarchyEdge, nodeId, moveToTop = fal
configureEdgeHierarchyCandidates(isHierarchyEdge)
const layoutData = new HierarchicLayoutData({
- edgeDirectedness: item => (isHierarchyEdge(item) ? 1 : 0),
- sourceGroupIds: item =>
+ edgeDirectedness: (item) => (isHierarchyEdge(item) ? 1 : 0),
+ sourceGroupIds: (item) =>
isHierarchyEdge(item) ? 's-' + nodeId(item.sourceNode).toString() : null,
- targetGroupIds: item =>
+ targetGroupIds: (item) =>
isHierarchyEdge(item) ? 't-' + nodeId(item.targetNode).toString() : null,
nodePortCandidateSets: createPortCandidateSet,
sourcePortCandidates: createSourcePortCandidates,
@@ -96,7 +96,7 @@ export function createLayoutData(graph, isHierarchyEdge, nodeId, moveToTop = fal
})
if (moveToTop) {
- layoutData.partitionGridData.rowIndices = new ItemMapping(node =>
+ layoutData.partitionGridData.rowIndices = new ItemMapping((node) =>
graph.inEdgesAt(node).filter(isHierarchyEdge).size === 0 ? 0 : 1
)
}
@@ -129,9 +129,9 @@ function configureEdgeHierarchyCandidates(isHierarchyEdge) {
return portCandidateSet
}
- const createSourcePortCandidates = edge =>
+ const createSourcePortCandidates = (edge) =>
isHierarchyEdge(edge) ? hierarchyEdgeSourceSideCandidates : regularEdgeSourceSideCandidates
- const createTargetPortCandidates = edge =>
+ const createTargetPortCandidates = (edge) =>
isHierarchyEdge(edge) ? hierarchyEdgeTargetSideCandidates : regularEdgeTargetSideCandidates
return { createPortCandidateSet, createSourcePortCandidates, createTargetPortCandidates }
diff --git a/demos/showcase/company-ownership/configure-layout.ts b/demos/showcase/company-ownership/configure-layout.ts
index c2115108a..8321dae9d 100644
--- a/demos/showcase/company-ownership/configure-layout.ts
+++ b/demos/showcase/company-ownership/configure-layout.ts
@@ -94,7 +94,7 @@ export function createLayoutData(
configureEdgeHierarchyCandidates(isHierarchyEdge)
const layoutData = new HierarchicLayoutData({
- edgeDirectedness: item => (isHierarchyEdge(item) ? 1 : 0),
+ edgeDirectedness: (item) => (isHierarchyEdge(item) ? 1 : 0),
sourceGroupIds: (item: IEdge) =>
isHierarchyEdge(item) ? 's-' + nodeId(item.sourceNode!).toString() : null,
targetGroupIds: (item: IEdge) =>
@@ -105,7 +105,7 @@ export function createLayoutData(
})
if (moveToTop) {
- layoutData.partitionGridData.rowIndices = new ItemMapping(node =>
+ layoutData.partitionGridData.rowIndices = new ItemMapping((node) =>
graph.inEdgesAt(node).filter(isHierarchyEdge).size === 0 ? 0 : 1
)
}
diff --git a/demos/showcase/company-ownership/index.html b/demos/showcase/company-ownership/index.html
index 914dc247d..3524a9374 100644
--- a/demos/showcase/company-ownership/index.html
+++ b/demos/showcase/company-ownership/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/company-ownership/prepare-smooth-animation.js b/demos/showcase/company-ownership/prepare-smooth-animation.js
index 16421bba9..217674654 100644
--- a/demos/showcase/company-ownership/prepare-smooth-animation.js
+++ b/demos/showcase/company-ownership/prepare-smooth-animation.js
@@ -89,7 +89,7 @@ export function modifyGraph(modification, graph) {
// then we reset the new edges so that they grow out of their source nodes by placing the target port at
// the source port's location
- newEdges.forEach(e => {
+ newEdges.forEach((e) => {
graph.clearBends(e)
graph.setPortLocationParameter(
e.targetPort,
diff --git a/demos/showcase/company-ownership/prepare-smooth-animation.ts b/demos/showcase/company-ownership/prepare-smooth-animation.ts
index a28d4d683..b47274403 100644
--- a/demos/showcase/company-ownership/prepare-smooth-animation.ts
+++ b/demos/showcase/company-ownership/prepare-smooth-animation.ts
@@ -100,7 +100,7 @@ export function modifyGraph(modification: (graph: IGraph) => void, graph: IGraph
// then we reset the new edges so that they grow out of their source nodes by placing the target port at
// the source port's location
- newEdges.forEach(e => {
+ newEdges.forEach((e) => {
graph.clearBends(e)
graph.setPortLocationParameter(
e.targetPort!,
diff --git a/demos/showcase/company-ownership/styles/CustomShapeNodeStyle.ts b/demos/showcase/company-ownership/styles/CustomShapeNodeStyle.ts
index 5f89c045f..99e21c814 100644
--- a/demos/showcase/company-ownership/styles/CustomShapeNodeStyle.ts
+++ b/demos/showcase/company-ownership/styles/CustomShapeNodeStyle.ts
@@ -50,7 +50,11 @@ export class CustomShapeNodeStyle extends NodeStyleBase {
/**
* Creates the custom style for the given type of node.
*/
- constructor(public type?: NodeTypeEnum, public stroke?: Stroke, public fill?: Fill) {
+ constructor(
+ public type?: NodeTypeEnum,
+ public stroke?: Stroke,
+ public fill?: Fill
+ ) {
super()
this.type = type ?? NodeTypeEnum.CORPORATION
this.stroke = Stroke.from(stroke ?? 'black')
diff --git a/demos/showcase/company-ownership/styles/TableNodeStyle.js b/demos/showcase/company-ownership/styles/TableNodeStyle.js
index c0c195263..7368a9c75 100644
--- a/demos/showcase/company-ownership/styles/TableNodeStyle.js
+++ b/demos/showcase/company-ownership/styles/TableNodeStyle.js
@@ -66,12 +66,12 @@ export const tableNodeStyle = new StringTemplateNodeStyle(`
export function initializeConverters() {
TemplateNodeStyle.CONVERTERS.templateNodeConverters = {
// converter function for the background color of nodes
- typeColorConverter: value => {
+ typeColorConverter: (value) => {
return colorSets[predefinedColorSets.get(value) || 'demo-palette-51'].fill || 'white'
},
// converter function for reading the values of the node attributes
- valueConverter: value => {
+ valueConverter: (value) => {
return value || '---'
}
}
diff --git a/demos/showcase/decisiontree/decision-tree-component/DecisionTree.js b/demos/showcase/decisiontree/decision-tree-component/DecisionTree.js
index 98b2bbe74..c4d8bb64b 100644
--- a/demos/showcase/decisiontree/decision-tree-component/DecisionTree.js
+++ b/demos/showcase/decisiontree/decision-tree-component/DecisionTree.js
@@ -264,7 +264,7 @@ export default class DecisionTree {
const copiedNodes = []
const copiedParentNodes = new Map()
// copy the successors from the original graph
- this.originalGraph.outEdgesAt(originalNode).forEach(originalEdge => {
+ this.originalGraph.outEdgesAt(originalNode).forEach((originalEdge) => {
const originalTargetNode = originalEdge.targetNode
if (!this.originalGraph.isGroupNode(originalTargetNode)) {
// target is not a group, thus copy it
@@ -295,14 +295,14 @@ export default class DecisionTree {
const copiedGroupNode = this.copyGroupNode(originalTargetNode)
// copy children
- this.originalGraph.getChildren(originalTargetNode).forEach(originalNode => {
+ this.originalGraph.getChildren(originalTargetNode).forEach((originalNode) => {
const copiedChildNode = this.copyNode(originalNode, copiedGroupNode)
copiedNodes.push(copiedChildNode)
})
this.copyEdge(originalEdge, copiedNode, copiedGroupNode)
- this.graph.getChildren(copiedGroupNode).forEach(copiedChildNode => {
+ this.graph.getChildren(copiedGroupNode).forEach((copiedChildNode) => {
if (this.getOriginalOutDegree(copiedChildNode) > 0) {
// child nodes that have outgoing edges are clickable nodes
this.activeNodes.add(copiedChildNode)
@@ -327,11 +327,11 @@ export default class DecisionTree {
// get all nodes in this layer
let layerNodes = this.layerToNodesMap.get(layer)
// remove all nodes in this layer from the path
- layerNodes.forEach(node => this.pathNodes.delete(node))
+ layerNodes.forEach((node) => this.pathNodes.delete(node))
// remove all nodes in lower layers
for (let l = layer + 1; l <= this.currentLayer; l++) {
layerNodes = this.layerToNodesMap.get(l)
- layerNodes.forEach(node => {
+ layerNodes.forEach((node) => {
this.graph.remove(node)
this.pathNodes.delete(node)
this.activeNodes.delete(node)
@@ -349,7 +349,7 @@ export default class DecisionTree {
* Updates the styles of all nodes.
*/
updateNodeStyles() {
- this.graph.nodes.forEach(node => {
+ this.graph.nodes.forEach((node) => {
if (this.graph.isGroupNode(node)) {
this.graph.setStyle(node, groupNodeStyle)
} else if (this.getOriginalOutDegree(node) === 0) {
@@ -379,7 +379,7 @@ export default class DecisionTree {
originalNode.style,
originalNode.tag
)
- originalNode.labels.forEach(label =>
+ originalNode.labels.forEach((label) =>
this.graph.addLabel(
copiedNode,
label.text,
@@ -410,7 +410,7 @@ export default class DecisionTree {
originalNode.style,
originalNode.tag
)
- originalNode.labels.forEach(label =>
+ originalNode.labels.forEach((label) =>
this.graph.addLabel(
copiedGroupNode,
label.text,
@@ -454,7 +454,7 @@ export default class DecisionTree {
edgeStyle,
originalEdge.tag
)
- originalEdge.labels.forEach(label =>
+ originalEdge.labels.forEach((label) =>
this.graph.addLabel(
copiedEdge,
label.text,
@@ -516,7 +516,7 @@ export default class DecisionTree {
layoutData.incrementalHints.incrementalLayeringNodes = incrementalNodes
// configure critical edges so the path edges are aligned
- layoutData.criticalEdgePriorities = edge =>
+ layoutData.criticalEdgePriorities = (edge) =>
this.pathNodes.has(edge.sourceNode) && this.pathNodes.has(edge.targetNode) ? 1 : 0
this.runningLayout = true
@@ -543,7 +543,7 @@ export default class DecisionTree {
// mark the new nodes and place them between their neighbors
const layoutData = new PlaceNodesAtBarycenterStageData({
- affectedNodes: node => incrementalNodes.indexOf(node) > -1
+ affectedNodes: (node) => incrementalNodes.indexOf(node) > -1
})
const layout = new PlaceNodesAtBarycenterStage()
graph.applyLayout(layout, layoutData)
diff --git a/demos/showcase/decisiontree/decision-tree-component/DecisionTree.ts b/demos/showcase/decisiontree/decision-tree-component/DecisionTree.ts
index 70db8c927..ceba21c42 100644
--- a/demos/showcase/decisiontree/decision-tree-component/DecisionTree.ts
+++ b/demos/showcase/decisiontree/decision-tree-component/DecisionTree.ts
@@ -257,7 +257,7 @@ export default class DecisionTree {
const copiedNodes: INode[] = []
const copiedParentNodes = new Map()
// copy the successors from the original graph
- this.originalGraph.outEdgesAt(originalNode).forEach(originalEdge => {
+ this.originalGraph.outEdgesAt(originalNode).forEach((originalEdge) => {
const originalTargetNode = originalEdge.targetNode!
if (!this.originalGraph.isGroupNode(originalTargetNode)) {
// target is not a group, thus copy it
@@ -288,14 +288,14 @@ export default class DecisionTree {
const copiedGroupNode = this.copyGroupNode(originalTargetNode)
// copy children
- this.originalGraph.getChildren(originalTargetNode).forEach(originalNode => {
+ this.originalGraph.getChildren(originalTargetNode).forEach((originalNode) => {
const copiedChildNode = this.copyNode(originalNode, copiedGroupNode)
copiedNodes.push(copiedChildNode)
})
this.copyEdge(originalEdge, copiedNode, copiedGroupNode)
- this.graph.getChildren(copiedGroupNode).forEach(copiedChildNode => {
+ this.graph.getChildren(copiedGroupNode).forEach((copiedChildNode) => {
if (this.getOriginalOutDegree(copiedChildNode) > 0) {
// child nodes that have outgoing edges are clickable nodes
this.activeNodes.add(copiedChildNode)
@@ -320,11 +320,11 @@ export default class DecisionTree {
// get all nodes in this layer
let layerNodes = this.layerToNodesMap.get(layer)!
// remove all nodes in this layer from the path
- layerNodes.forEach(node => this.pathNodes.delete(node))
+ layerNodes.forEach((node) => this.pathNodes.delete(node))
// remove all nodes in lower layers
for (let l: number = layer + 1; l <= this.currentLayer; l++) {
layerNodes = this.layerToNodesMap.get(l)!
- layerNodes.forEach(node => {
+ layerNodes.forEach((node) => {
this.graph.remove(node)
this.pathNodes.delete(node)
this.activeNodes.delete(node)
@@ -342,7 +342,7 @@ export default class DecisionTree {
* Updates the styles of all nodes.
*/
private updateNodeStyles(): void {
- this.graph.nodes.forEach(node => {
+ this.graph.nodes.forEach((node) => {
if (this.graph.isGroupNode(node)) {
this.graph.setStyle(node, groupNodeStyle)
} else if (this.getOriginalOutDegree(node) === 0) {
@@ -371,7 +371,7 @@ export default class DecisionTree {
originalNode.style,
originalNode.tag
)
- originalNode.labels.forEach(label =>
+ originalNode.labels.forEach((label) =>
this.graph.addLabel(
copiedNode,
label.text,
@@ -401,7 +401,7 @@ export default class DecisionTree {
originalNode.style,
originalNode.tag
)
- originalNode.labels.forEach(label =>
+ originalNode.labels.forEach((label) =>
this.graph.addLabel(
copiedGroupNode,
label.text,
@@ -445,7 +445,7 @@ export default class DecisionTree {
edgeStyle,
originalEdge.tag
)
- originalEdge.labels.forEach(label =>
+ originalEdge.labels.forEach((label) =>
this.graph.addLabel(
copiedEdge,
label.text,
@@ -532,7 +532,7 @@ export default class DecisionTree {
// mark the new nodes and place them between their neighbors
const layoutData = new PlaceNodesAtBarycenterStageData({
- affectedNodes: node => incrementalNodes.indexOf(node) > -1
+ affectedNodes: (node) => incrementalNodes.indexOf(node) > -1
})
const layout = new PlaceNodesAtBarycenterStage()
graph.applyLayout(layout, layoutData)
diff --git a/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.js b/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.js
index 824181569..a01fb9f80 100644
--- a/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.js
+++ b/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.js
@@ -55,7 +55,7 @@ export function initializeDecisionTreeComponent(graphComponent) {
// add the sample graphs
const samples = document.querySelector('#samples')
- ;['cars', 'what-to-do', 'quiz'].forEach(graph => {
+ ;['cars', 'what-to-do', 'quiz'].forEach((graph) => {
const option = document.createElement('option')
option.text = graph
option.value = graph
@@ -109,7 +109,7 @@ export function hideDecisionTree() {
*/
function setLayoutRunning(running, graphComponent) {
graphComponent.inputMode.waitInputMode.waiting = running
- document.querySelectorAll('#decision-tree-toolbar Button,Select').forEach(element => {
+ document.querySelectorAll('#decision-tree-toolbar Button,Select').forEach((element) => {
element.disabled = running
})
}
diff --git a/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.ts b/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.ts
index 499326b42..b2af61b9d 100644
--- a/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.ts
+++ b/demos/showcase/decisiontree/decision-tree-component/decision-tree-component.ts
@@ -50,7 +50,7 @@ export function initializeDecisionTreeComponent(graphComponent: GraphComponent):
// add the sample graphs
const samples = document.querySelector('#samples')!
- ;['cars', 'what-to-do', 'quiz'].forEach(graph => {
+ ;['cars', 'what-to-do', 'quiz'].forEach((graph) => {
const option = document.createElement('option')
option.text = graph
option.value = graph
@@ -105,7 +105,7 @@ function setLayoutRunning(running: boolean, graphComponent: GraphComponent): voi
;(graphComponent.inputMode as GraphEditorInputMode).waitInputMode.waiting = running
document
.querySelectorAll('#decision-tree-toolbar Button,Select')
- .forEach(element => {
+ .forEach((element) => {
element.disabled = running
})
}
diff --git a/demos/showcase/decisiontree/editor-component/context-menu.js b/demos/showcase/decisiontree/editor-component/context-menu.js
index 251850842..2090d0771 100644
--- a/demos/showcase/decisiontree/editor-component/context-menu.js
+++ b/demos/showcase/decisiontree/editor-component/context-menu.js
@@ -44,7 +44,7 @@ export function configureContextMenu(graphComponent, setAsRootNode) {
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback-function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
diff --git a/demos/showcase/decisiontree/editor-component/context-menu.ts b/demos/showcase/decisiontree/editor-component/context-menu.ts
index c61d61820..2c5dcd32c 100644
--- a/demos/showcase/decisiontree/editor-component/context-menu.ts
+++ b/demos/showcase/decisiontree/editor-component/context-menu.ts
@@ -45,7 +45,7 @@ export function configureContextMenu(
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback-function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
diff --git a/demos/showcase/decisiontree/editor-component/editor-component.js b/demos/showcase/decisiontree/editor-component/editor-component.js
index df140947f..0611b9003 100644
--- a/demos/showcase/decisiontree/editor-component/editor-component.js
+++ b/demos/showcase/decisiontree/editor-component/editor-component.js
@@ -69,7 +69,7 @@ export function initializeEditorComponent(graphComponent) {
// configures a green outline as custom highlight for the root node of the decision tree
// see also setAsRootNode action
graphComponent.graph.decorator.nodeDecorator.highlightDecorator.setImplementation(
- node => node === rootNode,
+ (node) => node === rootNode,
new NodeStyleDecorationInstaller({
nodeStyle: new ShapeNodeStyle({
fill: null,
@@ -115,8 +115,8 @@ function initializeGraph(graph) {
// provide a single port at the top of the node for group nodes
graph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
- node => graph.isGroupNode(node),
- node => new GroupNodePortCandidateProvider(node)
+ (node) => graph.isGroupNode(node),
+ (node) => new GroupNodePortCandidateProvider(node)
)
}
@@ -242,7 +242,7 @@ export async function readSampleGraph(graphComponent) {
function setLayoutRunning(running, graphComponent) {
runningLayout = running
graphComponent.inputMode.waitInputMode.waiting = running
- document.querySelectorAll('#editor-toolbar Button').forEach(button => {
+ document.querySelectorAll('#editor-toolbar Button').forEach((button) => {
button.disabled = running
})
}
diff --git a/demos/showcase/decisiontree/editor-component/editor-component.ts b/demos/showcase/decisiontree/editor-component/editor-component.ts
index bce9330da..3b49db6b9 100644
--- a/demos/showcase/decisiontree/editor-component/editor-component.ts
+++ b/demos/showcase/decisiontree/editor-component/editor-component.ts
@@ -69,7 +69,7 @@ export function initializeEditorComponent(graphComponent: GraphComponent): void
// configures a green outline as custom highlight for the root node of the decision tree
// see also setAsRootNode action
graphComponent.graph.decorator.nodeDecorator.highlightDecorator.setImplementation(
- node => node === rootNode,
+ (node) => node === rootNode,
new NodeStyleDecorationInstaller({
nodeStyle: new ShapeNodeStyle({
fill: null,
@@ -116,8 +116,8 @@ function initializeGraph(graph: IGraph): void {
// provide a single port at the top of the node for group nodes
graph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
- node => graph.isGroupNode(node),
- node => new GroupNodePortCandidateProvider(node)
+ (node) => graph.isGroupNode(node),
+ (node) => new GroupNodePortCandidateProvider(node)
)
}
@@ -237,7 +237,7 @@ export async function readSampleGraph(graphComponent: GraphComponent): Promise('#editor-toolbar Button').forEach(button => {
+ document.querySelectorAll('#editor-toolbar Button').forEach((button) => {
button.disabled = running
})
}
diff --git a/demos/showcase/decisiontree/index.html b/demos/showcase/decisiontree/index.html
index 42d0a1611..2015745d1 100644
--- a/demos/showcase/decisiontree/index.html
+++ b/demos/showcase/decisiontree/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/decisiontree/switch-components-button/switch-components-button.js b/demos/showcase/decisiontree/switch-components-button/switch-components-button.js
index 4804a09f1..2a72f1e62 100644
--- a/demos/showcase/decisiontree/switch-components-button/switch-components-button.js
+++ b/demos/showcase/decisiontree/switch-components-button/switch-components-button.js
@@ -101,7 +101,7 @@ export function updateButtonState(graphComponent) {
if (activeDecisionTree) {
switchComponentsButton.classList.remove('disabled')
switchComponentsButton.title = 'Edit Decision Tree Graph'
- } else if (graph.nodes.size > 0 && graph.nodes.some(node => !graph.isGroupNode(node))) {
+ } else if (graph.nodes.size > 0 && graph.nodes.some((node) => !graph.isGroupNode(node))) {
switchComponentsButton.classList.remove('disabled')
switchComponentsButton.title = 'Show Decision Tree'
} else {
diff --git a/demos/showcase/decisiontree/switch-components-button/switch-components-button.ts b/demos/showcase/decisiontree/switch-components-button/switch-components-button.ts
index 44b48bf90..f90b53148 100644
--- a/demos/showcase/decisiontree/switch-components-button/switch-components-button.ts
+++ b/demos/showcase/decisiontree/switch-components-button/switch-components-button.ts
@@ -100,7 +100,7 @@ export function updateButtonState(graphComponent: GraphComponent): void {
if (activeDecisionTree) {
switchComponentsButton.classList.remove('disabled')
switchComponentsButton.title = 'Edit Decision Tree Graph'
- } else if (graph.nodes.size > 0 && graph.nodes.some(node => !graph.isGroupNode(node))) {
+ } else if (graph.nodes.size > 0 && graph.nodes.some((node) => !graph.isGroupNode(node))) {
switchComponentsButton.classList.remove('disabled')
switchComponentsButton.title = 'Show Decision Tree'
} else {
diff --git a/demos/showcase/flowchart/index.html b/demos/showcase/flowchart/index.html
index 17eda1fc6..1432d3354 100644
--- a/demos/showcase/flowchart/index.html
+++ b/demos/showcase/flowchart/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/flowchart/interaction/drag-and-drop.js b/demos/showcase/flowchart/interaction/drag-and-drop.js
index 27e7fabfd..392d52a0f 100644
--- a/demos/showcase/flowchart/interaction/drag-and-drop.js
+++ b/demos/showcase/flowchart/interaction/drag-and-drop.js
@@ -40,7 +40,7 @@ export function initializeDnd(graphEditorInputMode) {
})
const dndNodes = Object.keys(FlowchartNodeType).map(
- type =>
+ (type) =>
new SimpleNode({
layout: new Rect(0, 0, 80, 40),
style: new FlowchartNodeStyle(FlowchartNodeType[type])
diff --git a/demos/showcase/flowchart/interaction/drag-and-drop.ts b/demos/showcase/flowchart/interaction/drag-and-drop.ts
index 4738dcdd8..a5a39c964 100644
--- a/demos/showcase/flowchart/interaction/drag-and-drop.ts
+++ b/demos/showcase/flowchart/interaction/drag-and-drop.ts
@@ -38,7 +38,7 @@ export function initializeDnd(graphEditorInputMode: GraphEditorInputMode): void
})
const dndNodes = Object.keys(FlowchartNodeType).map(
- type =>
+ (type) =>
new SimpleNode({
layout: new Rect(0, 0, 80, 40),
style: new FlowchartNodeStyle(FlowchartNodeType[type as keyof typeof FlowchartNodeType])
diff --git a/demos/showcase/flowchart/layout/FlowchartLayout.js b/demos/showcase/flowchart/layout/FlowchartLayout.js
index abbd4ef47..5813ca77a 100644
--- a/demos/showcase/flowchart/layout/FlowchartLayout.js
+++ b/demos/showcase/flowchart/layout/FlowchartLayout.js
@@ -201,12 +201,12 @@ export class FlowchartLayout extends BaseClass(ILayoutAlgorithm) {
const grid = PartitionGrid.getPartitionGrid(graph)
if (grid) {
// adjust insets
- grid.columns.forEach(column => {
+ grid.columns.forEach((column) => {
column.leftInset = this.laneInsets
column.rightInset = this.laneInsets
})
- grid.rows.forEach(row => {
+ grid.rows.forEach((row) => {
row.topInset = this.laneInsets
row.bottomInset = this.laneInsets
})
@@ -224,7 +224,7 @@ export class FlowchartLayout extends BaseClass(ILayoutAlgorithm) {
graph.removeDataProvider(HierarchicLayout.LAYER_INDEX_DP_KEY)
}
const edge2LayoutDescriptor = Maps.createHashedEdgeMap()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge2LayoutDescriptor.set(
edge,
this.createEdgeLayoutDescriptor(
@@ -306,7 +306,7 @@ export class FlowchartLayout extends BaseClass(ILayoutAlgorithm) {
createEdgeLayoutDescriptor(edge, graph, defaultDescriptor, horizontal) {
const ell = graph.getLabelLayout(edge)
let minLength = 0.0
- ell.forEach(label => {
+ ell.forEach((label) => {
const labelSize = label.boundingBox
if (isRegularEdge(graph, edge)) {
minLength += horizontal ? labelSize.width : labelSize.height
@@ -485,10 +485,6 @@ class FlowchartTransformerStage extends LayoutStageBase {
dummyLayerIds = null
groupNodeIdWrapper = null
- constructor() {
- super()
- }
-
/**
* @param {!LayoutGraph} graph
*/
@@ -631,7 +627,7 @@ class FlowchartTransformerStage extends LayoutStageBase {
const succeedingGroupingConfigurator = new SucceedingLayersInEdgeGroupingConfigurator(this)
const edgesToReverse = new EdgeList()
const groupingLists = getGroupingLists(graph)
- groupingLists.forEach(groupingList => {
+ groupingLists.forEach((groupingList) => {
if (groupingList === null || groupingList.isEmpty()) {
return
}
@@ -645,13 +641,13 @@ class FlowchartTransformerStage extends LayoutStageBase {
)
} else {
const target = groupingList.firstEdge().target
- groupingList.forEach(edge => {
+ groupingList.forEach((edge) => {
this.targetGroupIds.set(edge, target)
})
}
})
- edgesToReverse.forEach(edge => {
+ edgesToReverse.forEach((edge) => {
graph.reverseEdge(edge)
// Reverse the port candidate data if an original edge was reversed
if (
@@ -676,11 +672,11 @@ class FlowchartTransformerStage extends LayoutStageBase {
if (!directions) {
return
}
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let leftCount = 0
let rightCount = 0
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
const dir = directions.getInt(edge)
if (dir === BranchDirection.LeftInFlow) {
leftCount++
@@ -695,7 +691,7 @@ class FlowchartTransformerStage extends LayoutStageBase {
// If there is more than one edge to the left or right side,
// set less restrictive candidates to allow nicer images.
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
const dir = directions.getInt(edge)
if (dir === BranchDirection.LeftInFlow || dir === BranchDirection.RightInFlow) {
this.sourceCandidates.set(edge, this.getPortCandidateCollection(BranchDirection.Flatwise))
@@ -718,7 +714,7 @@ class FlowchartTransformerStage extends LayoutStageBase {
const precedingLayers = []
const succeedingLayers = []
let previousLayer = -1
- groupedInEdges.forEach(edge => {
+ groupedInEdges.forEach((edge) => {
const layer = this.getLayerId(edge.source)
const layers = layer <= referenceLayer ? precedingLayers : succeedingLayers
if (layer !== previousLayer) {
@@ -1054,7 +1050,7 @@ class InEdgeGroupingConfigurator {
const target = layers[0].firstEdge().target
const nonSingletonLayerEdges = new EdgeList()
const unfinishedEdges = new EdgeList()
- layers.forEach(layer => {
+ layers.forEach((layer) => {
// maybe we should also check if a singleton node is connected to too many such buses
if (nonSingletonLayerEdges.isEmpty() && layer.size === 1) {
const edge = layer.firstEdge()
@@ -1067,7 +1063,7 @@ class InEdgeGroupingConfigurator {
this.enclosing.getLayerId(edge.source)
)
// Change unfinished edges to the dummy node
- unfinishedEdges.forEach(e => {
+ unfinishedEdges.forEach((e) => {
this.changeEdge(graph, e, e.source, layerDummy)
if (unfinishedEdges.size > 1) {
this.setGroupId(e, layerDummy)
@@ -1120,7 +1116,7 @@ class InEdgeGroupingConfigurator {
createGrouping(nonBusEdges, neighborLayerNode, graph) {
const nodeIds = graph.getDataProvider(LayoutKeys.NODE_ID_DP_KEY)
const groupId = nodeIds.get(nonBusEdges.firstEdge().target)
- nonBusEdges.forEach(edge => {
+ nonBusEdges.forEach((edge) => {
this.setGroupId(edge, groupId)
this.enclosing.targetCandidates.set(
edge,
@@ -1189,13 +1185,6 @@ class InEdgeGroupingConfigurator {
class SucceedingLayersInEdgeGroupingConfigurator extends InEdgeGroupingConfigurator {
edgesToReverse = null
- /**
- * @param {!FlowchartTransformerStage} enclosing
- */
- constructor(enclosing) {
- super(enclosing)
- }
-
/**
* Creates the complete grouping dummy structure.
* This class stores all edges that must be reversed after the
@@ -1307,7 +1296,7 @@ class SucceedingLayersInEdgeGroupingConfigurator extends InEdgeGroupingConfigura
const target = nonBusEdges.firstEdge().target
const groupId = graph.getDataProvider(LayoutKeys.NODE_ID_DP_KEY).get(target)
const neighborLayerIndex = this.enclosing.getLayerId(neighborLayerNode)
- nonBusEdges.forEach(edge => {
+ nonBusEdges.forEach((edge) => {
let groupingEdge
if (neighborLayerIndex === this.enclosing.getLayerId(edge.source)) {
groupingEdge = edge
@@ -1342,7 +1331,7 @@ class SucceedingLayersInEdgeGroupingConfigurator extends InEdgeGroupingConfigura
sameLayerEdge,
this.createStrongPortCandidate(sameLayerEdge, true, PortDirections.AGAINST_THE_FLOW, graph)
)
- nonBusEdges.forEach(edge => {
+ nonBusEdges.forEach((edge) => {
graph.changeEdge(edge, edge.source, target)
})
}
@@ -1424,7 +1413,7 @@ function getGroupingLists(graph) {
const groupIdDP = graph.getDataProvider(PortConstraintKeys.TARGET_GROUP_ID_DP_KEY)
// Partition edges according to group id
const idToListsMap = Maps.createHashMap()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const id = groupIdDP.get(edge)
if (id) {
if (idToListsMap.has(id)) {
@@ -1437,12 +1426,12 @@ function getGroupingLists(graph) {
})
// Divide the group id partitions according to edge target nodes
const targetGroupLists = []
- idToListsMap.values.forEach(groupList => {
+ idToListsMap.values.forEach((groupList) => {
// Sort the edges according to target nodes such that edges with the same target have consecutive indices
groupList.sort(new EdgeIndexComparer())
// Add edges to lists and start a new list whenever a new target is found
let targetGroupList
- groupList.forEach(edge => {
+ groupList.forEach((edge) => {
if (!targetGroupList || !edge.target.equals(targetGroupList.firstEdge().target)) {
targetGroupList = new EdgeList()
targetGroupLists.push(targetGroupList)
@@ -1463,14 +1452,14 @@ function restoreOriginalGraph(graph) {
return
}
graph.removeDataProvider(FlowchartTransformerStage.GROUPING_NODES_DP_KEY)
- new YNodeList(graph.getNodeCursor()).forEach(node => {
+ new YNodeList(graph.getNodeCursor()).forEach((node) => {
let outPath
const groupingDummyId = groupingDummiesDP.getInt(node)
if (groupingDummyId === NodeLayerType.Preceding) {
const outEdge = node.firstOutEdge
outPath = graph.getPathList(outEdge)
outPath.set(0, graph.getCenter(node))
- new EdgeList(node.getInEdgeCursor()).forEach(edge => {
+ new EdgeList(node.getInEdgeCursor()).forEach((edge) => {
const inPath = graph.getPathList(edge)
inPath.pop()
graph.changeEdge(edge, edge.source, outEdge.target)
@@ -1482,7 +1471,7 @@ function restoreOriginalGraph(graph) {
const inEdgeFromOriginal = groupingDummiesDP.getInt(inEdge.source) === 0
const inPath = graph.getPathList(inEdge)
inPath.set(inPath.size - 1, graph.getCenter(node))
- new EdgeList(node.getOutEdgeCursor()).forEach(edge => {
+ new EdgeList(node.getOutEdgeCursor()).forEach((edge) => {
const outEdgeFromOriginal = groupingDummiesDP.getInt(edge.target) === 0
outPath = graph.getPathList(edge)
outPath.shift()
@@ -1666,7 +1655,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
*/
optimizeAfterSequencingForSingleNode(node, inEdgeOrder, outEdgeOrder, graph, ldp, itemFactory) {
// set EAST or WEST temporary constraints for the same layer edges
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
if (FlowchartPortOptimizer.isTemporarySameLayerEdge(edge, ldp)) {
const preferredSide = FlowchartPortOptimizer.getPreferredSideForTemporarySameLayerEdge(
edge,
@@ -1696,7 +1685,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
const flatwiseEdges = Maps.createHashSet()
const centralEdges = new EdgeList()
const edges = source ? node.outEdges : node.inEdges
- edges.forEach(edge => {
+ edges.forEach((edge) => {
const edgeData = ldp.getEdgeData(edge)
const constraint = source ? edgeData.sourcePortConstraint : edgeData.targetPortConstraint
const candidates = source ? edgeData.sourcePortCandidates : edgeData.targetPortCandidates
@@ -1717,7 +1706,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
centralEdges.addAll(flatwiseEdges)
centralEdges.sort(edgeOrder)
centralEdges.forEach((edge, i) => {
- if (flatwiseEdges.some(flatwiseEdge => flatwiseEdge === edge)) {
+ if (flatwiseEdges.some((flatwiseEdge) => flatwiseEdge === edge)) {
const side = i < ((centralEdges.size / 2) | 0) ? PortSide.WEST : PortSide.EAST
itemFactory.setTemporaryPortConstraint(edge, source, PortConstraint.create(side))
}
@@ -1733,7 +1722,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
* @param {!IDataProvider} edge2Length
*/
optimizeForAlignment(graph, ldp, itemFactory, node2AlignWith, edge2Length) {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (!this.alignmentCalculator.isSpecialNode(graph, node, ldp) || node.degree < 2) {
return
}
@@ -1750,7 +1739,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
// port constraint for the same side at the opposite end, too. Otherwise, such an edge gets many bends and
// may even destroy the alignment.
if (criticalInEdge !== null) {
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
if (criticalInEdge !== edge && criticalInEdge.source === edge.source) {
const pc = ldp.getEdgeData(edge).targetPortConstraint
if (FlowchartPortOptimizer.isFlatwisePortConstraint(pc)) {
@@ -1760,7 +1749,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
})
}
if (criticalOutEdge !== null) {
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
if (criticalOutEdge !== edge && criticalOutEdge.target === edge.target) {
const pc = ldp.getEdgeData(edge).sourcePortConstraint
if (FlowchartPortOptimizer.isFlatwisePortConstraint(pc)) {
@@ -1826,7 +1815,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
static getAllSameLayerEdges(graph, ldp) {
const sameLayerEdges = new EdgeList()
const edge2Seen = Maps.createHashedEdgeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nData = ldp.getNodeData(node)
for (let cell = nData.firstSameLayerEdgeCell; cell !== null; cell = cell.succ()) {
const sameLayerEdge = cell.info
@@ -1894,7 +1883,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
}
let containsEast = false
let containsWest = false
- portCandidates.forEach(pc => {
+ portCandidates.forEach((pc) => {
const direction = pc.getDirectionForLayoutOrientation(layoutOrientation)
if (!containsEast && (PortDirections.EAST & direction) !== 0) {
containsEast = true
@@ -2262,7 +2251,7 @@ function setOptimizedPortConstraint(edge, source, direction, ldp, factory) {
function optimizeMessageNodes(graph, ldp, factory) {
const edges = new EdgeList(graph.getEdgeCursor())
edges.splice(FlowchartPortOptimizer.getAllSameLayerEdges(graph, ldp))
- edges.forEach(e => {
+ edges.forEach((e) => {
const original = FlowchartPortOptimizer.getOriginalEdge(e, ldp)
const sourceLaneId = FlowchartPortOptimizer.getSwimlaneId(original.source, ldp)
const targetLaneId = FlowchartPortOptimizer.getSwimlaneId(original.target, ldp)
@@ -2296,7 +2285,7 @@ function optimizeMessageNodes(graph, ldp, factory) {
*/
function getCriticalInEdge(node, node2AlignWith, edge2Length) {
let bestEdge = null
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
if (
node2AlignWith.get(node) === edge.source &&
(bestEdge === null || edge2Length.getNumber(bestEdge) < edge2Length.getInt(edge))
@@ -2318,7 +2307,7 @@ function getCriticalInEdge(node, node2AlignWith, edge2Length) {
*/
function getCriticalOutEdge(node, node2AlignWith, edge2Length) {
let bestEdge = null
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
if (
node2AlignWith.get(edge.target) === node &&
(bestEdge === null || edge2Length.getNumber(bestEdge) < edge2Length.getInt(edge))
@@ -2347,13 +2336,6 @@ class FlowchartLayerer extends BaseClass(ILayerer) {
$assignStartNodesToLeftOrTop = false
$allowFlatwiseDefaultFlow = false
- // Be careful: due to the handling of edges attaching to group nodes the degree of "degree-one" nodes may be > 1.
- // We are interested in nodes with degree one in the initial graph.
-
- constructor() {
- super()
- }
-
/**
* Returns whether start nodes are assigned at the top or to the left of the layout.
* @type {boolean}
@@ -2405,16 +2387,16 @@ class FlowchartLayerer extends BaseClass(ILayerer) {
// assign layers
RankAssignmentAlgorithm.simplex(graph, node2Layer, weight, minLength)
// undo graph transformation
- dummies.forEach(dummy => {
+ dummies.forEach((dummy) => {
graph.removeNode(dummy)
})
hider.unhideAll()
- reversedEdges.forEach(edge => {
+ reversedEdges.forEach((edge) => {
graph.reverseEdge(edge)
})
// special handling for some single degree nodes (draw the incident edge as the same layer edge)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (isDegreeOneNode(node, ldp)) {
handleDegreeOneNode(node, graph, node2Layer, ldp)
}
@@ -2424,7 +2406,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) {
for (let i = 0; i < layerCount; i++) {
layers.insert(LayerType.NORMAL, i)
}
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const layer = node2Layer.getInt(node)
layers.getLayer(layer).add(node)
})
@@ -2451,16 +2433,16 @@ class FlowchartLayerer extends BaseClass(ILayerer) {
const groupingNodesDP = graph.getDataProvider(FlowchartTransformerStage.GROUPING_NODES_DP_KEY)
const targetGroupIdDP = graph.getDataProvider(PortConstraintKeys.TARGET_GROUP_ID_DP_KEY)
const outEdgeBranchTypes = graph.createNodeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let type = 0
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
type |= preferredDirectionDP.getInt(edge)
})
outEdgeBranchTypes.setInt(node, type)
})
const dummies = new YNodeList()
const edges = graph.getEdgeArray()
- edges.forEach(edge => {
+ edges.forEach((edge) => {
let dummyEdge2
let dummyEdge1
let dummyNode
@@ -2529,7 +2511,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) {
*/
insertSuperRoot(graph, weight, minLength) {
const superRoot = graph.createNode()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (!node.equals(superRoot) && node.inDegree === 0) {
const dummyEdge = graph.createEdge(superRoot, node)
weight.setInt(
@@ -2551,7 +2533,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) {
function reverseCycles(graph) {
// we only consider edges of type sequence flow
const hider = new LayoutGraphHider(graph)
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (getType(graph, e) !== EdgeType.SequenceFlow) {
hider.hide(e)
}
@@ -2562,7 +2544,7 @@ function reverseCycles(graph) {
try {
// try to identify backedges and assign lower weights to them
const coreNodes = new YNodeList()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.inDegree === 0) {
coreNodes.addLast(node)
}
@@ -2570,7 +2552,7 @@ function reverseCycles(graph) {
const node2Depth = graph.createNodeMap()
try {
BfsAlgorithm.getLayers(graph, coreNodes, true, node2Depth)
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (node2Depth.getInt(edge.source) > node2Depth.getInt(edge.target)) {
// likely to be a back-edge
edge2Weight.setNumber(edge, CYCLE_WEIGHT_BACKEDGE)
@@ -2585,7 +2567,7 @@ function reverseCycles(graph) {
reversedEdges = new EdgeList()
CycleAlgorithm.findCycleEdges(graph, cyclingEdges, edge2Weight)
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (cyclingEdges.getBoolean(e)) {
graph.reverseEdge(e)
reversedEdges.addLast(e)
@@ -2684,7 +2666,7 @@ function handleDegreeOneNode(node, graph, node2Layer, ldp) {
let sameLayerEdgeCount = 0
let oppositeOutDegree = 0
let oppositeInDegree = 0
- opposite.outEdges.forEach(edge => {
+ opposite.outEdges.forEach((edge) => {
if (!edge.equals(realEdge) && isNormalEdge(ldp.getEdgeData(edge))) {
const layerDiff = node2Layer.getInt(edge.source) - node2Layer.getInt(edge.target)
if (layerDiff > 0) {
@@ -2697,7 +2679,7 @@ function handleDegreeOneNode(node, graph, node2Layer, ldp) {
}
})
- opposite.inEdges.forEach(edge => {
+ opposite.inEdges.forEach((edge) => {
if (!edge.equals(realEdge) && isNormalEdge(ldp.getEdgeData(edge))) {
const layerDiff = node2Layer.getInt(edge.source) - node2Layer.getInt(edge.target)
if (layerDiff > 0) {
@@ -2848,7 +2830,7 @@ class FlowchartLabelProfitModel extends BaseClass(IProfitModel) {
super()
this.graph = graph
this.label2OriginalBox = Maps.createHashMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nll = graph.getLabelLayout(node)
for (let i = 0; i < nll.length; i++) {
const nlm = nll[i].labelModel
@@ -3096,7 +3078,7 @@ class FlowchartAlignmentCalculator {
ldp
) {
const edgeIsAlignable = Maps.createHashedEdgeMap()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edgeIsAlignable.setBoolean(
edge,
this.isAlignable(graph, ldp, edge) && this.isRelevant(graph, edge, ldp)
@@ -3119,7 +3101,7 @@ class FlowchartAlignmentCalculator {
const BasicEdgeLength = 5
const PenaltyLength = BasicEdgeLength + graph.nodeCount
const HighPenaltyLength = PenaltyLength * 8
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (hasFlatwisePortConstraint(layoutData.getEdgeData(e))) {
edgeLength.setInt(e, ZeroLength)
} else if (isRealEdge(e, layoutData)) {
@@ -3128,7 +3110,7 @@ class FlowchartAlignmentCalculator {
edgeLength.setInt(e, BasicDummyEdgeLength)
}
})
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let i
let edges
const nodeData = layoutData.getNodeData(node)
@@ -3178,7 +3160,7 @@ class FlowchartAlignmentCalculator {
}
}
let hasStraightBranch = false
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
if (isStraightBranch(graph, edge, layoutData)) {
hasStraightBranch = true
edgeLength.setInt(edge, edgeLength.getInt(edge) + PenaltyLength)
@@ -3263,7 +3245,7 @@ class NodeAlignmentCalculator {
const groupNode2EndRep = Maps.createHashMap()
const network = new Graph()
// create network nodes
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const data = ldp.getNodeData(node)
if (data !== null && data.type === NodeDataType.GROUP_BEGIN) {
// all groups begin dummies of the same group node are mapped to the same network node
@@ -3286,7 +3268,7 @@ class NodeAlignmentCalculator {
})
// consider edges
const nonAlignableEdges = new EdgeList()
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (e.selfLoop || (isGroupNodeBorder(e.source, ldp) && isGroupNodeBorder(e.target, ldp))) {
return
}
@@ -3362,7 +3344,7 @@ class NodeAlignmentCalculator {
// For each non-alignable edge, we create a connector with min length 1,
// but only it has no other alignable in-edge.
const nonAlignableConnectorMap = Maps.createHashedEdgeMap()
- nonAlignableEdges.forEach(e => {
+ nonAlignableEdges.forEach((e) => {
const hasAlignableInEdge = checkPredicate(e.target.getInEdgeCursor(), edgeAlignable)
if (hasAlignableInEdge) {
return
@@ -3488,7 +3470,7 @@ class NodeAlignmentCalculator {
ldp
) {
const node2LaneAlignment = Maps.createHashedNodeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
node2LaneAlignment.setInt(node, this.getLaneAlignment(node, ldp))
})
return node2LaneAlignment
@@ -3506,7 +3488,7 @@ class NodeAlignmentCalculator {
const nEdges = new EdgeList(node.getEdgeCursor())
nEdges.splice(FlowchartPortOptimizer.getSameLayerEdges(node, true, ldp))
nEdges.splice(FlowchartPortOptimizer.getSameLayerEdges(node, false, ldp))
- nEdges.forEach(edge => {
+ nEdges.forEach((edge) => {
if (FlowchartPortOptimizer.isToLeftPartition(node, edge.opposite(node), ldp)) {
toLeftCount++
} else if (FlowchartPortOptimizer.isToRightPartition(node, edge.opposite(node), ldp)) {
@@ -3752,7 +3734,7 @@ function determineEdgePriorities(graph, edgeIsAlignable, edgeLength) {
const hider = new LayoutGraphHider(graph)
try {
// hide irrelevant edges
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edgePriority.setInt(edge, Priority.Basic)
if (!edgeIsAlignable.getBoolean(edge)) {
hider.hide(edge)
@@ -3764,6 +3746,7 @@ function determineEdgePriorities(graph, edgeIsAlignable, edgeLength) {
const gpm = new GraphPartitionManager(graph, node2CompId)
try {
gpm.hideAll()
+ // biome-ignore lint/correctness/noUnreachable: Seems to be an incorrect warning
for (let i = 0; i < compCount; i++) {
gpm.displayPartition(i)
const localHider = new LayoutGraphHider(graph)
diff --git a/demos/showcase/flowchart/layout/FlowchartLayout.ts b/demos/showcase/flowchart/layout/FlowchartLayout.ts
index 9ccf4ff8f..6dda20122 100644
--- a/demos/showcase/flowchart/layout/FlowchartLayout.ts
+++ b/demos/showcase/flowchart/layout/FlowchartLayout.ts
@@ -244,12 +244,12 @@ export class FlowchartLayout
const grid = PartitionGrid.getPartitionGrid(graph)
if (grid) {
// adjust insets
- grid.columns.forEach(column => {
+ grid.columns.forEach((column) => {
column.leftInset = this.laneInsets
column.rightInset = this.laneInsets
})
- grid.rows.forEach(row => {
+ grid.rows.forEach((row) => {
row.topInset = this.laneInsets
row.bottomInset = this.laneInsets
})
@@ -267,7 +267,7 @@ export class FlowchartLayout
graph.removeDataProvider(HierarchicLayout.LAYER_INDEX_DP_KEY)
}
const edge2LayoutDescriptor = Maps.createHashedEdgeMap()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edge2LayoutDescriptor.set(
edge,
this.createEdgeLayoutDescriptor(
@@ -348,7 +348,7 @@ export class FlowchartLayout
): HierarchicLayoutEdgeLayoutDescriptor {
const ell = graph.getLabelLayout(edge)
let minLength = 0.0
- ell.forEach(label => {
+ ell.forEach((label) => {
const labelSize = label.boundingBox
if (isRegularEdge(graph, edge)) {
minLength += horizontal ? labelSize.width : labelSize.height
@@ -504,10 +504,6 @@ class FlowchartTransformerStage extends LayoutStageBase {
dummyLayerIds: INodeMap = null!
groupNodeIdWrapper: HashedDataProviderWrapper | null = null
- constructor() {
- super()
- }
-
applyLayout(graph: LayoutGraph): void {
const hierarchicLayout = getHierarchicCoreLayout(this)
if (!hierarchicLayout) {
@@ -646,7 +642,7 @@ class FlowchartTransformerStage extends LayoutStageBase {
const succeedingGroupingConfigurator = new SucceedingLayersInEdgeGroupingConfigurator(this)
const edgesToReverse = new EdgeList()
const groupingLists = getGroupingLists(graph)
- groupingLists.forEach(groupingList => {
+ groupingLists.forEach((groupingList) => {
if (groupingList === null || groupingList.isEmpty()) {
return
}
@@ -660,7 +656,7 @@ class FlowchartTransformerStage extends LayoutStageBase {
)
} else {
const target = groupingList.firstEdge()!.target
- groupingList.forEach(edge => {
+ groupingList.forEach((edge) => {
this.targetGroupIds.set(edge, target)
})
}
@@ -690,11 +686,11 @@ class FlowchartTransformerStage extends LayoutStageBase {
if (!directions) {
return
}
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let leftCount = 0
let rightCount = 0
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
const dir = directions.getInt(edge)
if (dir === BranchDirection.LeftInFlow) {
leftCount++
@@ -709,7 +705,7 @@ class FlowchartTransformerStage extends LayoutStageBase {
// If there is more than one edge to the left or right side,
// set less restrictive candidates to allow nicer images.
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
const dir = directions.getInt(edge)
if (dir === BranchDirection.LeftInFlow || dir === BranchDirection.RightInFlow) {
this.sourceCandidates.set(edge, this.getPortCandidateCollection(BranchDirection.Flatwise))
@@ -882,7 +878,10 @@ class IdProvider extends DataProviderBase {
* or else the value in the provider.
*/
class NodeIdDataProvider extends DataProviderBase {
- constructor(private backupNodeIdDP: IDataProvider, private provider: IdProvider) {
+ constructor(
+ private backupNodeIdDP: IDataProvider,
+ private provider: IdProvider
+ ) {
super()
}
@@ -912,7 +911,10 @@ class EdgeIndexComparer extends BaseClass>(IComparer) implements
* Comparer, which uses the layer index of the edges' source nodes as an order.
*/
class LayerIndexComparer extends BaseClass>(IComparer) implements IComparer {
- constructor(private enclosing: FlowchartTransformerStage, private hasLayerIds: boolean) {
+ constructor(
+ private enclosing: FlowchartTransformerStage,
+ private hasLayerIds: boolean
+ ) {
super()
}
@@ -1001,7 +1003,7 @@ class InEdgeGroupingConfigurator {
const target = layers[0].firstEdge()!.target
const nonSingletonLayerEdges = new EdgeList()
const unfinishedEdges = new EdgeList()
- layers.forEach(layer => {
+ layers.forEach((layer) => {
// maybe we should also check if a singleton node is connected to too many such buses
if (nonSingletonLayerEdges.isEmpty() && layer.size === 1) {
const edge = layer.firstEdge()!
@@ -1127,10 +1129,6 @@ class InEdgeGroupingConfigurator {
class SucceedingLayersInEdgeGroupingConfigurator extends InEdgeGroupingConfigurator {
private edgesToReverse: EdgeList | null = null
- constructor(enclosing: FlowchartTransformerStage) {
- super(enclosing)
- }
-
/**
* Creates the complete grouping dummy structure.
* This class stores all edges that must be reversed after the
@@ -1274,7 +1272,10 @@ class HashedDataProviderWrapper
extends BaseClass(IDataProvider)
implements IDataProvider
{
- constructor(readonly map: IMap, readonly fallback: IDataProvider) {
+ constructor(
+ readonly map: IMap,
+ readonly fallback: IDataProvider
+ ) {
super()
}
@@ -1342,7 +1343,7 @@ function getGroupingLists(graph: LayoutGraph): EdgeList[] {
})
// Divide the group id partitions according to edge target nodes
const targetGroupLists: EdgeList[] = []
- idToListsMap.values.forEach(groupList => {
+ idToListsMap.values.forEach((groupList) => {
// Sort the edges according to target nodes such that edges with the same target have consecutive indices
groupList.sort(new EdgeIndexComparer())
// Add edges to lists and start a new list whenever a new target is found
@@ -1569,7 +1570,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
itemFactory: IItemFactory
): void {
// set EAST or WEST temporary constraints for the same layer edges
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
if (FlowchartPortOptimizer.isTemporarySameLayerEdge(edge, ldp)) {
const preferredSide = FlowchartPortOptimizer.getPreferredSideForTemporarySameLayerEdge(
edge,
@@ -1600,7 +1601,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
const flatwiseEdges = Maps.createHashSet()
const centralEdges = new EdgeList()
const edges = source ? node.outEdges : node.inEdges
- edges.forEach(edge => {
+ edges.forEach((edge) => {
const edgeData = ldp.getEdgeData(edge)!
const constraint = source ? edgeData.sourcePortConstraint : edgeData.targetPortConstraint
const candidates = (
@@ -1623,7 +1624,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
centralEdges.addAll(flatwiseEdges)
centralEdges.sort(edgeOrder)
centralEdges.forEach((edge: Edge, i) => {
- if (flatwiseEdges.some(flatwiseEdge => flatwiseEdge === edge)) {
+ if (flatwiseEdges.some((flatwiseEdge) => flatwiseEdge === edge)) {
const side = i < ((centralEdges.size / 2) | 0) ? PortSide.WEST : PortSide.EAST
itemFactory.setTemporaryPortConstraint(edge, source, PortConstraint.create(side))
}
@@ -1640,7 +1641,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
node2AlignWith: IDataProvider,
edge2Length: IDataProvider
): void {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (!this.alignmentCalculator.isSpecialNode(graph, node, ldp) || node.degree < 2) {
return
}
@@ -1657,7 +1658,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
// port constraint for the same side at the opposite end, too. Otherwise, such an edge gets many bends and
// may even destroy the alignment.
if (criticalInEdge !== null) {
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
if (criticalInEdge !== edge && criticalInEdge.source === edge.source) {
const pc = ldp.getEdgeData(edge)!.targetPortConstraint!
if (FlowchartPortOptimizer.isFlatwisePortConstraint(pc)) {
@@ -1667,7 +1668,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
})
}
if (criticalOutEdge !== null) {
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
if (criticalOutEdge !== edge && criticalOutEdge.target === edge.target) {
const pc = ldp.getEdgeData(edge)!.sourcePortConstraint!
if (FlowchartPortOptimizer.isFlatwisePortConstraint(pc)) {
@@ -1720,7 +1721,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
static getAllSameLayerEdges(graph: LayoutGraph, ldp: ILayoutDataProvider): EdgeList {
const sameLayerEdges = new EdgeList()
const edge2Seen = Maps.createHashedEdgeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nData = ldp.getNodeData(node)!
for (let cell = nData.firstSameLayerEdgeCell; cell !== null; cell = cell.succ()) {
const sameLayerEdge = cell.info as Edge
@@ -1778,7 +1779,7 @@ class FlowchartPortOptimizer extends PortConstraintOptimizerBase {
}
let containsEast = false
let containsWest = false
- portCandidates.forEach(pc => {
+ portCandidates.forEach((pc) => {
const direction = pc.getDirectionForLayoutOrientation(layoutOrientation)
if (!containsEast && (PortDirections.EAST & direction) !== 0) {
containsEast = true
@@ -1867,7 +1868,10 @@ class PositionEdgeComparer
private sameLayerNodePositionComparer: SameLayerNodePositionComparer
private portConstraintComparer: SingleSidePortConstraintComparer
- constructor(private source: boolean, private ldp: ILayoutDataProvider) {
+ constructor(
+ private source: boolean,
+ private ldp: ILayoutDataProvider
+ ) {
super()
this.sameLayerNodePositionComparer = new SameLayerNodePositionComparer(ldp)
this.portConstraintComparer = new SingleSidePortConstraintComparer()
@@ -2151,7 +2155,7 @@ function getCriticalInEdge(
edge2Length: IDataProvider
): Edge | null {
let bestEdge: Edge | null = null
- node.inEdges.forEach(edge => {
+ node.inEdges.forEach((edge) => {
if (
node2AlignWith.get(node) === edge.source &&
(bestEdge === null || edge2Length.getNumber(bestEdge) < edge2Length.getInt(edge))
@@ -2173,7 +2177,7 @@ function getCriticalOutEdge(
edge2Length: IDataProvider
): Edge | null {
let bestEdge: Edge | null = null
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
if (
node2AlignWith.get(edge.target) === node &&
(bestEdge === null || edge2Length.getNumber(bestEdge) < edge2Length.getInt(edge))
@@ -2202,13 +2206,6 @@ class FlowchartLayerer extends BaseClass(ILayerer) implements ILayerer
private $assignStartNodesToLeftOrTop = false
private $allowFlatwiseDefaultFlow = false
- // Be careful: due to the handling of edges attaching to group nodes the degree of "degree-one" nodes may be > 1.
- // We are interested in nodes with degree one in the initial graph.
-
- constructor() {
- super()
- }
-
/**
* Returns whether start nodes are assigned at the top or to the left of the layout.
*/
@@ -2260,7 +2257,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) implements ILayerer
})
// special handling for some single degree nodes (draw the incident edge as the same layer edge)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (isDegreeOneNode(node, ldp)) {
handleDegreeOneNode(node, graph, node2Layer, ldp)
}
@@ -2270,7 +2267,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) implements ILayerer
for (let i = 0; i < layerCount; i++) {
layers.insert(LayerType.NORMAL, i)
}
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const layer = node2Layer.getInt(node)
layers.getLayer(layer)!.add(node)
})
@@ -2297,16 +2294,16 @@ class FlowchartLayerer extends BaseClass(ILayerer) implements ILayerer
const groupingNodesDP = graph.getDataProvider(FlowchartTransformerStage.GROUPING_NODES_DP_KEY)!
const targetGroupIdDP = graph.getDataProvider(PortConstraintKeys.TARGET_GROUP_ID_DP_KEY)!
const outEdgeBranchTypes = graph.createNodeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let type = 0
- node.outEdges.forEach(edge => {
+ node.outEdges.forEach((edge) => {
type |= preferredDirectionDP.getInt(edge)
})
outEdgeBranchTypes.setInt(node, type)
})
const dummies = new YNodeList()
const edges = graph.getEdgeArray()
- edges.forEach(edge => {
+ edges.forEach((edge) => {
let dummyEdge2: Edge
let dummyEdge1: Edge
let dummyNode: YNode
@@ -2371,7 +2368,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) implements ILayerer
*/
insertSuperRoot(graph: LayoutGraph, weight: IDataAcceptor, minLength: IDataAcceptor): YNode {
const superRoot = graph.createNode()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (!node.equals(superRoot) && node.inDegree === 0) {
const dummyEdge = graph.createEdge(superRoot, node)
weight.setInt(
@@ -2391,7 +2388,7 @@ class FlowchartLayerer extends BaseClass(ILayerer) implements ILayerer
function reverseCycles(graph: LayoutGraph): EdgeList {
// we only consider edges of type sequence flow
const hider = new LayoutGraphHider(graph)
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (getType(graph, e) !== EdgeType.SequenceFlow) {
hider.hide(e)
}
@@ -2402,7 +2399,7 @@ function reverseCycles(graph: LayoutGraph): EdgeList {
try {
// try to identify backedges and assign lower weights to them
const coreNodes = new YNodeList()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (node.inDegree === 0) {
coreNodes.addLast(node)
}
@@ -2410,7 +2407,7 @@ function reverseCycles(graph: LayoutGraph): EdgeList {
const node2Depth = graph.createNodeMap()
try {
BfsAlgorithm.getLayers(graph, coreNodes, true, node2Depth)
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (node2Depth.getInt(edge.source) > node2Depth.getInt(edge.target)) {
// likely to be a back-edge
edge2Weight.setNumber(edge, CYCLE_WEIGHT_BACKEDGE)
@@ -2425,7 +2422,7 @@ function reverseCycles(graph: LayoutGraph): EdgeList {
reversedEdges = new EdgeList()
CycleAlgorithm.findCycleEdges(graph, cyclingEdges, edge2Weight)
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (cyclingEdges.getBoolean(e)) {
graph.reverseEdge(e)
reversedEdges.addLast(e)
@@ -2519,7 +2516,7 @@ function handleDegreeOneNode(
let sameLayerEdgeCount = 0
let oppositeOutDegree = 0
let oppositeInDegree = 0
- opposite.outEdges.forEach(edge => {
+ opposite.outEdges.forEach((edge) => {
if (!edge.equals(realEdge) && isNormalEdge(ldp.getEdgeData(edge))) {
const layerDiff = node2Layer.getInt(edge.source) - node2Layer.getInt(edge.target)
if (layerDiff > 0) {
@@ -2532,7 +2529,7 @@ function handleDegreeOneNode(
}
})
- opposite.inEdges.forEach(edge => {
+ opposite.inEdges.forEach((edge) => {
if (!edge.equals(realEdge) && isNormalEdge(ldp.getEdgeData(edge))) {
const layerDiff = node2Layer.getInt(edge.source) - node2Layer.getInt(edge.target)
if (layerDiff > 0) {
@@ -2666,7 +2663,7 @@ class FlowchartLabelProfitModel
constructor(private graph: LayoutGraph) {
super()
this.label2OriginalBox = Maps.createHashMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nll = graph.getLabelLayout(node)
for (let i = 0; i < nll.length; i++) {
const nlm = nll[i].labelModel
@@ -2881,7 +2878,7 @@ class FlowchartAlignmentCalculator {
ldp: ILayoutDataProvider
): IDataProvider {
const edgeIsAlignable = Maps.createHashedEdgeMap()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edgeIsAlignable.setBoolean(
edge,
this.isAlignable(graph, ldp, edge) && this.isRelevant(graph, edge, ldp)
@@ -2905,7 +2902,7 @@ class FlowchartAlignmentCalculator {
const BasicEdgeLength = 5
const PenaltyLength = BasicEdgeLength + graph.nodeCount
const HighPenaltyLength = PenaltyLength * 8
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (hasFlatwisePortConstraint(layoutData.getEdgeData(e)!)) {
edgeLength.setInt(e, ZeroLength)
} else if (isRealEdge(e, layoutData)) {
@@ -2914,7 +2911,7 @@ class FlowchartAlignmentCalculator {
edgeLength.setInt(e, BasicDummyEdgeLength)
}
})
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
let i: number
let edges: Edge[]
const nodeData = layoutData.getNodeData(node)!
@@ -2964,7 +2961,7 @@ class FlowchartAlignmentCalculator {
}
}
let hasStraightBranch = false
- node.edges.forEach(edge => {
+ node.edges.forEach((edge) => {
if (isStraightBranch(graph, edge, layoutData)) {
hasStraightBranch = true
edgeLength.setInt(edge, edgeLength.getInt(edge) + PenaltyLength)
@@ -3041,7 +3038,7 @@ class NodeAlignmentCalculator {
const groupNode2EndRep = Maps.createHashMap()
const network = new Graph()
// create network nodes
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const data = ldp.getNodeData(node)
if (data !== null && data.type === NodeDataType.GROUP_BEGIN) {
// all groups begin dummies of the same group node are mapped to the same network node
@@ -3064,7 +3061,7 @@ class NodeAlignmentCalculator {
})
// consider edges
const nonAlignableEdges = new EdgeList()
- graph.edges.forEach(e => {
+ graph.edges.forEach((e) => {
if (e.selfLoop || (isGroupNodeBorder(e.source, ldp) && isGroupNodeBorder(e.target, ldp))) {
return
}
@@ -3263,7 +3260,7 @@ class NodeAlignmentCalculator {
ldp: ILayoutDataProvider
): INodeMap {
const node2LaneAlignment = Maps.createHashedNodeMap()
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
node2LaneAlignment.setInt(node, this.getLaneAlignment(node, ldp))
})
return node2LaneAlignment
@@ -3488,7 +3485,7 @@ function determineEdgePriorities(
const hider = new LayoutGraphHider(graph)
try {
// hide irrelevant edges
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
edgePriority.setInt(edge, Priority.Basic)
if (!edgeIsAlignable.getBoolean(edge)) {
hider.hide(edge)
@@ -3500,6 +3497,7 @@ function determineEdgePriorities(
const gpm = new GraphPartitionManager(graph, node2CompId)
try {
gpm.hideAll()
+ // biome-ignore lint/correctness/noUnreachable: Seems to be an incorrect warning
for (let i = 0; i < compCount; i++) {
gpm.displayPartition(i)
const localHider = new LayoutGraphHider(graph)
diff --git a/demos/showcase/flowchart/layout/FlowchartLayoutData.js b/demos/showcase/flowchart/layout/FlowchartLayoutData.js
index 5a5f46bbc..821088422 100644
--- a/demos/showcase/flowchart/layout/FlowchartLayoutData.js
+++ b/demos/showcase/flowchart/layout/FlowchartLayoutData.js
@@ -240,14 +240,14 @@ export class FlowchartLayoutData {
create(graph) {
const data = new GenericLayoutData()
- data.addEdgeItemMapping(FlowchartLayout.PREFERRED_DIRECTION_DP_KEY).delegate = edge =>
+ data.addEdgeItemMapping(FlowchartLayout.PREFERRED_DIRECTION_DP_KEY).delegate = (edge) =>
this.getBranchType(edge)
- data.addNodeItemMapping(NODE_TYPE_DP_KEY).delegate = node => this.getType(node)
- data.addEdgeItemMapping(EDGE_TYPE_DP_KEY).delegate = edge => this.getType(edge)
+ data.addNodeItemMapping(NODE_TYPE_DP_KEY).delegate = (node) => this.getType(node)
+ data.addEdgeItemMapping(EDGE_TYPE_DP_KEY).delegate = (edge) => this.getType(edge)
if (graph.groupingSupport.hasGroupNodes()) {
- data.addLabelItemMapping(FlowchartLayout.LABEL_LAYOUT_DP_KEY).delegate = label => {
+ data.addLabelItemMapping(FlowchartLayout.LABEL_LAYOUT_DP_KEY).delegate = (label) => {
const node = label.owner
return node instanceof INode && label === node.labels.at(0) && !graph.isGroupNode(node)
}
@@ -264,7 +264,7 @@ export class FlowchartLayoutData {
degreeThreshold = 4
}
- data.addEdgeItemMapping(PortConstraintKeys.TARGET_GROUP_ID_DP_KEY).delegate = edge => {
+ data.addEdgeItemMapping(PortConstraintKeys.TARGET_GROUP_ID_DP_KEY).delegate = (edge) => {
const node = edge.targetNode
return graph.inDegree(node) >= 2 &&
graph.inDegree(node) >= inDegreeThreshold &&
diff --git a/demos/showcase/flowchart/model/load-flowchart.js b/demos/showcase/flowchart/model/load-flowchart.js
index d6bfe2807..50f477513 100644
--- a/demos/showcase/flowchart/model/load-flowchart.js
+++ b/demos/showcase/flowchart/model/load-flowchart.js
@@ -54,11 +54,11 @@ export function loadFlowchart(graphComponent, sample) {
data: data.nodes,
id: 'id',
labels: ['label'],
- layout: dataItem =>
+ layout: (dataItem) =>
dataItem.type === 'decision'
? Rect.fromCenter(Point.ORIGIN, new Size(145, 100))
: Rect.fromCenter(Point.ORIGIN, new Size(145, 60)),
- style: dataItem => new FlowchartNodeStyle(dataItem.type)
+ style: (dataItem) => new FlowchartNodeStyle(dataItem.type)
}
],
edges: [
diff --git a/demos/showcase/flowchart/option-panel/option-panel.css b/demos/showcase/flowchart/option-panel/option-panel.css
index 42ae889bb..0c806dbf7 100644
--- a/demos/showcase/flowchart/option-panel/option-panel.css
+++ b/demos/showcase/flowchart/option-panel/option-panel.css
@@ -128,7 +128,8 @@
font-family: Tahoma, Verdana, sans-serif;
font-size: 14px;
letter-spacing: 1px;
- transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
+ transition:
+ background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.settings-editor-row5.flat-button:disabled {
diff --git a/demos/showcase/frauddetection/FraudDetectionDemo.js b/demos/showcase/frauddetection/FraudDetectionDemo.js
index fe72c4cf2..164ef5383 100644
--- a/demos/showcase/frauddetection/FraudDetectionDemo.js
+++ b/demos/showcase/frauddetection/FraudDetectionDemo.js
@@ -117,7 +117,7 @@ function initializeUI() {
const bankFraudDescription = document.querySelector('#bank-fraud-detection')
const insuranceFraudDescription = document.querySelector('#insurance-fraud-detection')
const samples = document.querySelector('#samples')
- samples.addEventListener('change', async event => {
+ samples.addEventListener('change', async (event) => {
clearPropertiesView()
// if an inspection view is open, close it
closeFraudDetectionView()
@@ -196,12 +196,12 @@ async function buildGraph(graph, data) {
graph.clear()
function convertDates(dates) {
- return Array.isArray(dates) ? dates.map(e => new Date(e)) : [new Date(dates)]
+ return Array.isArray(dates) ? dates.map((e) => new Date(e)) : [new Date(dates)]
}
const builder = new GraphBuilder(graph)
const entityNodesSource = builder.createNodesSource(data.nodesSource, 'id')
- entityNodesSource.nodeCreator.tagProvider = entity => ({
+ entityNodesSource.nodeCreator.tagProvider = (entity) => ({
...entity,
enter: convertDates(entity.enter),
exit: convertDates(entity.exit)
@@ -280,7 +280,7 @@ function initializeTimelineComponent(selector, graphComponent) {
timeline = new Timeline(selector, getTimeEntry)
// filter the elements that are not part of the current timeframe
- const filteredGraph = new FilteredGraphWrapper(graphComponent.graph, node =>
+ const filteredGraph = new FilteredGraphWrapper(graphComponent.graph, (node) =>
timeline.filter(getEntityData(node))
)
graphComponent.graph = filteredGraph
@@ -294,25 +294,25 @@ function initializeTimelineComponent(selector, graphComponent) {
updateFraudWarnings(fraudsters)
})
- timeline.addBarSelectListener(items => {
+ timeline.addBarSelectListener((items) => {
const selection = graphComponent.selection
selection.clear()
- const selectedItems = new Set(items.map(item => item.id))
- graphComponent.graph.nodes.forEach(node => {
+ const selectedItems = new Set(items.map((item) => item.id))
+ graphComponent.graph.nodes.forEach((node) => {
const entity = getEntityData(node)
if (selectedItems.has(entity.id)) {
selection.setSelected(node, true)
}
})
})
- timeline.addBarHoverListener(items => {
+ timeline.addBarHoverListener((items) => {
const highlightManager = graphComponent.highlightIndicatorManager
highlightManager.clearHighlights()
- const selected = new Set(items.map(item => item.id))
+ const selected = new Set(items.map((item) => item.id))
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
const entity = getEntityData(node)
if (selected.has(entity.id)) {
highlightManager.addHighlight(node)
diff --git a/demos/showcase/frauddetection/FraudDetectionDemo.ts b/demos/showcase/frauddetection/FraudDetectionDemo.ts
index 4d3502226..b46a11e75 100644
--- a/demos/showcase/frauddetection/FraudDetectionDemo.ts
+++ b/demos/showcase/frauddetection/FraudDetectionDemo.ts
@@ -120,7 +120,7 @@ function initializeUI(): void {
'#insurance-fraud-detection'
)!
const samples = document.querySelector('#samples')!
- samples.addEventListener('change', async event => {
+ samples.addEventListener('change', async (event) => {
clearPropertiesView()
// if an inspection view is open, close it
closeFraudDetectionView()
@@ -293,25 +293,25 @@ function initializeTimelineComponent(
updateFraudWarnings(fraudsters)
})
- timeline.addBarSelectListener(items => {
+ timeline.addBarSelectListener((items) => {
const selection = graphComponent.selection
selection.clear()
- const selectedItems = new Set(items.map(item => item.id))
- graphComponent.graph.nodes.forEach(node => {
+ const selectedItems = new Set(items.map((item) => item.id))
+ graphComponent.graph.nodes.forEach((node) => {
const entity = getEntityData(node)
if (selectedItems.has(entity.id)) {
selection.setSelected(node, true)
}
})
})
- timeline.addBarHoverListener(items => {
+ timeline.addBarHoverListener((items) => {
const highlightManager = graphComponent.highlightIndicatorManager
highlightManager.clearHighlights()
- const selected = new Set(items.map(item => item.id))
+ const selected = new Set(items.map((item) => item.id))
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
const entity = getEntityData(node)
if (selected.has(entity.id)) {
highlightManager.addHighlight(node)
diff --git a/demos/showcase/frauddetection/entity-data.js b/demos/showcase/frauddetection/entity-data.js
index 089c2978f..9ebfb61df 100644
--- a/demos/showcase/frauddetection/entity-data.js
+++ b/demos/showcase/frauddetection/entity-data.js
@@ -105,7 +105,7 @@ export function getInfoMap(node) {
return { info: info }
} else {
const records = {}
- Object.keys(info).forEach(key => {
+ Object.keys(info).forEach((key) => {
let value = info[key]
if (Array.isArray(value)) {
value = value[0]
@@ -184,7 +184,7 @@ export function getTimeEntry(item) {
* @returns {?INode}
*/
export function getNode(graph, entityData) {
- return graph.nodes.find(node => {
+ return graph.nodes.find((node) => {
const data = getEntityData(node)
return data.id === entityData.id
})
diff --git a/demos/showcase/frauddetection/entity-data.ts b/demos/showcase/frauddetection/entity-data.ts
index 2e2f3ac45..2a1653d13 100644
--- a/demos/showcase/frauddetection/entity-data.ts
+++ b/demos/showcase/frauddetection/entity-data.ts
@@ -164,7 +164,7 @@ export function getTimeEntry(item: Entity): TimeEntry {
}
export function getNode(graph: IGraph, entityData: Entity): INode | null {
- return graph.nodes.find(node => {
+ return graph.nodes.find((node) => {
const data = getEntityData(node)
return data.id === entityData.id
})
diff --git a/demos/showcase/frauddetection/fraud-detection/fraud-components.js b/demos/showcase/frauddetection/fraud-detection/fraud-components.js
index a45ce59c5..d2ce21a54 100644
--- a/demos/showcase/frauddetection/fraud-detection/fraud-components.js
+++ b/demos/showcase/frauddetection/fraud-detection/fraud-components.js
@@ -91,7 +91,7 @@ export function updateFraudWarnings(fraudsters) {
const currentFraudComponents = new Set()
// add fraud warning for new fraud components
- fraudsters.forEach(node => {
+ fraudsters.forEach((node) => {
const componentIdx = getComponentIdx(node)
if (visibleFraudComponents.indexOf(componentIdx) < 0) {
visibleFraudComponents.push(componentIdx)
@@ -108,7 +108,7 @@ export function updateFraudWarnings(fraudsters) {
visibleFraudComponents.splice(i, 1)
const componentNodes = getComponentNodes(componentIdx)
// remove highlight from the component related to the removed warning sign
- componentNodes.forEach(node => {
+ componentNodes.forEach((node) => {
fraudHighlightManager.removeHighlight(node)
})
removeFraudWarning(componentIdx)
@@ -137,7 +137,7 @@ function createFraudWarning(componentIdx) {
warningButton.addEventListener('click', () =>
openFraudDetectionView(componentIdx, graphComponent)
)
- warningButton.addEventListener('mouseover', event =>
+ warningButton.addEventListener('mouseover', (event) =>
addFraudComponentHighlight(parseInt(event.currentTarget.id))
)
warningButton.addEventListener('mouseleave', () => removeFraudComponentHighlight())
@@ -200,7 +200,7 @@ async function animateViewPort(componentIdx) {
let maxX = Number.NEGATIVE_INFINITY
let minY = Number.POSITIVE_INFINITY
let maxY = Number.NEGATIVE_INFINITY
- componentNodes.forEach(node => {
+ componentNodes.forEach((node) => {
if (graphComponent.graph.contains(node) && isFraud(node)) {
const { x, y, width, height } = node.layout
minX = Math.min(minX, x)
@@ -209,7 +209,12 @@ async function animateViewPort(componentIdx) {
maxY = Math.max(maxY, y + height)
}
})
- if (isFinite(minX) && isFinite(maxX) && isFinite(minY) && isFinite(maxY)) {
+ if (
+ Number.isFinite(minX) &&
+ Number.isFinite(maxX) &&
+ Number.isFinite(minY) &&
+ Number.isFinite(maxY)
+ ) {
let rect = new Rect(minX, minY, maxX - minX, maxY - minY)
if (graphComponent.viewport.contains(rect) && graphComponent.zoom > 0.8) {
return
@@ -269,12 +274,12 @@ function updateFraudHighlights(item, oldItem) {
function highlightFraudComponent(componentIndex) {
const componentNodes = getComponentNodes(componentIndex)
const componentNodesSet = new Set(componentNodes)
- graphComponent.graph.edges.forEach(edge => {
+ graphComponent.graph.edges.forEach((edge) => {
if (componentNodesSet.has(edge.sourceNode) && isFraud(edge)) {
fraudHighlightManager.addHighlight(edge)
}
})
- componentNodes.forEach(node => {
+ componentNodes.forEach((node) => {
if (isFraud(node)) {
fraudHighlightManager.addHighlight(node)
}
@@ -304,11 +309,11 @@ export function calculateComponents() {
// for bank fraud, we remove the bank branch nodes to avoid having
// large components that contain nodes that have no actual relationship with each other
const result = new ConnectedComponents({
- subgraphNodes: node => !bankFraud || getEntityData(node).type !== 'Bank Branch'
+ subgraphNodes: (node) => !bankFraud || getEntityData(node).type !== 'Bank Branch'
}).run(fullGraph)
const nodeComponentIds = result.nodeComponentIds
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
const componentIdx = nodeComponentIds.get(node)
node2Component.set(node, componentIdx)
if (!component2Nodes.get(componentIdx)) {
@@ -320,9 +325,9 @@ export function calculateComponents() {
if (bankFraud) {
// we un-hide the bank branch nodes
// and add them to the components to which their neighbor nodes belong
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
if (getEntityData(node).type === 'Bank Branch') {
- fullGraph.edgesAt(node).forEach(edge => {
+ fullGraph.edgesAt(node).forEach((edge) => {
const sourceNode = edge.sourceNode
const targetNode = edge.targetNode
const componentIdx =
diff --git a/demos/showcase/frauddetection/fraud-detection/fraud-components.ts b/demos/showcase/frauddetection/fraud-detection/fraud-components.ts
index 5d2db64ee..743923ea2 100644
--- a/demos/showcase/frauddetection/fraud-detection/fraud-components.ts
+++ b/demos/showcase/frauddetection/fraud-detection/fraud-components.ts
@@ -88,7 +88,7 @@ export function updateFraudWarnings(fraudsters: INode[]): void {
const currentFraudComponents = new Set()
// add fraud warning for new fraud components
- fraudsters.forEach(node => {
+ fraudsters.forEach((node) => {
const componentIdx = getComponentIdx(node)
if (visibleFraudComponents.indexOf(componentIdx) < 0) {
visibleFraudComponents.push(componentIdx)
@@ -105,7 +105,7 @@ export function updateFraudWarnings(fraudsters: INode[]): void {
visibleFraudComponents.splice(i, 1)
const componentNodes = getComponentNodes(componentIdx)
// remove highlight from the component related to the removed warning sign
- componentNodes.forEach(node => {
+ componentNodes.forEach((node) => {
fraudHighlightManager.removeHighlight(node)
})
removeFraudWarning(componentIdx)
@@ -134,7 +134,7 @@ function createFraudWarning(componentIdx: number): void {
warningButton.addEventListener('click', () =>
openFraudDetectionView(componentIdx, graphComponent)
)
- warningButton.addEventListener('mouseover', event =>
+ warningButton.addEventListener('mouseover', (event) =>
addFraudComponentHighlight(parseInt((event.currentTarget as HTMLElement).id))
)
warningButton.addEventListener('mouseleave', () => removeFraudComponentHighlight())
@@ -188,7 +188,7 @@ async function animateViewPort(componentIdx: number): Promise {
let maxX: number = Number.NEGATIVE_INFINITY
let minY: number = Number.POSITIVE_INFINITY
let maxY: number = Number.NEGATIVE_INFINITY
- componentNodes.forEach(node => {
+ componentNodes.forEach((node) => {
if (graphComponent.graph.contains(node) && isFraud(node)) {
const { x, y, width, height } = node.layout
minX = Math.min(minX, x)
@@ -197,7 +197,7 @@ async function animateViewPort(componentIdx: number): Promise {
maxY = Math.max(maxY, y + height)
}
})
- if (isFinite(minX) && isFinite(maxX) && isFinite(minY) && isFinite(maxY)) {
+ if (Number.isFinite(minX) && Number.isFinite(maxX) && Number.isFinite(minY) && Number.isFinite(maxY)) {
let rect: Rect = new Rect(minX, minY, maxX - minX, maxY - minY)
if (graphComponent.viewport.contains(rect) && graphComponent.zoom > 0.8) {
return
@@ -252,12 +252,12 @@ function updateFraudHighlights(item: IModelItem | null, oldItem: IModelItem | nu
function highlightFraudComponent(componentIndex: number): void {
const componentNodes = getComponentNodes(componentIndex)
const componentNodesSet = new Set(componentNodes)
- graphComponent.graph.edges.forEach(edge => {
+ graphComponent.graph.edges.forEach((edge) => {
if (componentNodesSet.has(edge.sourceNode!) && isFraud(edge)) {
fraudHighlightManager.addHighlight(edge)
}
})
- componentNodes.forEach(node => {
+ componentNodes.forEach((node) => {
if (isFraud(node)) {
fraudHighlightManager.addHighlight(node)
}
@@ -287,11 +287,11 @@ export function calculateComponents(): void {
// for bank fraud, we remove the bank branch nodes to avoid having
// large components that contain nodes that have no actual relationship with each other
const result = new ConnectedComponents({
- subgraphNodes: node => !bankFraud || getEntityData(node).type !== 'Bank Branch'
+ subgraphNodes: (node) => !bankFraud || getEntityData(node).type !== 'Bank Branch'
}).run(fullGraph)
const nodeComponentIds = result.nodeComponentIds
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
const componentIdx = nodeComponentIds.get(node)
node2Component.set(node, componentIdx)
if (!component2Nodes.get(componentIdx)) {
@@ -303,9 +303,9 @@ export function calculateComponents(): void {
if (bankFraud) {
// we un-hide the bank branch nodes
// and add them to the components to which their neighbor nodes belong
- fullGraph.nodes.forEach(node => {
+ fullGraph.nodes.forEach((node) => {
if (getEntityData(node).type === 'Bank Branch') {
- fullGraph.edgesAt(node).forEach(edge => {
+ fullGraph.edgesAt(node).forEach((edge) => {
const sourceNode = edge.sourceNode!
const targetNode = edge.targetNode!
const componentIdx =
diff --git a/demos/showcase/frauddetection/fraud-detection/fraud-detection.js b/demos/showcase/frauddetection/fraud-detection/fraud-detection.js
index 918ebcbdf..86270cb4f 100644
--- a/demos/showcase/frauddetection/fraud-detection/fraud-detection.js
+++ b/demos/showcase/frauddetection/fraud-detection/fraud-detection.js
@@ -50,7 +50,7 @@ export function detectBankFraud(graphComponent) {
const result = new CycleEdges({
directed: false,
// only consider "non-bank branch" nodes to avoid finding cycles other than fraud cycles
- subgraphNodes: node => getEntityData(node).type !== 'Bank Branch'
+ subgraphNodes: (node) => getEntityData(node).type !== 'Bank Branch'
}).run(graph)
for (const edge of result.edges) {
@@ -90,11 +90,11 @@ export function detectInsuranceFraud(graphComponent) {
const fraudsterNodes = []
const result = new ConnectedComponents().run(graph)
- result.components.forEach(component => {
+ result.components.forEach((component) => {
const node2Accidents = new Mapper()
let involvedAccidents = 0
- component.nodes.forEach(node => {
+ component.nodes.forEach((node) => {
const entityData = getEntityData(node)
if (entityData.type === 'Accident') {
involvedAccidents++
@@ -160,7 +160,7 @@ export function detectInsuranceFraud(graphComponent) {
updateNodeFraudTag(person, true)
fraudsterNodes.push(person)
- graph.edgesAt(person).forEach(edge => {
+ graph.edgesAt(person).forEach((edge) => {
updateEdgeFraudTag(edge, true)
})
}
@@ -214,10 +214,10 @@ function updateEdgeFraudTag(edge, isFraud) {
*/
function resetTags(graphComponent) {
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
updateNodeFraudTag(node, false)
})
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
updateEdgeFraudTag(edge, false)
})
}
diff --git a/demos/showcase/frauddetection/fraud-detection/fraud-detection.ts b/demos/showcase/frauddetection/fraud-detection/fraud-detection.ts
index d5fd06c0c..d2ab3c7e6 100644
--- a/demos/showcase/frauddetection/fraud-detection/fraud-detection.ts
+++ b/demos/showcase/frauddetection/fraud-detection/fraud-detection.ts
@@ -50,7 +50,7 @@ export function detectBankFraud(graphComponent: GraphComponent): INode[] {
const result = new CycleEdges({
directed: false,
// only consider "non-bank branch" nodes to avoid finding cycles other than fraud cycles
- subgraphNodes: node => getEntityData(node).type !== 'Bank Branch'
+ subgraphNodes: (node) => getEntityData(node).type !== 'Bank Branch'
}).run(graph)
for (const edge of result.edges) {
@@ -88,11 +88,11 @@ export function detectInsuranceFraud(graphComponent: GraphComponent): INode[] {
const fraudsterNodes: INode[] = []
const result = new ConnectedComponents().run(graph)
- result.components.forEach(component => {
+ result.components.forEach((component) => {
const node2Accidents = new Mapper()
let involvedAccidents = 0
- component.nodes.forEach(node => {
+ component.nodes.forEach((node) => {
const entityData = getEntityData(node)
if (entityData.type === 'Accident') {
involvedAccidents++
@@ -158,7 +158,7 @@ export function detectInsuranceFraud(graphComponent: GraphComponent): INode[] {
updateNodeFraudTag(person, true)
fraudsterNodes.push(person)
- graph.edgesAt(person).forEach(edge => {
+ graph.edgesAt(person).forEach((edge) => {
updateEdgeFraudTag(edge, true)
})
}
@@ -207,10 +207,10 @@ function updateEdgeFraudTag(edge: IEdge, isFraud: boolean): void {
*/
function resetTags(graphComponent: GraphComponent): void {
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
updateNodeFraudTag(node, false)
})
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
updateEdgeFraudTag(edge, false)
})
}
diff --git a/demos/showcase/frauddetection/fraud-detection/inspection-view.js b/demos/showcase/frauddetection/fraud-detection/inspection-view.js
index df6543d58..c1b49dd00 100644
--- a/demos/showcase/frauddetection/fraud-detection/inspection-view.js
+++ b/demos/showcase/frauddetection/fraud-detection/inspection-view.js
@@ -160,7 +160,7 @@ function initializeInputMode() {
const selection = evt.selection
for (const item of selection) {
if (item instanceof INode) {
- filteredGraph.edgesAt(item, AdjacencyTypes.ALL).forEach(edge => {
+ filteredGraph.edgesAt(item, AdjacencyTypes.ALL).forEach((edge) => {
if (!selection.isSelected(edge.opposite(item))) {
incrementalNodes.push(edge.opposite(item))
}
@@ -191,7 +191,7 @@ function copyGraph(graph, componentNodes) {
const graphCopier = new GraphCopier()
graphCopier.copy(
graph,
- item =>
+ (item) =>
!INode.isInstance(item) ||
(componentNodes.has(item) && getEntityData(item).type !== 'Bank Branch'),
fraudDetectionComponent.graph,
@@ -205,13 +205,13 @@ function copyGraph(graph, componentNodes) {
function initializeTimelineComponent() {
fraudDetectionTimeline = new Timeline('fraud-detection-timeline-component', getTimeEntry)
fraudDetectionTimeline.items = fraudDetectionComponent.graph.nodes.map(getEntityData).toArray()
- fraudDetectionTimeline.addBarHoverListener(nodes => {
+ fraudDetectionTimeline.addBarHoverListener((nodes) => {
const highlightManager = fraudDetectionComponent.highlightIndicatorManager
highlightManager.clearHighlights()
- const selected = new Set(nodes.map(node => node.id))
+ const selected = new Set(nodes.map((node) => node.id))
- fraudDetectionComponent.graph.nodes.forEach(node => {
+ fraudDetectionComponent.graph.nodes.forEach((node) => {
const entity = getEntityData(node)
if (selected.has(entity.id)) {
highlightManager.addHighlight(node)
@@ -219,7 +219,7 @@ function initializeTimelineComponent() {
})
})
- fraudDetectionTimeline.addBarSelectListener(nodes => {
+ fraudDetectionTimeline.addBarSelectListener((nodes) => {
fraudDetectionComponent.selection.clear()
if (nodes.length > 0) {
let minX = Number.POSITIVE_INFINITY
@@ -227,9 +227,9 @@ function initializeTimelineComponent() {
let minY = Number.POSITIVE_INFINITY
let maxY = Number.NEGATIVE_INFINITY
nodes
- .map(node => getNode(fraudDetectionComponent.graph, node))
- .filter(node => filteredGraph.contains(node))
- .forEach(node => {
+ .map((node) => getNode(fraudDetectionComponent.graph, node))
+ .filter((node) => filteredGraph.contains(node))
+ .forEach((node) => {
fraudDetectionComponent.selection.setSelected(node, true)
const { x, y, width, height } = node.layout
minX = Math.min(minX, x)
@@ -262,7 +262,7 @@ function initializeTimelineComponent() {
*/
function initializeGraph(graph) {
// get the graph from the timeline component
- filteredGraph = new FilteredGraphWrapper(graph, node => {
+ filteredGraph = new FilteredGraphWrapper(graph, (node) => {
const visible = fraudDetectionTimeline.filter(getEntityData(node))
if (!visible) {
@@ -278,7 +278,7 @@ function initializeGraph(graph) {
getEntityData(node).type === 'Bank Branch' &&
!filteredGraph.wrappedGraph
.neighbors(node)
- .every(neighbor => fraudDetectionTimeline.filter(getEntityData(neighbor)))
+ .every((neighbor) => fraudDetectionTimeline.filter(getEntityData(neighbor)))
) {
return false
}
@@ -448,14 +448,6 @@ export function closeFraudDetectionView() {
* neighbor that is already placed.
*/
class InitialPositionsStage extends LayoutStageBase {
- /**
- * Creates a new instance of InitialPositionsStage.
- * @param {!ILayoutAlgorithm} layout
- */
- constructor(layout) {
- super(layout)
- }
-
/**
* Applies the layout
* @param {!LayoutGraph} graph The graph to be laid out.
@@ -463,7 +455,7 @@ class InitialPositionsStage extends LayoutStageBase {
applyLayout(graph) {
const nodesAdded = graph.getDataProvider('NODES_ADDED')
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (nodesAdded.getBoolean(node)) {
const visited = new Set()
const stack = [node]
diff --git a/demos/showcase/frauddetection/fraud-detection/inspection-view.ts b/demos/showcase/frauddetection/fraud-detection/inspection-view.ts
index 14032b990..c7c4b76bf 100644
--- a/demos/showcase/frauddetection/fraud-detection/inspection-view.ts
+++ b/demos/showcase/frauddetection/fraud-detection/inspection-view.ts
@@ -152,7 +152,7 @@ function initializeInputMode(): void {
const selection = evt.selection
for (const item of selection) {
if (item instanceof INode) {
- filteredGraph.edgesAt(item, AdjacencyTypes.ALL).forEach(edge => {
+ filteredGraph.edgesAt(item, AdjacencyTypes.ALL).forEach((edge) => {
if (!selection.isSelected(edge.opposite(item))) {
incrementalNodes.push(edge.opposite(item) as INode)
}
@@ -181,7 +181,7 @@ function copyGraph(graph: IGraph, componentNodes: Set): void {
const graphCopier = new GraphCopier()
graphCopier.copy(
graph,
- item =>
+ (item) =>
!INode.isInstance(item) ||
(componentNodes.has(item) && getEntityData(item).type !== 'Bank Branch'),
fraudDetectionComponent.graph,
@@ -195,13 +195,13 @@ function copyGraph(graph: IGraph, componentNodes: Set): void {
function initializeTimelineComponent(): void {
fraudDetectionTimeline = new Timeline('fraud-detection-timeline-component', getTimeEntry)
fraudDetectionTimeline.items = fraudDetectionComponent.graph.nodes.map(getEntityData).toArray()
- fraudDetectionTimeline.addBarHoverListener(nodes => {
+ fraudDetectionTimeline.addBarHoverListener((nodes) => {
const highlightManager = fraudDetectionComponent.highlightIndicatorManager
highlightManager.clearHighlights()
- const selected = new Set(nodes.map(node => node.id))
+ const selected = new Set(nodes.map((node) => node.id))
- fraudDetectionComponent.graph.nodes.forEach(node => {
+ fraudDetectionComponent.graph.nodes.forEach((node) => {
const entity = getEntityData(node)
if (selected.has(entity.id)) {
highlightManager.addHighlight(node)
@@ -209,7 +209,7 @@ function initializeTimelineComponent(): void {
})
})
- fraudDetectionTimeline.addBarSelectListener(nodes => {
+ fraudDetectionTimeline.addBarSelectListener((nodes) => {
fraudDetectionComponent.selection.clear()
if (nodes.length > 0) {
let minX: number = Number.POSITIVE_INFINITY
@@ -217,9 +217,9 @@ function initializeTimelineComponent(): void {
let minY: number = Number.POSITIVE_INFINITY
let maxY: number = Number.NEGATIVE_INFINITY
nodes
- .map(node => getNode(fraudDetectionComponent.graph, node))
- .filter(node => filteredGraph.contains(node))
- .forEach(node => {
+ .map((node) => getNode(fraudDetectionComponent.graph, node))
+ .filter((node) => filteredGraph.contains(node))
+ .forEach((node) => {
fraudDetectionComponent.selection.setSelected(node!, true)
const { x, y, width, height } = node!.layout
minX = Math.min(minX, x)
@@ -251,7 +251,7 @@ function initializeTimelineComponent(): void {
*/
function initializeGraph(graph: IGraph): void {
// get the graph from the timeline component
- filteredGraph = new FilteredGraphWrapper(graph, node => {
+ filteredGraph = new FilteredGraphWrapper(graph, (node) => {
const visible = fraudDetectionTimeline.filter(getEntityData(node))
if (!visible) {
@@ -267,7 +267,7 @@ function initializeGraph(graph: IGraph): void {
getEntityData(node).type === 'Bank Branch' &&
!filteredGraph
.wrappedGraph!.neighbors(node)
- .every(neighbor => fraudDetectionTimeline.filter(getEntityData(neighbor)))
+ .every((neighbor) => fraudDetectionTimeline.filter(getEntityData(neighbor)))
) {
return false
}
@@ -436,12 +436,6 @@ export function closeFraudDetectionView(): void {
* neighbor that is already placed.
*/
class InitialPositionsStage extends LayoutStageBase {
- /**
- * Creates a new instance of InitialPositionsStage.
- */
- constructor(layout: ILayoutAlgorithm) {
- super(layout)
- }
/**
* Applies the layout
@@ -450,7 +444,7 @@ class InitialPositionsStage extends LayoutStageBase {
applyLayout(graph: LayoutGraph): void {
const nodesAdded = graph.getDataProvider('NODES_ADDED')!
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (nodesAdded.getBoolean(node)) {
const visited = new Set()
const stack = [node]
diff --git a/demos/showcase/frauddetection/index.html b/demos/showcase/frauddetection/index.html
index 504a16ac1..28ebbd9a1 100644
--- a/demos/showcase/frauddetection/index.html
+++ b/demos/showcase/frauddetection/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/frauddetection/interactive-layout.js b/demos/showcase/frauddetection/interactive-layout.js
index df907cb84..731466774 100644
--- a/demos/showcase/frauddetection/interactive-layout.js
+++ b/demos/showcase/frauddetection/interactive-layout.js
@@ -79,16 +79,16 @@ export function initializeLayout(gc) {
function prepareInteraction() {
const inputMode = graphComponent.inputMode
const moveUnselectedInputMode = inputMode.moveUnselectedInputMode
- moveUnselectedInputMode.addDragStartedListener(moveInputMode => {
+ moveUnselectedInputMode.addDragStartedListener((moveInputMode) => {
restartLayout(moveInputMode.affectedItems.at(0))
})
- moveUnselectedInputMode.addDraggedListener(moveInputMode => {
+ moveUnselectedInputMode.addDraggedListener((moveInputMode) => {
updateDraggedComponent(moveInputMode.affectedItems.at(0))
})
- moveUnselectedInputMode.addDragCanceledListener(moveInputMode => {
+ moveUnselectedInputMode.addDragCanceledListener((moveInputMode) => {
setFinalNodeLocation(moveInputMode.affectedItems.at(0))
})
- moveUnselectedInputMode.addDragFinishedListener(moveInputMode => {
+ moveUnselectedInputMode.addDragFinishedListener((moveInputMode) => {
setFinalNodeLocation(moveInputMode.affectedItems.at(0))
})
}
@@ -137,7 +137,7 @@ export function startLayout() {
// make the nodes unmovable at the beginning,
// so that the layout of the graph is maintained as it is in the initial layout
- copiedLayoutGraph.nodes.forEach(node => {
+ copiedLayoutGraph.nodes.forEach((node) => {
organicLayout.setInertia(node, 1)
})
@@ -149,7 +149,7 @@ export function startLayout() {
// configure how the new edges with their source/target node can move when an edge is added in the graph
if (edgesAdded.length > 0) {
- edgesAdded.forEach(edge => {
+ edgesAdded.forEach((edge) => {
const copiedSource = copiedLayoutGraph.getCopiedNode(edge.sourceNode)
const copiedTarget = copiedLayoutGraph.getCopiedNode(edge.targetNode)
@@ -184,7 +184,7 @@ export function startLayout() {
// configure how the new node can move when they are added in the graph
if (nodesAdded.length > 0) {
// configure how the new nodes can be moved
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (nodesAdded.includes(node)) {
const copiedNode = copiedLayoutGraph.getCopiedNode(node)
if (copiedNode) {
@@ -200,7 +200,7 @@ export function startLayout() {
// configure how the source/target nodes of an edge can move when an edge is removed from the graph
if (edgesRemoved.length > 0) {
- edgesRemoved.forEach(edge => {
+ edgesRemoved.forEach((edge) => {
const sourceNode = edge.sourceNode
if (graph.contains(sourceNode)) {
const copiedSource = copiedLayoutGraph.getCopiedNode(sourceNode)
@@ -347,7 +347,7 @@ function updateStressAndInertiaForOtherNodes(draggedNode) {
graphComponent.graph
)
- movedComponent.reachableNodes.forEach(node => {
+ movedComponent.reachableNodes.forEach((node) => {
const copiedNode = copiedLayoutGraph.getCopiedNode(node)
if (copiedNode && copiedNode !== copiedMovedNode) {
// allow the nodes of the moved component to move close to the dragged node
diff --git a/demos/showcase/frauddetection/interactive-layout.ts b/demos/showcase/frauddetection/interactive-layout.ts
index 83f3f5cc0..15d19fa03 100644
--- a/demos/showcase/frauddetection/interactive-layout.ts
+++ b/demos/showcase/frauddetection/interactive-layout.ts
@@ -83,16 +83,16 @@ export function initializeLayout(gc: GraphComponent): void {
function prepareInteraction(): void {
const inputMode = graphComponent.inputMode as GraphEditorInputMode
const moveUnselectedInputMode = inputMode.moveUnselectedInputMode
- moveUnselectedInputMode.addDragStartedListener(moveInputMode => {
+ moveUnselectedInputMode.addDragStartedListener((moveInputMode) => {
restartLayout(moveInputMode.affectedItems.at(0) as INode)
})
- moveUnselectedInputMode.addDraggedListener(moveInputMode => {
+ moveUnselectedInputMode.addDraggedListener((moveInputMode) => {
updateDraggedComponent(moveInputMode.affectedItems.at(0) as INode)
})
- moveUnselectedInputMode.addDragCanceledListener(moveInputMode => {
+ moveUnselectedInputMode.addDragCanceledListener((moveInputMode) => {
setFinalNodeLocation(moveInputMode.affectedItems.at(0) as INode)
})
- moveUnselectedInputMode.addDragFinishedListener(moveInputMode => {
+ moveUnselectedInputMode.addDragFinishedListener((moveInputMode) => {
setFinalNodeLocation(moveInputMode.affectedItems.at(0) as INode)
})
}
@@ -141,7 +141,7 @@ export function startLayout(): void {
// make the nodes unmovable at the beginning,
// so that the layout of the graph is maintained as it is in the initial layout
- copiedLayoutGraph.nodes.forEach(node => {
+ copiedLayoutGraph.nodes.forEach((node) => {
organicLayout.setInertia(node, 1)
})
@@ -153,7 +153,7 @@ export function startLayout(): void {
// configure how the new edges with their source/target node can move when an edge is added in the graph
if (edgesAdded.length > 0) {
- edgesAdded.forEach(edge => {
+ edgesAdded.forEach((edge) => {
const copiedSource = copiedLayoutGraph.getCopiedNode(edge.sourceNode)
const copiedTarget = copiedLayoutGraph.getCopiedNode(edge.targetNode)
@@ -188,7 +188,7 @@ export function startLayout(): void {
// configure how the new node can move when they are added in the graph
if (nodesAdded.length > 0) {
// configure how the new nodes can be moved
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
if (nodesAdded.includes(node)) {
const copiedNode = copiedLayoutGraph.getCopiedNode(node)
if (copiedNode) {
@@ -204,7 +204,7 @@ export function startLayout(): void {
// configure how the source/target nodes of an edge can move when an edge is removed from the graph
if (edgesRemoved.length > 0) {
- edgesRemoved.forEach(edge => {
+ edgesRemoved.forEach((edge) => {
const sourceNode = edge.sourceNode
if (graph.contains(sourceNode)) {
const copiedSource = copiedLayoutGraph.getCopiedNode(sourceNode)
@@ -343,7 +343,7 @@ function updateStressAndInertiaForOtherNodes(draggedNode: INode): void {
graphComponent.graph
)
- movedComponent.reachableNodes.forEach(node => {
+ movedComponent.reachableNodes.forEach((node) => {
const copiedNode = copiedLayoutGraph.getCopiedNode(node)
if (copiedNode && copiedNode !== copiedMovedNode) {
// allow the nodes of the moved component to move close to the dragged node
diff --git a/demos/showcase/frauddetection/properties-view.js b/demos/showcase/frauddetection/properties-view.js
index 9a075d947..ecc1c6ea7 100644
--- a/demos/showcase/frauddetection/properties-view.js
+++ b/demos/showcase/frauddetection/properties-view.js
@@ -125,7 +125,7 @@ function showEntityProperties(node, parentContainer) {
tableContainer.appendChild(table)
const infoMap = getInfoMap(node)
- Object.keys(infoMap).forEach(key => {
+ Object.keys(infoMap).forEach((key) => {
const tr = document.createElement('tr')
tr.appendChild(createElement('td', key))
tr.appendChild(createElement('td', infoMap[key]))
diff --git a/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.js b/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.js
index 7d9ed4160..8265902ee 100644
--- a/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.js
+++ b/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.js
@@ -102,7 +102,7 @@ class EdgeRenderVisual extends HtmlCanvasVisual {
ctx.beginPath()
let location = this.edge.sourcePort.location
ctx.moveTo(location.x, location.y)
- this.edge.bends.forEach(bend => {
+ this.edge.bends.forEach((bend) => {
location = bend.location
ctx.lineTo(location.x, location.y)
})
diff --git a/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.ts b/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.ts
index d0565686c..8d76fe5d2 100644
--- a/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.ts
+++ b/demos/showcase/frauddetection/styles/ConnectionEdgeStyle.ts
@@ -96,7 +96,7 @@ class EdgeRenderVisual extends HtmlCanvasVisual {
ctx.beginPath()
let location: IPoint = this.edge.sourcePort!.location
ctx.moveTo(location.x, location.y)
- this.edge.bends.forEach(bend => {
+ this.edge.bends.forEach((bend) => {
location = bend.location
ctx.lineTo(location.x, location.y)
})
diff --git a/demos/showcase/frauddetection/styles/initialize-webgl-styles.js b/demos/showcase/frauddetection/styles/initialize-webgl-styles.js
index 94417855f..823e8716e 100644
--- a/demos/showcase/frauddetection/styles/initialize-webgl-styles.js
+++ b/demos/showcase/frauddetection/styles/initialize-webgl-styles.js
@@ -142,11 +142,11 @@ export function setWebGL2Styles(graphComponent) {
return
}
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
updateNodeStyle(graphComponent, node)
})
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
updateEdgeStyle(graphComponent, edge)
})
}
diff --git a/demos/showcase/frauddetection/styles/initialize-webgl-styles.ts b/demos/showcase/frauddetection/styles/initialize-webgl-styles.ts
index 9391aeec9..50659e31d 100644
--- a/demos/showcase/frauddetection/styles/initialize-webgl-styles.ts
+++ b/demos/showcase/frauddetection/styles/initialize-webgl-styles.ts
@@ -135,11 +135,11 @@ export function setWebGL2Styles(graphComponent: GraphComponent): void {
return
}
const graph = graphComponent.graph
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
updateNodeStyle(graphComponent, node)
})
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
updateEdgeStyle(graphComponent, edge)
})
}
diff --git a/demos/showcase/frauddetection/timeline/Styling.js b/demos/showcase/frauddetection/timeline/Styling.js
index 478ae480c..e8bc31cda 100644
--- a/demos/showcase/frauddetection/timeline/Styling.js
+++ b/demos/showcase/frauddetection/timeline/Styling.js
@@ -90,7 +90,7 @@ export class Styling {
nodeDecorator.focusIndicatorDecorator.hideImplementation()
nodeDecorator.highlightDecorator.hideImplementation()
nodeDecorator.selectionDecorator.setFactory(
- node =>
+ (node) =>
new NodeStyleDecorationInstaller({
nodeStyle: graphComponent.graph.isGroupNode(node)
? new ShapeNodeStyle(style.sectionSelect ?? defaultStyling.sectionSelect)
diff --git a/demos/showcase/frauddetection/timeline/Styling.ts b/demos/showcase/frauddetection/timeline/Styling.ts
index fcc141e6f..1a85cd2bc 100644
--- a/demos/showcase/frauddetection/timeline/Styling.ts
+++ b/demos/showcase/frauddetection/timeline/Styling.ts
@@ -103,7 +103,7 @@ export class Styling {
nodeDecorator.focusIndicatorDecorator.hideImplementation()
nodeDecorator.highlightDecorator.hideImplementation()
nodeDecorator.selectionDecorator.setFactory(
- node =>
+ (node) =>
new NodeStyleDecorationInstaller({
nodeStyle: graphComponent.graph.isGroupNode(node)
? new ShapeNodeStyle(style.sectionSelect ?? defaultStyling.sectionSelect)
diff --git a/demos/showcase/frauddetection/timeline/TimeframeRectangle.ts b/demos/showcase/frauddetection/timeline/TimeframeRectangle.ts
index 1e99ebb1b..406ce155b 100644
--- a/demos/showcase/frauddetection/timeline/TimeframeRectangle.ts
+++ b/demos/showcase/frauddetection/timeline/TimeframeRectangle.ts
@@ -180,7 +180,10 @@ class RectangleVisual extends BaseClass(IVisualCreator) {
* @param rectangle The rectangle that determines the bounds of this visual object.
* @param style The styling for the rectangle
*/
- constructor(public rectangle: MutableRectangle, private readonly style?: TimeFrameStyle) {
+ constructor(
+ public rectangle: MutableRectangle,
+ private readonly style?: TimeFrameStyle
+ ) {
super()
}
@@ -244,7 +247,10 @@ class RectangleVisual extends BaseClass(IVisualCreator) {
class RectanglePositionHandler extends BaseClass(IPositionHandler) {
private initialPosition = new Point(0, 0)
- constructor(private readonly rectangle: IMutableRectangle, public limits: Rect = Rect.INFINITE) {
+ constructor(
+ private readonly rectangle: IMutableRectangle,
+ public limits: Rect = Rect.INFINITE
+ ) {
super()
}
diff --git a/demos/showcase/frauddetection/timeline/Timeline.js b/demos/showcase/frauddetection/timeline/Timeline.js
index b63830c48..e0317b335 100644
--- a/demos/showcase/frauddetection/timeline/Timeline.js
+++ b/demos/showcase/frauddetection/timeline/Timeline.js
@@ -201,7 +201,7 @@ export default class Timeline {
get selectedItems() {
return this.graphComponent.selection.selectedNodes
.toArray()
- .flatMap(selectedNode => getItemsFromBucket(selectedNode))
+ .flatMap((selectedNode) => getItemsFromBucket(selectedNode))
}
/**
@@ -318,7 +318,7 @@ export default class Timeline {
})
// install a tooltip on the timeline items that reports the content of the possibly aggregated entry
- initializeToolTips(inputMode, item => {
+ initializeToolTips(inputMode, (item) => {
if (item instanceof INode) {
const bucket = getBucket(item)
if (bucket.label !== undefined) {
@@ -354,7 +354,7 @@ export default class Timeline {
}
}
})
- inputMode.addCanvasClickedListener(_ => {
+ inputMode.addCanvasClickedListener((_) => {
this.barSelectListener?.([])
})
@@ -596,16 +596,16 @@ export default class Timeline {
*/
initializeGraphBuilder(masterGraph) {
const graphBuilder = new GraphBuilder(masterGraph)
- const getBucketId = b => `${b.layer}-${b.start.getTime()}-${b.end.getTime()}`
+ const getBucketId = (b) => `${b.layer}-${b.start.getTime()}-${b.end.getTime()}`
const nodesSource = graphBuilder.createGroupNodesSource({
data: this.buckets,
id: getBucketId,
- parentId: b => (b.parent ? getBucketId(b.parent) : null)
+ parentId: (b) => (b.parent ? getBucketId(b.parent) : null)
})
const nodeCreator = nodesSource.nodeCreator
nodeCreator.createLabelsSource({
- data: b => (b.label != null ? [b] : []),
+ data: (b) => (b.label != null ? [b] : []),
text: 'label'
})
@@ -627,7 +627,7 @@ export default class Timeline {
rectangleIndicator.setBounds(graphComponent.contentRect)
rectangleIndicator.limits = graphComponent.contentRect
- rectangleIndicator.addBoundsChangedListener(bounds => {
+ rectangleIndicator.addBoundsChangedListener((bounds) => {
this.updateTimeframe(bounds)
})
@@ -657,8 +657,8 @@ export default class Timeline {
getTimeframeFromBounds(bounds) {
const graph = this.graphComponent.graph
const nodesInFrame = graph.nodes
- .filter(node => !graph.isGroupNode(node))
- .filter(node => bounds.contains(node.layout.center))
+ .filter((node) => !graph.isGroupNode(node))
+ .filter((node) => bounds.contains(node.layout.center))
if (nodesInFrame.size === 0) {
// no nodes in timeframe, this returns an "empty" timeframe to trigger the update
@@ -710,8 +710,8 @@ export default class Timeline {
const graphComponent = this.graphComponent
const graph = graphComponent.graph
const nodesInTimeframe = graph.nodes
- .filter(node => !graph.isGroupNode(node))
- .filter(node => {
+ .filter((node) => !graph.isGroupNode(node))
+ .filter((node) => {
const bucket = getBucket(node)
return intervalsIntersect(bucket.start, bucket.end, timeframe[0], timeframe[1])
})
@@ -725,7 +725,7 @@ export default class Timeline {
let minX = Number.POSITIVE_INFINITY
let maxX = Number.NEGATIVE_INFINITY
- nodesInTimeframe.forEach(current => {
+ nodesInTimeframe.forEach((current) => {
minX = Math.min(minX, current.layout.x)
maxX = Math.max(maxX, current.layout.maxX)
})
@@ -778,7 +778,7 @@ export default class Timeline {
const timeEntry = this.getTimeEntry(item)
if (Array.isArray(timeEntry)) {
- return timeEntry.some(entry => {
+ return timeEntry.some((entry) => {
if (typeof entry === 'number') {
const time = entry
return start <= time && time < end
@@ -926,7 +926,7 @@ export default class Timeline {
) {
// create a new animation object if there is none or if the timeframe has changed
this.timeframeAnimation = new TimeframeAnimation(this.timeframeRect.rect, this.graphComponent)
- this.timeframeAnimation.addTimeframeListener(rect => this.updateTimeframe(rect))
+ this.timeframeAnimation.addTimeframeListener((rect) => this.updateTimeframe(rect))
this.timeframeAnimation.addAnimationEndedListener(() => {
// stop the animation and revert the state of the play button
if (this.showPlayButton && !(this.timeframeAnimation?.animating ?? false)) {
@@ -982,7 +982,7 @@ export default class Timeline {
},
true
)
- playButton.addEventListener('mousedown', evt => {
+ playButton.addEventListener('mousedown', (evt) => {
// prevent events to trigger a selection in the timeline
evt.stopPropagation()
})
diff --git a/demos/showcase/frauddetection/timeline/Timeline.ts b/demos/showcase/frauddetection/timeline/Timeline.ts
index afe102b9d..f166edf64 100644
--- a/demos/showcase/frauddetection/timeline/Timeline.ts
+++ b/demos/showcase/frauddetection/timeline/Timeline.ts
@@ -195,7 +195,7 @@ export default class Timeline {
get selectedItems(): TDataItem[] {
return this.graphComponent.selection.selectedNodes
.toArray()
- .flatMap(selectedNode => getItemsFromBucket(selectedNode))
+ .flatMap((selectedNode) => getItemsFromBucket(selectedNode))
}
/**
@@ -297,7 +297,7 @@ export default class Timeline {
})
// install a tooltip on the timeline items that reports the content of the possibly aggregated entry
- initializeToolTips(inputMode, item => {
+ initializeToolTips(inputMode, (item) => {
if (item instanceof INode) {
const bucket = getBucket(item)
if (bucket.label !== undefined) {
@@ -332,7 +332,7 @@ export default class Timeline {
}
}
})
- inputMode.addCanvasClickedListener(_ => {
+ inputMode.addCanvasClickedListener((_) => {
this.barSelectListener?.([])
})
@@ -564,12 +564,12 @@ export default class Timeline {
const nodesSource = graphBuilder.createGroupNodesSource({
data: this.buckets,
id: getBucketId,
- parentId: b => (b.parent ? getBucketId(b.parent) : null)
+ parentId: (b) => (b.parent ? getBucketId(b.parent) : null)
})
const nodeCreator = nodesSource.nodeCreator
nodeCreator.createLabelsSource>({
- data: b => (b.label != null ? [b] : []),
+ data: (b) => (b.label != null ? [b] : []),
text: 'label'
})
@@ -590,7 +590,7 @@ export default class Timeline {
rectangleIndicator.setBounds(graphComponent.contentRect)
rectangleIndicator.limits = graphComponent.contentRect
- rectangleIndicator.addBoundsChangedListener(bounds => {
+ rectangleIndicator.addBoundsChangedListener((bounds) => {
this.updateTimeframe(bounds)
})
@@ -618,8 +618,8 @@ export default class Timeline {
private getTimeframeFromBounds(bounds: Rect): TimeInterval {
const graph = this.graphComponent.graph
const nodesInFrame = graph.nodes
- .filter(node => !graph.isGroupNode(node))
- .filter(node => bounds.contains(node.layout.center))
+ .filter((node) => !graph.isGroupNode(node))
+ .filter((node) => bounds.contains(node.layout.center))
if (nodesInFrame.size === 0) {
// no nodes in timeframe, this returns an "empty" timeframe to trigger the update
@@ -668,8 +668,8 @@ export default class Timeline {
const graphComponent = this.graphComponent
const graph = graphComponent.graph
const nodesInTimeframe = graph.nodes
- .filter(node => !graph.isGroupNode(node))
- .filter(node => {
+ .filter((node) => !graph.isGroupNode(node))
+ .filter((node) => {
const bucket = getBucket(node)
return intervalsIntersect(bucket.start, bucket.end, timeframe[0], timeframe[1])
})
@@ -683,7 +683,7 @@ export default class Timeline {
let minX = Number.POSITIVE_INFINITY
let maxX = Number.NEGATIVE_INFINITY
- nodesInTimeframe.forEach(current => {
+ nodesInTimeframe.forEach((current) => {
minX = Math.min(minX, current.layout.x)
maxX = Math.max(maxX, current.layout.maxX)
})
@@ -733,7 +733,7 @@ export default class Timeline {
const timeEntry = this.getTimeEntry(item)
if (Array.isArray(timeEntry)) {
- return timeEntry.some(entry => {
+ return timeEntry.some((entry) => {
if (typeof entry === 'number') {
const time = entry
return start <= time && time < end
@@ -876,7 +876,7 @@ export default class Timeline {
) {
// create a new animation object if there is none or if the timeframe has changed
this.timeframeAnimation = new TimeframeAnimation(this.timeframeRect.rect, this.graphComponent)
- this.timeframeAnimation.addTimeframeListener(rect => this.updateTimeframe(rect))
+ this.timeframeAnimation.addTimeframeListener((rect) => this.updateTimeframe(rect))
this.timeframeAnimation.addAnimationEndedListener(() => {
// stop the animation and revert the state of the play button
if (this.showPlayButton && !(this.timeframeAnimation?.animating ?? false)) {
@@ -932,7 +932,7 @@ export default class Timeline {
},
true
)
- playButton.addEventListener('mousedown', evt => {
+ playButton.addEventListener('mousedown', (evt) => {
// prevent events to trigger a selection in the timeline
evt.stopPropagation()
})
diff --git a/demos/showcase/frauddetection/timeline/bucket-aggregation.js b/demos/showcase/frauddetection/timeline/bucket-aggregation.js
index 546eacd83..0e034c150 100644
--- a/demos/showcase/frauddetection/timeline/bucket-aggregation.js
+++ b/demos/showcase/frauddetection/timeline/bucket-aggregation.js
@@ -213,11 +213,11 @@ function createLeafBucket(item, label, start, end) {
* @returns {!Array.>}
*/
function collectLeafBuckets(items, getTimeEntry) {
- const entries = items.flatMap(item => {
+ const entries = items.flatMap((item) => {
const timeEntry = getTimeEntry(item)
if (timeEntry) {
if (Array.isArray(timeEntry)) {
- return timeEntry.flatMap(entry => {
+ return timeEntry.flatMap((entry) => {
if (typeof entry === 'number') {
const date = new Date(entry)
return createLeafBucket(item, `${date.getHours()}:${date.getMinutes()}`, date, date)
@@ -250,6 +250,6 @@ function getLeaves(bucket) {
if (bucket.type === 'leaf') {
return [bucket.item]
} else {
- return bucket.children.flatMap(child => getLeaves(child))
+ return bucket.children.flatMap((child) => getLeaves(child))
}
}
diff --git a/demos/showcase/frauddetection/timeline/bucket-aggregation.ts b/demos/showcase/frauddetection/timeline/bucket-aggregation.ts
index 108c043b8..bb0f828f3 100644
--- a/demos/showcase/frauddetection/timeline/bucket-aggregation.ts
+++ b/demos/showcase/frauddetection/timeline/bucket-aggregation.ts
@@ -200,11 +200,11 @@ function collectLeafBuckets(
items: TDataItem[],
getTimeEntry: (t: TDataItem) => TimeEntry | undefined
): Bucket[] {
- const entries: Bucket[] = items.flatMap(item => {
+ const entries: Bucket[] = items.flatMap((item) => {
const timeEntry = getTimeEntry(item)
if (timeEntry) {
if (Array.isArray(timeEntry)) {
- return timeEntry.flatMap(entry => {
+ return timeEntry.flatMap((entry) => {
if (typeof entry === 'number') {
const date = new Date(entry)
return createLeafBucket(item, `${date.getHours()}:${date.getMinutes()}`, date, date)
@@ -234,6 +234,6 @@ function getLeaves(bucket: Bucket): TDataItem[] {
if (bucket.type === 'leaf') {
return [bucket.item]
} else {
- return bucket.children.flatMap(child => getLeaves(child))
+ return bucket.children.flatMap((child) => getLeaves(child))
}
}
diff --git a/demos/showcase/frauddetection/timeline/timeline-layout.js b/demos/showcase/frauddetection/timeline/timeline-layout.js
index e3111d419..8dc994043 100644
--- a/demos/showcase/frauddetection/timeline/timeline-layout.js
+++ b/demos/showcase/frauddetection/timeline/timeline-layout.js
@@ -75,7 +75,7 @@ export function applyTimelineLayout(graphComponent, styling, zoom, minZoom, maxZ
partitionGridData: new PartitionGridData({
grid: new PartitionGrid({ rowCount: 1, columnCount: 31 })
}),
- nodeHalos: item => {
+ nodeHalos: (item) => {
const bucket = getBucket(item)
const index = bucket.index ?? -1
return NodeHalo.create(
@@ -152,14 +152,14 @@ class BarScalingStage extends LayoutStageBase {
const tagProvider = graph.getDataProvider(LayoutGraphAdapter.ORIGINAL_TAG_DP_KEY)
let maxValue = 0
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const tag = tagProvider.get(node)
if (tag?.type === 'group' && tag.layer === this.zoom) {
maxValue = Math.max(maxValue, tag.aggregatedValue)
}
})
const scale = maxValue > 0 ? this.maxHeight / maxValue : 1
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const tag = tagProvider.get(node)
if (tag?.type === 'group') {
graph.setSize(node, graph.getWidth(node), tag.aggregatedValue * scale)
diff --git a/demos/showcase/frauddetection/timeline/timeline-layout.ts b/demos/showcase/frauddetection/timeline/timeline-layout.ts
index 7adffa3b4..03d9f33f4 100644
--- a/demos/showcase/frauddetection/timeline/timeline-layout.ts
+++ b/demos/showcase/frauddetection/timeline/timeline-layout.ts
@@ -140,7 +140,10 @@ export function applyTimelineLayout(
* components bounds.
*/
class BarScalingStage extends LayoutStageBase {
- constructor(private maxHeight: number, private zoom: number) {
+ constructor(
+ private maxHeight: number,
+ private zoom: number
+ ) {
super()
}
@@ -148,14 +151,14 @@ class BarScalingStage extends LayoutStageBase {
const tagProvider = graph.getDataProvider(LayoutGraphAdapter.ORIGINAL_TAG_DP_KEY)!
let maxValue = 0
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const tag = tagProvider.get(node) as Bucket | null
if (tag?.type === 'group' && tag.layer === this.zoom) {
maxValue = Math.max(maxValue, tag.aggregatedValue)
}
})
const scale = maxValue > 0 ? this.maxHeight / maxValue : 1
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const tag = tagProvider.get(node) as Bucket | null
if (tag?.type === 'group') {
graph.setSize(node, graph.getWidth(node), tag.aggregatedValue * scale)
diff --git a/demos/showcase/graph-wizard-for-flowchart/Actions.js b/demos/showcase/graph-wizard-for-flowchart/Actions.js
index 8f629346d..e3e867c9b 100644
--- a/demos/showcase/graph-wizard-for-flowchart/Actions.js
+++ b/demos/showcase/graph-wizard-for-flowchart/Actions.js
@@ -74,7 +74,7 @@ import { GraphWizardInputMode, WizardEventArgs } from './GraphWizardInputMode.js
export function createSmartNavigate() {
return new WizardAction(
'navigate',
- mode => true,
+ (mode) => true,
(mode, item, type, args) => {
const graph = mode.graph
const key = args.key
@@ -136,9 +136,9 @@ export function createSmartNavigate() {
// check for connected hits in 90°
let children = graph
.outEdgesAt(item)
- .map(edge => edge.targetNode)
- .concat(graph.inEdgesAt(item).map(edge => edge.sourceNode))
- .filter(child => {
+ .map((edge) => edge.targetNode)
+ .concat(graph.inEdgesAt(item).map((edge) => edge.sourceNode))
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -149,7 +149,7 @@ export function createSmartNavigate() {
// check for unconnected hits in 90°
if (children.length === 0) {
children = graph.nodes
- .filter(child => {
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -162,9 +162,9 @@ export function createSmartNavigate() {
if (children.length === 0) {
children = graph
.outEdgesAt(item)
- .map(edge => edge.targetNode)
- .concat(graph.inEdgesAt(item).map(edge => edge.sourceNode))
- .filter(child => {
+ .map((edge) => edge.targetNode)
+ .concat(graph.inEdgesAt(item).map((edge) => edge.sourceNode))
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -176,7 +176,7 @@ export function createSmartNavigate() {
// check for unconnected hits in general direction
if (children.length === 0) {
children = graph.nodes
- .filter(child => {
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -185,7 +185,7 @@ export function createSmartNavigate() {
.toArray()
}
- const childScores = children.map(child => {
+ const childScores = children.map((child) => {
const childCenter = child.layout.center
const dx = Math.abs(center.x - childCenter.x)
const dy = Math.abs(center.y - childCenter.y)
@@ -213,7 +213,7 @@ export function createSmartNavigate() {
} else {
// no current item => select the one closest to the center of the viewport
const center = mode.graphComponent.viewport.center
- target = mode.graph.nodes.orderBy(node => center.distanceTo(node.layout.center)).at(0)
+ target = mode.graph.nodes.orderBy((node) => center.distanceTo(node.layout.center)).at(0)
}
if (target) {
mode.graphComponent.currentItem = target
@@ -248,7 +248,7 @@ export function createSmartNavigateEdge(direction) {
checkForEdge,
checkAnd([
checkForNode,
- mode => {
+ (mode) => {
const item = mode.currentItem
return (
(direction === 'NextOutgoing' && mode.graph.outDegree(item) > 0) ||
@@ -358,11 +358,11 @@ export function createChangeNodeColorSet(preCondition, colorTheme, getItemFill,
style: { type: 'rect', fill: colorTheme[i].fill, outline: colorTheme[i].outline }
})
}
- const itemToColorSetIndex = node => {
+ const itemToColorSetIndex = (node) => {
const fill = getItemFill(node)
if (fill instanceof SolidColorFill) {
const fillString = colorToHexString(fill.color)
- return colorTheme.findIndex(colorSet => colorSet.fill === fillString)
+ return colorTheme.findIndex((colorSet) => colorSet.fill === fillString)
}
return 0
}
@@ -373,7 +373,7 @@ export function createChangeNodeColorSet(preCondition, colorTheme, getItemFill,
(mode, item, type, args) => {
const currentItem = item
let colorSetIndex = parseInt(type)
- if (isNaN(colorSetIndex)) {
+ if (Number.isNaN(colorSetIndex)) {
colorSetIndex = itemToColorSetIndex(currentItem)
}
let colorSet = colorTheme[colorSetIndex]
@@ -385,7 +385,7 @@ export function createChangeNodeColorSet(preCondition, colorTheme, getItemFill,
const nodeStyle = currentItem.style.clone()
setStyleColors(nodeStyle, colorSet.fill, colorSet.outline)
mode.graph.setStyle(currentItem, nodeStyle)
- currentItem.labels.forEach(label => {
+ currentItem.labels.forEach((label) => {
const style = label.style.clone()
style.textFill = colorSet.labelText
style.backgroundFill = colorSet.labelFill
@@ -396,8 +396,8 @@ export function createChangeNodeColorSet(preCondition, colorTheme, getItemFill,
[{ key: Key.C }],
'Change the node color',
{
- typeFactory: item => String(itemToColorSetIndex(item)),
- styleFactory: item => {
+ typeFactory: (item) => String(itemToColorSetIndex(item)),
+ styleFactory: (item) => {
const colorSet = colorTheme[itemToColorSetIndex(item)]
return { type: 'rect', fill: colorSet.fill, outline: colorSet.outline }
},
@@ -418,7 +418,7 @@ export function createChangeNodeColorSet(preCondition, colorTheme, getItemFill,
export function createStartEdgeCreation(helpText, buttonOptions) {
return new WizardAction(
'startEdgeCreation',
- checkAnd([checkNotCreatingEdge, checkForNode, mode => mode.graph.nodes.size > 1]),
+ checkAnd([checkNotCreatingEdge, checkForNode, (mode) => mode.graph.nodes.size > 1]),
(mode, item) => {
mode.createEdgeMode.doStartEdgeCreation(
new DefaultPortCandidate(item, FreeNodePortLocationModel.NODE_CENTER_ANCHORED),
@@ -484,7 +484,7 @@ export function runLayout(mode, layout, layoutData, fixNodes, newNodes, deletedN
const oldNodeSizes = new Mapper()
if (newNodes) {
const graph = mode.graph
- newNodes.forEach(node => {
+ newNodes.forEach((node) => {
oldNodeSizes.set(node, node.layout.toSize())
graph.setNodeLayout(node, new Rect(node.layout.center, Size.ZERO))
})
diff --git a/demos/showcase/graph-wizard-for-flowchart/Actions.ts b/demos/showcase/graph-wizard-for-flowchart/Actions.ts
index 13aa5563d..abe120512 100644
--- a/demos/showcase/graph-wizard-for-flowchart/Actions.ts
+++ b/demos/showcase/graph-wizard-for-flowchart/Actions.ts
@@ -76,7 +76,7 @@ import { GraphWizardInputMode, WizardEventArgs } from './GraphWizardInputMode'
export function createSmartNavigate(): WizardAction {
return new WizardAction(
'navigate',
- mode => true,
+ (mode) => true,
(mode, item, type, args) => {
const graph = mode.graph
const key = (args as KeyEventArgs).key
@@ -138,9 +138,9 @@ export function createSmartNavigate(): WizardAction {
// check for connected hits in 90°
let children = graph
.outEdgesAt(item)
- .map(edge => edge.targetNode!)
- .concat(graph.inEdgesAt(item).map(edge => edge.sourceNode))
- .filter(child => {
+ .map((edge) => edge.targetNode!)
+ .concat(graph.inEdgesAt(item).map((edge) => edge.sourceNode))
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -151,7 +151,7 @@ export function createSmartNavigate(): WizardAction {
// check for unconnected hits in 90°
if (children.length === 0) {
children = graph.nodes
- .filter(child => {
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -164,9 +164,9 @@ export function createSmartNavigate(): WizardAction {
if (children.length === 0) {
children = graph
.outEdgesAt(item)
- .map(edge => edge.targetNode!)
- .concat(graph.inEdgesAt(item).map(edge => edge.sourceNode))
- .filter(child => {
+ .map((edge) => edge.targetNode!)
+ .concat(graph.inEdgesAt(item).map((edge) => edge.sourceNode))
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -178,7 +178,7 @@ export function createSmartNavigate(): WizardAction {
// check for unconnected hits in general direction
if (children.length === 0) {
children = graph.nodes
- .filter(child => {
+ .filter((child) => {
const childCenter = child.layout.center
const dx = center.x - childCenter.x
const dy = center.y - childCenter.y
@@ -187,7 +187,7 @@ export function createSmartNavigate(): WizardAction {
.toArray()
}
- const childScores = children.map(child => {
+ const childScores = children.map((child) => {
const childCenter = child.layout.center
const dx = Math.abs(center.x - childCenter.x)
const dy = Math.abs(center.y - childCenter.y)
@@ -215,7 +215,7 @@ export function createSmartNavigate(): WizardAction {
} else {
// no current item => select the one closest to the center of the viewport
const center = mode.graphComponent.viewport.center
- target = mode.graph.nodes.orderBy(node => center.distanceTo(node.layout.center)).at(0)
+ target = mode.graph.nodes.orderBy((node) => center.distanceTo(node.layout.center)).at(0)
}
if (target) {
mode.graphComponent.currentItem = target
@@ -249,7 +249,7 @@ export function createSmartNavigateEdge(direction: 'NextOutgoing' | 'NextIncomin
checkForEdge,
checkAnd([
checkForNode,
- mode => {
+ (mode) => {
const item = mode.currentItem as INode
return (
(direction === 'NextOutgoing' && mode.graph.outDegree(item) > 0) ||
@@ -368,7 +368,7 @@ export function createChangeNodeColorSet(
const fill = getItemFill(node)
if (fill instanceof SolidColorFill) {
const fillString = colorToHexString(fill.color)
- return colorTheme.findIndex(colorSet => colorSet.fill === fillString)
+ return colorTheme.findIndex((colorSet) => colorSet.fill === fillString)
}
return 0
}
@@ -379,7 +379,7 @@ export function createChangeNodeColorSet(
(mode, item, type, args) => {
const currentItem = item as INode
let colorSetIndex = parseInt(type)
- if (isNaN(colorSetIndex)) {
+ if (Number.isNaN(colorSetIndex)) {
colorSetIndex = itemToColorSetIndex(currentItem)
}
let colorSet = colorTheme[colorSetIndex]
@@ -391,7 +391,7 @@ export function createChangeNodeColorSet(
const nodeStyle = currentItem.style.clone()
setStyleColors(nodeStyle, colorSet.fill, colorSet.outline)
mode.graph.setStyle(currentItem, nodeStyle)
- currentItem.labels.forEach(label => {
+ currentItem.labels.forEach((label) => {
const style = label.style.clone() as DefaultLabelStyle
style.textFill = colorSet.labelText
style.backgroundFill = colorSet.labelFill
@@ -402,8 +402,8 @@ export function createChangeNodeColorSet(
[{ key: Key.C }],
'Change the node color',
{
- typeFactory: item => String(itemToColorSetIndex(item as INode)),
- styleFactory: item => {
+ typeFactory: (item) => String(itemToColorSetIndex(item as INode)),
+ styleFactory: (item) => {
const colorSet = colorTheme[itemToColorSetIndex(item as INode)]
return { type: 'rect', fill: colorSet.fill, outline: colorSet.outline }
},
@@ -424,7 +424,7 @@ export function createStartEdgeCreation(
): WizardAction {
return new WizardAction(
'startEdgeCreation',
- checkAnd([checkNotCreatingEdge, checkForNode, mode => mode.graph.nodes.size > 1]),
+ checkAnd([checkNotCreatingEdge, checkForNode, (mode) => mode.graph.nodes.size > 1]),
(mode, item) => {
mode.createEdgeMode.doStartEdgeCreation(
new DefaultPortCandidate(item as INode, FreeNodePortLocationModel.NODE_CENTER_ANCHORED),
@@ -493,7 +493,7 @@ export function runLayout(
const oldNodeSizes = new Mapper()
if (newNodes) {
const graph = mode.graph
- newNodes.forEach(node => {
+ newNodes.forEach((node) => {
oldNodeSizes.set(node, node.layout.toSize())
graph.setNodeLayout(node, new Rect(node.layout.center, Size.ZERO))
})
diff --git a/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.js b/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.js
index 7ac157df4..767fc77d8 100644
--- a/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.js
+++ b/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.js
@@ -310,7 +310,7 @@ export default class FlowchartConfiguration {
const wizardMode = new GraphWizardInputMode(legendDiv)
mode.moveUnselectedInputMode.enabled = true
mode.moveUnselectedInputMode.priority = mode.moveViewportInputMode.priority - 1
- mode.moveUnselectedInputMode.addDragFinishedListener(_ =>
+ mode.moveUnselectedInputMode.addDragFinishedListener((_) =>
runLayout(wizardMode, this.createLayout(true), this.layoutData)
)
@@ -375,7 +375,7 @@ export default class FlowchartConfiguration {
createChangeNodeColorSet(
checkAnd([checkNotCreatingEdge, checkForNodeStyle(FlowchartNodeStyle)]),
this.colorTheme,
- node => node.style.fill,
+ (node) => node.style.fill,
(style, fill, outline) => {
style.fill = Fill.from(fill)
style.stroke = new Stroke({ fill: outline, thickness: 1.5 })
@@ -421,8 +421,8 @@ export default class FlowchartConfiguration {
[{ key: Key.T }],
'Change the node type',
{
- typeFactory: item => this.getFlowchartType(item),
- styleFactory: item => {
+ typeFactory: (item) => this.getFlowchartType(item),
+ styleFactory: (item) => {
return {
type: 'icon',
iconPath: 'resources/icons/flowchart-' + this.getFlowchartType(item) + '.svg'
@@ -464,10 +464,10 @@ export default class FlowchartConfiguration {
* @returns {!Array.}
*/
createChangeFlowchartTypeButtons() {
- const typeToTooltip = type => {
+ const typeToTooltip = (type) => {
const name = type
- .replace(/\d+/, value => ' ' + value)
- .replace(/([a-z][A-Z])/g, value => value.substring(0, 1) + ' ' + value.substring(1, 2))
+ .replace(/\d+/, (value) => ' ' + value)
+ .replace(/([a-z][A-Z])/g, (value) => value.substring(0, 1) + ' ' + value.substring(1, 2))
return name.substring(0, 1).toUpperCase() + name.substring(1, name.length)
}
const pickerButtons = []
@@ -644,7 +644,7 @@ export default class FlowchartConfiguration {
checkAnd([
checkNotCreatingEdge,
checkOr([checkForNode, checkForEdge]),
- mode => mode.graph.nodes.size > 1
+ (mode) => mode.graph.nodes.size > 1
]),
(mode, item, type, args) => {
const graph = mode.graph
@@ -739,7 +739,7 @@ export default class FlowchartConfiguration {
outData: { child, edge }
}
},
- undo: undoData => {
+ undo: (undoData) => {
const { currentItem, child, edge } = undoData
const graph = mode.graph
graph.remove(edge)
@@ -757,7 +757,7 @@ export default class FlowchartConfiguration {
) {
// only add an edge label when parent was a decision node
const step2 = {
- action: async inData => {
+ action: async (inData) => {
const { edge } = inData
const labelPicked = await mode.showPickerSelection(
this.createSelectEdgeLabelTextAction(edge, parentInputMode),
@@ -770,7 +770,7 @@ export default class FlowchartConfiguration {
outData: inData
}
},
- undo: inData => {
+ undo: (inData) => {
if (inData) {
mode.graph.remove(inData)
}
@@ -798,7 +798,7 @@ export default class FlowchartConfiguration {
}
return { success, undoData: null, outData: inData }
},
- undo: undoData => {
+ undo: (undoData) => {
// don't undo setting the flowchart type so the new picker selection starts with the previous
// choice
}
@@ -808,7 +808,7 @@ export default class FlowchartConfiguration {
if (parentInputMode instanceof GraphEditorInputMode) {
// edit node label
const step4 = {
- action: async inData => {
+ action: async (inData) => {
const { child, edge } = inData
// when label editing was canceled, it returns null
const label = await parentInputMode.addLabel(child)
@@ -819,7 +819,7 @@ export default class FlowchartConfiguration {
}
return { success: label != null, undoData: label, outData: edge }
},
- undo: inData => {
+ undo: (inData) => {
if (inData) {
mode.graph.remove(inData)
}
@@ -842,7 +842,7 @@ export default class FlowchartConfiguration {
createSelectEdgeLabelTextAction(edge, geim) {
return new WizardAction(
'text',
- mode => true,
+ (mode) => true,
async (mode, item, type) => {
if (type === 'custom') {
const newLabel = await geim.addLabel(edge)
@@ -931,7 +931,7 @@ export default class FlowchartConfiguration {
* @returns {!PreCondition}
*/
isNodeType(type) {
- return mode =>
+ return (mode) =>
mode.currentItem instanceof INode &&
mode.currentItem.style instanceof FlowchartNodeStyle &&
mode.currentItem.style.type === type
@@ -942,10 +942,6 @@ export default class FlowchartConfiguration {
* A {@link FlowchartLayout} using an incremental {@link HierarchicLayout}.
*/
class IncrementalFlowchartLayout extends FlowchartLayout {
- constructor() {
- super()
- }
-
/**
* @returns {!HierarchicLayout}
*/
diff --git a/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.ts b/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.ts
index 0f72e4869..7d9de83be 100644
--- a/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.ts
+++ b/demos/showcase/graph-wizard-for-flowchart/FlowchartConfiguration.ts
@@ -300,7 +300,7 @@ export default class FlowchartConfiguration {
const wizardMode = new GraphWizardInputMode(legendDiv)
mode.moveUnselectedInputMode.enabled = true
mode.moveUnselectedInputMode.priority = mode.moveViewportInputMode.priority - 1
- mode.moveUnselectedInputMode.addDragFinishedListener(_ =>
+ mode.moveUnselectedInputMode.addDragFinishedListener((_) =>
runLayout(wizardMode, this.createLayout(true), this.layoutData!)
)
@@ -365,7 +365,7 @@ export default class FlowchartConfiguration {
createChangeNodeColorSet(
checkAnd([checkNotCreatingEdge, checkForNodeStyle(FlowchartNodeStyle)]),
this.colorTheme,
- node => (node.style as FlowchartNodeStyle).fill,
+ (node) => (node.style as FlowchartNodeStyle).fill,
(style, fill, outline) => {
;(style as FlowchartNodeStyle).fill = Fill.from(fill)
;(style as FlowchartNodeStyle).stroke = new Stroke({ fill: outline, thickness: 1.5 })
@@ -408,8 +408,8 @@ export default class FlowchartConfiguration {
[{ key: Key.T }],
'Change the node type',
{
- typeFactory: item => this.getFlowchartType(item as INode),
- styleFactory: item => {
+ typeFactory: (item) => this.getFlowchartType(item as INode),
+ styleFactory: (item) => {
return {
type: 'icon',
iconPath: 'resources/icons/flowchart-' + this.getFlowchartType(item as INode) + '.svg'
@@ -446,8 +446,8 @@ export default class FlowchartConfiguration {
private createChangeFlowchartTypeButtons(): ButtonOptions[] {
const typeToTooltip = (type: FlowchartNodeType) => {
const name = type
- .replace(/\d+/, value => ' ' + value)
- .replace(/([a-z][A-Z])/g, value => value.substring(0, 1) + ' ' + value.substring(1, 2))
+ .replace(/\d+/, (value) => ' ' + value)
+ .replace(/([a-z][A-Z])/g, (value) => value.substring(0, 1) + ' ' + value.substring(1, 2))
return name.substring(0, 1).toUpperCase() + name.substring(1, name.length)
}
const pickerButtons: ButtonOptions[] = []
@@ -704,7 +704,7 @@ export default class FlowchartConfiguration {
outData: { child, edge }
}
},
- undo: undoData => {
+ undo: (undoData) => {
const { currentItem, child, edge } = undoData as {
currentItem: IModelItem
child: INode
@@ -726,7 +726,7 @@ export default class FlowchartConfiguration {
) {
// only add an edge label when parent was a decision node
const step2: ActionStep = {
- action: async inData => {
+ action: async (inData) => {
const { edge } = inData as { edge: IEdge }
const labelPicked = await mode.showPickerSelection(
this.createSelectEdgeLabelTextAction(edge, parentInputMode),
@@ -739,7 +739,7 @@ export default class FlowchartConfiguration {
outData: inData
}
},
- undo: inData => {
+ undo: (inData) => {
if (inData) {
mode.graph.remove(inData as ILabel)
}
@@ -767,7 +767,7 @@ export default class FlowchartConfiguration {
}
return { success, undoData: null, outData: inData }
},
- undo: undoData => {
+ undo: (undoData) => {
// don't undo setting the flowchart type so the new picker selection starts with the previous
// choice
}
@@ -777,7 +777,7 @@ export default class FlowchartConfiguration {
if (parentInputMode instanceof GraphEditorInputMode) {
// edit node label
const step4: ActionStep = {
- action: async inData => {
+ action: async (inData) => {
const { child, edge } = inData as { child: INode; edge: IEdge }
// when label editing was canceled, it returns null
const label = await parentInputMode.addLabel(child)
@@ -788,7 +788,7 @@ export default class FlowchartConfiguration {
}
return { success: label != null, undoData: label, outData: edge }
},
- undo: inData => {
+ undo: (inData) => {
if (inData) {
mode.graph.remove(inData as ILabel)
}
@@ -810,7 +810,7 @@ export default class FlowchartConfiguration {
createSelectEdgeLabelTextAction(edge: IEdge, geim: GraphEditorInputMode): WizardAction {
return new WizardAction(
'text',
- mode => true,
+ (mode) => true,
async (mode, item, type) => {
if (type === 'custom') {
const newLabel = await geim.addLabel(edge)
@@ -897,7 +897,7 @@ export default class FlowchartConfiguration {
* @param type The type of flowchart node to check for.
*/
isNodeType(type: FlowchartNodeType): PreCondition {
- return mode =>
+ return (mode) =>
mode.currentItem instanceof INode &&
mode.currentItem.style instanceof FlowchartNodeStyle &&
mode.currentItem.style.type === type
@@ -908,9 +908,6 @@ export default class FlowchartConfiguration {
* A {@link FlowchartLayout} using an incremental {@link HierarchicLayout}.
*/
class IncrementalFlowchartLayout extends FlowchartLayout {
- constructor() {
- super()
- }
createHierarchicLayout(): HierarchicLayout {
const hierarchicLayout = super.createHierarchicLayout()
diff --git a/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.js b/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.js
index 96736016c..3b33a5e3b 100644
--- a/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.js
+++ b/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.js
@@ -368,7 +368,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
// clear all active actions and find new ones whose pre-condition is met
this.clear()
- this._activeActions = this._actions.filter(action => action.preCondition(this)).toList()
+ this._activeActions = this._actions.filter((action) => action.preCondition(this)).toList()
// update the buttons and the legend for the active actions
this.updateButtons()
@@ -386,8 +386,8 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
const gridDiv = document.createElement('div')
this._legendDiv.appendChild(gridDiv)
this._activeActions
- .filter(action => !!action.description)
- .forEach(action => {
+ .filter((action) => !!action.description)
+ .forEach((action) => {
const div = document.createElement('div')
div.innerHTML = WizardAction.getTextWithShortcuts(
action.description,
@@ -474,7 +474,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
}
// find an active action that is triggered by the source/event combination
- const triggeredAction = this._activeActions.find(action => action.trigger(source, e))
+ const triggeredAction = this._activeActions.find((action) => action.trigger(source, e))
if (triggeredAction !== null) {
if (e instanceof KeyEventArgs || e instanceof MouseEventArgs) {
e.preventDefault()
@@ -632,14 +632,14 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
// place all auto-placed buttons in a row
this.addAutoPlacedButtons(
- autoPlacedActions.map(action => action.buttonOptions),
+ autoPlacedActions.map((action) => action.buttonOptions),
PickerLayout.Row,
GraphWizardInputMode.getBaseLayout(this.currentItem),
- index => this.createWizardActionHandler(autoPlacedActions[index]),
+ (index) => this.createWizardActionHandler(autoPlacedActions[index]),
(button, index) => {
autoPlacedActions[index].button = button
},
- index => autoPlacedActions[index].shortcuts,
+ (index) => autoPlacedActions[index].shortcuts,
evt
)
@@ -663,9 +663,9 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
options.pickerButtons,
options.pickerLayout ?? PickerLayout.Grid,
backgroundLayout,
- options => defaultActionHandler,
+ (options) => defaultActionHandler,
this.setPickerButton.bind(this),
- index => undefined,
+ (index) => undefined,
evt
)
}
@@ -679,7 +679,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
addPickerSelectionButtons(action, evt) {
const parentOptions = action.buttonOptions
// handle action and close picker selection afterwards
- const handler = async button => {
+ const handler = async (button) => {
this.buttonMode.hideButtons()
const actionSuccessful = await action.handler(
this,
@@ -695,9 +695,9 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
parentOptions.pickerButtons,
parentOptions.pickerLayout ?? PickerLayout.Grid,
WizardAction.getButtonLayout(parentOptions, evt.owner),
- index => handler.bind(this),
+ (index) => handler.bind(this),
this.setPickerButton.bind(this),
- index => undefined,
+ (index) => undefined,
evt
)
}
@@ -750,7 +750,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
// triggering the main button when picker buttons are available should toggle whether those
// picker buttons are visible
return action.buttonOptions.pickerButtons
- ? button => this.togglePickerButtons(action)
+ ? (button) => this.togglePickerButtons(action)
: this.createDefaultButtonHandler(action)
}
@@ -760,7 +760,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
* @returns {!ButtonActionListener}
*/
createDefaultButtonHandler(action) {
- return button => {
+ return (button) => {
this.handleAction(
action,
button.owner,
@@ -842,10 +842,10 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
}
// if no picker button has its own layout parameter set, add a common background 'button'
- if (options.every(opt => !opt.layout && !opt.layoutFactory)) {
+ if (options.every((opt) => !opt.layout && !opt.layoutFactory)) {
// add background button
evt.addButton({
- onAction: button => {},
+ onAction: (button) => {},
layoutParameter: baseLayout,
style: new DefaultLabelStyle({
renderer: new DropShadowLabelRenderer(),
@@ -977,7 +977,9 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
if (hidePickers) {
const pickerButtonWasFocused =
this.pickerButtons &&
- this.pickerButtons.some(row => row.some(button => button === this.buttonMode.focusedButton))
+ this.pickerButtons.some((row) =>
+ row.some((button) => button === this.buttonMode.focusedButton)
+ )
const pickerActionWasFocused =
this.activePickersAction &&
this.activePickersAction.button === this.buttonMode.focusedButton
@@ -994,7 +996,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
let newActivePickersAction = action ? action : null
if (!newActivePickersAction && this.buttonMode.focusedButton) {
newActivePickersAction = this._activeActions.find(
- action =>
+ (action) =>
action.button === this.buttonMode.focusedButton &&
action.buttonOptions !== null &&
action.buttonOptions.pickerButtons !== null
@@ -1019,8 +1021,8 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
* @param {*} mainTag
*/
findPickerButtonToFocus(mainTag) {
- this.pickerButtons.forEach(row => {
- row.forEach(button => {
+ this.pickerButtons.forEach((row) => {
+ row.forEach((button) => {
if (button.tag == mainTag) {
return button
}
@@ -1087,7 +1089,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
* Calls {@link WizardAction.clear clear} for all active actions.
*/
cleanupActiveAction() {
- this._activeActions.forEach(action => action.clear())
+ this._activeActions.forEach((action) => action.clear())
this.activePickersAction = null
this.pickerButtons = null
}
@@ -1234,10 +1236,6 @@ export class WizardEventArgs extends EventArgs {
* Adds the __container-drop-shadow__ style class to the {@link SVGElement} of the created visual.
*/
class DropShadowLabelRenderer extends DefaultLabelStyleRenderer {
- constructor() {
- super()
- }
-
/**
* @param {!IRenderContext} context
* @returns {?Visual}
diff --git a/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.ts b/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.ts
index 251543540..e78540fd6 100644
--- a/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.ts
+++ b/demos/showcase/graph-wizard-for-flowchart/GraphWizardInputMode.ts
@@ -349,7 +349,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
// clear all active actions and find new ones whose pre-condition is met
this.clear()
- this._activeActions = this._actions.filter(action => action.preCondition(this)).toList()
+ this._activeActions = this._actions.filter((action) => action.preCondition(this)).toList()
// update the buttons and the legend for the active actions
this.updateButtons()
@@ -367,8 +367,8 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
const gridDiv = document.createElement('div')
this._legendDiv.appendChild(gridDiv)
this._activeActions
- .filter(action => !!action.description)
- .forEach(action => {
+ .filter((action) => !!action.description)
+ .forEach((action) => {
const div = document.createElement('div')
div.innerHTML = WizardAction.getTextWithShortcuts(
action.description!,
@@ -447,7 +447,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
}
// find an active action that is triggered by the source/event combination
- const triggeredAction = this._activeActions.find(action => action.trigger(source, e))
+ const triggeredAction = this._activeActions.find((action) => action.trigger(source, e))
if (triggeredAction !== null) {
if (e instanceof KeyEventArgs || e instanceof MouseEventArgs) {
e.preventDefault()
@@ -599,11 +599,11 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
autoPlacedActions.map((action: WizardAction) => action.buttonOptions!),
PickerLayout.Row,
GraphWizardInputMode.getBaseLayout(this.currentItem!),
- index => this.createWizardActionHandler(autoPlacedActions[index]),
+ (index) => this.createWizardActionHandler(autoPlacedActions[index]),
(button, index) => {
autoPlacedActions[index].button = button
},
- index => autoPlacedActions[index].shortcuts,
+ (index) => autoPlacedActions[index].shortcuts,
evt
)
@@ -627,9 +627,9 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
options.pickerButtons!,
options.pickerLayout ?? PickerLayout.Grid,
backgroundLayout,
- options => defaultActionHandler,
+ (options) => defaultActionHandler,
this.setPickerButton.bind(this),
- index => undefined,
+ (index) => undefined,
evt
)
}
@@ -643,7 +643,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
private addPickerSelectionButtons(action: WizardAction, evt: QueryButtonsEvent): void {
const parentOptions = action.buttonOptions!
// handle action and close picker selection afterwards
- const handler: ButtonActionListener = async button => {
+ const handler: ButtonActionListener = async (button) => {
this.buttonMode.hideButtons()
const actionSuccessful = await action.handler(
this,
@@ -659,9 +659,9 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
parentOptions.pickerButtons!,
parentOptions.pickerLayout ?? PickerLayout.Grid,
WizardAction.getButtonLayout(parentOptions, evt.owner),
- index => handler.bind(this),
+ (index) => handler.bind(this),
this.setPickerButton.bind(this),
- index => undefined,
+ (index) => undefined,
evt
)
}
@@ -804,10 +804,10 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
}
// if no picker button has its own layout parameter set, add a common background 'button'
- if (options.every(opt => !opt.layout && !opt.layoutFactory)) {
+ if (options.every((opt) => !opt.layout && !opt.layoutFactory)) {
// add background button
evt.addButton({
- onAction: button => {},
+ onAction: (button) => {},
layoutParameter: baseLayout,
style: new DefaultLabelStyle({
renderer: new DropShadowLabelRenderer(),
@@ -944,7 +944,9 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
if (hidePickers) {
const pickerButtonWasFocused =
this.pickerButtons &&
- this.pickerButtons.some(row => row.some(button => button === this.buttonMode.focusedButton))
+ this.pickerButtons.some((row) =>
+ row.some((button) => button === this.buttonMode.focusedButton)
+ )
const pickerActionWasFocused =
this.activePickersAction &&
this.activePickersAction.button === this.buttonMode.focusedButton
@@ -961,7 +963,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
let newActivePickersAction: WizardAction | null = action ? action : null
if (!newActivePickersAction && this.buttonMode.focusedButton) {
newActivePickersAction = this._activeActions.find(
- action =>
+ (action) =>
action.button === this.buttonMode.focusedButton &&
action.buttonOptions !== null &&
action.buttonOptions.pickerButtons !== null
@@ -983,8 +985,8 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
}
private findPickerButtonToFocus(mainTag: any) {
- this.pickerButtons!.forEach(row => {
- row.forEach(button => {
+ this.pickerButtons!.forEach((row) => {
+ row.forEach((button) => {
if (button.tag == mainTag) {
return button
}
@@ -1051,7 +1053,7 @@ export class GraphWizardInputMode extends MultiplexingInputMode {
* Calls {@link WizardAction.clear clear} for all active actions.
*/
public cleanupActiveAction(): void {
- this._activeActions.forEach(action => action.clear())
+ this._activeActions.forEach((action) => action.clear())
this.activePickersAction = null
this.pickerButtons = null
}
@@ -1198,9 +1200,6 @@ export class WizardEventArgs extends EventArgs {
* Adds the __container-drop-shadow__ style class to the {@link SVGElement} of the created visual.
*/
class DropShadowLabelRenderer extends DefaultLabelStyleRenderer {
- constructor() {
- super()
- }
createVisual(context: IRenderContext): Visual | null {
const visual = super.createVisual(context) as SvgVisual
diff --git a/demos/showcase/graph-wizard-for-flowchart/Preconditions.js b/demos/showcase/graph-wizard-for-flowchart/Preconditions.js
index 3082566b3..11cc1916c 100644
--- a/demos/showcase/graph-wizard-for-flowchart/Preconditions.js
+++ b/demos/showcase/graph-wizard-for-flowchart/Preconditions.js
@@ -38,7 +38,7 @@ import { CreateEdgeInputMode, IEdge, INode } from 'yfiles'
* @returns {!PreCondition}
*/
export function checkAnd(conditions) {
- return mode => conditions.every(condition => condition(mode))
+ return (mode) => conditions.every((condition) => condition(mode))
}
/**
@@ -47,7 +47,7 @@ export function checkAnd(conditions) {
* @returns {!PreCondition}
*/
export function checkOr(conditions) {
- return mode => conditions.some(condition => condition(mode))
+ return (mode) => conditions.some((condition) => condition(mode))
}
/**
@@ -56,7 +56,7 @@ export function checkOr(conditions) {
* @returns {!PreCondition}
*/
export function checkNot(condition) {
- return mode => !condition(mode)
+ return (mode) => !condition(mode)
}
/**
@@ -84,7 +84,7 @@ export function checkForEdge(mode) {
* @returns {!PreCondition}
*/
export function checkForNodeStyle(styleClass) {
- return mode => mode.currentItem instanceof INode && mode.currentItem.style instanceof styleClass
+ return (mode) => mode.currentItem instanceof INode && mode.currentItem.style instanceof styleClass
}
/**
@@ -94,7 +94,7 @@ export function checkForNodeStyle(styleClass) {
* @returns {!PreCondition}
*/
export function checkForEdgeStyle(styleClass) {
- return mode => mode.currentItem instanceof IEdge && mode.currentItem.style instanceof styleClass
+ return (mode) => mode.currentItem instanceof IEdge && mode.currentItem.style instanceof styleClass
}
/**
diff --git a/demos/showcase/graph-wizard-for-flowchart/Preconditions.ts b/demos/showcase/graph-wizard-for-flowchart/Preconditions.ts
index 96251653d..60d8af02f 100644
--- a/demos/showcase/graph-wizard-for-flowchart/Preconditions.ts
+++ b/demos/showcase/graph-wizard-for-flowchart/Preconditions.ts
@@ -36,7 +36,7 @@ export type PreCondition = (mode: GraphWizardInputMode) => boolean
* @param conditions The conditions to combine.
*/
export function checkAnd(conditions: PreCondition[]): PreCondition {
- return mode => conditions.every(condition => condition(mode))
+ return (mode) => conditions.every((condition) => condition(mode))
}
/**
@@ -44,7 +44,7 @@ export function checkAnd(conditions: PreCondition[]): PreCondition {
* @param conditions The conditions to combine.
*/
export function checkOr(conditions: PreCondition[]): PreCondition {
- return mode => conditions.some(condition => condition(mode))
+ return (mode) => conditions.some((condition) => condition(mode))
}
/**
@@ -52,7 +52,7 @@ export function checkOr(conditions: PreCondition[]): PreCondition {
* @param condition The condition to negate.
*/
export function checkNot(condition: PreCondition): PreCondition {
- return mode => !condition(mode)
+ return (mode) => !condition(mode)
}
/**
@@ -77,7 +77,7 @@ export function checkForEdge(mode: GraphWizardInputMode): boolean {
* @param styleClass The style class the current node is checked for.
*/
export function checkForNodeStyle(styleClass: any): PreCondition {
- return mode => mode.currentItem instanceof INode && mode.currentItem.style instanceof styleClass
+ return (mode) => mode.currentItem instanceof INode && mode.currentItem.style instanceof styleClass
}
/**
@@ -86,7 +86,7 @@ export function checkForNodeStyle(styleClass: any): PreCondition {
* @param styleClass The style class the current edge is checked for.
*/
export function checkForEdgeStyle(styleClass: any): PreCondition {
- return mode => mode.currentItem instanceof IEdge && mode.currentItem.style instanceof styleClass
+ return (mode) => mode.currentItem instanceof IEdge && mode.currentItem.style instanceof styleClass
}
/**
diff --git a/demos/showcase/graph-wizard-for-flowchart/WizardAction.js b/demos/showcase/graph-wizard-for-flowchart/WizardAction.js
index 98ef51ed2..833785f40 100644
--- a/demos/showcase/graph-wizard-for-flowchart/WizardAction.js
+++ b/demos/showcase/graph-wizard-for-flowchart/WizardAction.js
@@ -177,7 +177,7 @@ export default class WizardAction {
evt.eventType === KeyEventType.DOWN
) {
return this.shortcuts.some(
- shortCut =>
+ (shortCut) =>
shortCut.key == evt.key &&
(shortCut.modifier === undefined || shortCut.modifier == evt.modifiers)
)
@@ -253,7 +253,7 @@ export default class WizardAction {
* @returns {!ButtonActionListener}
*/
getDefaultAction(mode) {
- return button => {
+ return (button) => {
mode.handleAction(
this,
button.owner,
@@ -388,7 +388,7 @@ export default class WizardAction {
} else if (options.tooltipFactory) {
tooltip = options.tooltipFactory(owner)
}
- return this.getTextWithShortcuts(tooltip, 'tooltip', shortcuts)
+ return WizardAction.getTextWithShortcuts(tooltip, 'tooltip', shortcuts)
}
/**
@@ -441,7 +441,7 @@ export default class WizardAction {
tooltip += startKey + 'Alt' + endKey + '+'
}
}
- tooltip += startKey + this.getKeyName(shortcut.key) + endKey
+ tooltip += startKey + WizardAction.getKeyName(shortcut.key) + endKey
}
return tooltip
}
diff --git a/demos/showcase/graph-wizard-for-flowchart/WizardAction.ts b/demos/showcase/graph-wizard-for-flowchart/WizardAction.ts
index af9986bf8..20dca5de2 100644
--- a/demos/showcase/graph-wizard-for-flowchart/WizardAction.ts
+++ b/demos/showcase/graph-wizard-for-flowchart/WizardAction.ts
@@ -188,7 +188,7 @@ export default class WizardAction {
evt.eventType === KeyEventType.DOWN
) {
return this.shortcuts.some(
- shortCut =>
+ (shortCut) =>
shortCut.key == evt.key &&
(shortCut.modifier === undefined || shortCut.modifier == evt.modifiers)
)
@@ -389,7 +389,7 @@ export default class WizardAction {
} else if (options.tooltipFactory) {
tooltip = options.tooltipFactory(owner)
}
- return this.getTextWithShortcuts(tooltip, 'tooltip', shortcuts)
+ return WizardAction.getTextWithShortcuts(tooltip, 'tooltip', shortcuts)
}
/**
@@ -439,7 +439,7 @@ export default class WizardAction {
tooltip += startKey + 'Alt' + endKey + '+'
}
}
- tooltip += startKey + this.getKeyName(shortcut.key) + endKey
+ tooltip += startKey + WizardAction.getKeyName(shortcut.key) + endKey
}
return tooltip
}
diff --git a/demos/showcase/graph-wizard-for-flowchart/index.html b/demos/showcase/graph-wizard-for-flowchart/index.html
index 347d9f0a6..7dd7d19f4 100644
--- a/demos/showcase/graph-wizard-for-flowchart/index.html
+++ b/demos/showcase/graph-wizard-for-flowchart/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/graph-wizard-for-flowchart/resources/graph-creation-wizard.css b/demos/showcase/graph-wizard-for-flowchart/resources/graph-creation-wizard.css
index cf6c2b691..62807b982 100644
--- a/demos/showcase/graph-wizard-for-flowchart/resources/graph-creation-wizard.css
+++ b/demos/showcase/graph-wizard-for-flowchart/resources/graph-creation-wizard.css
@@ -49,7 +49,9 @@
legend {
color: grey;
padding: 3px 6px;
- font: 1rem 'Fira Sans', sans-serif;
+ font:
+ 1rem 'Fira Sans',
+ sans-serif;
}
.demo-overlay {
@@ -66,7 +68,9 @@ legend {
background-color: #e1e3e5;
border: 1px solid #ccc;
border-radius: 3px;
- box-shadow: 0 1px 0 rgb(0 0 0), 0 0 0 0.1em #fff inset;
+ box-shadow:
+ 0 1px 0 rgb(0 0 0),
+ 0 0 0 0.1em #fff inset;
white-space: nowrap;
font-style: normal;
color: #000;
diff --git a/demos/showcase/graphanalysis/GraphAnalysisDemo.js b/demos/showcase/graphanalysis/GraphAnalysisDemo.js
index 3625ffdfb..b74bc86a2 100644
--- a/demos/showcase/graphanalysis/GraphAnalysisDemo.js
+++ b/demos/showcase/graphanalysis/GraphAnalysisDemo.js
@@ -144,12 +144,12 @@ function createEditorMode(graphComponent) {
// deletion
const graph = graphComponent.graph
- inputMode.addDeletingSelectionListener(async _ => {
+ inputMode.addDeletingSelectionListener(async (_) => {
applyAlgorithm(graph)
await runLayout(graphComponent, true, [])
})
- inputMode.addDeletedSelectionListener(async _ => {
+ inputMode.addDeletedSelectionListener(async (_) => {
applyAlgorithm(graph)
await runLayout(graphComponent, true, [])
})
@@ -173,9 +173,9 @@ function createEditorMode(graphComponent) {
await runLayout(graphComponent, true, incrementalNodes)
})
- inputMode.moveInputMode.addDragFinishedListener(async inputModeMove => {
+ inputMode.moveInputMode.addDragFinishedListener(async (inputModeMove) => {
const affectedNodes = inputModeMove.affectedItems
- .filter(item => item instanceof INode)
+ .filter((item) => item instanceof INode)
.toArray()
if (affectedNodes.length < graph.nodes.size) {
applyAlgorithm(graph)
@@ -184,11 +184,11 @@ function createEditorMode(graphComponent) {
})
// run the algorithm on node creation, edge port changes or label text changes
- inputMode.addEdgePortsChangedListener(async _ => {
+ inputMode.addEdgePortsChangedListener(async (_) => {
applyAlgorithm(graph)
})
- inputMode.addNodeCreatedListener(_ => {
+ inputMode.addNodeCreatedListener((_) => {
applyAlgorithm(graph)
})
diff --git a/demos/showcase/graphanalysis/GraphAnalysisDemo.ts b/demos/showcase/graphanalysis/GraphAnalysisDemo.ts
index 41213318f..02e37f9d0 100644
--- a/demos/showcase/graphanalysis/GraphAnalysisDemo.ts
+++ b/demos/showcase/graphanalysis/GraphAnalysisDemo.ts
@@ -140,12 +140,12 @@ function createEditorMode(graphComponent: GraphComponent): GraphEditorInputMode
// deletion
const graph = graphComponent.graph
- inputMode.addDeletingSelectionListener(async _ => {
+ inputMode.addDeletingSelectionListener(async (_) => {
applyAlgorithm(graph)
await runLayout(graphComponent, true, [])
})
- inputMode.addDeletedSelectionListener(async _ => {
+ inputMode.addDeletedSelectionListener(async (_) => {
applyAlgorithm(graph)
await runLayout(graphComponent, true, [])
})
@@ -169,9 +169,9 @@ function createEditorMode(graphComponent: GraphComponent): GraphEditorInputMode
await runLayout(graphComponent, true, incrementalNodes)
})
- inputMode.moveInputMode.addDragFinishedListener(async inputModeMove => {
+ inputMode.moveInputMode.addDragFinishedListener(async (inputModeMove) => {
const affectedNodes = inputModeMove.affectedItems
- .filter(item => item instanceof INode)
+ .filter((item) => item instanceof INode)
.toArray() as INode[]
if (affectedNodes.length < graph.nodes.size) {
applyAlgorithm(graph)
@@ -180,11 +180,11 @@ function createEditorMode(graphComponent: GraphComponent): GraphEditorInputMode
})
// run the algorithm on node creation, edge port changes or label text changes
- inputMode.addEdgePortsChangedListener(async _ => {
+ inputMode.addEdgePortsChangedListener(async (_) => {
applyAlgorithm(graph)
})
- inputMode.addNodeCreatedListener(_ => {
+ inputMode.addNodeCreatedListener((_) => {
applyAlgorithm(graph)
})
diff --git a/demos/showcase/graphanalysis/algorithms/algorithms.js b/demos/showcase/graphanalysis/algorithms/algorithms.js
index cbb07d051..52e64718a 100644
--- a/demos/showcase/graphanalysis/algorithms/algorithms.js
+++ b/demos/showcase/graphanalysis/algorithms/algorithms.js
@@ -129,7 +129,7 @@ import {
* @param {!IGraph} graph
*/
export function resetTypes(graph) {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
resetType(node)
})
}
@@ -159,17 +159,17 @@ export function applyAlgorithm(graph) {
* @param {!IGraph} graph
*/
export function resetGraph(graph) {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
resetResult(node)
})
- graph.edges.forEach(edge => resetResult(edge))
- graph.nodeLabels.toArray().forEach(label => {
+ graph.edges.forEach((edge) => resetResult(edge))
+ graph.nodeLabels.toArray().forEach((label) => {
graph.remove(label)
})
graph.edgeLabels
.toArray()
- .filter(label => label.tag !== 'weight')
- .forEach(label => {
+ .filter((label) => label.tag !== 'weight')
+ .forEach((label) => {
graph.remove(label)
})
}
@@ -378,7 +378,7 @@ export const algorithms = {
*/
function getEdgeWeights(graph) {
const weights = new Map()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (useUniformEdgeWeights()) {
weights.set(edge, 1)
} else {
@@ -407,7 +407,7 @@ function getStartNodes(graph) {
return []
}
- const startNodes = graph.nodes.filter(node => getTag(node).type === 'start').toArray()
+ const startNodes = graph.nodes.filter((node) => getTag(node).type === 'start').toArray()
if (startNodes.length === 0) {
const startNode = graph.nodes.first()
const tag = copyAndReplaceTag(startNode)
@@ -429,7 +429,7 @@ function getEndNodes(graph) {
return []
}
- const endNodes = graph.nodes.filter(node => getTag(node).type === 'end').toArray()
+ const endNodes = graph.nodes.filter((node) => getTag(node).type === 'end').toArray()
if (endNodes.length === 0) {
const endNode = graph.nodes.last()
const tag = copyAndReplaceTag(endNode)
diff --git a/demos/showcase/graphanalysis/algorithms/algorithms.ts b/demos/showcase/graphanalysis/algorithms/algorithms.ts
index 8b1bfcaef..4956749d3 100644
--- a/demos/showcase/graphanalysis/algorithms/algorithms.ts
+++ b/demos/showcase/graphanalysis/algorithms/algorithms.ts
@@ -131,7 +131,7 @@ export type AlgorithmConfig = {
* Resets the node types.
*/
export function resetTypes(graph: IGraph): void {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
resetType(node)
})
}
@@ -159,17 +159,17 @@ export function applyAlgorithm(graph: IGraph): void {
* Removes all result-labels and resets the tag.
*/
export function resetGraph(graph: IGraph): void {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
resetResult(node)
})
- graph.edges.forEach(edge => resetResult(edge))
- graph.nodeLabels.toArray().forEach(label => {
+ graph.edges.forEach((edge) => resetResult(edge))
+ graph.nodeLabels.toArray().forEach((label) => {
graph.remove(label)
})
graph.edgeLabels
.toArray()
- .filter(label => label.tag !== 'weight')
- .forEach(label => {
+ .filter((label) => label.tag !== 'weight')
+ .forEach((label) => {
graph.remove(label)
})
}
@@ -376,7 +376,7 @@ export const algorithms: Record = {
*/
function getEdgeWeights(graph: IGraph): Map {
const weights = new Map()
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
if (useUniformEdgeWeights()) {
weights.set(edge, 1)
} else {
@@ -403,7 +403,7 @@ function getStartNodes(graph: IGraph): INode[] {
return []
}
- const startNodes = graph.nodes.filter(node => getTag(node).type === 'start').toArray()
+ const startNodes = graph.nodes.filter((node) => getTag(node).type === 'start').toArray()
if (startNodes.length === 0) {
const startNode = graph.nodes.first()
const tag = copyAndReplaceTag(startNode)
@@ -423,7 +423,7 @@ function getEndNodes(graph: IGraph): INode[] {
return []
}
- const endNodes = graph.nodes.filter(node => getTag(node).type === 'end').toArray()
+ const endNodes = graph.nodes.filter((node) => getTag(node).type === 'end').toArray()
if (endNodes.length === 0) {
const endNode = graph.nodes.last()
const tag = copyAndReplaceTag(endNode)
diff --git a/demos/showcase/graphanalysis/algorithms/centrality.js b/demos/showcase/graphanalysis/algorithms/centrality.js
index aad7992f2..0295de35c 100644
--- a/demos/showcase/graphanalysis/algorithms/centrality.js
+++ b/demos/showcase/graphanalysis/algorithms/centrality.js
@@ -68,7 +68,7 @@ export function calculateDegreeCentrality(graph) {
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)
setCentrality(node, centrality)
graph.addLabel({
@@ -100,7 +100,7 @@ export const weightCentralityDescription = `
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)
setCentrality(node, centrality)
graph.addLabel({ owner: node, text: nodeCentrality.get(node).toFixed(2) })
@@ -131,7 +131,7 @@ export function calculateGraphCentrality(graph, config) {
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)
setCentrality(node, centrality)
graph.addLabel({ owner: node, text: nodeCentrality.get(node).toFixed(2) })
@@ -160,7 +160,7 @@ export function calculateNodeEdgeBetweennessCentrality(graph, config) {
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)
setCentrality(node, centrality)
graph.addLabel({ owner: node, text: nodeCentrality.get(node).toFixed(2) })
@@ -168,7 +168,7 @@ export function calculateNodeEdgeBetweennessCentrality(graph, config) {
const edgeCentrality = result.edgeCentrality
const normalizedEdgeCentrality = result.normalizedEdgeCentrality
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const centrality = normalizedEdgeCentrality.get(edge)
setCentrality(edge, centrality)
graph.addLabel({
@@ -204,7 +204,7 @@ export function calculateClosenessCentrality(graph, config) {
}).run(graph)
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)
setCentrality(node, centrality)
graph.addLabel({
@@ -217,7 +217,7 @@ export function calculateClosenessCentrality(graph, config) {
// if the graph is not connected, we run the algorithm separately to each connected component
const connectedComponentsResult = new ConnectedComponents().run(graph)
- connectedComponentsResult.components.forEach(component => {
+ connectedComponentsResult.components.forEach((component) => {
const result = new ClosenessCentrality({
weights: config.edgeWeights,
directed: config.directed,
@@ -225,7 +225,7 @@ export function calculateClosenessCentrality(graph, config) {
}).run(graph)
const normalizedNodeCentrality = result.normalizedNodeCentrality
- component.nodes.forEach(node => {
+ component.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)
setCentrality(node, centrality)
// we use normalized node centrality for the labels to avoid very small values
@@ -252,12 +252,12 @@ export function calculateEigenvectorCentrality(graph) {
const result = new EigenvectorCentrality().run(graph)
const nodeCentrality = result.nodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = nodeCentrality.get(node)
setCentrality(node, centrality)
graph.addLabel({
owner: node,
- text: isNaN(centrality) ? 'Inf' : centrality.toFixed(2)
+ text: Number.isNaN(centrality) ? 'Inf' : centrality.toFixed(2)
})
})
}
@@ -296,7 +296,7 @@ export function calculatePageRankCentrality(graph, config) {
return Math.max(maxRank, pageRank.get(node))
}, 0)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const rank = pageRank.get(node)
setCentrality(node, rank / maximumRank)
graph.addLabel({
diff --git a/demos/showcase/graphanalysis/algorithms/centrality.ts b/demos/showcase/graphanalysis/algorithms/centrality.ts
index 669e2d64a..3a7ea6c29 100644
--- a/demos/showcase/graphanalysis/algorithms/centrality.ts
+++ b/demos/showcase/graphanalysis/algorithms/centrality.ts
@@ -69,7 +69,7 @@ export function calculateDegreeCentrality(graph: IGraph): void {
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)!
setCentrality(node, centrality)
graph.addLabel({
@@ -99,7 +99,7 @@ export const weightCentralityDescription = `
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)!
setCentrality(node, centrality)
graph.addLabel({ owner: node, text: nodeCentrality.get(node)!.toFixed(2) })
@@ -128,7 +128,7 @@ export function calculateGraphCentrality(graph: IGraph, config: AlgorithmConfig)
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)!
setCentrality(node, centrality)
graph.addLabel({ owner: node, text: nodeCentrality.get(node)!.toFixed(2) })
@@ -158,7 +158,7 @@ export function calculateNodeEdgeBetweennessCentrality(
const nodeCentrality = result.nodeCentrality
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)!
setCentrality(node, centrality)
graph.addLabel({ owner: node, text: nodeCentrality.get(node)!.toFixed(2) })
@@ -166,7 +166,7 @@ export function calculateNodeEdgeBetweennessCentrality(
const edgeCentrality = result.edgeCentrality
const normalizedEdgeCentrality = result.normalizedEdgeCentrality
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
const centrality = normalizedEdgeCentrality.get(edge)!
setCentrality(edge, centrality)
graph.addLabel({
@@ -200,7 +200,7 @@ export function calculateClosenessCentrality(graph: IGraph, config: AlgorithmCon
}).run(graph)
const normalizedNodeCentrality = result.normalizedNodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)!
setCentrality(node, centrality)
graph.addLabel({
@@ -213,7 +213,7 @@ export function calculateClosenessCentrality(graph: IGraph, config: AlgorithmCon
// if the graph is not connected, we run the algorithm separately to each connected component
const connectedComponentsResult = new ConnectedComponents().run(graph)
- connectedComponentsResult.components.forEach(component => {
+ connectedComponentsResult.components.forEach((component) => {
const result = new ClosenessCentrality({
weights: config.edgeWeights,
directed: config.directed,
@@ -221,7 +221,7 @@ export function calculateClosenessCentrality(graph: IGraph, config: AlgorithmCon
}).run(graph)
const normalizedNodeCentrality = result.normalizedNodeCentrality
- component.nodes.forEach(node => {
+ component.nodes.forEach((node) => {
const centrality = normalizedNodeCentrality.get(node)!
setCentrality(node, centrality)
// we use normalized node centrality for the labels to avoid very small values
@@ -247,12 +247,12 @@ export function calculateEigenvectorCentrality(graph: IGraph): void {
const result = new EigenvectorCentrality().run(graph)
const nodeCentrality = result.nodeCentrality
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const centrality = nodeCentrality.get(node)!
setCentrality(node, centrality)
graph.addLabel({
owner: node,
- text: isNaN(centrality) ? 'Inf' : centrality.toFixed(2)
+ text: Number.isNaN(centrality) ? 'Inf' : centrality.toFixed(2)
})
})
}
@@ -289,7 +289,7 @@ export function calculatePageRankCentrality(graph: IGraph, config: AlgorithmConf
return Math.max(maxRank, pageRank.get(node)!)
}, 0)
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const rank = pageRank.get(node)!
setCentrality(node, rank / maximumRank)
graph.addLabel({
diff --git a/demos/showcase/graphanalysis/algorithms/connectivity.js b/demos/showcase/graphanalysis/algorithms/connectivity.js
index 50522ae7c..b2d00549c 100644
--- a/demos/showcase/graphanalysis/algorithms/connectivity.js
+++ b/demos/showcase/graphanalysis/algorithms/connectivity.js
@@ -50,8 +50,8 @@ export function calculateConnectedComponents(graph) {
const result = new ConnectedComponents().run(graph)
result.components.forEach((component, componentIndex) => {
- component.nodes.forEach(node => markItem(node, componentIndex))
- component.inducedEdges.forEach(edge => markItem(edge, componentIndex))
+ component.nodes.forEach((node) => markItem(node, componentIndex))
+ component.inducedEdges.forEach((edge) => markItem(edge, componentIndex))
})
}
@@ -71,10 +71,10 @@ export function calculateBiconnectedComponents(graph) {
const result = new BiconnectedComponents().run(graph)
result.components.forEach((component, componentIndex) => {
- component.nodes.forEach(node => {
+ component.nodes.forEach((node) => {
markItem(node, componentIndex)
})
- component.edges.forEach(edge => {
+ component.edges.forEach((edge) => {
markItem(edge, componentIndex)
})
})
@@ -95,8 +95,8 @@ export function calculateStronglyConnectedComponents(graph) {
const result = new StronglyConnectedComponents().run(graph)
result.components.forEach((component, componentIndex) => {
- component.nodes.forEach(node => markItem(node, componentIndex))
- component.inducedEdges.forEach(edge => markItem(edge, componentIndex))
+ component.nodes.forEach((node) => markItem(node, componentIndex))
+ component.inducedEdges.forEach((edge) => markItem(edge, componentIndex))
})
}
@@ -126,13 +126,13 @@ export function calculateReachableNodes(graph, config) {
startNodes: markedSource
}).run(graph)
- result.reachableNodes.forEach(node => {
+ result.reachableNodes.forEach((node) => {
markItem(node, 0)
})
graph.edges
- .filter(edge => result.isReachable(edge.sourceNode) && result.isReachable(edge.targetNode))
- .forEach(edge => {
+ .filter((edge) => result.isReachable(edge.sourceNode) && result.isReachable(edge.targetNode))
+ .forEach((edge) => {
markItem(edge, 0)
})
}
@@ -166,13 +166,13 @@ export function calculateKCoreComponents(graph) {
for (let k = maximumK; k > 0; k--) {
const kCore = result.getKCore(k)
- kCore.forEach(node => markItem(node, k))
+ kCore.forEach((node) => markItem(node, k))
graph.edges
- .filter(edge => kCore.contains(edge.sourceNode) && kCore.contains(edge.targetNode))
- .forEach(edge => markItem(edge, k))
+ .filter((edge) => kCore.contains(edge.sourceNode) && kCore.contains(edge.targetNode))
+ .forEach((edge) => markItem(edge, k))
}
const kCores = result.kCores
- graph.nodes.forEach(node => graph.addLabel({ owner: node, text: String(kCores.get(node)) }))
+ graph.nodes.forEach((node) => graph.addLabel({ owner: node, text: String(kCores.get(node)) }))
}
diff --git a/demos/showcase/graphanalysis/algorithms/connectivity.ts b/demos/showcase/graphanalysis/algorithms/connectivity.ts
index 45eb91578..94f2844f8 100644
--- a/demos/showcase/graphanalysis/algorithms/connectivity.ts
+++ b/demos/showcase/graphanalysis/algorithms/connectivity.ts
@@ -50,8 +50,8 @@ export function calculateConnectedComponents(graph: IGraph): void {
const result = new ConnectedComponents().run(graph)
result.components.forEach((component, componentIndex) => {
- component.nodes.forEach(node => markItem(node, componentIndex))
- component.inducedEdges.forEach(edge => markItem(edge, componentIndex))
+ component.nodes.forEach((node) => markItem(node, componentIndex))
+ component.inducedEdges.forEach((edge) => markItem(edge, componentIndex))
})
}
@@ -70,10 +70,10 @@ export function calculateBiconnectedComponents(graph: IGraph): void {
const result = new BiconnectedComponents().run(graph)
result.components.forEach((component, componentIndex) => {
- component.nodes.forEach(node => {
+ component.nodes.forEach((node) => {
markItem(node, componentIndex)
})
- component.edges.forEach(edge => {
+ component.edges.forEach((edge) => {
markItem(edge, componentIndex)
})
})
@@ -93,8 +93,8 @@ export function calculateStronglyConnectedComponents(graph: IGraph): void {
const result = new StronglyConnectedComponents().run(graph)
result.components.forEach((component, componentIndex) => {
- component.nodes.forEach(node => markItem(node, componentIndex))
- component.inducedEdges.forEach(edge => markItem(edge, componentIndex))
+ component.nodes.forEach((node) => markItem(node, componentIndex))
+ component.inducedEdges.forEach((edge) => markItem(edge, componentIndex))
})
}
@@ -122,13 +122,13 @@ export function calculateReachableNodes(graph: IGraph, config: AlgorithmConfig):
startNodes: markedSource
}).run(graph)
- result.reachableNodes.forEach(node => {
+ result.reachableNodes.forEach((node) => {
markItem(node, 0)
})
graph.edges
- .filter(edge => result.isReachable(edge.sourceNode!) && result.isReachable(edge.targetNode!))
- .forEach(edge => {
+ .filter((edge) => result.isReachable(edge.sourceNode!) && result.isReachable(edge.targetNode!))
+ .forEach((edge) => {
markItem(edge, 0)
})
}
@@ -161,13 +161,13 @@ export function calculateKCoreComponents(graph: IGraph): void {
for (let k = maximumK; k > 0; k--) {
const kCore = result.getKCore(k)
- kCore.forEach(node => markItem(node, k))
+ kCore.forEach((node) => markItem(node, k))
graph.edges
- .filter(edge => kCore.contains(edge.sourceNode!) && kCore.contains(edge.targetNode!))
- .forEach(edge => markItem(edge, k))
+ .filter((edge) => kCore.contains(edge.sourceNode!) && kCore.contains(edge.targetNode!))
+ .forEach((edge) => markItem(edge, k))
}
const kCores = result.kCores
- graph.nodes.forEach(node => graph.addLabel({ owner: node, text: String(kCores.get(node)) }))
+ graph.nodes.forEach((node) => graph.addLabel({ owner: node, text: String(kCores.get(node)) }))
}
diff --git a/demos/showcase/graphanalysis/algorithms/cycles.js b/demos/showcase/graphanalysis/algorithms/cycles.js
index 945475b43..05f89c2bf 100644
--- a/demos/showcase/graphanalysis/algorithms/cycles.js
+++ b/demos/showcase/graphanalysis/algorithms/cycles.js
@@ -56,12 +56,12 @@ export function calculateCycles(graph, config) {
// consisting only of elements that belong a cycle
const connectedComponentsResult = new ConnectedComponents({
subgraphEdges: cycleEdges,
- subgraphNodes: node => graph.edgesAt(node).some(edge => cycleEdges.includes(edge))
+ subgraphNodes: (node) => graph.edgesAt(node).some((edge) => cycleEdges.includes(edge))
}).run(graph)
// color the cycle edges depending on which component they belong to
connectedComponentsResult.components.forEach((cycle, cycleId) => {
- cycle.nodes.forEach(node => markItem(node, cycleId))
- cycle.inducedEdges.forEach(edge => markItem(edge, cycleId))
+ cycle.nodes.forEach((node) => markItem(node, cycleId))
+ cycle.inducedEdges.forEach((edge) => markItem(edge, cycleId))
})
}
diff --git a/demos/showcase/graphanalysis/algorithms/cycles.ts b/demos/showcase/graphanalysis/algorithms/cycles.ts
index d88c84d26..f5f859350 100644
--- a/demos/showcase/graphanalysis/algorithms/cycles.ts
+++ b/demos/showcase/graphanalysis/algorithms/cycles.ts
@@ -54,12 +54,12 @@ export function calculateCycles(graph: IGraph, config: AlgorithmConfig): void {
// consisting only of elements that belong a cycle
const connectedComponentsResult = new ConnectedComponents({
subgraphEdges: cycleEdges,
- subgraphNodes: node => graph.edgesAt(node).some(edge => cycleEdges.includes(edge))
+ subgraphNodes: (node) => graph.edgesAt(node).some((edge) => cycleEdges.includes(edge))
}).run(graph)
// color the cycle edges depending on which component they belong to
connectedComponentsResult.components.forEach((cycle, cycleId) => {
- cycle.nodes.forEach(node => markItem(node, cycleId))
- cycle.inducedEdges.forEach(edge => markItem(edge, cycleId))
+ cycle.nodes.forEach((node) => markItem(node, cycleId))
+ cycle.inducedEdges.forEach((edge) => markItem(edge, cycleId))
})
}
diff --git a/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.js b/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.js
index 8b42098db..55b33c6f6 100644
--- a/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.js
+++ b/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.js
@@ -51,11 +51,11 @@ export function calculateMinimumSpanningTree(graph, config) {
const result = new SpanningTree({ costs: config.edgeWeights }).run(graph)
// mark those edges
- result.edges.forEach(edge => {
+ result.edges.forEach((edge) => {
markItem(edge)
})
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
markItem(node)
})
}
diff --git a/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.ts b/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.ts
index a2bdf7c28..0d8bb6c67 100644
--- a/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.ts
+++ b/demos/showcase/graphanalysis/algorithms/minimum-spanning-tree.ts
@@ -50,11 +50,11 @@ export function calculateMinimumSpanningTree(graph: IGraph, config: AlgorithmCon
const result = new SpanningTree({ costs: config.edgeWeights }).run(graph)
// mark those edges
- result.edges.forEach(edge => {
+ result.edges.forEach((edge) => {
markItem(edge)
})
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
markItem(node)
})
}
diff --git a/demos/showcase/graphanalysis/algorithms/paths.js b/demos/showcase/graphanalysis/algorithms/paths.js
index c2a4998ac..102143809 100644
--- a/demos/showcase/graphanalysis/algorithms/paths.js
+++ b/demos/showcase/graphanalysis/algorithms/paths.js
@@ -68,10 +68,10 @@ export function calculatedShortestPaths(graph, config) {
sink: endNodes[0]
}).run(graph)
- result.nodes.forEach(node => {
+ result.nodes.forEach((node) => {
markItem(node)
})
- result.edges.forEach(edge => {
+ result.edges.forEach((edge) => {
markItem(edge)
})
} else {
@@ -83,10 +83,10 @@ export function calculatedShortestPaths(graph, config) {
}).run(graph)
result.paths.forEach((path, pathIndex) => {
- path.nodes.forEach(node => {
+ path.nodes.forEach((node) => {
markItem(node, pathIndex)
})
- path.edges.forEach(edge => {
+ path.edges.forEach((edge) => {
markItem(edge, pathIndex)
})
})
@@ -123,10 +123,10 @@ export function calculateAllPaths(graph, config) {
}).run(graph)
result.paths.forEach((path, pathIndex) => {
- path.nodes.forEach(node => {
+ path.nodes.forEach((node) => {
markItem(node, pathIndex)
})
- path.edges.forEach(edge => {
+ path.edges.forEach((edge) => {
markItem(edge, pathIndex)
})
})
@@ -150,10 +150,10 @@ export function calculateAllChains(graph, config) {
const result = new Chains({ directed: config.directed }).run(graph)
result.chains.forEach((chain, pathIndex) => {
- chain.nodes.forEach(node => {
+ chain.nodes.forEach((node) => {
markItem(node, pathIndex)
})
- chain.edges.forEach(edge => {
+ chain.edges.forEach((edge) => {
markItem(edge, pathIndex)
})
})
@@ -202,11 +202,11 @@ export function calculateSingleSourceShortestPaths(graph, config) {
const predecessors = result.predecessors
result.paths
.orderBy(
- path => path.nodes.size,
+ (path) => path.nodes.size,
(p1, p2) => p1 - p2
)
.forEach((path, pathIndex) => {
- path.nodes.forEach(node => {
+ path.nodes.forEach((node) => {
const distance = distances.get(node) / longestPathLength
setComponent(node, pathIndex)
diff --git a/demos/showcase/graphanalysis/algorithms/paths.ts b/demos/showcase/graphanalysis/algorithms/paths.ts
index 946d8bf6b..e7212547d 100644
--- a/demos/showcase/graphanalysis/algorithms/paths.ts
+++ b/demos/showcase/graphanalysis/algorithms/paths.ts
@@ -68,10 +68,10 @@ export function calculatedShortestPaths(graph: IGraph, config: AlgorithmConfig):
sink: endNodes[0]
}).run(graph)
- result.nodes.forEach(node => {
+ result.nodes.forEach((node) => {
markItem(node)
})
- result.edges.forEach(edge => {
+ result.edges.forEach((edge) => {
markItem(edge)
})
} else {
@@ -83,10 +83,10 @@ export function calculatedShortestPaths(graph: IGraph, config: AlgorithmConfig):
}).run(graph)
result.paths.forEach((path, pathIndex) => {
- path.nodes.forEach(node => {
+ path.nodes.forEach((node) => {
markItem(node, pathIndex)
})
- path.edges.forEach(edge => {
+ path.edges.forEach((edge) => {
markItem(edge, pathIndex)
})
})
@@ -121,10 +121,10 @@ export function calculateAllPaths(graph: IGraph, config: AlgorithmConfig): void
}).run(graph)
result.paths.forEach((path, pathIndex) => {
- path.nodes.forEach(node => {
+ path.nodes.forEach((node) => {
markItem(node, pathIndex)
})
- path.edges.forEach(edge => {
+ path.edges.forEach((edge) => {
markItem(edge, pathIndex)
})
})
@@ -146,10 +146,10 @@ export function calculateAllChains(graph: IGraph, config: AlgorithmConfig): void
const result = new Chains({ directed: config.directed }).run(graph)
result.chains.forEach((chain, pathIndex) => {
- chain.nodes.forEach(node => {
+ chain.nodes.forEach((node) => {
markItem(node, pathIndex)
})
- chain.edges.forEach(edge => {
+ chain.edges.forEach((edge) => {
markItem(edge, pathIndex)
})
})
@@ -196,11 +196,11 @@ export function calculateSingleSourceShortestPaths(graph: IGraph, config: Algori
const predecessors = result.predecessors
result.paths
.orderBy(
- path => path.nodes.size,
+ (path) => path.nodes.size,
(p1, p2) => p1 - p2
)
.forEach((path, pathIndex) => {
- path.nodes.forEach(node => {
+ path.nodes.forEach((node) => {
const distance = distances.get(node)! / longestPathLength
setComponent(node, pathIndex)
diff --git a/demos/showcase/graphanalysis/algorithms/substructures.js b/demos/showcase/graphanalysis/algorithms/substructures.js
index a3d59969b..5b65c6d22 100644
--- a/demos/showcase/graphanalysis/algorithms/substructures.js
+++ b/demos/showcase/graphanalysis/algorithms/substructures.js
@@ -58,10 +58,10 @@ export function calculateChainSubstructures(graph, config) {
const substructures = chainSubstructures.run(graph)
substructures.chains.forEach((chain, chainIndex) => {
- chain.nodes.forEach(node => {
+ chain.nodes.forEach((node) => {
markItem(node, chainIndex)
})
- chain.edges.forEach(edge => {
+ chain.edges.forEach((edge) => {
markItem(edge, chainIndex)
})
})
@@ -92,10 +92,10 @@ export function calculateCycleSubstructures(graph, config) {
const substructures = cycleSubstructures.run(graph)
substructures.cycles.forEach((cycle, cycleIndex) => {
- cycle.nodes.forEach(node => {
+ cycle.nodes.forEach((node) => {
markItem(node, cycleIndex)
})
- cycle.edges.forEach(edge => {
+ cycle.edges.forEach((edge) => {
markItem(edge, cycleIndex)
})
})
@@ -124,10 +124,10 @@ export function calculateStarSubstructures(graph, config) {
const substructures = starSubstructures.run(graph)
substructures.stars.forEach((star, starIndex) => {
- star.nodes.forEach(node => {
+ star.nodes.forEach((node) => {
markItem(node, starIndex)
})
- star.edges.forEach(edge => {
+ star.edges.forEach((edge) => {
markItem(edge, starIndex)
})
})
@@ -155,10 +155,10 @@ export function calculateTreeSubstructures(graph, config) {
const substructures = treeSubstructures.run(graph)
substructures.trees.forEach((tree, treeIndex) => {
- tree.nodes.forEach(node => {
+ tree.nodes.forEach((node) => {
markItem(node, treeIndex)
})
- tree.edges.forEach(edge => {
+ tree.edges.forEach((edge) => {
markItem(edge, treeIndex)
})
})
@@ -185,10 +185,10 @@ export function calculateCliqueSubstructures(graph) {
const substructures = cliqueSubstructures.run(graph)
substructures.cliques.forEach((clique, cliqueIndex) => {
- clique.nodes.forEach(node => {
+ clique.nodes.forEach((node) => {
markItem(node, cliqueIndex)
})
- clique.edges.forEach(edge => {
+ clique.edges.forEach((edge) => {
markItem(edge, cliqueIndex)
})
})
diff --git a/demos/showcase/graphanalysis/algorithms/substructures.ts b/demos/showcase/graphanalysis/algorithms/substructures.ts
index 452023670..4ad0b5db2 100644
--- a/demos/showcase/graphanalysis/algorithms/substructures.ts
+++ b/demos/showcase/graphanalysis/algorithms/substructures.ts
@@ -58,10 +58,10 @@ export function calculateChainSubstructures(graph: IGraph, config: AlgorithmConf
const substructures = chainSubstructures.run(graph)
substructures.chains.forEach((chain, chainIndex) => {
- chain.nodes.forEach(node => {
+ chain.nodes.forEach((node) => {
markItem(node, chainIndex)
})
- chain.edges.forEach(edge => {
+ chain.edges.forEach((edge) => {
markItem(edge, chainIndex)
})
})
@@ -90,10 +90,10 @@ export function calculateCycleSubstructures(graph: IGraph, config: AlgorithmConf
const substructures = cycleSubstructures.run(graph)
substructures.cycles.forEach((cycle, cycleIndex) => {
- cycle.nodes.forEach(node => {
+ cycle.nodes.forEach((node) => {
markItem(node, cycleIndex)
})
- cycle.edges.forEach(edge => {
+ cycle.edges.forEach((edge) => {
markItem(edge, cycleIndex)
})
})
@@ -120,10 +120,10 @@ export function calculateStarSubstructures(graph: IGraph, config: AlgorithmConfi
const substructures = starSubstructures.run(graph)
substructures.stars.forEach((star, starIndex) => {
- star.nodes.forEach(node => {
+ star.nodes.forEach((node) => {
markItem(node, starIndex)
})
- star.edges.forEach(edge => {
+ star.edges.forEach((edge) => {
markItem(edge, starIndex)
})
})
@@ -149,10 +149,10 @@ export function calculateTreeSubstructures(graph: IGraph, config: AlgorithmConfi
const substructures = treeSubstructures.run(graph)
substructures.trees.forEach((tree, treeIndex) => {
- tree.nodes.forEach(node => {
+ tree.nodes.forEach((node) => {
markItem(node, treeIndex)
})
- tree.edges.forEach(edge => {
+ tree.edges.forEach((edge) => {
markItem(edge, treeIndex)
})
})
@@ -178,10 +178,10 @@ export function calculateCliqueSubstructures(graph: IGraph): void {
const substructures = cliqueSubstructures.run(graph)
substructures.cliques.forEach((clique, cliqueIndex) => {
- clique.nodes.forEach(node => {
+ clique.nodes.forEach((node) => {
markItem(node, cliqueIndex)
})
- clique.edges.forEach(edge => {
+ clique.edges.forEach((edge) => {
markItem(edge, cliqueIndex)
})
})
diff --git a/demos/showcase/graphanalysis/index.html b/demos/showcase/graphanalysis/index.html
index 4541ffcd6..db42a2eaf 100644
--- a/demos/showcase/graphanalysis/index.html
+++ b/demos/showcase/graphanalysis/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/demos/showcase/graphanalysis/layout/CentralityStage.js b/demos/showcase/graphanalysis/layout/CentralityStage.js
index 8e5e20abf..707d190fd 100644
--- a/demos/showcase/graphanalysis/layout/CentralityStage.js
+++ b/demos/showcase/graphanalysis/layout/CentralityStage.js
@@ -37,14 +37,6 @@ export class CentralityStage extends LayoutStageBase {
*/
directed = false
- /**
- * Creates a new instance of CentralityStage
- * @param {!ILayoutAlgorithm} layout
- */
- constructor(layout) {
- super(layout)
- }
-
/**
* Applies the layout to the given graph.
* @param {!LayoutGraph} graph the given graph
@@ -54,16 +46,16 @@ export class CentralityStage extends LayoutStageBase {
// change the node sizes if a centrality algorithm is applied
const isCentralityAlgorithm = graph.nodes.find(
- node => this.getTag(tags, node).centrality !== undefined
+ (node) => this.getTag(tags, node).centrality !== undefined
)
if (isCentralityAlgorithm) {
const mostCentralSize = 100
const leastCentralSize = 30
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nodeLayout = graph.getLayout(node)
let centralityId = this.getTag(tags, node).centrality
// centrality values are already normalized in [0,1]
- if (isNaN(centralityId)) {
+ if (Number.isNaN(centralityId)) {
centralityId = 0
}
const size = Math.floor(
@@ -72,7 +64,7 @@ export class CentralityStage extends LayoutStageBase {
nodeLayout.setSize(size, size)
})
} else {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nodeLayout = graph.getLayout(node)
nodeLayout.setSize(30, 30)
})
diff --git a/demos/showcase/graphanalysis/layout/CentralityStage.ts b/demos/showcase/graphanalysis/layout/CentralityStage.ts
index 636c6e127..33aa21429 100644
--- a/demos/showcase/graphanalysis/layout/CentralityStage.ts
+++ b/demos/showcase/graphanalysis/layout/CentralityStage.ts
@@ -45,13 +45,6 @@ export class CentralityStage extends LayoutStageBase {
*/
directed = false
- /**
- * Creates a new instance of CentralityStage
- */
- constructor(layout: ILayoutAlgorithm) {
- super(layout)
- }
-
/**
* Applies the layout to the given graph.
* @param graph the given graph
@@ -61,16 +54,16 @@ export class CentralityStage extends LayoutStageBase {
// change the node sizes if a centrality algorithm is applied
const isCentralityAlgorithm = graph.nodes.find(
- node => this.getTag(tags, node).centrality !== undefined
+ (node) => this.getTag(tags, node).centrality !== undefined
)
if (isCentralityAlgorithm) {
const mostCentralSize = 100
const leastCentralSize = 30
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nodeLayout = graph.getLayout(node)
let centralityId = this.getTag(tags, node).centrality!
// centrality values are already normalized in [0,1]
- if (isNaN(centralityId)) {
+ if (Number.isNaN(centralityId)) {
centralityId = 0
}
const size = Math.floor(
@@ -79,7 +72,7 @@ export class CentralityStage extends LayoutStageBase {
nodeLayout.setSize(size, size)
})
} else {
- graph.nodes.forEach(node => {
+ graph.nodes.forEach((node) => {
const nodeLayout = graph.getLayout(node)
nodeLayout.setSize(30, 30)
})
diff --git a/demos/showcase/graphanalysis/layout/layout.js b/demos/showcase/graphanalysis/layout/layout.js
index ceccf9135..19d50a2f5 100644
--- a/demos/showcase/graphanalysis/layout/layout.js
+++ b/demos/showcase/graphanalysis/layout/layout.js
@@ -79,7 +79,7 @@ function getOrganicLayoutConfiguration(affectedNodes) {
organicLayout.prependStage(new CentralityStage(organicLayout))
const organicLayoutData = new OrganicLayoutData({
- preferredEdgeLengths: edge =>
+ preferredEdgeLengths: (edge) =>
edge.labels.reduce((width, label) => {
return Math.max(label.layout.width + 50, width)
}, 100),
@@ -88,7 +88,7 @@ function getOrganicLayoutConfiguration(affectedNodes) {
})
const labelingData = new LabelingData({
- edgeLabelPreferredPlacement: label => {
+ edgeLabelPreferredPlacement: (label) => {
return new PreferredPlacementDescriptor({
sideOfEdge: label.tag === 'centrality' ? 'on-edge' : 'left-of-edge',
distanceToEdge: 5
diff --git a/demos/showcase/graphanalysis/layout/layout.ts b/demos/showcase/graphanalysis/layout/layout.ts
index 5f578a156..64754dfac 100644
--- a/demos/showcase/graphanalysis/layout/layout.ts
+++ b/demos/showcase/graphanalysis/layout/layout.ts
@@ -86,7 +86,7 @@ function getOrganicLayoutConfiguration(affectedNodes?: INode[] | undefined): {
organicLayout.prependStage(new CentralityStage(organicLayout))
const organicLayoutData = new OrganicLayoutData({
- preferredEdgeLengths: edge =>
+ preferredEdgeLengths: (edge) =>
edge.labels.reduce((width, label) => {
return Math.max(label.layout.width + 50, width)
}, 100),
diff --git a/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.js b/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.js
index 421731a59..f82f70503 100644
--- a/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.js
+++ b/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.js
@@ -362,7 +362,7 @@ class ComponentOverlayDescriptor extends BaseClass(
if (
visual.size === width &&
components.length === visual.components.size &&
- components.every(c => visual.components.has(c))
+ components.every((c) => visual.components.has(c))
) {
const g = visual.svgElement
diff --git a/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.ts b/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.ts
index 8d65f3c97..d4fd096a7 100644
--- a/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.ts
+++ b/demos/showcase/graphanalysis/ui/ComponentSwitchingInputMode.ts
@@ -343,7 +343,7 @@ class ComponentOverlayDescriptor extends BaseClass(
if (
visual.size === width &&
components.length === visual.components.size &&
- components.every(c => visual.components!.has(c))
+ components.every((c) => visual.components!.has(c))
) {
const g = visual.svgElement
diff --git a/demos/showcase/graphanalysis/ui/context-menu.js b/demos/showcase/graphanalysis/ui/context-menu.js
index 0fa1838bb..099f9ba8a 100644
--- a/demos/showcase/graphanalysis/ui/context-menu.js
+++ b/demos/showcase/graphanalysis/ui/context-menu.js
@@ -45,7 +45,7 @@ export function initializeContextMenu(inputMode, graphComponent) {
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback-function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
@@ -88,7 +88,7 @@ function populateContextMenu(graphComponent, contextMenu, args) {
// get the item which is located at the mouse position
const hits = graphComponent.graphModelManager.hitElementsAt(args.queryLocation).toArray()
// use the first hit node
- const hitNode = hits.find(hit => hit instanceof INode)
+ const hitNode = hits.find((hit) => hit instanceof INode)
const selection = graphComponent.selection
if (hitNode) {
selection.setSelected(hitNode, true)
@@ -104,7 +104,7 @@ function populateContextMenu(graphComponent, contextMenu, args) {
if (needsStartNodes) {
contextMenu.addMenuItem('Mark as Start Node', () => {
// clear previous start nodes
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
if (getTag(node).type === 'start') {
const tag = copyAndReplaceTag(node)
delete tag.type
@@ -116,7 +116,7 @@ function populateContextMenu(graphComponent, contextMenu, args) {
const tag = copyAndReplaceTag(hitNode || selectedNodes.first())
tag.type = 'start'
} else {
- selectedNodes.forEach(node => {
+ selectedNodes.forEach((node) => {
const tag = copyAndReplaceTag(node)
tag.type = 'start'
})
@@ -128,7 +128,7 @@ function populateContextMenu(graphComponent, contextMenu, args) {
}
if (needsEndNodes) {
contextMenu.addMenuItem('Mark as End Node', () => {
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
// clear previous end nodes
if (getTag(node).type === 'end') {
const tag = copyAndReplaceTag(node)
@@ -136,7 +136,7 @@ function populateContextMenu(graphComponent, contextMenu, args) {
}
})
- selectedNodes.forEach(node => {
+ selectedNodes.forEach((node) => {
const tag = copyAndReplaceTag(node)
tag.type = 'end'
})
diff --git a/demos/showcase/graphanalysis/ui/context-menu.ts b/demos/showcase/graphanalysis/ui/context-menu.ts
index 0c2fcdae9..33b030acc 100644
--- a/demos/showcase/graphanalysis/ui/context-menu.ts
+++ b/demos/showcase/graphanalysis/ui/context-menu.ts
@@ -54,7 +54,7 @@ export function initializeContextMenu(
// Add event listeners to the various events that open the context menu. These listeners then
// call the provided callback-function which in turn asks the current ContextMenuInputMode if a
// context menu should be shown at the current location.
- contextMenu.addOpeningEventListeners(graphComponent, location => {
+ contextMenu.addOpeningEventListeners(graphComponent, (location) => {
if (inputMode.contextMenuInputMode.shouldOpenMenu(graphComponent.toWorldFromPage(location))) {
contextMenu.show(location)
}
@@ -98,7 +98,7 @@ function populateContextMenu(
// get the item which is located at the mouse position
const hits = graphComponent.graphModelManager.hitElementsAt(args.queryLocation).toArray()
// use the first hit node
- const hitNode: IModelItem | undefined = hits.find(hit => hit instanceof INode)
+ const hitNode: IModelItem | undefined = hits.find((hit) => hit instanceof INode)
const selection = graphComponent.selection
if (hitNode) {
selection.setSelected(hitNode, true)
@@ -114,7 +114,7 @@ function populateContextMenu(
if (needsStartNodes) {
contextMenu.addMenuItem('Mark as Start Node', () => {
// clear previous start nodes
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
if (getTag(node).type === 'start') {
const tag = copyAndReplaceTag(node)
delete tag.type
@@ -126,7 +126,7 @@ function populateContextMenu(
const tag = copyAndReplaceTag(hitNode || selectedNodes.first())
tag.type = 'start'
} else {
- selectedNodes.forEach(node => {
+ selectedNodes.forEach((node) => {
const tag = copyAndReplaceTag(node)
tag.type = 'start'
})
@@ -138,7 +138,7 @@ function populateContextMenu(
}
if (needsEndNodes) {
contextMenu.addMenuItem('Mark as End Node', () => {
- graphComponent.graph.nodes.forEach(node => {
+ graphComponent.graph.nodes.forEach((node) => {
// clear previous end nodes
if (getTag(node).type === 'end') {
const tag = copyAndReplaceTag(node)
@@ -146,7 +146,7 @@ function populateContextMenu(
}
})
- selectedNodes.forEach(node => {
+ selectedNodes.forEach((node) => {
const tag = copyAndReplaceTag(node)
tag.type = 'end'
})
diff --git a/demos/showcase/graphanalysis/ui/graph-structure-information.js b/demos/showcase/graphanalysis/ui/graph-structure-information.js
index 28c76ce99..a917d72d5 100644
--- a/demos/showcase/graphanalysis/ui/graph-structure-information.js
+++ b/demos/showcase/graphanalysis/ui/graph-structure-information.js
@@ -36,24 +36,24 @@ import './graph-structure-information.css'
export function initializeGraphInformation(graphComponent) {
const inputMode = graphComponent.inputMode
- inputMode.addDeletingSelectionListener(async _ => {
+ inputMode.addDeletingSelectionListener(async (_) => {
updateGraphInformation(graphComponent)
})
- inputMode.addDeletedSelectionListener(async _ => {
+ inputMode.addDeletedSelectionListener(async (_) => {
updateGraphInformation(graphComponent)
})
// edge creation
- inputMode.createEdgeInputMode.addEdgeCreatedListener(async _ => {
+ inputMode.createEdgeInputMode.addEdgeCreatedListener(async (_) => {
updateGraphInformation(graphComponent)
})
- inputMode.addEdgePortsChangedListener(async _ => {
+ inputMode.addEdgePortsChangedListener(async (_) => {
updateGraphInformation(graphComponent)
})
- inputMode.addNodeCreatedListener(_ => {
+ inputMode.addNodeCreatedListener((_) => {
updateGraphInformation(graphComponent)
})
@@ -197,7 +197,7 @@ function updateNumberOfElements(graph, container) {
container.lastElementChild?.remove()
}
- ;['Nodes', 'Edges'].forEach(element => {
+ ;['Nodes', 'Edges'].forEach((element) => {
const row = document.createElement('div')
row.classList.add('row', 'bold')
container.appendChild(row)
@@ -226,7 +226,7 @@ function updateStructureAnalysis(graph, container) {
container.lastElementChild?.remove()
}
- structureAnalysis.forEach(algorithm => {
+ structureAnalysis.forEach((algorithm) => {
const row = document.createElement('div')
row.className = 'row'
container.appendChild(row)
diff --git a/demos/showcase/graphanalysis/ui/graph-structure-information.ts b/demos/showcase/graphanalysis/ui/graph-structure-information.ts
index aa025de9c..d0dd189b1 100644
--- a/demos/showcase/graphanalysis/ui/graph-structure-information.ts
+++ b/demos/showcase/graphanalysis/ui/graph-structure-information.ts
@@ -40,24 +40,24 @@ import './graph-structure-information.css'
export function initializeGraphInformation(graphComponent: GraphComponent): void {
const inputMode = graphComponent.inputMode as GraphEditorInputMode
- inputMode.addDeletingSelectionListener(async _ => {
+ inputMode.addDeletingSelectionListener(async (_) => {
updateGraphInformation(graphComponent)
})
- inputMode.addDeletedSelectionListener(async _ => {
+ inputMode.addDeletedSelectionListener(async (_) => {
updateGraphInformation(graphComponent)
})
// edge creation
- inputMode.createEdgeInputMode.addEdgeCreatedListener(async _ => {
+ inputMode.createEdgeInputMode.addEdgeCreatedListener(async (_) => {
updateGraphInformation(graphComponent)
})
- inputMode.addEdgePortsChangedListener(async _ => {
+ inputMode.addEdgePortsChangedListener(async (_) => {
updateGraphInformation(graphComponent)
})
- inputMode.addNodeCreatedListener(_ => {
+ inputMode.addNodeCreatedListener((_) => {
updateGraphInformation(graphComponent)
})
@@ -176,7 +176,7 @@ function updateNumberOfElements(graph: IGraph, container: HTMLDivElement): void
container.lastElementChild?.remove()
}
- ;['Nodes', 'Edges'].forEach(element => {
+ ;['Nodes', 'Edges'].forEach((element) => {
const row = document.createElement('div')
row.classList.add('row', 'bold')
container.appendChild(row)
@@ -203,7 +203,7 @@ function updateStructureAnalysis(graph: IGraph, container: Element): void {
container.lastElementChild?.remove()
}
- structureAnalysis.forEach(algorithm => {
+ structureAnalysis.forEach((algorithm) => {
const row = document.createElement('div')
row.className = 'row'
container.appendChild(row)
diff --git a/demos/showcase/graphanalysis/ui/ui-utils.js b/demos/showcase/graphanalysis/ui/ui-utils.js
index 2d12bff10..066d355ba 100644
--- a/demos/showcase/graphanalysis/ui/ui-utils.js
+++ b/demos/showcase/graphanalysis/ui/ui-utils.js
@@ -198,7 +198,7 @@ function loadGraph(graph, sample) {
edgeCreator.tagProvider = () => ({
components: []
})
- nodesSource.addSuccessorIds(item => item, edgeCreator)
+ nodesSource.addSuccessorIds((item) => item, edgeCreator)
graphBuilder.buildGraph()
}
@@ -231,7 +231,7 @@ async function switchAlgorithm(graphComponent) {
export function setUIDisabled(disabled, graphComponent) {
document
.querySelectorAll('.demo-page__toolbar select, .demo-page__toolbar button')
- .forEach(element => {
+ .forEach((element) => {
if (element instanceof HTMLSelectElement || element instanceof HTMLButtonElement) {
element.disabled = disabled
}
@@ -255,8 +255,8 @@ export function setUIDisabled(disabled, graphComponent) {
function deleteWeightLabels(graph) {
graph.edgeLabels
.toArray()
- .filter(label => label.tag === 'weight')
- .forEach(label => {
+ .filter((label) => label.tag === 'weight')
+ .forEach((label) => {
graph.remove(label)
})
}
@@ -266,7 +266,7 @@ function deleteWeightLabels(graph) {
* @param {!IGraph} graph
*/
function generateWeightLabels(graph) {
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
graph.addLabel({
owner: edge,
// select a weight from 1 to 20
diff --git a/demos/showcase/graphanalysis/ui/ui-utils.ts b/demos/showcase/graphanalysis/ui/ui-utils.ts
index 319d5a523..8483626c3 100644
--- a/demos/showcase/graphanalysis/ui/ui-utils.ts
+++ b/demos/showcase/graphanalysis/ui/ui-utils.ts
@@ -200,7 +200,7 @@ function loadGraph(graph: IGraph, sample: SampleData): void {
edgeCreator.defaults.style = graph.edgeDefaults.style
// add an array to each edge's tag to store the component to which it belongs
edgeCreator.tagProvider = (): Tag => ({ components: [] })
- nodesSource.addSuccessorIds(item => item, edgeCreator)
+ nodesSource.addSuccessorIds((item) => item, edgeCreator)
graphBuilder.buildGraph()
}
@@ -229,7 +229,7 @@ async function switchAlgorithm(graphComponent: GraphComponent): Promise {
export function setUIDisabled(disabled: boolean, graphComponent: GraphComponent): void {
document
.querySelectorAll('.demo-page__toolbar select, .demo-page__toolbar button')
- .forEach(element => {
+ .forEach((element) => {
if (element instanceof HTMLSelectElement || element instanceof HTMLButtonElement) {
element.disabled = disabled
}
@@ -252,8 +252,8 @@ export function setUIDisabled(disabled: boolean, graphComponent: GraphComponent)
function deleteWeightLabels(graph: IGraph): void {
graph.edgeLabels
.toArray()
- .filter(label => label.tag === 'weight')
- .forEach(label => {
+ .filter((label) => label.tag === 'weight')
+ .forEach((label) => {
graph.remove(label)
})
}
@@ -262,7 +262,7 @@ function deleteWeightLabels(graph: IGraph): void {
* Generates labels for each edge in the graph with a random weight.
*/
function generateWeightLabels(graph: IGraph): void {
- graph.edges.forEach(edge => {
+ graph.edges.forEach((edge) => {
graph.addLabel({
owner: edge,
// select a weight from 1 to 20
diff --git a/demos/showcase/home-automation/FlowEdge/FlowEdge.js b/demos/showcase/home-automation/FlowEdge/FlowEdge.js
new file mode 100644
index 000000000..7b6a8a645
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/FlowEdge.js
@@ -0,0 +1,231 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { CreateEdgeInputMode, GraphComponent, IGraph, INode, Point, YPoint } from 'yfiles'
+import './flowEdge.css'
+import { FlowPortRelocationHandleProvider } from './FlowPortRelocationHandleProvider.js'
+import { validatePortTag } from '../FlowNode/FlowNodePort.js'
+import { FlowEdgeStyle } from './FlowEdgeStyle.js'
+
+/**
+ * Modifies general edge-related settings on the graph component.
+ * @param {!GraphComponent} gc
+ */
+export function configureFlowEdges(gc) {
+ const { graph } = gc
+
+ graph.edgeDefaults.style = new FlowEdgeStyle()
+ graph.decorator.edgeDecorator.selectionDecorator.hideImplementation()
+ graph.decorator.edgeDecorator.highlightDecorator.hideImplementation()
+ graph.decorator.edgeDecorator.focusIndicatorDecorator.hideImplementation()
+
+ graph.decorator.edgeDecorator.edgePortHandleProviderDecorator.setFactory((edge) => {
+ return new FlowPortRelocationHandleProvider(graph, edge)
+ })
+}
+
+/**
+ * Calculates and applies custom edge bends.
+ * @param {!IGraph} graph
+ * @param {!INode} node
+ */
+export function recalculateEdges(graph, node) {
+ const affectedEdges = graph.edgesAt(node)
+ affectedEdges.forEach((edge) => {
+ const portTag = edge.sourcePort?.tag
+ if (!validatePortTag(portTag)) {
+ return
+ }
+ const fromSide = portTag.side
+ const bends = getSmoothEdgeControlPoints({
+ start: edge.sourcePort.location,
+ end: edge.targetPort.location,
+ fromSide
+ })
+
+ graph.clearBends(edge)
+ graph.addBends(edge, bends)
+ })
+}
+
+/**
+ * Modifies edge-related input mode settings.
+ * @param {!CreateEdgeInputMode} inputMode
+ */
+export function configureCreateEdgeInputMode(inputMode) {
+ inputMode.startOverCandidateOnly = true
+ inputMode.useHitItemsCandidatesOnly = false
+ inputMode.allowCreateBend = false
+
+ inputMode.addEdgeCreationStartedListener(({ inputModeContext, dummyEdgeGraph, dummyEdge }) => {
+ const gc = inputModeContext?.canvasComponent
+ if (!(gc instanceof GraphComponent)) {
+ return
+ }
+ // Clear any existing selection when a new edge is being created.
+ // This is for visual purposes: a node being selected affects the appearance
+ // of its connected edges, which makes the graph look very "busy".
+ gc.selection.clear()
+
+ dummyEdgeGraph.setStyle(dummyEdge, new FlowEdgeStyle('newEdge'))
+ })
+
+ inputMode.addEdgeCreatedListener(({ inputModeContext }, { item: edge }) => {
+ const gc = inputModeContext?.canvasComponent
+ if (!(gc instanceof GraphComponent)) {
+ return
+ }
+ gc.selection.setSelected(edge, true)
+ gc.graph.setStyle(edge, new FlowEdgeStyle())
+ })
+
+ inputMode.edgeCreator = (_, graph, sourcePortCandidate, targetPortCandidate, dummyEdge) => {
+ // Assign ports to constants to simplify references
+ let targetPort = targetPortCandidate.port
+ let sourcePort = sourcePortCandidate.port
+ const sourcePortSide = sourcePort?.tag.side
+ const targetPortSide = targetPort?.tag.side
+ if (sourcePortSide === 'left' && targetPortSide === 'right') {
+ const tempPort = targetPort
+ targetPort = sourcePort
+ sourcePort = tempPort
+ }
+ const portTag = sourcePort.tag
+ if (!validatePortTag(portTag)) {
+ return null
+ }
+ const fromSide = portTag.side
+
+ const bends = getSmoothEdgeControlPoints({
+ start: sourcePort.location.toPoint(),
+ end: targetPort.location.toPoint(),
+ fromSide
+ })
+ const edge = graph.createEdge(sourcePort, targetPort, dummyEdge.style)
+ graph.addBends(edge, bends)
+
+ // create the edge from the source port candidate to the new node
+ return edge
+ }
+}
+
+/**
+ * Calculates 2 cubic Bezier control points to create a smooth curve
+ * instead of a straight line segment when creating a new edge
+ * or reconnecting an existing one. This algorithm is also used to modify
+ * any edges connected to a node whose layout has changed.
+ *
+ * The shape of the resulting curve depends on both the relative position
+ * of the two endpoints and from which side (left/right)
+ * the edge is being plotted. The idea here is that the end portions
+ * of the resulting edge should curve away from the intended port for a moment.
+ * @param {!object} edge
+ * @returns {!Array.}
+ */
+export function getSmoothEdgeControlPoints(edge) {
+ // Minimum length between the endpoint and its corresponding control point.
+ // If too close to 0, edges that are close to vertical get almost no curve.
+ let minCPDisplacement = 36
+
+ // Maximum length between the endpoint and its corresponding control point.
+ // It must be capped, or otherwise plotting edges between very distant ports
+ // results in bends that go very far away from the ports (in extreme cases,
+ // beyond the graph viewport).
+ const maxCPDisplacement = 200
+
+ const start = new YPoint(edge.start.x, edge.start.y)
+ const end = new YPoint(edge.end.x, edge.end.y)
+ const displacement = YPoint.subtract(start, end)
+ const direction = { left: -1, right: 1 }[edge.fromSide]
+
+ // For extremely short edges, cap the max control point displacement
+ // depending on the distance between `start` and `end`:
+ minCPDisplacement = Math.min(minCPDisplacement, Math.abs(start.distanceTo(end)) / 2)
+
+ const cPDisplacementMagnitude = Math.max(
+ minCPDisplacement,
+ Math.min(maxCPDisplacement, Math.abs(displacement.x) / 2)
+ )
+
+ const controlPoints = [
+ new Point(start.x + direction * cPDisplacementMagnitude, start.y),
+ new Point(end.x - direction * cPDisplacementMagnitude, end.y)
+ ]
+
+ // Depending on the angle of the line segment (start, end), we may want to rotate (start, C1)
+ // and (C2, end) slightly. We ignore this angle for some time, meaning that for the most part,
+ // the derived angle will be 0 and have no effect.
+
+ const deadAngleZone = Math.PI * 0.75
+ const angleModifier = 0.5
+
+ let angle = direction === 1 ? getAngle(start, end) : getAngle(end, start)
+ const angleSign = Math.sign(angle)
+ angle = Math.abs(angle)
+ angle = Math.max(0, angle - deadAngleZone) * angleModifier
+ angle = angle * angleSign
+
+ // Apply the rotation, if any:
+ controlPoints[0] = rotateByAngle(start.toPoint(), controlPoints[0], angle)[1]
+ controlPoints[1] = rotateByAngle(end.toPoint(), controlPoints[1], angle)[1]
+
+ return controlPoints
+}
+
+/**
+ * Calculates the angle (in radians) between the line crossing points `a` and `b` and the horizontal line
+ * passing through `a`.
+ * @param {!YPoint} a
+ * @param {!YPoint} b
+ * @returns {number}
+ */
+function getAngle(a, b) {
+ const deltaY = b.y - a.y
+ const deltaX = b.x - a.x
+ return Math.atan2(deltaY, deltaX)
+}
+
+/**
+ * For a line segment (`a`, `b`), calculates a new line segment by applying
+ * the specified angle (in radians).
+ * @param {!Point} a
+ * @param {!Point} b
+ * @param {number} angle
+ * @returns {!Array.}
+ */
+function rotateByAngle(a, b, angle) {
+ const distanceAB = Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2)
+
+ const currentAngle = Math.atan2(b.y - a.y, b.x - a.x)
+ const newAngle = currentAngle + angle
+
+ const newX = a.x + distanceAB * Math.cos(newAngle)
+ const newY = a.y + distanceAB * Math.sin(newAngle)
+
+ return [a, new Point(newX, newY)]
+}
diff --git a/demos/showcase/home-automation/FlowEdge/FlowEdge.ts b/demos/showcase/home-automation/FlowEdge/FlowEdge.ts
new file mode 100644
index 000000000..116313595
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/FlowEdge.ts
@@ -0,0 +1,222 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { CreateEdgeInputMode, GraphComponent, IGraph, INode, Point, YPoint } from 'yfiles'
+import './flowEdge.css'
+import { FlowPortRelocationHandleProvider } from './FlowPortRelocationHandleProvider'
+import { validatePortTag } from '../FlowNode/FlowNodePort'
+import { FlowEdgeStyle } from './FlowEdgeStyle'
+
+/**
+ * Modifies general edge-related settings on the graph component.
+ */
+export function configureFlowEdges(gc: GraphComponent): void {
+ const { graph } = gc
+
+ graph.edgeDefaults.style = new FlowEdgeStyle()
+ graph.decorator.edgeDecorator.selectionDecorator.hideImplementation()
+ graph.decorator.edgeDecorator.highlightDecorator.hideImplementation()
+ graph.decorator.edgeDecorator.focusIndicatorDecorator.hideImplementation()
+
+ graph.decorator.edgeDecorator.edgePortHandleProviderDecorator.setFactory(edge => {
+ return new FlowPortRelocationHandleProvider(graph, edge)
+ })
+}
+
+/**
+ * Calculates and applies custom edge bends.
+ */
+export function recalculateEdges(graph: IGraph, node: INode): void {
+ const affectedEdges = graph.edgesAt(node)
+ affectedEdges.forEach(edge => {
+ const portTag = edge.sourcePort?.tag
+ if (!validatePortTag(portTag)) {
+ return
+ }
+ const fromSide = portTag.side
+ const bends = getSmoothEdgeControlPoints({
+ start: edge.sourcePort!.location,
+ end: edge.targetPort!.location,
+ fromSide
+ })
+
+ graph.clearBends(edge)
+ graph.addBends(edge, bends)
+ })
+}
+
+/**
+ * Modifies edge-related input mode settings.
+ */
+export function configureCreateEdgeInputMode(inputMode: CreateEdgeInputMode): void {
+ inputMode.startOverCandidateOnly = true
+ inputMode.useHitItemsCandidatesOnly = false
+ inputMode.allowCreateBend = false
+
+ inputMode.addEdgeCreationStartedListener(({ inputModeContext, dummyEdgeGraph, dummyEdge }) => {
+ const gc = inputModeContext?.canvasComponent
+ if (!(gc instanceof GraphComponent)) {
+ return
+ }
+ // Clear any existing selection when a new edge is being created.
+ // This is for visual purposes: a node being selected affects the appearance
+ // of its connected edges, which makes the graph look very "busy".
+ gc.selection.clear()
+
+ dummyEdgeGraph.setStyle(dummyEdge, new FlowEdgeStyle('newEdge'))
+ })
+
+ inputMode.addEdgeCreatedListener(({ inputModeContext }, { item: edge }) => {
+ const gc = inputModeContext?.canvasComponent
+ if (!(gc instanceof GraphComponent)) {
+ return
+ }
+ gc.selection.setSelected(edge, true)
+ gc.graph.setStyle(edge, new FlowEdgeStyle())
+ })
+
+ inputMode.edgeCreator = (_, graph, sourcePortCandidate, targetPortCandidate, dummyEdge) => {
+ // Assign ports to constants to simplify references
+ let targetPort = targetPortCandidate!.port!
+ let sourcePort = sourcePortCandidate.port!
+ const sourcePortSide = sourcePort?.tag.side
+ const targetPortSide = targetPort?.tag.side
+ if (sourcePortSide === 'left' && targetPortSide === 'right') {
+ const tempPort = targetPort
+ targetPort = sourcePort
+ sourcePort = tempPort
+ }
+ const portTag = sourcePort.tag
+ if (!validatePortTag(portTag)) {
+ return null
+ }
+ const fromSide = portTag.side
+
+ const bends = getSmoothEdgeControlPoints({
+ start: sourcePort.location.toPoint(),
+ end: targetPort.location.toPoint(),
+ fromSide
+ })
+ const edge = graph.createEdge(sourcePort, targetPort, dummyEdge.style)
+ graph.addBends(edge, bends)
+
+ // create the edge from the source port candidate to the new node
+ return edge
+ }
+}
+
+/**
+ * Calculates 2 cubic Bezier control points to create a smooth curve
+ * instead of a straight line segment when creating a new edge
+ * or reconnecting an existing one. This algorithm is also used to modify
+ * any edges connected to a node whose layout has changed.
+ *
+ * The shape of the resulting curve depends on both the relative position
+ * of the two endpoints and from which side (left/right)
+ * the edge is being plotted. The idea here is that the end portions
+ * of the resulting edge should curve away from the intended port for a moment.
+ */
+export function getSmoothEdgeControlPoints(edge: {
+ start: Readonly
+ end: Readonly
+ fromSide: 'left' | 'right'
+}): Array {
+ // Minimum length between the endpoint and its corresponding control point.
+ // If too close to 0, edges that are close to vertical get almost no curve.
+ let minCPDisplacement = 36
+
+ // Maximum length between the endpoint and its corresponding control point.
+ // It must be capped, or otherwise plotting edges between very distant ports
+ // results in bends that go very far away from the ports (in extreme cases,
+ // beyond the graph viewport).
+ const maxCPDisplacement = 200
+
+ const start = new YPoint(edge.start.x, edge.start.y)
+ const end = new YPoint(edge.end.x, edge.end.y)
+ const displacement = YPoint.subtract(start, end)
+ const direction = { left: -1, right: 1 }[edge.fromSide]
+
+ // For extremely short edges, cap the max control point displacement
+ // depending on the distance between `start` and `end`:
+ minCPDisplacement = Math.min(minCPDisplacement, Math.abs(start.distanceTo(end)) / 2)
+
+ const cPDisplacementMagnitude = Math.max(
+ minCPDisplacement,
+ Math.min(maxCPDisplacement, Math.abs(displacement.x) / 2)
+ )
+
+ const controlPoints = [
+ new Point(start.x + direction * cPDisplacementMagnitude, start.y),
+ new Point(end.x - direction * cPDisplacementMagnitude, end.y)
+ ]
+
+ // Depending on the angle of the line segment (start, end), we may want to rotate (start, C1)
+ // and (C2, end) slightly. We ignore this angle for some time, meaning that for the most part,
+ // the derived angle will be 0 and have no effect.
+
+ const deadAngleZone = Math.PI * 0.75
+ const angleModifier = 0.5
+
+ let angle = direction === 1 ? getAngle(start, end) : getAngle(end, start)
+ const angleSign = Math.sign(angle)
+ angle = Math.abs(angle)
+ angle = Math.max(0, angle - deadAngleZone) * angleModifier
+ angle = angle * angleSign
+
+ // Apply the rotation, if any:
+ controlPoints[0] = rotateByAngle(start.toPoint(), controlPoints[0], angle)[1]
+ controlPoints[1] = rotateByAngle(end.toPoint(), controlPoints[1], angle)[1]
+
+ return controlPoints
+}
+
+/**
+ * Calculates the angle (in radians) between the line crossing points `a` and `b` and the horizontal line
+ * passing through `a`.
+ */
+function getAngle(a: YPoint, b: YPoint): number {
+ const deltaY = b.y - a.y
+ const deltaX = b.x - a.x
+ return Math.atan2(deltaY, deltaX)
+}
+
+/**
+ * For a line segment (`a`, `b`), calculates a new line segment by applying
+ * the specified angle (in radians).
+ */
+function rotateByAngle(a: Point, b: Point, angle: number): [Point, Point] {
+ const distanceAB = Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2)
+
+ const currentAngle = Math.atan2(b.y - a.y, b.x - a.x)
+ const newAngle = currentAngle + angle
+
+ const newX = a.x + distanceAB * Math.cos(newAngle)
+ const newY = a.y + distanceAB * Math.sin(newAngle)
+
+ return [a, new Point(newX, newY)]
+}
diff --git a/demos/showcase/home-automation/FlowEdge/FlowEdgeStyle.js b/demos/showcase/home-automation/FlowEdge/FlowEdgeStyle.js
new file mode 100644
index 000000000..219025465
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/FlowEdgeStyle.js
@@ -0,0 +1,236 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ BezierEdgeStyle,
+ BezierEdgeStyleRenderer,
+ GeneralPath,
+ GraphComponent,
+ IRenderContext,
+ SvgVisualGroup,
+ Visual
+} from 'yfiles'
+
+/**
+ * This class decorates the original `BezierEdgeStyleRenderer` in such a way that the resulting
+ * SVG visuals stay almost the same, but gain an additional outline edge that follows
+ * the same curve as the original path. This way we don't need to re-implement any of the complex logic
+ * behind plotting cubic Beziér curves based on point data.
+ */
+class FlowEdgeRenderer extends BezierEdgeStyleRenderer {
+ /** @type {{container: 'flow-edge', basePath: 'flow-edge__main', outline: 'flow-edge__outline', animation: 'flow-edge__animation'}} */
+ static get cssClass() {
+ if (typeof FlowEdgeRenderer.$cssClass === 'undefined') {
+ FlowEdgeRenderer.$cssClass = {
+ container: 'flow-edge',
+ basePath: 'flow-edge__main',
+ outline: 'flow-edge__outline',
+ animation: 'flow-edge__animation'
+ }
+ }
+
+ return FlowEdgeRenderer.$cssClass
+ }
+
+ /** @type {{container: 'flow-edge', basePath: 'flow-edge__main', outline: 'flow-edge__outline', animation: 'flow-edge__animation'}} */
+ static set cssClass(cssClass) {
+ FlowEdgeRenderer.$cssClass = cssClass
+ }
+
+ /**
+ * @param {?Visual} visual
+ * @returns {?SVGGElement}
+ */
+ static getGroupElement(visual) {
+ if (!(visual instanceof SvgVisualGroup) || !(visual.svgElement instanceof SVGGElement)) {
+ return null
+ }
+ return visual.svgElement
+ }
+
+ /**
+ * Retrieves the created by the original `createVisual` implementation.
+ * @param {?Visual} visual
+ * @returns {?SVGPathElement}
+ */
+ static getOriginalPathElement(visual) {
+ if (!(visual instanceof SvgVisualGroup)) {
+ return null
+ }
+ const path = visual.svgElement.querySelector(
+ `path:not(.${FlowEdgeRenderer.cssClass.outline}):not(.${FlowEdgeRenderer.cssClass.animation})`
+ )
+ return path instanceof SVGPathElement ? path : null
+ }
+
+ /**
+ * Retrieves the outline created by our ` createVisual` override.
+ * @param {?Visual} visual
+ * @returns {?SVGPathElement}
+ */
+ static getPathOutlineElement(visual) {
+ if (!(visual instanceof SvgVisualGroup)) {
+ return null
+ }
+ const path = visual.svgElement.querySelector(`path.${FlowEdgeRenderer.cssClass.outline}`)
+ return path instanceof SVGPathElement ? path : null
+ }
+
+ /**
+ * Retrieves the animation created by our ` createVisual` override.
+ * @param {?Visual} visual
+ * @returns {?SVGPathElement}
+ */
+ static getPathAnimationElement(visual) {
+ if (!(visual instanceof SvgVisualGroup)) {
+ return null
+ }
+ const path = visual.svgElement.querySelector(`path.${FlowEdgeRenderer.cssClass.animation}`)
+ return path instanceof SVGPathElement ? path : null
+ }
+
+ isDummyNewEdge
+ isReconnecting
+
+ /**
+ * @param {!('newEdge'|'edgeReconnection')} [mode]
+ */
+ constructor(mode) {
+ super()
+ this.isDummyNewEdge = mode === 'newEdge'
+ this.isReconnecting = mode === 'edgeReconnection'
+ }
+
+ /**
+ * Applies BEM-style class modifiers to the provided element depending on the state
+ * of the edge.
+ * @param {!IRenderContext} context
+ * @param {!SVGElement} element
+ */
+ setClassModifiers(context, element) {
+ const gc = context.canvasComponent instanceof GraphComponent ? context.canvasComponent : null
+ const { sourceNode, targetNode } = this.edge
+
+ const isEdgeSelected = gc?.selection.isSelected(this.edge)
+ const isEdgeHovered = gc?.highlightIndicatorManager.selectionModel?.includes(this.edge)
+
+ const isConnectedNodeSelected =
+ (sourceNode && gc?.selection.isSelected(sourceNode)) ||
+ (targetNode && gc?.selection.isSelected(targetNode))
+
+ const modifiers = {
+ selected: isEdgeSelected,
+ 'connected-node-selected': isConnectedNodeSelected,
+ reversed: this.edge.sourcePort?.tag.side === 'left',
+ hovered: isEdgeHovered,
+ 'dummy-new-edge': this.isDummyNewEdge,
+ reconnecting: this.isReconnecting
+ }
+
+ for (const [modifier, enabled] of Object.entries(modifiers)) {
+ element.classList.toggle(
+ `${FlowEdgeRenderer.cssClass.container}--${modifier}`,
+ enabled ?? false
+ )
+ }
+ }
+
+ /**
+ * Takes whatever visual is created by `BezierEdgeStyleRenderer`,
+ * clones the `` element from its group, sets a slightly thicker stroke
+ * with a different color, and appends it to the top of the group so that
+ * it's displayed in the background. This creates a border effect along the path.
+ * @param {!IRenderContext} context
+ * @returns {?Visual}
+ */
+ createVisual(context) {
+ const visual = super.createVisual(context)
+ const groupElement = FlowEdgeRenderer.getGroupElement(visual)
+ const path = FlowEdgeRenderer.getOriginalPathElement(visual)
+ if (!groupElement || !path) {
+ return visual
+ }
+
+ this.setClassModifiers(context, groupElement)
+
+ const outline = path.cloneNode(true)
+ const animation = path.cloneNode(true)
+ path.insertAdjacentElement('beforebegin', outline)
+ path.insertAdjacentElement('afterend', animation)
+
+ groupElement.classList.add(FlowEdgeRenderer.cssClass.container)
+ path.classList.add(FlowEdgeRenderer.cssClass.basePath)
+ outline.classList.add(FlowEdgeRenderer.cssClass.outline)
+ animation.classList.add(FlowEdgeRenderer.cssClass.animation)
+
+ return visual
+ }
+
+ /**
+ * While updating the visual, we retrieve the extra outline added earlier
+ * and synchronize its path data with the original 's data.
+ * @param {!IRenderContext} context
+ * @param {?Visual} oldVisual
+ * @returns {?Visual}
+ */
+ updateVisual(context, oldVisual) {
+ const visual = super.updateVisual(context, oldVisual)
+ const groupElement = FlowEdgeRenderer.getGroupElement(visual)
+ const path = FlowEdgeRenderer.getOriginalPathElement(visual)
+ const outline = FlowEdgeRenderer.getPathOutlineElement(visual)
+ const animation = FlowEdgeRenderer.getPathAnimationElement(visual)
+
+ if (path && outline && animation) {
+ const pathData = path.getAttribute('d')
+ pathData && outline.setAttribute('d', pathData)
+ pathData && animation.setAttribute('d', pathData)
+ }
+
+ groupElement && this.setClassModifiers(context, groupElement)
+
+ return visual
+ }
+
+ /**
+ * @param {!GeneralPath} path
+ * @returns {!GeneralPath}
+ */
+ cropPath(path) {
+ return path
+ }
+}
+
+export class FlowEdgeStyle extends BezierEdgeStyle {
+ /**
+ * @param {!('newEdge'|'edgeReconnection')} [mode]
+ */
+ constructor(mode) {
+ const renderer = new FlowEdgeRenderer(mode)
+ super(renderer)
+ }
+}
diff --git a/demos/showcase/home-automation/FlowEdge/FlowEdgeStyle.ts b/demos/showcase/home-automation/FlowEdge/FlowEdgeStyle.ts
new file mode 100644
index 000000000..cd7febfc1
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/FlowEdgeStyle.ts
@@ -0,0 +1,197 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ BezierEdgeStyle,
+ BezierEdgeStyleRenderer,
+ GeneralPath,
+ GraphComponent,
+ IRenderContext,
+ SvgVisualGroup,
+ Visual
+} from 'yfiles'
+
+/**
+ * This class decorates the original `BezierEdgeStyleRenderer` in such a way that the resulting
+ * SVG visuals stay almost the same, but gain an additional outline edge that follows
+ * the same curve as the original path. This way we don't need to re-implement any of the complex logic
+ * behind plotting cubic Beziér curves based on point data.
+ */
+class FlowEdgeRenderer extends BezierEdgeStyleRenderer {
+ private static cssClass = {
+ container: 'flow-edge',
+ basePath: 'flow-edge__main',
+ outline: 'flow-edge__outline',
+ animation: 'flow-edge__animation'
+ }
+
+ private static getGroupElement(visual: Visual | null): SVGGElement | null {
+ if (!(visual instanceof SvgVisualGroup) || !(visual.svgElement instanceof SVGGElement)) {
+ return null
+ }
+ return visual.svgElement
+ }
+
+ /**
+ * Retrieves the created by the original `createVisual` implementation.
+ */
+ private static getOriginalPathElement(visual: Visual | null): SVGPathElement | null {
+ if (!(visual instanceof SvgVisualGroup)) {
+ return null
+ }
+ const path = visual.svgElement.querySelector(
+ `path:not(.${FlowEdgeRenderer.cssClass.outline}):not(.${FlowEdgeRenderer.cssClass.animation})`
+ )
+ return path instanceof SVGPathElement ? path : null
+ }
+
+ /**
+ * Retrieves the outline created by our ` createVisual` override.
+ */
+ private static getPathOutlineElement(visual: Visual | null): SVGPathElement | null {
+ if (!(visual instanceof SvgVisualGroup)) {
+ return null
+ }
+ const path = visual.svgElement.querySelector(`path.${FlowEdgeRenderer.cssClass.outline}`)
+ return path instanceof SVGPathElement ? path : null
+ }
+
+ /**
+ * Retrieves the animation created by our ` createVisual` override.
+ */
+ private static getPathAnimationElement(visual: Visual | null): SVGPathElement | null {
+ if (!(visual instanceof SvgVisualGroup)) {
+ return null
+ }
+ const path = visual.svgElement.querySelector(`path.${FlowEdgeRenderer.cssClass.animation}`)
+ return path instanceof SVGPathElement ? path : null
+ }
+
+ private readonly isDummyNewEdge: boolean
+ private readonly isReconnecting: boolean
+
+ constructor(mode?: 'newEdge' | 'edgeReconnection') {
+ super()
+ this.isDummyNewEdge = mode === 'newEdge'
+ this.isReconnecting = mode === 'edgeReconnection'
+ }
+
+ /**
+ * Applies BEM-style class modifiers to the provided element depending on the state
+ * of the edge.
+ */
+ private setClassModifiers(context: IRenderContext, element: SVGElement): void {
+ const gc = context.canvasComponent instanceof GraphComponent ? context.canvasComponent : null
+ const { sourceNode, targetNode } = this.edge
+
+ const isEdgeSelected = gc?.selection.isSelected(this.edge)
+ const isEdgeHovered = gc?.highlightIndicatorManager.selectionModel?.includes(this.edge)
+
+ const isConnectedNodeSelected =
+ (sourceNode && gc?.selection.isSelected(sourceNode)) ||
+ (targetNode && gc?.selection.isSelected(targetNode))
+
+ const modifiers = {
+ selected: isEdgeSelected,
+ 'connected-node-selected': isConnectedNodeSelected,
+ reversed: this.edge.sourcePort?.tag.side === 'left',
+ hovered: isEdgeHovered,
+ 'dummy-new-edge': this.isDummyNewEdge,
+ reconnecting: this.isReconnecting
+ }
+
+ for (const [modifier, enabled] of Object.entries(modifiers)) {
+ element.classList.toggle(
+ `${FlowEdgeRenderer.cssClass.container}--${modifier}`,
+ enabled ?? false
+ )
+ }
+ }
+
+ /**
+ * Takes whatever visual is created by `BezierEdgeStyleRenderer`,
+ * clones the `` element from its group, sets a slightly thicker stroke
+ * with a different color, and appends it to the top of the group so that
+ * it's displayed in the background. This creates a border effect along the path.
+ */
+ createVisual(context: IRenderContext): Visual | null {
+ const visual = super.createVisual(context)
+ const groupElement = FlowEdgeRenderer.getGroupElement(visual)
+ const path = FlowEdgeRenderer.getOriginalPathElement(visual)
+ if (!groupElement || !path) {
+ return visual
+ }
+
+ this.setClassModifiers(context, groupElement)
+
+ const outline = path.cloneNode(true) as SVGPathElement
+ const animation = path.cloneNode(true) as SVGPathElement
+ path.insertAdjacentElement('beforebegin', outline)
+ path.insertAdjacentElement('afterend', animation)
+
+ groupElement.classList.add(FlowEdgeRenderer.cssClass.container)
+ path.classList.add(FlowEdgeRenderer.cssClass.basePath)
+ outline.classList.add(FlowEdgeRenderer.cssClass.outline)
+ animation.classList.add(FlowEdgeRenderer.cssClass.animation)
+
+ return visual
+ }
+
+ /**
+ * While updating the visual, we retrieve the extra outline added earlier
+ * and synchronize its path data with the original 's data.
+ */
+ updateVisual(context: IRenderContext, oldVisual: Visual | null): Visual | null {
+ const visual = super.updateVisual(context, oldVisual)
+ const groupElement = FlowEdgeRenderer.getGroupElement(visual)
+ const path = FlowEdgeRenderer.getOriginalPathElement(visual)
+ const outline = FlowEdgeRenderer.getPathOutlineElement(visual)
+ const animation = FlowEdgeRenderer.getPathAnimationElement(visual)
+
+ if (path && outline && animation) {
+ const pathData = path.getAttribute('d')
+ pathData && outline.setAttribute('d', pathData)
+ pathData && animation.setAttribute('d', pathData)
+ }
+
+ groupElement && this.setClassModifiers(context, groupElement)
+
+ return visual
+ }
+
+ protected cropPath(path: GeneralPath): GeneralPath {
+ return path
+ }
+}
+
+export class FlowEdgeStyle extends BezierEdgeStyle {
+ constructor(mode?: 'newEdge' | 'edgeReconnection') {
+ const renderer = new FlowEdgeRenderer(mode)
+ super(renderer)
+ }
+}
diff --git a/demos/showcase/home-automation/FlowEdge/FlowPortRelocationHandleProvider.js b/demos/showcase/home-automation/FlowEdge/FlowPortRelocationHandleProvider.js
new file mode 100644
index 000000000..d6b2ea627
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/FlowPortRelocationHandleProvider.js
@@ -0,0 +1,153 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ IEdge,
+ IGraph,
+ IHandle,
+ IInputModeContext,
+ IPort,
+ IPortCandidate,
+ Point,
+ PortRelocationHandle,
+ PortRelocationHandleProvider,
+ Visualization
+} from 'yfiles'
+import { FlowEdgeStyle } from './FlowEdgeStyle.js'
+import { validatePortTag } from '../FlowNode/FlowNodePort.js'
+import { getSmoothEdgeControlPoints } from './FlowEdge.js'
+
+/**
+ * A handle provider that provides port relocation handles that look the same as the handles
+ * as during new edge creation.
+ */
+export class FlowPortRelocationHandleProvider extends PortRelocationHandleProvider {
+ /**
+ * @param {?IGraph} graph
+ * @param {!IEdge} edge
+ * @param {boolean} sourcePort
+ * @returns {?IHandle}
+ */
+ createPortRelocationHandle(graph, edge, sourcePort) {
+ if (!graph) {
+ return null
+ }
+ const portRelocationHandle = new FlowPortRelocationHandle(graph, edge, sourcePort)
+ portRelocationHandle.showHitPortOwnerCandidatesOnly = false
+ portRelocationHandle.addExistingPort = false
+ portRelocationHandle.visualization = Visualization.DUMMY
+ return portRelocationHandle
+ }
+}
+
+class FlowPortRelocationHandle extends PortRelocationHandle {
+ originalBendLocations = null
+ fixedPort = null
+ lastClosestPortCandidate = null
+
+ /**
+ * Store the port candidate so that the edge can visually snap to it.
+ * @param {?IPortCandidate} portCandidate
+ */
+ setClosestCandidate(portCandidate) {
+ super.setClosestCandidate(portCandidate)
+ this.lastClosestPortCandidate = portCandidate
+ }
+
+ /**
+ * To perform edge curve calculations later on, we need to identify which port
+ * is the one that's not going to change as a result of the reconnection process.
+ *
+ * We also store the original bends of the edge, so they can be restored
+ * if reconnection is canceled.
+ * @param {!IInputModeContext} context
+ */
+ initializeDrag(context) {
+ super.initializeDrag(context)
+ this.fixedPort = this.sourceEnd ? this.edge.targetPort : this.edge.sourcePort
+ this.originalBendLocations = this.edge.bends.map((bend) => bend.location.toPoint()).toArray()
+ this.getGraph(context)?.setStyle(this.edge, new FlowEdgeStyle('edgeReconnection'))
+ if (this.dummyEdge) {
+ this.dummyEdge.style = new FlowEdgeStyle('edgeReconnection')
+ }
+ }
+
+ /**
+ * On each position change, apply new edge bends. The visual result should be exactly the same
+ * as during creating a new edge.
+ * @param {!IInputModeContext} context
+ * @param {!Point} originalLocation
+ * @param {!Point} newLocation
+ */
+ handleMove(context, originalLocation, newLocation) {
+ super.handleMove(context, originalLocation, newLocation)
+
+ const { fixedPort, sourceEnd } = this
+ const fromSide = validatePortTag(fixedPort?.tag) ? fixedPort?.tag.side : null
+
+ const newVisualLocation = this.lastClosestPortCandidate?.port?.location ?? newLocation
+ const fixedPortLocation = fixedPort?.location
+
+ if (!fromSide || !fixedPortLocation) {
+ return
+ }
+
+ const oppositeSide = { left: 'right', right: 'left' }
+
+ const bends = getSmoothEdgeControlPoints({
+ start: sourceEnd ? newVisualLocation : fixedPortLocation,
+ end: sourceEnd ? fixedPortLocation : newVisualLocation,
+ fromSide: sourceEnd ? oppositeSide[fromSide] : fromSide
+ })
+
+ this.getGraph(context)?.clearBends(this.edge)
+ this.getGraph(context)?.addBends(this.edge, bends)
+ }
+
+ /**
+ * Restore the original edge bends that were saved earlier.
+ * @param {!IInputModeContext} context
+ * @param {!Point} originalLocation
+ */
+ cancelDrag(context, originalLocation) {
+ super.cancelDrag(context, originalLocation)
+ this.getGraph(context)?.clearBends(this.edge)
+ this.getGraph(context)?.addBends(this.edge, this.originalBendLocations)
+ }
+
+ /**
+ * Restore the standard, unmodified edge style.
+ * @param {!IInputModeContext} context
+ * @param {!Point} originalLocation
+ * @param {!Point} newLocation
+ */
+ dragFinished(context, originalLocation, newLocation) {
+ super.dragFinished(context, originalLocation, newLocation)
+ this.getGraph(context)?.setStyle(this.edge, new FlowEdgeStyle())
+ }
+}
diff --git a/demos/showcase/home-automation/FlowEdge/FlowPortRelocationHandleProvider.ts b/demos/showcase/home-automation/FlowEdge/FlowPortRelocationHandleProvider.ts
new file mode 100644
index 000000000..efab5260e
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/FlowPortRelocationHandleProvider.ts
@@ -0,0 +1,141 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ IEdge,
+ IGraph,
+ IHandle,
+ IInputModeContext,
+ IPort,
+ IPortCandidate,
+ Point,
+ PortRelocationHandle,
+ PortRelocationHandleProvider,
+ Visualization
+} from 'yfiles'
+import { FlowEdgeStyle } from './FlowEdgeStyle'
+import { validatePortTag } from '../FlowNode/FlowNodePort'
+import { getSmoothEdgeControlPoints } from './FlowEdge'
+
+/**
+ * A handle provider that provides port relocation handles that look the same as the handles
+ * as during new edge creation.
+ */
+export class FlowPortRelocationHandleProvider extends PortRelocationHandleProvider {
+ protected createPortRelocationHandle(
+ graph: IGraph | null,
+ edge: IEdge,
+ sourcePort: boolean
+ ): IHandle | null {
+ if (!graph) {
+ return null
+ }
+ const portRelocationHandle = new FlowPortRelocationHandle(graph, edge, sourcePort)
+ portRelocationHandle.showHitPortOwnerCandidatesOnly = false
+ portRelocationHandle.addExistingPort = false
+ portRelocationHandle.visualization = Visualization.DUMMY
+ return portRelocationHandle
+ }
+}
+
+class FlowPortRelocationHandle extends PortRelocationHandle {
+ private originalBendLocations: Array | null = null
+ private fixedPort: IPort | null = null
+ private lastClosestPortCandidate: IPortCandidate | null = null
+
+ /**
+ * Store the port candidate so that the edge can visually snap to it.
+ */
+ protected setClosestCandidate(portCandidate: IPortCandidate | null): void {
+ super.setClosestCandidate(portCandidate)
+ this.lastClosestPortCandidate = portCandidate
+ }
+
+ /**
+ * To perform edge curve calculations later on, we need to identify which port
+ * is the one that's not going to change as a result of the reconnection process.
+ *
+ * We also store the original bends of the edge, so they can be restored
+ * if reconnection is canceled.
+ */
+ initializeDrag(context: IInputModeContext): void {
+ super.initializeDrag(context)
+ this.fixedPort = this.sourceEnd ? this.edge.targetPort : this.edge.sourcePort
+ this.originalBendLocations = this.edge.bends.map(bend => bend.location.toPoint()).toArray()
+ this.getGraph(context)?.setStyle(this.edge, new FlowEdgeStyle('edgeReconnection'))
+ if (this.dummyEdge) {
+ this.dummyEdge.style = new FlowEdgeStyle('edgeReconnection')
+ }
+ }
+
+ /**
+ * On each position change, apply new edge bends. The visual result should be exactly the same
+ * as during creating a new edge.
+ */
+ handleMove(context: IInputModeContext, originalLocation: Point, newLocation: Point): void {
+ super.handleMove(context, originalLocation, newLocation)
+
+ const { fixedPort, sourceEnd } = this
+ const fromSide = validatePortTag(fixedPort?.tag) ? fixedPort?.tag.side : null
+
+ const newVisualLocation = this.lastClosestPortCandidate?.port?.location ?? newLocation
+ const fixedPortLocation = fixedPort?.location
+
+ if (!fromSide || !fixedPortLocation) {
+ return
+ }
+
+ const oppositeSide = { left: 'right', right: 'left' } as const
+
+ const bends = getSmoothEdgeControlPoints({
+ start: sourceEnd ? newVisualLocation : fixedPortLocation,
+ end: sourceEnd ? fixedPortLocation : newVisualLocation,
+ fromSide: sourceEnd ? oppositeSide[fromSide] : fromSide
+ })
+
+ this.getGraph(context)?.clearBends(this.edge)
+ this.getGraph(context)?.addBends(this.edge, bends)
+ }
+
+ /**
+ * Restore the original edge bends that were saved earlier.
+ */
+ cancelDrag(context: IInputModeContext, originalLocation: Point): void {
+ super.cancelDrag(context, originalLocation)
+ this.getGraph(context)?.clearBends(this.edge)
+ this.getGraph(context)?.addBends(this.edge, this.originalBendLocations!)
+ }
+
+ /**
+ * Restore the standard, unmodified edge style.
+ */
+ dragFinished(context: IInputModeContext, originalLocation: Point, newLocation: Point): void {
+ super.dragFinished(context, originalLocation, newLocation)
+ this.getGraph(context)?.setStyle(this.edge, new FlowEdgeStyle())
+ }
+}
diff --git a/demos/showcase/home-automation/FlowEdge/flowEdge.css b/demos/showcase/home-automation/FlowEdge/flowEdge.css
new file mode 100644
index 000000000..fe2cea168
--- /dev/null
+++ b/demos/showcase/home-automation/FlowEdge/flowEdge.css
@@ -0,0 +1,104 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+.flow-edge {
+}
+
+.flow-edge__main {
+ stroke-width: 2;
+ transition:
+ opacity 0.4s,
+ stroke 0.2s;
+ stroke: rgb(153, 153, 153);
+}
+
+.flow-edge__outline {
+ stroke-width: 4;
+ stroke: rgb(153, 153, 153);
+}
+
+.flow-edge__animation {
+ opacity: 0;
+ stroke-width: 2;
+ transition: opacity 0.4s;
+ stroke: rgb(255, 255, 255);
+ stroke-dasharray: 5;
+ stroke-dashoffset: 0;
+ animation: marquee 0.5s linear infinite;
+}
+
+.flow-edge--reversed .flow-edge__animation {
+ animation: marquee-reversed 0.5s linear infinite;
+}
+
+@keyframes marquee {
+ to {
+ stroke-dashoffset: -10;
+ }
+}
+
+@keyframes marquee-reversed {
+ to {
+ stroke-dashoffset: 10;
+ }
+}
+
+/* Existing edge is hovered */
+
+.flow-edge--hovered .flow-edge__main {
+ stroke: rgb(93, 93, 93);
+}
+
+/* Existing edge is selected OR edge is being reconnected */
+
+.flow-edge--selected .flow-edge__main,
+.flow-edge--reconnecting .flow-edge__main {
+ stroke: rgb(255, 108, 0);
+}
+
+/* New edge is being created */
+
+.flow-edge--dummy-new-edge .flow-edge__main {
+ stroke: rgb(255, 108, 0);
+}
+
+.flow-edge--dummy-new-edge .flow-edge__animation {
+ opacity: 1;
+}
+
+/* Connected node is selected OR edge is selected & hovered */
+
+.flow-edge--selected.flow-edge--hovered .flow-edge__main,
+.flow-edge--connected-node-selected .flow-edge__main {
+ stroke: rgb(255, 108, 0);
+}
+
+.flow-edge--selected.flow-edge--hovered .flow-edge__animation,
+.flow-edge--connected-node-selected .flow-edge__animation {
+ opacity: 1;
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowEdgeReconnectionPortCandidateProvider.js b/demos/showcase/home-automation/FlowNode/FlowEdgeReconnectionPortCandidateProvider.js
new file mode 100644
index 000000000..844d0c2a2
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowEdgeReconnectionPortCandidateProvider.js
@@ -0,0 +1,123 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ List,
+ BaseClass,
+ IEnumerable,
+ IPortCandidate,
+ IInputModeContext,
+ IEdgeReconnectionPortCandidateProvider,
+ IEdge,
+ DefaultPortCandidate,
+ PortCandidateValidity
+} from 'yfiles'
+
+export class FlowEdgeReconnectionPortCandidateProvider extends BaseClass(
+ IEdgeReconnectionPortCandidateProvider
+) {
+ edge
+
+ /**
+ * @param {!IEdge} edge
+ */
+ constructor(edge) {
+ super()
+ this.edge = edge
+ }
+
+ /**
+ * @param {!IInputModeContext} undefined
+ * @returns {!IEnumerable.}
+ */
+ getSourcePortCandidates({ graph }) {
+ const { edge } = this
+ const candidates = new List()
+ if (!graph) {
+ return candidates
+ }
+
+ graph.ports
+ // Exclude right-side port on the edge's source node:
+ .filter((port) => port.owner !== edge.targetNode)
+ // Exclude any right-side ports
+ .filter((port) => port.tag.side !== 'left')
+ // Exclude source ports that the edge's target node already connects to:
+ .filter(
+ (port) =>
+ !graph.edges.some(
+ (otherEdge) =>
+ otherEdge !== edge &&
+ otherEdge.targetPort === edge.targetPort &&
+ otherEdge.sourcePort === port
+ )
+ )
+ .forEach((port) => {
+ const portCandidate = new DefaultPortCandidate(port)
+ portCandidate.validity = PortCandidateValidity.VALID
+ candidates.add(portCandidate)
+ })
+
+ return candidates
+ }
+
+ /**
+ * @param {!IInputModeContext} undefined
+ * @returns {!IEnumerable.}
+ */
+ getTargetPortCandidates({ graph }) {
+ const { edge } = this
+ const candidates = new List()
+ if (!graph) {
+ return candidates
+ }
+
+ graph.ports
+ // Exclude left-side port on the edge's source node:
+ .filter((port) => port.owner !== edge.sourceNode)
+ // Exclude any right-side ports
+ .filter((port) => port.tag.side !== 'right')
+ // Exclude target ports that the edge's source node already connects to:
+ .filter(
+ (port) =>
+ !graph.edges.some(
+ (otherEdge) =>
+ otherEdge !== edge &&
+ otherEdge.sourcePort === edge.sourcePort &&
+ otherEdge.targetPort === port
+ )
+ )
+ .forEach((port) => {
+ const portCandidate = new DefaultPortCandidate(port)
+ portCandidate.validity = PortCandidateValidity.VALID
+ candidates.add(portCandidate)
+ })
+
+ return candidates
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowEdgeReconnectionPortCandidateProvider.ts b/demos/showcase/home-automation/FlowNode/FlowEdgeReconnectionPortCandidateProvider.ts
new file mode 100644
index 000000000..27e44af6e
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowEdgeReconnectionPortCandidateProvider.ts
@@ -0,0 +1,113 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ List,
+ BaseClass,
+ IEnumerable,
+ IPortCandidate,
+ IInputModeContext,
+ IEdgeReconnectionPortCandidateProvider,
+ IEdge,
+ DefaultPortCandidate,
+ PortCandidateValidity
+} from 'yfiles'
+
+export class FlowEdgeReconnectionPortCandidateProvider
+ extends BaseClass(IEdgeReconnectionPortCandidateProvider)
+ implements IEdgeReconnectionPortCandidateProvider
+{
+ private edge: IEdge
+
+ constructor(edge: IEdge) {
+ super()
+ this.edge = edge
+ }
+
+ getSourcePortCandidates({ graph }: IInputModeContext): IEnumerable {
+ const { edge } = this
+ const candidates = new List()
+ if (!graph) {
+ return candidates
+ }
+
+ graph.ports
+ // Exclude right-side port on the edge's source node:
+ .filter(port => port.owner !== edge.targetNode)
+ // Exclude any right-side ports
+ .filter(port => port.tag.side !== 'left')
+ // Exclude source ports that the edge's target node already connects to:
+ .filter(
+ port =>
+ !graph.edges.some(
+ otherEdge =>
+ otherEdge !== edge &&
+ otherEdge.targetPort === edge.targetPort &&
+ otherEdge.sourcePort === port
+ )
+ )
+ .forEach(port => {
+ const portCandidate = new DefaultPortCandidate(port)
+ portCandidate.validity = PortCandidateValidity.VALID
+ candidates.add(portCandidate)
+ })
+
+ return candidates
+ }
+
+ getTargetPortCandidates({ graph }: IInputModeContext): IEnumerable {
+ const { edge } = this
+ const candidates = new List()
+ if (!graph) {
+ return candidates
+ }
+
+ graph.ports
+ // Exclude left-side port on the edge's source node:
+ .filter(port => port.owner !== edge.sourceNode)
+ // Exclude any right-side ports
+ .filter(port => port.tag.side !== 'right')
+ // Exclude target ports that the edge's source node already connects to:
+ .filter(
+ port =>
+ !graph.edges.some(
+ otherEdge =>
+ otherEdge !== edge &&
+ otherEdge.sourcePort === edge.sourcePort &&
+ otherEdge.targetPort === port
+ )
+ )
+ .forEach(port => {
+ const portCandidate = new DefaultPortCandidate(port)
+ portCandidate.validity = PortCandidateValidity.VALID
+ candidates.add(portCandidate)
+ })
+
+ return candidates
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNode.js b/demos/showcase/home-automation/FlowNode/FlowNode.js
new file mode 100644
index 000000000..af7aa7644
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNode.js
@@ -0,0 +1,216 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { FreeNodePortLocationModel, GraphComponent, IGraph, INode, Point, SimpleNode } from 'yfiles'
+import { FlowNodePortStyle } from './FlowNodePortStyle.js'
+import { FlowNodeStyle } from './FlowNodeStyle.js'
+import { flowNodeProperties } from './flowNodeProperties.js'
+
+export const flowNodeVariants = [
+ 'storageWriteFile',
+ 'storageReadFile',
+ 'parserCsv',
+ 'parserJson',
+ 'parserXml',
+ 'sequenceSort',
+ 'sequenceJoin',
+ 'networkTcpIn',
+ 'networkTcpOut',
+ 'networkTcpRequest',
+ 'functionFunction',
+ 'functionDelay',
+ 'functionFilter',
+ 'commonComment',
+ 'commonLinkIn',
+ 'commonLinkOut',
+ 'commonLinkCall',
+ 'commonStatus'
+]
+/**
+ * @typedef {*} FlowNodeVariant
+ */
+/**
+ * @typedef {Object} FlowNodeValidation
+ * @property {Array.} invalidProperties
+ * @property {Array.} validationMessages
+ */
+/**
+ * @typedef {function} FlowNodeValidationFn
+ */
+
+/**
+ * @typedef {Object} FlowNodeProperties
+ * @property {FlowNodeVariant} variant
+ * @property {string} label
+ * @property {boolean} hasLeftPort
+ * @property {boolean} hasRightPort
+ * @property {FlowNodeValidationFn} [validate]
+ */
+
+/**
+ * @typedef {*} FlowNode
+ */
+
+/**
+ * @typedef {Object} FlowNodeInGraphOptions
+ * @property {FlowNodeVariant} variant
+ * @property {Point} position
+ * @property {IGraph} graph
+ */
+
+/**
+ * Properties that should never appear in the tag editor
+ */
+export let hiddenProperties = ['hasLeftPort', 'hasRightPort', 'validate']
+export let lockedProperties = ['variant']
+
+const portStyle = new FlowNodePortStyle()
+
+/**
+ * Modifies node-related graph configuration.
+ * @param {!GraphComponent} undefined
+ */
+export function configureFlowNodes({ graph, selection }) {
+ graph.decorator.nodeDecorator.focusIndicatorDecorator.hideImplementation()
+ graph.decorator.nodeDecorator.highlightDecorator.hideImplementation()
+ graph.decorator.nodeDecorator.selectionDecorator.hideImplementation()
+
+ // When a new node appears in the graph, its ports are added automatically. This is done
+ // in reaction to `NodeCreated` event so that nodes added from the DnD palette, which doesn't
+ // handle nodes with ports correctly, end up having their ports properly configured as soon as
+ // they're dropped onto the main graph.
+ graph.addNodeCreatedListener((_sender, event) => {
+ const node = event.item
+ if (!isFlowNode(node)) {
+ return
+ }
+ const { hasLeftPort, hasRightPort } = node.tag
+ if (node.ports.size === 0) {
+ hasLeftPort &&
+ graph.addPort({
+ owner: node,
+ style: portStyle,
+ locationParameter: FreeNodePortLocationModel.NODE_LEFT_ANCHORED,
+ tag: {
+ side: 'left'
+ }
+ })
+ hasRightPort &&
+ graph.addPort({
+ owner: node,
+ style: portStyle,
+ locationParameter: FreeNodePortLocationModel.NODE_RIGHT_ANCHORED,
+ tag: {
+ side: 'right'
+ }
+ })
+ }
+ const label = node.tag.label
+ const duplicateLabelNodes = graph.nodes.filter((node) => node.tag.label.startsWith(label))
+ if (!!label && duplicateLabelNodes.size > 1) {
+ const lastLabelNumber = duplicateLabelNodes
+ .toArray()
+ .map((node) => node.tag.label.split('#')[1] || '0')
+ .map((value) => Number.parseInt(value))
+ .sort((a, b) => b - a)[0]
+ node.tag = { ...node.tag, label: label + ` #${lastLabelNumber + 1}` }
+ }
+
+ selection.clear()
+ selection.setSelected(node, true)
+ })
+}
+
+/**
+ * Creates a FlowNode and adds it to the graph at the specified position.
+ * Ports will be added automatically on node creation.
+ * @param {!FlowNodeInGraphOptions} undefined
+ * @returns {!FlowNode}
+ */
+export function createInGraph({ variant, position, graph }) {
+ const properties = { ...flowNodeProperties[variant] }
+ return graph.createNode({
+ style: new FlowNodeStyle(),
+ layout: {
+ width: FlowNodeStyle.defaultWidth,
+ height: FlowNodeStyle.defaultHeight,
+ x: position.x,
+ y: position.y
+ },
+ tag: properties
+ })
+}
+
+/**
+ * Creates a graph-less FlowNode without ports (but dummy port visuals will still be rendered
+ * as part of the node visual).
+ * @param {!FlowNodeVariant} variant
+ * @returns {!FlowNode}
+ */
+export function createFlowNode(variant) {
+ const properties = { ...flowNodeProperties[variant] }
+ return new SimpleNode({
+ style: new FlowNodeStyle(),
+ layout: {
+ width: FlowNodeStyle.defaultWidth,
+ height: FlowNodeStyle.defaultHeight,
+ x: 0,
+ y: 0
+ },
+ tag: properties
+ })
+}
+
+/**
+ * @param {!unknown} node
+ * @returns {!FlowNode}
+ */
+export function assertIsFlowNode(node) {
+ if (!isFlowNode(node)) {
+ throw new Error('Node not satisfy type FlowNode')
+ }
+}
+
+/**
+ * @param {!unknown} node
+ * @returns {!FlowNode}
+ */
+export function isFlowNode(node) {
+ if (!(node instanceof INode)) {
+ return false
+ }
+ return validateNodeTag(node.tag)
+}
+
+/**
+ * @param {!unknown} tag
+ * @returns {!FlowNodeProperties}
+ */
+export function validateNodeTag(tag) {
+ return typeof tag === 'object' && tag !== null && flowNodeVariants.includes(tag.variant)
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNode.ts b/demos/showcase/home-automation/FlowNode/FlowNode.ts
new file mode 100644
index 000000000..3e1065483
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNode.ts
@@ -0,0 +1,200 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { FreeNodePortLocationModel, GraphComponent, IGraph, INode, Point, SimpleNode } from 'yfiles'
+import { type FlowNodePortProperties } from './FlowNodePort'
+import { FlowNodePortStyle } from './FlowNodePortStyle'
+import { FlowNodeStyle } from './FlowNodeStyle'
+import { flowNodeProperties } from './flowNodeProperties'
+
+export const flowNodeVariants = [
+ 'storageWriteFile',
+ 'storageReadFile',
+ 'parserCsv',
+ 'parserJson',
+ 'parserXml',
+ 'sequenceSort',
+ 'sequenceJoin',
+ 'networkTcpIn',
+ 'networkTcpOut',
+ 'networkTcpRequest',
+ 'functionFunction',
+ 'functionDelay',
+ 'functionFilter',
+ 'commonComment',
+ 'commonLinkIn',
+ 'commonLinkOut',
+ 'commonLinkCall',
+ 'commonStatus'
+]
+export type FlowNodeVariant = (typeof flowNodeVariants)[number]
+export type FlowNodeValidation = {
+ invalidProperties: Array
+ validationMessages: Array
+}
+export type FlowNodeValidationFn = (args: FlowNodeProperties) => FlowNodeValidation
+
+export type FlowNodeProperties = {
+ readonly variant: FlowNodeVariant
+ label: string
+ hasLeftPort: boolean
+ hasRightPort: boolean
+ validate?: FlowNodeValidationFn
+ [key: string]: string | number | boolean | undefined | Array | FlowNodeValidationFn
+}
+
+export type FlowNode = Omit & { tag: FlowNodeProperties }
+
+type FlowNodeInGraphOptions = {
+ variant: FlowNodeVariant
+ position: Point
+ graph: IGraph
+}
+
+/**
+ * Properties that should never appear in the tag editor
+ */
+export let hiddenProperties: Array = [
+ 'hasLeftPort',
+ 'hasRightPort',
+ 'validate'
+]
+export let lockedProperties: Array = ['variant']
+
+const portStyle = new FlowNodePortStyle()
+
+/**
+ * Modifies node-related graph configuration.
+ */
+export function configureFlowNodes({ graph, selection }: GraphComponent): void {
+ graph.decorator.nodeDecorator.focusIndicatorDecorator.hideImplementation()
+ graph.decorator.nodeDecorator.highlightDecorator.hideImplementation()
+ graph.decorator.nodeDecorator.selectionDecorator.hideImplementation()
+
+ // When a new node appears in the graph, its ports are added automatically. This is done
+ // in reaction to `NodeCreated` event so that nodes added from the DnD palette, which doesn't
+ // handle nodes with ports correctly, end up having their ports properly configured as soon as
+ // they're dropped onto the main graph.
+ graph.addNodeCreatedListener((_sender, event) => {
+ const node = event.item
+ if (!isFlowNode(node)) {
+ return
+ }
+ const { hasLeftPort, hasRightPort } = node.tag
+ if (node.ports.size === 0) {
+ hasLeftPort &&
+ graph.addPort({
+ owner: node,
+ style: portStyle,
+ locationParameter: FreeNodePortLocationModel.NODE_LEFT_ANCHORED,
+ tag: {
+ side: 'left'
+ } as FlowNodePortProperties
+ })
+ hasRightPort &&
+ graph.addPort({
+ owner: node,
+ style: portStyle,
+ locationParameter: FreeNodePortLocationModel.NODE_RIGHT_ANCHORED,
+ tag: {
+ side: 'right'
+ } as FlowNodePortProperties
+ })
+ }
+ const label = node.tag.label
+ const duplicateLabelNodes = graph.nodes.filter(node => node.tag.label.startsWith(label))
+ if (!!label && duplicateLabelNodes.size > 1) {
+ const lastLabelNumber = duplicateLabelNodes
+ .toArray()
+ .map(node => node.tag.label.split('#')[1] || '0')
+ .map(value => Number.parseInt(value))
+ .sort((a, b) => b - a)[0]
+ node.tag = { ...node.tag, label: label + ` #${lastLabelNumber + 1}` }
+ }
+
+ selection.clear()
+ selection.setSelected(node, true)
+ })
+}
+
+/**
+ * Creates a FlowNode and adds it to the graph at the specified position.
+ * Ports will be added automatically on node creation.
+ */
+export function createInGraph({ variant, position, graph }: FlowNodeInGraphOptions): FlowNode {
+ const properties = { ...flowNodeProperties[variant] }
+ return graph.createNode({
+ style: new FlowNodeStyle(),
+ layout: {
+ width: FlowNodeStyle.defaultWidth,
+ height: FlowNodeStyle.defaultHeight,
+ x: position.x,
+ y: position.y
+ },
+ tag: properties
+ })
+}
+
+/**
+ * Creates a graph-less FlowNode without ports (but dummy port visuals will still be rendered
+ * as part of the node visual).
+ */
+export function createFlowNode(variant: FlowNodeVariant): FlowNode {
+ const properties = { ...flowNodeProperties[variant] }
+ return new SimpleNode({
+ style: new FlowNodeStyle(),
+ layout: {
+ width: FlowNodeStyle.defaultWidth,
+ height: FlowNodeStyle.defaultHeight,
+ x: 0,
+ y: 0
+ },
+ tag: properties
+ })
+}
+
+export function assertIsFlowNode(node: unknown): asserts node is FlowNode {
+ if (!isFlowNode(node)) {
+ throw new Error('Node not satisfy type FlowNode')
+ }
+}
+
+export function isFlowNode(node: unknown): node is FlowNode {
+ if (!(node instanceof INode)) {
+ return false
+ }
+ return validateNodeTag(node.tag)
+}
+
+export function validateNodeTag(tag: unknown): tag is FlowNodeProperties {
+ return (
+ typeof tag === 'object' &&
+ tag !== null &&
+ flowNodeVariants.includes((tag).variant)
+ )
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodePort.js b/demos/showcase/home-automation/FlowNode/FlowNodePort.js
new file mode 100644
index 000000000..a0444741c
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodePort.js
@@ -0,0 +1,74 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { GraphComponent, PortLayerPolicy } from 'yfiles'
+import { FlowNodePortCandidateProvider } from './FlowNodePortCandidateProvider.js'
+import { FlowEdgeReconnectionPortCandidateProvider } from './FlowEdgeReconnectionPortCandidateProvider.js'
+
+/**
+ * @typedef {Object} FlowNodePortProperties
+ * @property {('left'|'right')} side
+ */
+
+/**
+ * Modifies port-related graph configuration.
+ * @param {!GraphComponent} gc
+ */
+export function configureFlowNodePorts(gc) {
+ gc.graphModelManager.portLayerPolicy = PortLayerPolicy.AT_OWNER
+ gc.graph.nodeDefaults.ports.autoCleanUp = false
+ gc.graph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
+ (node) => new FlowNodePortCandidateProvider(node)
+ )
+ gc.graph.decorator.edgeDecorator.edgeReconnectionPortCandidateProviderDecorator.setFactory(
+ (edge) => new FlowEdgeReconnectionPortCandidateProvider(edge)
+ )
+}
+
+/**
+ * @param {!unknown} tag
+ * @returns {!FlowNodePortProperties}
+ */
+export function assertPortTag(tag) {
+ if (validatePortTag(tag)) {
+ return
+ } else {
+ throw new Error('Tag value does not satisfy type FlowNodePortProperties')
+ }
+}
+
+/**
+ * @param {!unknown} tag
+ * @returns {!FlowNodePortProperties}
+ */
+export function validatePortTag(tag) {
+ return (
+ (typeof tag === 'object' && tag !== null && 'side' in tag && tag.side === 'left') ||
+ tag.side === 'right'
+ )
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodePort.ts b/demos/showcase/home-automation/FlowNode/FlowNodePort.ts
new file mode 100644
index 000000000..789e9d644
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodePort.ts
@@ -0,0 +1,67 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { GraphComponent, PortLayerPolicy } from 'yfiles'
+import { FlowNodePortCandidateProvider } from './FlowNodePortCandidateProvider'
+import { FlowEdgeReconnectionPortCandidateProvider } from './FlowEdgeReconnectionPortCandidateProvider'
+
+export type FlowNodePortProperties = {
+ side: 'left' | 'right'
+}
+
+/**
+ * Modifies port-related graph configuration.
+ */
+export function configureFlowNodePorts(gc: GraphComponent): void {
+ gc.graphModelManager.portLayerPolicy = PortLayerPolicy.AT_OWNER
+ gc.graph.nodeDefaults.ports.autoCleanUp = false
+ gc.graph.decorator.nodeDecorator.portCandidateProviderDecorator.setFactory(
+ node => new FlowNodePortCandidateProvider(node)
+ )
+ gc.graph.decorator.edgeDecorator.edgeReconnectionPortCandidateProviderDecorator.setFactory(
+ edge => new FlowEdgeReconnectionPortCandidateProvider(edge)
+ )
+}
+
+export function assertPortTag(tag: unknown): asserts tag is FlowNodePortProperties {
+ if (validatePortTag(tag)) {
+ return
+ } else {
+ throw new Error('Tag value does not satisfy type FlowNodePortProperties')
+ }
+}
+
+export function validatePortTag(tag: unknown): tag is FlowNodePortProperties {
+ return (
+ (typeof tag === 'object' &&
+ tag !== null &&
+ 'side' in tag &&
+ (tag as FlowNodePortProperties).side === 'left') ||
+ (tag as FlowNodePortProperties).side === 'right'
+ )
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodePortCandidateProvider.js b/demos/showcase/home-automation/FlowNode/FlowNodePortCandidateProvider.js
new file mode 100644
index 000000000..9879274e4
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodePortCandidateProvider.js
@@ -0,0 +1,105 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ DefaultPortCandidate,
+ IEnumerable,
+ IInputModeContext,
+ INode,
+ IPortCandidate,
+ List,
+ PortCandidateProviderBase,
+ PortCandidateValidity
+} from 'yfiles'
+import { assertPortTag } from './FlowNodePort.js'
+
+export class FlowNodePortCandidateProvider extends PortCandidateProviderBase {
+ /**
+ * @param {!INode} owner
+ */
+ constructor(owner) {
+ super()
+ this.owner = owner
+ }
+
+ /**
+ * @param {!IInputModeContext} _context
+ * @returns {!IEnumerable.}
+ */
+ getPortCandidates(_context) {
+ const candidates = new List()
+ this.addExistingPorts(this.owner, candidates)
+ return candidates
+ }
+
+ /**
+ * A valid target port candidate must:
+ * - have a different side than the source port;
+ * - be on a different node than the source port;
+ * - not already be connected to the source port (regardless of the direction).
+ * @param {!IInputModeContext} context
+ * @param {!IPortCandidate} source
+ * @returns {!IEnumerable.}
+ */
+ getTargetPortCandidates(context, source) {
+ const graph = context.graph
+ const candidates = new List()
+ if (!graph || !source.port) {
+ return candidates
+ }
+ assertPortTag(source.port.tag)
+
+ const sourceSide = source.port.tag.side
+
+ graph.ports
+ // Exclude same-sided ports:
+ .filter((port) => port.tag.side !== sourceSide)
+ // Exclude ports on the source node:
+ .filter((port) => port.owner !== source.owner)
+ // Exclude ports that the source port already connects to:
+ .filter(
+ (port) =>
+ !graph.edges.some((edge) => {
+ // Compare points by string representations instead of comparing just simple port instances.
+ // This helps to avoid scenario where node is recreated with undo and port instances don't match on the recreated edge
+ const edgePortPoints = [edge.sourcePort?.toString(), edge.targetPort?.toString()]
+ return (
+ edgePortPoints.includes(port.toString()) &&
+ edgePortPoints.includes(source.port?.toString())
+ )
+ })
+ )
+ .forEach((port) => {
+ const portCandidate = new DefaultPortCandidate(port)
+ portCandidate.validity = PortCandidateValidity.VALID
+ candidates.add(portCandidate)
+ })
+
+ return candidates
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodePortCandidateProvider.ts b/demos/showcase/home-automation/FlowNode/FlowNodePortCandidateProvider.ts
new file mode 100644
index 000000000..9acab2dfe
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodePortCandidateProvider.ts
@@ -0,0 +1,97 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ DefaultPortCandidate,
+ IEnumerable,
+ IInputModeContext,
+ INode,
+ IPortCandidate,
+ List,
+ PortCandidateProviderBase,
+ PortCandidateValidity
+} from 'yfiles'
+import { assertPortTag } from './FlowNodePort'
+
+export class FlowNodePortCandidateProvider extends PortCandidateProviderBase {
+ constructor(private owner: INode) {
+ super()
+ }
+
+ protected getPortCandidates(_context: IInputModeContext): IEnumerable {
+ const candidates = new List()
+ this.addExistingPorts(this.owner, candidates)
+ return candidates
+ }
+
+ /**
+ * A valid target port candidate must:
+ * - have a different side than the source port;
+ * - be on a different node than the source port;
+ * - not already be connected to the source port (regardless of the direction).
+ */
+ getTargetPortCandidates(
+ context: IInputModeContext,
+ source: IPortCandidate
+ ): IEnumerable {
+ const graph = context.graph
+ const candidates = new List()
+ if (!graph || !source.port) {
+ return candidates
+ }
+ assertPortTag(source.port.tag)
+
+ const sourceSide = source.port.tag.side
+
+ graph.ports
+ // Exclude same-sided ports:
+ .filter(port => port.tag.side !== sourceSide)
+ // Exclude ports on the source node:
+ .filter(port => port.owner !== source.owner)
+ // Exclude ports that the source port already connects to:
+ .filter(
+ port =>
+ !graph.edges.some(edge => {
+ // Compare points by string representations instead of comparing just simple port instances.
+ // This helps to avoid scenario where node is recreated with undo and port instances don't match on the recreated edge
+ const edgePortPoints = [edge.sourcePort?.toString(), edge.targetPort?.toString()]
+ return (
+ edgePortPoints.includes(port.toString()) &&
+ edgePortPoints.includes(source.port?.toString())
+ )
+ })
+ )
+ .forEach(port => {
+ const portCandidate = new DefaultPortCandidate(port)
+ portCandidate.validity = PortCandidateValidity.VALID
+ candidates.add(portCandidate)
+ })
+
+ return candidates
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodePortStyle.js b/demos/showcase/home-automation/FlowNode/FlowNodePortStyle.js
new file mode 100644
index 000000000..789292236
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodePortStyle.js
@@ -0,0 +1,144 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { ICanvasContext, IPort, Point, PortStyleBase, Rect } from 'yfiles'
+
+/**
+ * @typedef {Object} DummyPortOptions
+ * @property {Rect} nodeBounds
+ * @property {*} side
+ * @property {boolean} [isConnected]
+ */
+
+export class FlowNodePortStyle extends PortStyleBase {
+ /** @type {number} */
+ static get size() {
+ if (typeof FlowNodePortStyle.$size === 'undefined') {
+ FlowNodePortStyle.$size = 12
+ }
+
+ return FlowNodePortStyle.$size
+ }
+
+ /** @type {number} */
+ static get nodeMargin() {
+ if (typeof FlowNodePortStyle.$nodeMargin === 'undefined') {
+ FlowNodePortStyle.$nodeMargin = 3
+ }
+
+ return FlowNodePortStyle.$nodeMargin
+ }
+
+ /** @type {undefined} */
+ static get nodeReservedWidthForPort() {
+ if (typeof FlowNodePortStyle.$nodeReservedWidthForPort === 'undefined') {
+ FlowNodePortStyle.$nodeReservedWidthForPort =
+ FlowNodePortStyle.size / 2 + FlowNodePortStyle.nodeMargin
+ }
+
+ return FlowNodePortStyle.$nodeReservedWidthForPort
+ }
+
+ /**
+ * Creates a visual for the dummy "port" that will be rendered as part of node visual
+ * to bypass DnD limitations. (We can't render actual ports when preparing nodes
+ * for the DnD palette, as dragging such a node to the main graph results in an
+ * uncatchable exception).
+ * @param {!DummyPortOptions} undefined
+ * @returns {!SVGGElement}
+ */
+ static createDummyPortElement({ nodeBounds, side, isConnected = false }) {
+ const { size } = FlowNodePortStyle
+ const outerRadius = size / 2
+ const innerRadius = size / 2 / 2 + 0.5
+ const color = isConnected ? 'rgb(0, 0, 0)' : 'rgb(153, 153, 153)'
+
+ const location = {
+ left: new Point(0, nodeBounds.height / 2),
+ right: new Point(nodeBounds.width, nodeBounds.height / 2)
+ }[side]
+ const { x, y } = location
+
+ const group = document.createElementNS('http://www.w3.org/2000/svg', 'g')
+ const outer = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse')
+ const inner = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse')
+
+ outer.setAttribute('cx', String(x))
+ outer.setAttribute('cy', String(y))
+ outer.setAttribute('rx', String(outerRadius))
+ outer.setAttribute('ry', String(outerRadius))
+ outer.setAttribute('fill', 'rgb(255, 255, 255)')
+ outer.setAttribute('stroke', color)
+ outer.setAttribute('stroke-width', '1')
+
+ inner.setAttribute('cx', String(x))
+ inner.setAttribute('cy', String(y))
+ inner.setAttribute('rx', String(innerRadius))
+ inner.setAttribute('ry', String(innerRadius))
+ inner.setAttribute('fill', color)
+
+ group.setAttribute('style', 'cursor: crosshair')
+ group.appendChild(outer)
+ group.appendChild(inner)
+
+ return group
+ }
+
+ /**
+ * @param {*} undefined
+ */
+ static updateDummyPortElement({ element, nodeBounds, side }) {
+ const location = {
+ left: new Point(0, nodeBounds.height / 2),
+ right: new Point(nodeBounds.width, nodeBounds.height / 2)
+ }[side]
+ const { x, y } = location
+ element.querySelectorAll('ellipse').forEach((e) => {
+ e.setAttribute('cx', String(x))
+ e.setAttribute('cy', String(y))
+ })
+ }
+
+ /**
+ * The actual visual is rendered as part of the accompanying node.
+ * @returns {!null}
+ */
+ createVisual() {
+ return null
+ }
+
+ /**
+ * @param {!ICanvasContext} _context
+ * @param {!IPort} port
+ * @returns {!Rect}
+ */
+ getBounds(_context, port) {
+ const { size } = FlowNodePortStyle
+ return Rect.fromCenter(port.location, [size, size])
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodePortStyle.ts b/demos/showcase/home-automation/FlowNode/FlowNodePortStyle.ts
new file mode 100644
index 000000000..67fb5d815
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodePortStyle.ts
@@ -0,0 +1,118 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { ICanvasContext, IPort, Point, PortStyleBase, Rect } from 'yfiles'
+import type { FlowNodePortProperties } from './FlowNodePort'
+
+type DummyPortOptions = {
+ nodeBounds: Rect
+ side: FlowNodePortProperties['side']
+ isConnected?: boolean
+}
+
+export class FlowNodePortStyle extends PortStyleBase {
+ static readonly size = 12
+ static readonly nodeMargin = 3
+ static readonly nodeReservedWidthForPort =
+ FlowNodePortStyle.size / 2 + FlowNodePortStyle.nodeMargin
+
+ /**
+ * Creates a visual for the dummy "port" that will be rendered as part of node visual
+ * to bypass DnD limitations. (We can't render actual ports when preparing nodes
+ * for the DnD palette, as dragging such a node to the main graph results in an
+ * uncatchable exception).
+ */
+ static createDummyPortElement({
+ nodeBounds,
+ side,
+ isConnected = false
+ }: DummyPortOptions): SVGGElement {
+ const { size } = FlowNodePortStyle
+ const outerRadius = size / 2
+ const innerRadius = size / 2 / 2 + 0.5
+ const color = isConnected ? 'rgb(0, 0, 0)' : 'rgb(153, 153, 153)'
+
+ const location = {
+ left: new Point(0, nodeBounds.height / 2),
+ right: new Point(nodeBounds.width, nodeBounds.height / 2)
+ }[side]
+ const { x, y } = location
+
+ const group = document.createElementNS('http://www.w3.org/2000/svg', 'g')
+ const outer = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse')
+ const inner = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse')
+
+ outer.setAttribute('cx', String(x))
+ outer.setAttribute('cy', String(y))
+ outer.setAttribute('rx', String(outerRadius))
+ outer.setAttribute('ry', String(outerRadius))
+ outer.setAttribute('fill', 'rgb(255, 255, 255)')
+ outer.setAttribute('stroke', color)
+ outer.setAttribute('stroke-width', '1')
+
+ inner.setAttribute('cx', String(x))
+ inner.setAttribute('cy', String(y))
+ inner.setAttribute('rx', String(innerRadius))
+ inner.setAttribute('ry', String(innerRadius))
+ inner.setAttribute('fill', color)
+
+ group.setAttribute('style', 'cursor: crosshair')
+ group.appendChild(outer)
+ group.appendChild(inner)
+
+ return group
+ }
+
+ static updateDummyPortElement({
+ element,
+ nodeBounds,
+ side
+ }: { element: SVGGElement } & DummyPortOptions): void {
+ const location = {
+ left: new Point(0, nodeBounds.height / 2),
+ right: new Point(nodeBounds.width, nodeBounds.height / 2)
+ }[side]
+ const { x, y } = location
+ element.querySelectorAll('ellipse').forEach((e) => {
+ e.setAttribute('cx', String(x))
+ e.setAttribute('cy', String(y))
+ })
+ }
+
+ /**
+ * The actual visual is rendered as part of the accompanying node.
+ */
+ protected createVisual(): null {
+ return null
+ }
+
+ protected getBounds(_context: ICanvasContext, port: IPort): Rect {
+ const { size } = FlowNodePortStyle
+ return Rect.fromCenter(port.location, [size, size])
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodeStyle.js b/demos/showcase/home-automation/FlowNode/FlowNodeStyle.js
new file mode 100644
index 000000000..bf07d77e9
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodeStyle.js
@@ -0,0 +1,617 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ Font,
+ GraphComponent,
+ ICanvasContext,
+ INode,
+ IRenderContext,
+ NodeStyleBase,
+ Point,
+ Rect,
+ Size,
+ SvgVisual,
+ TextRenderSupport,
+ TextWrapping
+} from 'yfiles'
+import { FlowNodePortStyle } from './FlowNodePortStyle.js'
+import { getNodeIconSvg } from './icons.js'
+import { assertIsFlowNode } from './FlowNode.js'
+
+/**
+ * @typedef {TaggedSvgVisual.} SvgVisualWithCache
+ */
+
+/**
+ * @typedef {Object} SvgComponents
+ * @property {SVGGElement} wrapper
+ * @property {SVGRectElement} mainShape
+ * @property {SVGRectElement} iconBox
+ * @property {SVGRectElement} border
+ * @property {SVGTextElement} label
+ * @property {SVGGElement} invalidMark
+ * @property {SVGGElement} leftDummyPort
+ * @property {SVGGElement} rightDummyPort
+ */
+
+export class FlowNodeStyle extends NodeStyleBase {
+ /** @type {number} */
+ static get defaultWidth() {
+ if (typeof FlowNodeStyle.$defaultWidth === 'undefined') {
+ FlowNodeStyle.$defaultWidth = 150
+ }
+
+ return FlowNodeStyle.$defaultWidth
+ }
+
+ /** @type {undefined} */
+ static get defaultWidthWithPorts() {
+ if (typeof FlowNodeStyle.$defaultWidthWithPorts === 'undefined') {
+ FlowNodeStyle.$defaultWidthWithPorts = 150 + FlowNodePortStyle.size
+ }
+
+ return FlowNodeStyle.$defaultWidthWithPorts
+ }
+
+ /** @type {number} */
+ static get defaultHeight() {
+ if (typeof FlowNodeStyle.$defaultHeight === 'undefined') {
+ FlowNodeStyle.$defaultHeight = 32
+ }
+
+ return FlowNodeStyle.$defaultHeight
+ }
+
+ /** @type {number} */
+ static get minWidth() {
+ if (typeof FlowNodeStyle.$minWidth === 'undefined') {
+ FlowNodeStyle.$minWidth = 150
+ }
+
+ return FlowNodeStyle.$minWidth
+ }
+
+ /** @type {number} */
+ static get maxWidth() {
+ if (typeof FlowNodeStyle.$maxWidth === 'undefined') {
+ FlowNodeStyle.$maxWidth = 300
+ }
+
+ return FlowNodeStyle.$maxWidth
+ }
+
+ /** @type {number} */
+ static get labelFontSize() {
+ if (typeof FlowNodeStyle.$labelFontSize === 'undefined') {
+ FlowNodeStyle.$labelFontSize = 14
+ }
+
+ return FlowNodeStyle.$labelFontSize
+ }
+
+ /** @type {number} */
+ static get labelHorizontalMargin() {
+ if (typeof FlowNodeStyle.$labelHorizontalMargin === 'undefined') {
+ FlowNodeStyle.$labelHorizontalMargin = 8
+ }
+
+ return FlowNodeStyle.$labelHorizontalMargin
+ }
+
+ /** @type {number} */
+ static get radius() {
+ if (typeof FlowNodeStyle.$radius === 'undefined') {
+ FlowNodeStyle.$radius = 8
+ }
+
+ return FlowNodeStyle.$radius
+ }
+
+ /** @type {number} */
+ static get iconSize() {
+ if (typeof FlowNodeStyle.$iconSize === 'undefined') {
+ FlowNodeStyle.$iconSize = 14
+ }
+
+ return FlowNodeStyle.$iconSize
+ }
+
+ /** @type {number} */
+ static get iconContainerWidth() {
+ if (typeof FlowNodeStyle.$iconContainerWidth === 'undefined') {
+ FlowNodeStyle.$iconContainerWidth = 20
+ }
+
+ return FlowNodeStyle.$iconContainerWidth
+ }
+
+ /** @type {number} */
+ static get iconContainerHeight() {
+ if (typeof FlowNodeStyle.$iconContainerHeight === 'undefined') {
+ FlowNodeStyle.$iconContainerHeight = 20
+ }
+
+ return FlowNodeStyle.$iconContainerHeight
+ }
+
+ /** @type {number} */
+ static get iconContainerRadius() {
+ if (typeof FlowNodeStyle.$iconContainerRadius === 'undefined') {
+ FlowNodeStyle.$iconContainerRadius = 4
+ }
+
+ return FlowNodeStyle.$iconContainerRadius
+ }
+
+ /** @type {'M11.8649 9.16693C12.2495 9.83348 11.7668 10.6667 10.9988 10.6667H1.00113C0.23161 10.6667 -0.248848 9.83218 0.134943 9.16693L5.13382 0.499687C5.51855 -0.167167 6.48215 -0.165958 6.86619 0.499687L11.8649 9.16693ZM6 7.375C5.47073 7.375 5.04167 7.80406 5.04167 8.33333C5.04167 8.8626 5.47073 9.29166 6 9.29166C6.52927 9.29166 6.95834 8.8626 6.95834 8.33333C6.95834 7.80406 6.52927 7.375 6 7.375ZM5.09015 3.93029L5.24469 6.76362C5.25192 6.89621 5.36155 7 5.49432 7H6.50569C6.63846 7 6.74809 6.89621 6.75532 6.76362L6.90986 3.93029C6.91767 3.78708 6.80365 3.66667 6.66023 3.66667H5.33975C5.19634 3.66667 5.08234 3.78708 5.09015 3.93029Z'} */
+ static get errorIndicatorPath() {
+ if (typeof FlowNodeStyle.$errorIndicatorPath === 'undefined') {
+ FlowNodeStyle.$errorIndicatorPath =
+ 'M11.8649 9.16693C12.2495 9.83348 11.7668 10.6667 10.9988 10.6667H1.00113C0.23161 10.6667 -0.248848 9.83218 0.134943 9.16693L5.13382 0.499687C5.51855 -0.167167 6.48215 -0.165958 6.86619 0.499687L11.8649 9.16693ZM6 7.375C5.47073 7.375 5.04167 7.80406 5.04167 8.33333C5.04167 8.8626 5.47073 9.29166 6 9.29166C6.52927 9.29166 6.95834 8.8626 6.95834 8.33333C6.95834 7.80406 6.52927 7.375 6 7.375ZM5.09015 3.93029L5.24469 6.76362C5.25192 6.89621 5.36155 7 5.49432 7H6.50569C6.63846 7 6.74809 6.89621 6.75532 6.76362L6.90986 3.93029C6.91767 3.78708 6.80365 3.66667 6.66023 3.66667H5.33975C5.19634 3.66667 5.08234 3.78708 5.09015 3.93029Z'
+ }
+
+ return FlowNodeStyle.$errorIndicatorPath
+ }
+
+ /** @type {number} */
+ static get errorIndicatorWidth() {
+ if (typeof FlowNodeStyle.$errorIndicatorWidth === 'undefined') {
+ FlowNodeStyle.$errorIndicatorWidth = 12
+ }
+
+ return FlowNodeStyle.$errorIndicatorWidth
+ }
+
+ /** @type {number} */
+ static get errorIndicatorHeight() {
+ if (typeof FlowNodeStyle.$errorIndicatorHeight === 'undefined') {
+ FlowNodeStyle.$errorIndicatorHeight = 12
+ }
+
+ return FlowNodeStyle.$errorIndicatorHeight
+ }
+
+ /** @type {Record.<,string>} */
+ static get color() {
+ if (typeof FlowNodeStyle.$color === 'undefined') {
+ FlowNodeStyle.$color = {
+ storageWriteFile: '#DEB887',
+ storageReadFile: '#DEB887',
+ parserCsv: '#DEBD5C',
+ parserJson: '#DEBD5C',
+ parserXml: '#DEBD5C',
+ sequenceSort: '#E2D96E',
+ sequenceJoin: '#E2D96E',
+ networkTcpIn: '#C0C0C0',
+ networkTcpOut: '#C0C0C0',
+ networkTcpRequest: '#C0C0C0',
+ functionFunction: '#F8CFA1',
+ functionDelay: '#E6E0F8',
+ functionFilter: '#E2D96E',
+ commonComment: '#FFFFFF',
+ commonLinkIn: '#DDDDDD',
+ commonLinkOut: '#DDDDDD',
+ commonLinkCall: '#DDDDDD',
+ commonStatus: '#94C1D0'
+ }
+ }
+
+ return FlowNodeStyle.$color
+ }
+
+ /** @type {Record.<,string>} */
+ static set color(color) {
+ FlowNodeStyle.$color = color
+ }
+
+ /**
+ * Resolves detailed dimensions of every specific item of the node visual. Importantly,
+ * the total width calculated depends on the actual width of the label text.
+ * @param {!object} undefined
+ */
+ static getDimensions({ label, hasErrorIndicator = false }) {
+ const {
+ defaultHeight: height,
+ minWidth,
+ maxWidth,
+ labelFontSize,
+ labelHorizontalMargin,
+ radius,
+ iconSize,
+ iconContainerWidth,
+ iconContainerHeight,
+ iconContainerRadius,
+ errorIndicatorWidth,
+ errorIndicatorHeight
+ } = FlowNodeStyle
+ const { nodeReservedWidthForPort: portReservedWidth } = FlowNodePortStyle
+
+ const iconContainerMargin = (height - iconContainerHeight) / 2
+ const errorIndicatorMargin = (height - errorIndicatorHeight) / 2
+
+ let maxLabelWidth = maxWidth - 2 * portReservedWidth - 2 * labelHorizontalMargin
+ // Reserve space for left icon box
+ maxLabelWidth = maxLabelWidth - iconContainerWidth - iconContainerMargin
+ // Reserve space for right icon box (error indicator)
+ if (hasErrorIndicator) {
+ maxLabelWidth = maxLabelWidth - errorIndicatorWidth - errorIndicatorMargin
+ }
+
+ const { width: labelWidth, height: labelHeight } = TextRenderSupport.measureText({
+ text: label,
+ font: new Font('sans-serif', labelFontSize),
+ wrapping: TextWrapping.CHARACTER_ELLIPSIS,
+ maximumSize: new Size(maxLabelWidth, height)
+ })
+
+ // Layout width & height includes some extra left & right spacing to accommodate
+ // ports, which are outside the node shape (but in reality, we want them
+ // to be right on the edge of the "true" node layout).
+ const layoutHeight = height
+ let layoutWidth = Math.max(
+ minWidth,
+ 2 * portReservedWidth +
+ iconContainerMargin +
+ iconContainerWidth +
+ labelHorizontalMargin +
+ labelWidth +
+ labelHorizontalMargin
+ )
+ let actualWidth =
+ 2 * portReservedWidth +
+ iconContainerMargin +
+ labelWidth +
+ iconContainerWidth +
+ 2 * labelHorizontalMargin
+ if (hasErrorIndicator) {
+ actualWidth = actualWidth + errorIndicatorMargin + errorIndicatorWidth
+ }
+ if (hasErrorIndicator && actualWidth > minWidth) {
+ layoutWidth = layoutWidth + errorIndicatorWidth + errorIndicatorMargin
+ }
+
+ const visibleWidth = layoutWidth - 2 * portReservedWidth
+ const visibleHeight = layoutHeight
+
+ return {
+ layoutWidth,
+ layoutHeight,
+ visibleWidth,
+ visibleHeight,
+ portReservedWidth,
+ radius,
+ labelFontSize,
+ maxLabelWidth,
+ labelWidth,
+ labelHeight,
+ labelHorizontalMargin,
+ iconSize,
+ iconContainerWidth,
+ iconContainerHeight,
+ iconContainerMargin,
+ iconContainerRadius,
+ errorIndicatorWidth,
+ errorIndicatorHeight,
+ errorIndicatorMargin
+ }
+ }
+
+ /**
+ * @param {!IRenderContext} context
+ * @param {!INode} node
+ * @returns {boolean}
+ */
+ static isSelected(context, node) {
+ const gc = context.canvasComponent instanceof GraphComponent ? context.canvasComponent : null
+ return gc?.selection.isSelected(node) ?? false
+ }
+
+ /**
+ * @param {!IRenderContext} context
+ * @param {!INode} node
+ * @returns {boolean}
+ */
+ static isHovered(context, node) {
+ const gc = context.canvasComponent instanceof GraphComponent ? context.canvasComponent : null
+ return gc?.highlightIndicatorManager.selectionModel?.includes(node) ?? false
+ }
+
+ /**
+ * @param {!IRenderContext} context
+ * @param {!INode} node
+ * @returns {!SvgVisualWithCache}
+ */
+ createVisual(context, node) {
+ assertIsFlowNode(node)
+
+ const graph =
+ context.canvasComponent instanceof GraphComponent ? context.canvasComponent.graph : null
+
+ const { variant, label, hasLeftPort, hasRightPort } = node.tag
+ const { x, y } = node.layout
+ const isHovered = FlowNodeStyle.isHovered(context, node)
+ const isSelected = FlowNodeStyle.isSelected(context, node)
+ const {
+ labelFontSize,
+ radius,
+ maxLabelWidth,
+ labelHeight,
+ iconSize,
+ iconContainerWidth,
+ iconContainerHeight,
+ iconContainerMargin,
+ iconContainerRadius,
+ layoutWidth,
+ layoutHeight,
+ visibleWidth,
+ visibleHeight,
+ portReservedWidth,
+ labelHorizontalMargin,
+ errorIndicatorWidth,
+ errorIndicatorMargin
+ } = FlowNodeStyle.getDimensions({ label })
+
+ const svg = {
+ wrapper: document.createElementNS('http://www.w3.org/2000/svg', 'g'),
+ mainShape: document.createElementNS('http://www.w3.org/2000/svg', 'rect'),
+ iconBox: document.createElementNS('http://www.w3.org/2000/svg', 'rect'),
+ border: document.createElementNS('http://www.w3.org/2000/svg', 'rect'),
+ label: document.createElementNS('http://www.w3.org/2000/svg', 'text'),
+ invalidMark: document.createElementNS('http://www.w3.org/2000/svg', 'g'),
+ leftDummyPort: null,
+ rightDummyPort: null
+ }
+
+ svg.wrapper.classList.add('flow-node', variant)
+ svg.mainShape.classList.add('flow-node__main')
+ svg.iconBox.classList.add('flow-node__icon-box')
+ svg.border.classList.add('flow-node__border')
+ svg.label.classList.add('flow-node__label')
+ svg.invalidMark.classList.add('flow-node__invalid-mark')
+
+ svg.wrapper.setAttribute('transform', `translate(${x} ${y})`)
+
+ TextRenderSupport.addText({
+ targetElement: svg.label,
+ text: label,
+ font: new Font('sans-serif', labelFontSize),
+ wrapping: TextWrapping.CHARACTER_ELLIPSIS,
+ maximumSize: new Size(maxLabelWidth, visibleHeight)
+ })
+ svg.label.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + iconContainerMargin + iconContainerWidth + labelHorizontalMargin
+ } ${(visibleHeight - labelHeight) / 2})`
+ )
+ svg.label.setAttribute('fill', 'rgb(85, 85, 85)')
+
+ svg.mainShape.setAttribute('width', String(visibleWidth))
+ svg.mainShape.setAttribute('x', String(portReservedWidth))
+ svg.mainShape.setAttribute('height', String(visibleHeight))
+ svg.mainShape.setAttribute('rx', String(radius))
+ svg.mainShape.setAttribute('fill', 'rgb(255, 255, 255)')
+
+ svg.iconBox.setAttribute('x', String(portReservedWidth + iconContainerMargin))
+ svg.iconBox.setAttribute('y', String(iconContainerMargin))
+ svg.iconBox.setAttribute('width', String(iconContainerWidth))
+ svg.iconBox.setAttribute('height', String(iconContainerHeight))
+ svg.iconBox.setAttribute('rx', String(iconContainerRadius))
+
+ const icon = getNodeIconSvg({
+ nodeVariant: variant,
+ size: iconSize,
+ color:
+ FlowNodeStyle.color[variant] === '#FFFFFF' ? 'rgb(191, 191, 191)' : 'rgb(255, 255, 255)'
+ })
+
+ const iconPosition = new Point(
+ (layoutHeight - iconSize) / 2 + portReservedWidth,
+ (layoutHeight - iconSize) / 2
+ )
+ const iconContainer = document.createElementNS('http://www.w3.org/2000/svg', 'g')
+ iconContainer.setAttribute('transform', `translate(${iconPosition.x}, ${iconPosition.y})`)
+ iconContainer.appendChild(icon)
+
+ svg.iconBox.setAttribute('fill', FlowNodeStyle.color[variant])
+ svg.iconBox.setAttribute('stroke', 'rgba(0, 0, 0, 0.1)')
+
+ const invalidMarkPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')
+ invalidMarkPath.setAttribute('d', FlowNodeStyle.errorIndicatorPath)
+ svg.invalidMark.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + visibleWidth - errorIndicatorWidth - errorIndicatorMargin
+ } ${errorIndicatorMargin})`
+ )
+ svg.invalidMark.setAttribute('fill', 'rgb(203,20,20)')
+ svg.invalidMark.style.opacity = '0'
+ svg.invalidMark.style.transition = 'opacity 0.2s'
+ svg.invalidMark.append(invalidMarkPath)
+
+ svg.border.setAttribute('width', String(visibleWidth))
+ svg.border.setAttribute('x', String(portReservedWidth))
+ svg.border.setAttribute('height', String(visibleHeight))
+ svg.border.setAttribute('rx', '5')
+ svg.border.setAttribute('fill', 'transparent')
+ svg.border.style.transition = 'stroke .4s, stroke-width .2s'
+ svg.border.setAttribute('stroke', isHovered || isSelected ? 'rgb(255, 108, 0)' : '#999999')
+ svg.border.setAttribute('stroke-width', isSelected ? '2' : '1')
+
+ svg.wrapper.append(
+ svg.mainShape,
+ svg.iconBox,
+ iconContainer,
+ svg.border,
+ svg.label,
+ svg.invalidMark
+ )
+
+ // During drag & drop operation, a node is created before becoming part of the target graph.
+ // In that case, setting the layout won't work anyway.
+ if (graph?.nodes.includes(node)) {
+ graph.setNodeLayout(node, new Rect(x, y, layoutWidth, layoutHeight))
+ }
+
+ // Add dummy port visuals
+ const nodeBounds = new Rect(x, y, layoutWidth, layoutHeight)
+ if (hasLeftPort) {
+ const dummyPort = FlowNodePortStyle.createDummyPortElement({ nodeBounds, side: 'left' })
+ dummyPort.classList.add('flow-node__dummy-port--left')
+ svg.wrapper.appendChild(dummyPort)
+ }
+ if (hasRightPort) {
+ const dummyPort = FlowNodePortStyle.createDummyPortElement({ nodeBounds, side: 'right' })
+ dummyPort.classList.add('flow-node__dummy-port--right')
+ svg.wrapper.appendChild(dummyPort)
+ }
+
+ return SvgVisual.from(svg.wrapper, {
+ label,
+ layoutWidth,
+ hasErrorIndicator: false
+ })
+ }
+
+ /**
+ * @param {!IRenderContext} context
+ * @param {!SvgVisualWithCache} oldVisual
+ * @param {!unknown} node
+ * @returns {!SvgVisualWithCache}
+ */
+ updateVisual(context, oldVisual, node) {
+ assertIsFlowNode(node)
+
+ const graph =
+ context.canvasComponent instanceof GraphComponent ? context.canvasComponent.graph : null
+
+ const { x, y } = node.layout
+ const { label, validate } = node.tag
+ const isHovered = FlowNodeStyle.isHovered(context, node)
+ const isSelected = FlowNodeStyle.isSelected(context, node)
+ const cache = oldVisual.tag
+ const hasErrorIndicator = validate(node.tag).invalidProperties.length > 0
+
+ const {
+ labelFontSize,
+ maxLabelWidth,
+ labelHeight,
+ iconContainerWidth,
+ iconContainerMargin,
+ layoutWidth,
+ layoutHeight,
+ visibleWidth,
+ visibleHeight,
+ portReservedWidth,
+ labelHorizontalMargin,
+ errorIndicatorWidth,
+ errorIndicatorMargin
+ } = FlowNodeStyle.getDimensions({ label, hasErrorIndicator })
+
+ const svg = {
+ wrapper: oldVisual.svgElement,
+ mainShape: oldVisual.svgElement.querySelector('.flow-node__main'),
+ iconBox: oldVisual.svgElement.querySelector('.flow-node__icon-box'),
+ border: oldVisual.svgElement.querySelector('.flow-node__border'),
+ label: oldVisual.svgElement.querySelector('.flow-node__label'),
+ invalidMark: oldVisual.svgElement.querySelector('.flow-node__invalid-mark'),
+ leftDummyPort: oldVisual.svgElement.querySelector('.flow-node__dummy-port--left'),
+ rightDummyPort: oldVisual.svgElement.querySelector('.flow-node__dummy-port--right')
+ }
+
+ if (cache.label !== label || cache.hasErrorIndicator !== hasErrorIndicator) {
+ cache.label = label
+ cache.hasErrorIndicator = hasErrorIndicator
+
+ TextRenderSupport.addText({
+ targetElement: svg.label,
+ text: label,
+ font: new Font('sans-serif', labelFontSize),
+ wrapping: TextWrapping.CHARACTER_ELLIPSIS,
+ maximumSize: new Size(maxLabelWidth, visibleHeight)
+ })
+
+ svg.label.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + iconContainerMargin + iconContainerWidth + labelHorizontalMargin
+ } ${(visibleHeight - labelHeight) / 2})`
+ )
+
+ svg.mainShape.setAttribute('width', String(visibleWidth))
+ svg.border.setAttribute('width', String(visibleWidth))
+
+ // This may fail while drag-and-dropping, which is completely fine.
+ try {
+ graph?.setNodeLayout(node, new Rect(x, y, layoutWidth, layoutHeight))
+ } catch (e) {}
+ }
+
+ svg.border.setAttribute('stroke', isHovered || isSelected ? 'rgb(255, 108, 0)' : '#999999')
+ svg.border.setAttribute('stroke-width', isSelected ? '2' : '1')
+
+ svg.wrapper.setAttribute('transform', `translate(${x} ${y})`)
+
+ svg.invalidMark.style.opacity = hasErrorIndicator ? '1' : '0'
+ svg.invalidMark.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + visibleWidth - errorIndicatorWidth - errorIndicatorMargin
+ } ${errorIndicatorMargin})`
+ )
+
+ // Update right port position if necessary:
+ if (cache.layoutWidth !== layoutWidth) {
+ cache.layoutWidth = layoutWidth
+ if (svg.rightDummyPort) {
+ const nodeBounds = new Rect(x, y, layoutWidth, layoutHeight)
+ FlowNodePortStyle.updateDummyPortElement({
+ element: svg.rightDummyPort,
+ nodeBounds,
+ side: 'right'
+ })
+ }
+ }
+
+ return oldVisual
+ }
+
+ /**
+ * @param {!ICanvasContext} _context
+ * @param {!unknown} node
+ * @returns {!Rect}
+ */
+ getBounds(_context, node) {
+ assertIsFlowNode(node)
+ const { label } = node.tag
+ const { x, y } = node.layout
+ const { layoutWidth, layoutHeight } = FlowNodeStyle.getDimensions({ label })
+ return new Rect(x, y, layoutWidth, layoutHeight)
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodeStyle.ts b/demos/showcase/home-automation/FlowNode/FlowNodeStyle.ts
new file mode 100644
index 000000000..3e5cddeb1
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodeStyle.ts
@@ -0,0 +1,478 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ Font,
+ GraphComponent,
+ ICanvasContext,
+ INode,
+ IRenderContext,
+ NodeStyleBase,
+ Point,
+ Rect,
+ Size,
+ SvgVisual,
+ type TaggedSvgVisual,
+ TextRenderSupport,
+ TextWrapping
+} from 'yfiles'
+import { FlowNodePortStyle } from './FlowNodePortStyle'
+import { getNodeIconSvg } from './icons'
+import { assertIsFlowNode, type FlowNodeProperties } from './FlowNode'
+
+type SvgVisualWithCache = TaggedSvgVisual<
+ SVGGElement,
+ {
+ label: string
+ hasErrorIndicator: boolean
+ layoutWidth: number
+ }
+>
+
+type SvgComponents = {
+ wrapper: SVGGElement
+ mainShape: SVGRectElement
+ iconBox: SVGRectElement
+ border: SVGRectElement
+ label: SVGTextElement
+ invalidMark: SVGGElement
+ leftDummyPort: SVGGElement | null
+ rightDummyPort: SVGGElement | null
+}
+
+export class FlowNodeStyle extends NodeStyleBase {
+ static readonly defaultWidth = 150
+ static readonly defaultWidthWithPorts = 150 + FlowNodePortStyle.size
+ static readonly defaultHeight = 32
+ static readonly minWidth = 150
+ static readonly maxWidth = 300
+
+ static readonly labelFontSize = 14
+ static readonly labelHorizontalMargin = 8
+
+ static readonly radius = 8
+
+ static readonly iconSize = 14
+ static readonly iconContainerWidth = 20
+ static readonly iconContainerHeight = 20
+ static readonly iconContainerRadius = 4
+
+ static readonly errorIndicatorPath =
+ 'M11.8649 9.16693C12.2495 9.83348 11.7668 10.6667 10.9988 10.6667H1.00113C0.23161 10.6667 -0.248848 9.83218 0.134943 9.16693L5.13382 0.499687C5.51855 -0.167167 6.48215 -0.165958 6.86619 0.499687L11.8649 9.16693ZM6 7.375C5.47073 7.375 5.04167 7.80406 5.04167 8.33333C5.04167 8.8626 5.47073 9.29166 6 9.29166C6.52927 9.29166 6.95834 8.8626 6.95834 8.33333C6.95834 7.80406 6.52927 7.375 6 7.375ZM5.09015 3.93029L5.24469 6.76362C5.25192 6.89621 5.36155 7 5.49432 7H6.50569C6.63846 7 6.74809 6.89621 6.75532 6.76362L6.90986 3.93029C6.91767 3.78708 6.80365 3.66667 6.66023 3.66667H5.33975C5.19634 3.66667 5.08234 3.78708 5.09015 3.93029Z'
+ static readonly errorIndicatorWidth = 12
+ static readonly errorIndicatorHeight = 12
+
+ private static color: Record = {
+ storageWriteFile: '#DEB887',
+ storageReadFile: '#DEB887',
+ parserCsv: '#DEBD5C',
+ parserJson: '#DEBD5C',
+ parserXml: '#DEBD5C',
+ sequenceSort: '#E2D96E',
+ sequenceJoin: '#E2D96E',
+ networkTcpIn: '#C0C0C0',
+ networkTcpOut: '#C0C0C0',
+ networkTcpRequest: '#C0C0C0',
+ functionFunction: '#F8CFA1',
+ functionDelay: '#E6E0F8',
+ functionFilter: '#E2D96E',
+ commonComment: '#FFFFFF',
+ commonLinkIn: '#DDDDDD',
+ commonLinkOut: '#DDDDDD',
+ commonLinkCall: '#DDDDDD',
+ commonStatus: '#94C1D0'
+ }
+
+ /**
+ * Resolves detailed dimensions of every specific item of the node visual. Importantly,
+ * the total width calculated depends on the actual width of the label text.
+ */
+ private static getDimensions({
+ label,
+ hasErrorIndicator = false
+ }: {
+ label: string
+ hasErrorIndicator?: boolean
+ }) {
+ const {
+ defaultHeight: height,
+ minWidth,
+ maxWidth,
+ labelFontSize,
+ labelHorizontalMargin,
+ radius,
+ iconSize,
+ iconContainerWidth,
+ iconContainerHeight,
+ iconContainerRadius,
+ errorIndicatorWidth,
+ errorIndicatorHeight
+ } = FlowNodeStyle
+ const { nodeReservedWidthForPort: portReservedWidth } = FlowNodePortStyle
+
+ const iconContainerMargin = (height - iconContainerHeight) / 2
+ const errorIndicatorMargin = (height - errorIndicatorHeight) / 2
+
+ let maxLabelWidth = maxWidth - 2 * portReservedWidth - 2 * labelHorizontalMargin
+ // Reserve space for left icon box
+ maxLabelWidth = maxLabelWidth - iconContainerWidth - iconContainerMargin
+ // Reserve space for right icon box (error indicator)
+ if (hasErrorIndicator) {
+ maxLabelWidth = maxLabelWidth - errorIndicatorWidth - errorIndicatorMargin
+ }
+
+ const { width: labelWidth, height: labelHeight } = TextRenderSupport.measureText({
+ text: label,
+ font: new Font('sans-serif', labelFontSize),
+ wrapping: TextWrapping.CHARACTER_ELLIPSIS,
+ maximumSize: new Size(maxLabelWidth, height)
+ })
+
+ // Layout width & height includes some extra left & right spacing to accommodate
+ // ports, which are outside the node shape (but in reality, we want them
+ // to be right on the edge of the "true" node layout).
+ const layoutHeight = height
+ let layoutWidth = Math.max(
+ minWidth,
+ 2 * portReservedWidth +
+ iconContainerMargin +
+ iconContainerWidth +
+ labelHorizontalMargin +
+ labelWidth +
+ labelHorizontalMargin
+ )
+ let actualWidth =
+ 2 * portReservedWidth +
+ iconContainerMargin +
+ labelWidth +
+ iconContainerWidth +
+ 2 * labelHorizontalMargin
+ if (hasErrorIndicator) {
+ actualWidth = actualWidth + errorIndicatorMargin + errorIndicatorWidth
+ }
+ if (hasErrorIndicator && actualWidth > minWidth) {
+ layoutWidth = layoutWidth + errorIndicatorWidth + errorIndicatorMargin
+ }
+
+ const visibleWidth = layoutWidth - 2 * portReservedWidth
+ const visibleHeight = layoutHeight
+
+ return {
+ layoutWidth,
+ layoutHeight,
+ visibleWidth,
+ visibleHeight,
+ portReservedWidth,
+ radius,
+ labelFontSize,
+ maxLabelWidth,
+ labelWidth,
+ labelHeight,
+ labelHorizontalMargin,
+ iconSize,
+ iconContainerWidth,
+ iconContainerHeight,
+ iconContainerMargin,
+ iconContainerRadius,
+ errorIndicatorWidth,
+ errorIndicatorHeight,
+ errorIndicatorMargin
+ }
+ }
+
+ private static isSelected(context: IRenderContext, node: INode): boolean {
+ const gc = context.canvasComponent instanceof GraphComponent ? context.canvasComponent : null
+ return gc?.selection.isSelected(node) ?? false
+ }
+
+ private static isHovered(context: IRenderContext, node: INode): boolean {
+ const gc = context.canvasComponent instanceof GraphComponent ? context.canvasComponent : null
+ return gc?.highlightIndicatorManager.selectionModel?.includes(node) ?? false
+ }
+
+ protected createVisual(context: IRenderContext, node: INode): SvgVisualWithCache {
+ assertIsFlowNode(node)
+
+ const graph =
+ context.canvasComponent instanceof GraphComponent ? context.canvasComponent.graph : null
+
+ const { variant, label, hasLeftPort, hasRightPort } = node.tag
+ const { x, y } = node.layout
+ const isHovered = FlowNodeStyle.isHovered(context, node as INode)
+ const isSelected = FlowNodeStyle.isSelected(context, node as INode)
+ const {
+ labelFontSize,
+ radius,
+ maxLabelWidth,
+ labelHeight,
+ iconSize,
+ iconContainerWidth,
+ iconContainerHeight,
+ iconContainerMargin,
+ iconContainerRadius,
+ layoutWidth,
+ layoutHeight,
+ visibleWidth,
+ visibleHeight,
+ portReservedWidth,
+ labelHorizontalMargin,
+ errorIndicatorWidth,
+ errorIndicatorMargin
+ } = FlowNodeStyle.getDimensions({ label })
+
+ const svg: SvgComponents = {
+ wrapper: document.createElementNS('http://www.w3.org/2000/svg', 'g'),
+ mainShape: document.createElementNS('http://www.w3.org/2000/svg', 'rect'),
+ iconBox: document.createElementNS('http://www.w3.org/2000/svg', 'rect'),
+ border: document.createElementNS('http://www.w3.org/2000/svg', 'rect'),
+ label: document.createElementNS('http://www.w3.org/2000/svg', 'text'),
+ invalidMark: document.createElementNS('http://www.w3.org/2000/svg', 'g'),
+ leftDummyPort: null,
+ rightDummyPort: null
+ }
+
+ svg.wrapper.classList.add('flow-node', variant)
+ svg.mainShape.classList.add('flow-node__main')
+ svg.iconBox.classList.add('flow-node__icon-box')
+ svg.border.classList.add('flow-node__border')
+ svg.label.classList.add('flow-node__label')
+ svg.invalidMark.classList.add('flow-node__invalid-mark')
+
+ svg.wrapper.setAttribute('transform', `translate(${x} ${y})`)
+
+ TextRenderSupport.addText({
+ targetElement: svg.label,
+ text: label,
+ font: new Font('sans-serif', labelFontSize),
+ wrapping: TextWrapping.CHARACTER_ELLIPSIS,
+ maximumSize: new Size(maxLabelWidth, visibleHeight)
+ })
+ svg.label.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + iconContainerMargin + iconContainerWidth + labelHorizontalMargin
+ } ${(visibleHeight - labelHeight) / 2})`
+ )
+ svg.label.setAttribute('fill', 'rgb(85, 85, 85)')
+
+ svg.mainShape.setAttribute('width', String(visibleWidth))
+ svg.mainShape.setAttribute('x', String(portReservedWidth))
+ svg.mainShape.setAttribute('height', String(visibleHeight))
+ svg.mainShape.setAttribute('rx', String(radius))
+ svg.mainShape.setAttribute('fill', 'rgb(255, 255, 255)')
+
+ svg.iconBox.setAttribute('x', String(portReservedWidth + iconContainerMargin))
+ svg.iconBox.setAttribute('y', String(iconContainerMargin))
+ svg.iconBox.setAttribute('width', String(iconContainerWidth))
+ svg.iconBox.setAttribute('height', String(iconContainerHeight))
+ svg.iconBox.setAttribute('rx', String(iconContainerRadius))
+
+ const icon = getNodeIconSvg({
+ nodeVariant: variant,
+ size: iconSize,
+ color:
+ FlowNodeStyle.color[variant] === '#FFFFFF' ? 'rgb(191, 191, 191)' : 'rgb(255, 255, 255)'
+ })
+
+ const iconPosition = new Point(
+ (layoutHeight - iconSize) / 2 + portReservedWidth,
+ (layoutHeight - iconSize) / 2
+ )
+ const iconContainer = document.createElementNS('http://www.w3.org/2000/svg', 'g')
+ iconContainer.setAttribute('transform', `translate(${iconPosition.x}, ${iconPosition.y})`)
+ iconContainer.appendChild(icon)
+
+ svg.iconBox.setAttribute('fill', FlowNodeStyle.color[variant])
+ svg.iconBox.setAttribute('stroke', 'rgba(0, 0, 0, 0.1)')
+
+ const invalidMarkPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')
+ invalidMarkPath.setAttribute('d', FlowNodeStyle.errorIndicatorPath)
+ svg.invalidMark.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + visibleWidth - errorIndicatorWidth - errorIndicatorMargin
+ } ${errorIndicatorMargin})`
+ )
+ svg.invalidMark.setAttribute('fill', 'rgb(203,20,20)')
+ svg.invalidMark.style.opacity = '0'
+ svg.invalidMark.style.transition = 'opacity 0.2s'
+ svg.invalidMark.append(invalidMarkPath)
+
+ svg.border.setAttribute('width', String(visibleWidth))
+ svg.border.setAttribute('x', String(portReservedWidth))
+ svg.border.setAttribute('height', String(visibleHeight))
+ svg.border.setAttribute('rx', '5')
+ svg.border.setAttribute('fill', 'transparent')
+ svg.border.style.transition = 'stroke .4s, stroke-width .2s'
+ svg.border.setAttribute('stroke', isHovered || isSelected ? 'rgb(255, 108, 0)' : '#999999')
+ svg.border.setAttribute('stroke-width', isSelected ? '2' : '1')
+
+ svg.wrapper.append(
+ svg.mainShape,
+ svg.iconBox,
+ iconContainer,
+ svg.border,
+ svg.label,
+ svg.invalidMark
+ )
+
+ // During drag & drop operation, a node is created before becoming part of the target graph.
+ // In that case, setting the layout won't work anyway.
+ if (graph?.nodes.includes(node as INode)) {
+ graph.setNodeLayout(node as INode, new Rect(x, y, layoutWidth, layoutHeight))
+ }
+
+ // Add dummy port visuals
+ const nodeBounds = new Rect(x, y, layoutWidth, layoutHeight)
+ if (hasLeftPort) {
+ const dummyPort = FlowNodePortStyle.createDummyPortElement({ nodeBounds, side: 'left' })
+ dummyPort.classList.add('flow-node__dummy-port--left')
+ svg.wrapper.appendChild(dummyPort)
+ }
+ if (hasRightPort) {
+ const dummyPort = FlowNodePortStyle.createDummyPortElement({ nodeBounds, side: 'right' })
+ dummyPort.classList.add('flow-node__dummy-port--right')
+ svg.wrapper.appendChild(dummyPort)
+ }
+
+ return SvgVisual.from(svg.wrapper, {
+ label,
+ layoutWidth,
+ hasErrorIndicator: false
+ })
+ }
+
+ protected updateVisual(
+ context: IRenderContext,
+ oldVisual: SvgVisualWithCache,
+ node: unknown
+ ): SvgVisualWithCache {
+ assertIsFlowNode(node)
+
+ const graph =
+ context.canvasComponent instanceof GraphComponent ? context.canvasComponent.graph : null
+
+ const { x, y } = node.layout
+ const { label, validate } = node.tag
+ const isHovered = FlowNodeStyle.isHovered(context, node as INode)
+ const isSelected = FlowNodeStyle.isSelected(context, node as INode)
+ const cache = oldVisual.tag
+ const hasErrorIndicator = validate!(node.tag)!.invalidProperties.length > 0
+
+ const {
+ labelFontSize,
+ maxLabelWidth,
+ labelHeight,
+ iconContainerWidth,
+ iconContainerMargin,
+ layoutWidth,
+ layoutHeight,
+ visibleWidth,
+ visibleHeight,
+ portReservedWidth,
+ labelHorizontalMargin,
+ errorIndicatorWidth,
+ errorIndicatorMargin
+ } = FlowNodeStyle.getDimensions({ label, hasErrorIndicator })
+
+ const svg: SvgComponents = {
+ wrapper: oldVisual.svgElement,
+ mainShape: oldVisual.svgElement.querySelector('.flow-node__main')!,
+ iconBox: oldVisual.svgElement.querySelector('.flow-node__icon-box')!,
+ border: oldVisual.svgElement.querySelector('.flow-node__border')!,
+ label: oldVisual.svgElement.querySelector('.flow-node__label')!,
+ invalidMark: oldVisual.svgElement.querySelector('.flow-node__invalid-mark')!,
+ leftDummyPort: oldVisual.svgElement.querySelector('.flow-node__dummy-port--left'),
+ rightDummyPort: oldVisual.svgElement.querySelector('.flow-node__dummy-port--right')
+ }
+
+ if (cache.label !== label || cache.hasErrorIndicator !== hasErrorIndicator) {
+ cache.label = label
+ cache.hasErrorIndicator = hasErrorIndicator
+
+ TextRenderSupport.addText({
+ targetElement: svg.label,
+ text: label,
+ font: new Font('sans-serif', labelFontSize),
+ wrapping: TextWrapping.CHARACTER_ELLIPSIS,
+ maximumSize: new Size(maxLabelWidth, visibleHeight)
+ })
+
+ svg.label.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + iconContainerMargin + iconContainerWidth + labelHorizontalMargin
+ } ${(visibleHeight - labelHeight) / 2})`
+ )
+
+ svg.mainShape.setAttribute('width', String(visibleWidth))
+ svg.border.setAttribute('width', String(visibleWidth))
+
+ // This may fail while drag-and-dropping, which is completely fine.
+ try {
+ graph?.setNodeLayout(node as INode, new Rect(x, y, layoutWidth, layoutHeight))
+ } catch (e) {}
+ }
+
+ svg.border.setAttribute('stroke', isHovered || isSelected ? 'rgb(255, 108, 0)' : '#999999')
+ svg.border.setAttribute('stroke-width', isSelected ? '2' : '1')
+
+ svg.wrapper.setAttribute('transform', `translate(${x} ${y})`)
+
+ svg.invalidMark.style.opacity = hasErrorIndicator ? '1' : '0'
+ svg.invalidMark.setAttribute(
+ 'transform',
+ `translate(${
+ portReservedWidth + visibleWidth - errorIndicatorWidth - errorIndicatorMargin
+ } ${errorIndicatorMargin})`
+ )
+
+ // Update right port position if necessary:
+ if (cache.layoutWidth !== layoutWidth) {
+ cache.layoutWidth = layoutWidth
+ if (svg.rightDummyPort) {
+ const nodeBounds = new Rect(x, y, layoutWidth, layoutHeight)
+ FlowNodePortStyle.updateDummyPortElement({
+ element: svg.rightDummyPort,
+ nodeBounds,
+ side: 'right'
+ })
+ }
+ }
+
+ return oldVisual
+ }
+
+ protected getBounds(_context: ICanvasContext, node: unknown): Rect {
+ assertIsFlowNode(node)
+ const { label } = node.tag
+ const { x, y } = node.layout
+ const { layoutWidth, layoutHeight } = FlowNodeStyle.getDimensions({ label })
+ return new Rect(x, y, layoutWidth, layoutHeight)
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodeValidators.js b/demos/showcase/home-automation/FlowNode/FlowNodeValidators.js
new file mode 100644
index 000000000..73ed52708
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodeValidators.js
@@ -0,0 +1,165 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+/**
+ * @param {!FlowNodeProperties} _
+ * @returns {!FlowNodeValidation}
+ */
+export function defaultFlowNodeValidationFn(_) {
+ return {
+ invalidProperties: [],
+ validationMessages: []
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateStorageReadWriteNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.fileName) {
+ invalidProperties.push('fileName')
+ validationMessages.push('File name is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateParserCsvNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.separator) {
+ invalidProperties.push('separator')
+ validationMessages.push('Separator is not defined')
+ }
+ if (!args.newLine) {
+ invalidProperties.push('newLine')
+ validationMessages.push('New line symbol is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateParserJsonNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.property) {
+ invalidProperties.push('property')
+ validationMessages.push('Property value is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateParserXmlNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.property) {
+ invalidProperties.push('property')
+ validationMessages.push('Property value is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateNetworkTcpNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.server) {
+ invalidProperties.push('server')
+ validationMessages.push('Server is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateFunctionFunctionNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.function) {
+ invalidProperties.push('function')
+ validationMessages.push('No function to execute')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+/**
+ * @param {!FlowNodeProperties} args
+ * @returns {!FlowNodeValidation}
+ */
+export function validateFunctionDelayNode(args) {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.timeout) {
+ invalidProperties.push('timeout')
+ validationMessages.push('Timeout is not defined')
+ }
+ if (!args.timeoutUnits) {
+ invalidProperties.push('timeoutUnits')
+ validationMessages.push('Timeout units are not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/FlowNodeValidators.ts b/demos/showcase/home-automation/FlowNode/FlowNodeValidators.ts
new file mode 100644
index 000000000..3fb3ff089
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/FlowNodeValidators.ts
@@ -0,0 +1,135 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import { type FlowNodeProperties, type FlowNodeValidation } from './FlowNode'
+
+export function defaultFlowNodeValidationFn(_: FlowNodeProperties): FlowNodeValidation {
+ return {
+ invalidProperties: [],
+ validationMessages: []
+ }
+}
+
+export function validateStorageReadWriteNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.fileName) {
+ invalidProperties.push('fileName')
+ validationMessages.push('File name is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+export function validateParserCsvNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.separator) {
+ invalidProperties.push('separator')
+ validationMessages.push('Separator is not defined')
+ }
+ if (!args.newLine) {
+ invalidProperties.push('newLine')
+ validationMessages.push('New line symbol is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+export function validateParserJsonNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.property) {
+ invalidProperties.push('property')
+ validationMessages.push('Property value is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+export function validateParserXmlNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.property) {
+ invalidProperties.push('property')
+ validationMessages.push('Property value is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+export function validateNetworkTcpNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.server) {
+ invalidProperties.push('server')
+ validationMessages.push('Server is not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+export function validateFunctionFunctionNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.function) {
+ invalidProperties.push('function')
+ validationMessages.push('No function to execute')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
+
+export function validateFunctionDelayNode(args: FlowNodeProperties): FlowNodeValidation {
+ const invalidProperties = []
+ const validationMessages = []
+ if (!args.timeout) {
+ invalidProperties.push('timeout')
+ validationMessages.push('Timeout is not defined')
+ }
+ if (!args.timeoutUnits) {
+ invalidProperties.push('timeoutUnits')
+ validationMessages.push('Timeout units are not defined')
+ }
+ return {
+ invalidProperties,
+ validationMessages
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/flowNodeProperties.js b/demos/showcase/home-automation/FlowNode/flowNodeProperties.js
new file mode 100644
index 000000000..771e77859
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/flowNodeProperties.js
@@ -0,0 +1,222 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ defaultFlowNodeValidationFn,
+ validateFunctionDelayNode,
+ validateFunctionFunctionNode,
+ validateNetworkTcpNode,
+ validateParserCsvNode,
+ validateParserJsonNode,
+ validateParserXmlNode,
+ validateStorageReadWriteNode
+} from './FlowNodeValidators.js'
+
+export const flowNodeProperties = {
+ storageWriteFile: {
+ variant: 'storageWriteFile',
+ label: 'Write File',
+ hasLeftPort: true,
+ hasRightPort: true,
+ fileName: '',
+ validate: validateStorageReadWriteNode
+ },
+ storageReadFile: {
+ variant: 'storageReadFile',
+ label: 'Read File',
+ hasLeftPort: true,
+ hasRightPort: true,
+ fileName: '',
+ validate: validateStorageReadWriteNode
+ },
+ parserCsv: {
+ variant: 'parserCsv',
+ label: 'csv',
+ hasLeftPort: true,
+ hasRightPort: true,
+ separator: ',',
+ newLine: '\\n',
+ validate: validateParserCsvNode
+ },
+ parserJson: {
+ variant: 'parserJson',
+ label: 'json',
+ hasLeftPort: true,
+ hasRightPort: true,
+ property: 'payload',
+ pretty: false,
+ validate: validateParserJsonNode
+ },
+ parserXml: {
+ variant: 'parserXml',
+ label: 'xml',
+ hasLeftPort: true,
+ hasRightPort: true,
+ property: 'payload',
+ attribute: '',
+ validate: validateParserXmlNode
+ },
+ sequenceSort: {
+ variant: 'sequenceSort',
+ label: 'sort',
+ hasLeftPort: true,
+ hasRightPort: true,
+ order: 'ascending',
+ asNumber: false,
+ target: 'payload',
+ targetType: 'msg',
+ msgKey: 'payload',
+ msgKeyType: 'elem',
+ seqKey: 'payload',
+ seqKeyType: 'msg',
+ validate: defaultFlowNodeValidationFn
+ },
+ sequenceJoin: {
+ variant: 'sequenceJoin',
+ label: 'join',
+ hasLeftPort: true,
+ hasRightPort: true,
+ mode: 'auto',
+ build: 'object',
+ property: 'payload',
+ propertyType: 'msg',
+ key: 'topic',
+ joiner: '\\n',
+ joinerType: 'str',
+ accumulate: false,
+ timeout: '',
+ count: '',
+ reduceRight: false,
+ validate: defaultFlowNodeValidationFn
+ },
+ networkTcpIn: {
+ variant: 'networkTcpIn',
+ label: 'tcp in',
+ hasLeftPort: false,
+ hasRightPort: true,
+ server: '',
+ host: '',
+ port: '',
+ dataMode: 'stream',
+ dataType: 'buffer',
+ base64: false,
+ validate: validateNetworkTcpNode
+ },
+ networkTcpOut: {
+ variant: 'networkTcpOut',
+ label: 'tcp out',
+ hasLeftPort: true,
+ hasRightPort: false,
+ host: '',
+ port: '',
+ server: '',
+ base64: false,
+ validate: validateNetworkTcpNode
+ },
+ networkTcpRequest: {
+ variant: 'networkTcpRequest',
+ label: 'tcp request',
+ hasLeftPort: true,
+ hasRightPort: true,
+ server: 'server',
+ port: '',
+ out: 'time',
+ ret: 'buffer',
+ validate: validateNetworkTcpNode
+ },
+ functionFunction: {
+ variant: 'functionFunction',
+ label: 'function',
+ hasLeftPort: true,
+ hasRightPort: true,
+ function: 'return msg;',
+ validate: validateFunctionFunctionNode
+ },
+ functionDelay: {
+ variant: 'functionDelay',
+ label: 'delay',
+ hasLeftPort: true,
+ hasRightPort: true,
+ pauseType: 'delay',
+ timeout: '5',
+ timeoutUnits: 'seconds',
+ validate: validateFunctionDelayNode
+ },
+ functionFilter: {
+ variant: 'functionFilter',
+ label: 'filter',
+ hasLeftPort: true,
+ hasRightPort: true,
+ function: 'rbe',
+ gap: '',
+ start: '',
+ inout: 'out',
+ property: 'payload',
+ topic: 'topic',
+ validate: defaultFlowNodeValidationFn
+ },
+ commonComment: {
+ variant: 'commonComment',
+ label: 'comment',
+ hasLeftPort: false,
+ hasRightPort: false,
+ comment: '',
+ validate: defaultFlowNodeValidationFn
+ },
+ commonLinkIn: {
+ variant: 'commonLinkIn',
+ label: 'link in',
+ hasLeftPort: false,
+ hasRightPort: true,
+ validate: defaultFlowNodeValidationFn
+ },
+ commonLinkOut: {
+ variant: 'commonLinkOut',
+ label: 'link out',
+ hasLeftPort: true,
+ hasRightPort: false,
+ validate: defaultFlowNodeValidationFn
+ },
+ commonLinkCall: {
+ variant: 'commonLinkCall',
+ label: 'link call',
+ hasLeftPort: true,
+ hasRightPort: true,
+ linkType: 'static',
+ timeout: 30,
+ validate: defaultFlowNodeValidationFn
+ },
+ commonStatus: {
+ variant: 'commonStatus',
+ label: 'status',
+ hasLeftPort: false,
+ hasRightPort: true,
+ status: undefined,
+ validate: defaultFlowNodeValidationFn
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/flowNodeProperties.ts b/demos/showcase/home-automation/FlowNode/flowNodeProperties.ts
new file mode 100644
index 000000000..480788101
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/flowNodeProperties.ts
@@ -0,0 +1,223 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+import {
+ defaultFlowNodeValidationFn,
+ validateFunctionDelayNode,
+ validateFunctionFunctionNode,
+ validateNetworkTcpNode,
+ validateParserCsvNode,
+ validateParserJsonNode,
+ validateParserXmlNode,
+ validateStorageReadWriteNode
+} from './FlowNodeValidators'
+import type { FlowNodeProperties, FlowNodeVariant } from './FlowNode'
+
+export const flowNodeProperties: Record = {
+ storageWriteFile: {
+ variant: 'storageWriteFile',
+ label: 'Write File',
+ hasLeftPort: true,
+ hasRightPort: true,
+ fileName: '',
+ validate: validateStorageReadWriteNode
+ },
+ storageReadFile: {
+ variant: 'storageReadFile',
+ label: 'Read File',
+ hasLeftPort: true,
+ hasRightPort: true,
+ fileName: '',
+ validate: validateStorageReadWriteNode
+ },
+ parserCsv: {
+ variant: 'parserCsv',
+ label: 'csv',
+ hasLeftPort: true,
+ hasRightPort: true,
+ separator: ',',
+ newLine: '\\n',
+ validate: validateParserCsvNode
+ },
+ parserJson: {
+ variant: 'parserJson',
+ label: 'json',
+ hasLeftPort: true,
+ hasRightPort: true,
+ property: 'payload',
+ pretty: false,
+ validate: validateParserJsonNode
+ },
+ parserXml: {
+ variant: 'parserXml',
+ label: 'xml',
+ hasLeftPort: true,
+ hasRightPort: true,
+ property: 'payload',
+ attribute: '',
+ validate: validateParserXmlNode
+ },
+ sequenceSort: {
+ variant: 'sequenceSort',
+ label: 'sort',
+ hasLeftPort: true,
+ hasRightPort: true,
+ order: 'ascending',
+ asNumber: false,
+ target: 'payload',
+ targetType: 'msg',
+ msgKey: 'payload',
+ msgKeyType: 'elem',
+ seqKey: 'payload',
+ seqKeyType: 'msg',
+ validate: defaultFlowNodeValidationFn
+ },
+ sequenceJoin: {
+ variant: 'sequenceJoin',
+ label: 'join',
+ hasLeftPort: true,
+ hasRightPort: true,
+ mode: 'auto',
+ build: 'object',
+ property: 'payload',
+ propertyType: 'msg',
+ key: 'topic',
+ joiner: '\\n',
+ joinerType: 'str',
+ accumulate: false,
+ timeout: '',
+ count: '',
+ reduceRight: false,
+ validate: defaultFlowNodeValidationFn
+ },
+ networkTcpIn: {
+ variant: 'networkTcpIn',
+ label: 'tcp in',
+ hasLeftPort: false,
+ hasRightPort: true,
+ server: '',
+ host: '',
+ port: '',
+ dataMode: 'stream',
+ dataType: 'buffer',
+ base64: false,
+ validate: validateNetworkTcpNode
+ },
+ networkTcpOut: {
+ variant: 'networkTcpOut',
+ label: 'tcp out',
+ hasLeftPort: true,
+ hasRightPort: false,
+ host: '',
+ port: '',
+ server: '',
+ base64: false,
+ validate: validateNetworkTcpNode
+ },
+ networkTcpRequest: {
+ variant: 'networkTcpRequest',
+ label: 'tcp request',
+ hasLeftPort: true,
+ hasRightPort: true,
+ server: 'server',
+ port: '',
+ out: 'time',
+ ret: 'buffer',
+ validate: validateNetworkTcpNode
+ },
+ functionFunction: {
+ variant: 'functionFunction',
+ label: 'function',
+ hasLeftPort: true,
+ hasRightPort: true,
+ function: 'return msg;',
+ validate: validateFunctionFunctionNode
+ },
+ functionDelay: {
+ variant: 'functionDelay',
+ label: 'delay',
+ hasLeftPort: true,
+ hasRightPort: true,
+ pauseType: 'delay',
+ timeout: '5',
+ timeoutUnits: 'seconds',
+ validate: validateFunctionDelayNode
+ },
+ functionFilter: {
+ variant: 'functionFilter',
+ label: 'filter',
+ hasLeftPort: true,
+ hasRightPort: true,
+ function: 'rbe',
+ gap: '',
+ start: '',
+ inout: 'out',
+ property: 'payload',
+ topic: 'topic',
+ validate: defaultFlowNodeValidationFn
+ },
+ commonComment: {
+ variant: 'commonComment',
+ label: 'comment',
+ hasLeftPort: false,
+ hasRightPort: false,
+ comment: '',
+ validate: defaultFlowNodeValidationFn
+ },
+ commonLinkIn: {
+ variant: 'commonLinkIn',
+ label: 'link in',
+ hasLeftPort: false,
+ hasRightPort: true,
+ validate: defaultFlowNodeValidationFn
+ },
+ commonLinkOut: {
+ variant: 'commonLinkOut',
+ label: 'link out',
+ hasLeftPort: true,
+ hasRightPort: false,
+ validate: defaultFlowNodeValidationFn
+ },
+ commonLinkCall: {
+ variant: 'commonLinkCall',
+ label: 'link call',
+ hasLeftPort: true,
+ hasRightPort: true,
+ linkType: 'static',
+ timeout: 30,
+ validate: defaultFlowNodeValidationFn
+ },
+ commonStatus: {
+ variant: 'commonStatus',
+ label: 'status',
+ hasLeftPort: false,
+ hasRightPort: true,
+ status: undefined,
+ validate: defaultFlowNodeValidationFn
+ }
+}
diff --git a/demos/showcase/home-automation/FlowNode/icons.js b/demos/showcase/home-automation/FlowNode/icons.js
new file mode 100644
index 000000000..3b25f731f
--- /dev/null
+++ b/demos/showcase/home-automation/FlowNode/icons.js
@@ -0,0 +1,101 @@
+/****************************************************************************
+ ** @license
+ ** This demo file is part of yFiles for HTML 2.6.
+ ** Copyright (c) 2000-2023 by yWorks GmbH, Vor dem Kreuzberg 28,
+ ** 72070 Tuebingen, Germany. All rights reserved.
+ **
+ ** yFiles demo files exhibit yFiles for HTML functionalities. Any redistribution
+ ** of demo files in source code or binary form, with or without
+ ** modification, is not permitted.
+ **
+ ** Owners of a valid software license for a yFiles for HTML version that this
+ ** demo is shipped with are allowed to use the demo source code as basis
+ ** for their own yFiles for HTML powered applications. Use of such programs is
+ ** governed by the rights and conditions as set out in the yFiles for HTML
+ ** license agreement.
+ **
+ ** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ ** NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **
+ ***************************************************************************/
+/**
+ * @param {!object} undefined
+ * @returns {!SVGElement}
+ */
+export function getNodeIconSvg({ nodeVariant, size, color }) {
+ const svgContent = nodeIcons[nodeVariant]
+
+ const svgWrapper = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+ svgWrapper.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
+ svgWrapper.setAttribute('viewBox', `0 0 ${size} ${size}`)
+ svgWrapper.setAttribute('width', String(size))
+ svgWrapper.setAttribute('height', String(size))
+
+ // Create a