@api-client/ui 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -2
- package/test/env.ts +15 -0
- package/test/tsconfig.json +1 -7
- package/web-test-runner.config.js +5 -1
- package/build/src/visualization/elements/VizAssociationElement.d.ts +0 -4
- package/build/src/visualization/elements/VizAssociationElement.d.ts.map +0 -1
- package/build/src/visualization/elements/VizAssociationElement.js +0 -4
- package/build/src/visualization/elements/VizAssociationElement.js.map +0 -1
- package/build/src/visualization/elements/VizWorkspaceElement.d.ts +0 -110
- package/build/src/visualization/elements/VizWorkspaceElement.d.ts.map +0 -1
- package/build/src/visualization/elements/VizWorkspaceElement.js +0 -321
- package/build/src/visualization/elements/VizWorkspaceElement.js.map +0 -1
- package/build/src/visualization/elements/WorkspaceStyles.d.ts +0 -3
- package/build/src/visualization/elements/WorkspaceStyles.d.ts.map +0 -1
- package/build/src/visualization/elements/WorkspaceStyles.js +0 -168
- package/build/src/visualization/elements/WorkspaceStyles.js.map +0 -1
- package/build/src/visualization/lib/AnchorFinder.d.ts +0 -64
- package/build/src/visualization/lib/AnchorFinder.d.ts.map +0 -1
- package/build/src/visualization/lib/AnchorFinder.js +0 -107
- package/build/src/visualization/lib/AnchorFinder.js.map +0 -1
- package/build/src/visualization/lib/AnchorUtils.d.ts +0 -10
- package/build/src/visualization/lib/AnchorUtils.d.ts.map +0 -1
- package/build/src/visualization/lib/AnchorUtils.js +0 -44
- package/build/src/visualization/lib/AnchorUtils.js.map +0 -1
- package/build/src/visualization/lib/AssociationAnchors.d.ts +0 -134
- package/build/src/visualization/lib/AssociationAnchors.d.ts.map +0 -1
- package/build/src/visualization/lib/AssociationAnchors.js +0 -351
- package/build/src/visualization/lib/AssociationAnchors.js.map +0 -1
- package/build/src/visualization/lib/LabelSketch.d.ts +0 -16
- package/build/src/visualization/lib/LabelSketch.d.ts.map +0 -1
- package/build/src/visualization/lib/LabelSketch.js +0 -53
- package/build/src/visualization/lib/LabelSketch.js.map +0 -1
- package/build/src/visualization/lib/LineSketch.d.ts +0 -26
- package/build/src/visualization/lib/LineSketch.d.ts.map +0 -1
- package/build/src/visualization/lib/LineSketch.js +0 -55
- package/build/src/visualization/lib/LineSketch.js.map +0 -1
- package/build/src/visualization/lib/Point.d.ts +0 -74
- package/build/src/visualization/lib/Point.d.ts.map +0 -1
- package/build/src/visualization/lib/Point.js +0 -121
- package/build/src/visualization/lib/Point.js.map +0 -1
- package/build/src/visualization/lib/PositionUtils.d.ts +0 -65
- package/build/src/visualization/lib/PositionUtils.d.ts.map +0 -1
- package/build/src/visualization/lib/PositionUtils.js +0 -205
- package/build/src/visualization/lib/PositionUtils.js.map +0 -1
- package/build/src/visualization/lib/SelectionManager.d.ts +0 -183
- package/build/src/visualization/lib/SelectionManager.d.ts.map +0 -1
- package/build/src/visualization/lib/SelectionManager.js +0 -481
- package/build/src/visualization/lib/SelectionManager.js.map +0 -1
- package/build/src/visualization/lib/ShapeArtist.d.ts +0 -45
- package/build/src/visualization/lib/ShapeArtist.d.ts.map +0 -1
- package/build/src/visualization/lib/ShapeArtist.js +0 -209
- package/build/src/visualization/lib/ShapeArtist.js.map +0 -1
- package/build/src/visualization/lib/SvgMarkers.d.ts +0 -14
- package/build/src/visualization/lib/SvgMarkers.d.ts.map +0 -1
- package/build/src/visualization/lib/SvgMarkers.js +0 -77
- package/build/src/visualization/lib/SvgMarkers.js.map +0 -1
- package/build/src/visualization/lib/TipSketch.d.ts +0 -26
- package/build/src/visualization/lib/TipSketch.d.ts.map +0 -1
- package/build/src/visualization/lib/TipSketch.js +0 -77
- package/build/src/visualization/lib/TipSketch.js.map +0 -1
- package/build/src/visualization/lib/TouchSupport.d.ts +0 -14
- package/build/src/visualization/lib/TouchSupport.d.ts.map +0 -1
- package/build/src/visualization/lib/TouchSupport.js +0 -55
- package/build/src/visualization/lib/TouchSupport.js.map +0 -1
- package/build/src/visualization/lib/Utils.d.ts +0 -25
- package/build/src/visualization/lib/Utils.d.ts.map +0 -1
- package/build/src/visualization/lib/Utils.js +0 -59
- package/build/src/visualization/lib/Utils.js.map +0 -1
- package/build/src/visualization/lib/VisualizationTypes.d.ts +0 -216
- package/build/src/visualization/lib/VisualizationTypes.d.ts.map +0 -1
- package/build/src/visualization/lib/VisualizationTypes.js +0 -3
- package/build/src/visualization/lib/VisualizationTypes.js.map +0 -1
- package/build/src/visualization/lib/WorkspaceAlignment.d.ts +0 -51
- package/build/src/visualization/lib/WorkspaceAlignment.d.ts.map +0 -1
- package/build/src/visualization/lib/WorkspaceAlignment.js +0 -243
- package/build/src/visualization/lib/WorkspaceAlignment.js.map +0 -1
- package/build/src/visualization/lib/WorkspaceDebugging.d.ts +0 -104
- package/build/src/visualization/lib/WorkspaceDebugging.d.ts.map +0 -1
- package/build/src/visualization/lib/WorkspaceDebugging.js +0 -286
- package/build/src/visualization/lib/WorkspaceDebugging.js.map +0 -1
- package/build/src/visualization/lib/WorkspaceEdges.d.ts +0 -293
- package/build/src/visualization/lib/WorkspaceEdges.d.ts.map +0 -1
- package/build/src/visualization/lib/WorkspaceEdges.js +0 -1073
- package/build/src/visualization/lib/WorkspaceEdges.js.map +0 -1
- package/build/src/visualization/lib/WorkspaceGestures.d.ts +0 -119
- package/build/src/visualization/lib/WorkspaceGestures.d.ts.map +0 -1
- package/build/src/visualization/lib/WorkspaceGestures.js +0 -376
- package/build/src/visualization/lib/WorkspaceGestures.js.map +0 -1
- package/build/src/visualization/lib/WorkspaceSizing.d.ts +0 -66
- package/build/src/visualization/lib/WorkspaceSizing.d.ts.map +0 -1
- package/build/src/visualization/lib/WorkspaceSizing.js +0 -168
- package/build/src/visualization/lib/WorkspaceSizing.js.map +0 -1
- package/build/src/visualization/lib/lines/RectilinearLine.d.ts +0 -114
- package/build/src/visualization/lib/lines/RectilinearLine.d.ts.map +0 -1
- package/build/src/visualization/lib/lines/RectilinearLine.js +0 -605
- package/build/src/visualization/lib/lines/RectilinearLine.js.map +0 -1
- package/build/src/visualization/lib/tips/RectilinearTip.d.ts +0 -26
- package/build/src/visualization/lib/tips/RectilinearTip.d.ts.map +0 -1
- package/build/src/visualization/lib/tips/RectilinearTip.js +0 -149
- package/build/src/visualization/lib/tips/RectilinearTip.js.map +0 -1
- package/build/src/visualization/lib/tips/TipArtist.d.ts +0 -22
- package/build/src/visualization/lib/tips/TipArtist.d.ts.map +0 -1
- package/build/src/visualization/lib/tips/TipArtist.js +0 -31
- package/build/src/visualization/lib/tips/TipArtist.js.map +0 -1
- package/build/src/visualization/lib/types.d.ts +0 -164
- package/build/src/visualization/lib/types.d.ts.map +0 -1
- package/build/src/visualization/lib/types.js +0 -2
- package/build/src/visualization/lib/types.js.map +0 -1
- package/build/src/visualization/plugin/dnd/DragAndDropPlugin.d.ts +0 -126
- package/build/src/visualization/plugin/dnd/DragAndDropPlugin.d.ts.map +0 -1
- package/build/src/visualization/plugin/dnd/DragAndDropPlugin.js +0 -260
- package/build/src/visualization/plugin/dnd/DragAndDropPlugin.js.map +0 -1
- package/build/src/visualization/plugin/group-selection/GroupSelection.d.ts +0 -93
- package/build/src/visualization/plugin/group-selection/GroupSelection.d.ts.map +0 -1
- package/build/src/visualization/plugin/group-selection/GroupSelection.js +0 -250
- package/build/src/visualization/plugin/group-selection/GroupSelection.js.map +0 -1
- package/build/src/visualization/plugin/positioning/DataModelLayout.d.ts +0 -10
- package/build/src/visualization/plugin/positioning/DataModelLayout.d.ts.map +0 -1
- package/build/src/visualization/plugin/positioning/DataModelLayout.js +0 -105
- package/build/src/visualization/plugin/positioning/DataModelLayout.js.map +0 -1
- package/build/src/visualization/plugin/positioning/WorkspaceLayout.d.ts +0 -93
- package/build/src/visualization/plugin/positioning/WorkspaceLayout.d.ts.map +0 -1
- package/build/src/visualization/plugin/positioning/WorkspaceLayout.js +0 -96
- package/build/src/visualization/plugin/positioning/WorkspaceLayout.js.map +0 -1
- package/build/src/visualization/viz-association.d.ts +0 -7
- package/build/src/visualization/viz-association.d.ts.map +0 -1
- package/build/src/visualization/viz-association.js +0 -3
- package/build/src/visualization/viz-association.js.map +0 -1
- package/build/src/visualization/viz-workspace.d.ts +0 -7
- package/build/src/visualization/viz-workspace.d.ts.map +0 -1
- package/build/src/visualization/viz-workspace.js +0 -3
- package/build/src/visualization/viz-workspace.js.map +0 -1
- package/src/visualization/elements/VizAssociationElement.ts +0 -3
- package/src/visualization/elements/VizWorkspaceElement.ts +0 -302
- package/src/visualization/elements/WorkspaceStyles.ts +0 -168
- package/src/visualization/lib/AnchorFinder.ts +0 -112
- package/src/visualization/lib/AnchorUtils.ts +0 -53
- package/src/visualization/lib/AssociationAnchors.ts +0 -418
- package/src/visualization/lib/LabelSketch.ts +0 -67
- package/src/visualization/lib/LineSketch.ts +0 -62
- package/src/visualization/lib/Point.ts +0 -134
- package/src/visualization/lib/PositionUtils.ts +0 -218
- package/src/visualization/lib/SelectionManager.ts +0 -513
- package/src/visualization/lib/ShapeArtist.ts +0 -222
- package/src/visualization/lib/SvgMarkers.ts +0 -80
- package/src/visualization/lib/TipSketch.ts +0 -91
- package/src/visualization/lib/TouchSupport.ts +0 -72
- package/src/visualization/lib/Utils.ts +0 -63
- package/src/visualization/lib/VisualizationTypes.ts +0 -232
- package/src/visualization/lib/WorkspaceAlignment.ts +0 -261
- package/src/visualization/lib/WorkspaceDebugging.ts +0 -313
- package/src/visualization/lib/WorkspaceEdges.ts +0 -1153
- package/src/visualization/lib/WorkspaceGestures.ts +0 -400
- package/src/visualization/lib/WorkspaceSizing.ts +0 -181
- package/src/visualization/lib/lines/RectilinearLine.ts +0 -589
- package/src/visualization/lib/tips/RectilinearTip.ts +0 -156
- package/src/visualization/lib/tips/TipArtist.ts +0 -34
- package/src/visualization/lib/types.ts +0 -173
- package/src/visualization/plugin/dnd/DragAndDropPlugin.ts +0 -294
- package/src/visualization/plugin/group-selection/GroupSelection.ts +0 -271
- package/src/visualization/plugin/positioning/DataModelLayout.ts +0 -114
- package/src/visualization/plugin/positioning/WorkspaceLayout.ts +0 -149
- package/src/visualization/viz-association.ts +0 -9
- package/src/visualization/viz-workspace.ts +0 -9
- package/test/env.d.ts +0 -9
- package/test/env.js +0 -7
- package/test/visualization/lib/AnchorFinder.test.ts +0 -313
- package/test/visualization/lib/AnchorUtils.test.ts +0 -178
- package/test/visualization/lib/PositionUtils.test.ts +0 -406
- package/test/visualization/lib/test-styles.css +0 -80
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
-
import VizWorkspaceElement from '../../elements/VizWorkspaceElement.js'
|
|
3
|
-
import { Point } from '../../lib/Point.js'
|
|
4
|
-
import { getRelativeClickPoint, getObjectBoundingClientRect } from '../../lib/PositionUtils.js'
|
|
5
|
-
|
|
6
|
-
export const mouseDownHandler = Symbol('mouseDownHandler')
|
|
7
|
-
export const mouseUpHandler = Symbol('mouseUpHandler')
|
|
8
|
-
export const mouseMoveHandler = Symbol('mouseMoveHandler')
|
|
9
|
-
export const connectedValue = Symbol('connectedValue')
|
|
10
|
-
|
|
11
|
-
const CLS = 'selection-zone'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A plugin that adds support for a group selection via pointer device on the visualization workspace.
|
|
15
|
-
*
|
|
16
|
-
* This plugin draws a selection rectangle from the starting position until the pointer is released.
|
|
17
|
-
* Each selectable element that is inside the rectangle is selected.
|
|
18
|
-
*
|
|
19
|
-
* After the modeling workspace is created create instance of this class and call `connect()` function
|
|
20
|
-
* to start listening for the events. Call `disconnect()` when the workspace is no longer in use.
|
|
21
|
-
*/
|
|
22
|
-
export class GroupSelection {
|
|
23
|
-
[connectedValue] = false
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @returns True when the plug-in is listening for the input events.
|
|
27
|
-
*/
|
|
28
|
-
get connected(): boolean {
|
|
29
|
-
return this[connectedValue]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Whether a selection is currently being made.
|
|
34
|
-
*/
|
|
35
|
-
selecting = false
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The element that is being rendered as a selection box.
|
|
39
|
-
*/
|
|
40
|
-
selectionZone: HTMLDivElement | null = null
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* The click start point
|
|
44
|
-
*/
|
|
45
|
-
startPoint: Point | null = null
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The position delta between the start and the current pointer position.
|
|
49
|
-
*/
|
|
50
|
-
delta: Point | null = null
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @param target The target workspace element.
|
|
54
|
-
*/
|
|
55
|
-
constructor(public target: VizWorkspaceElement) {
|
|
56
|
-
this[mouseUpHandler] = this[mouseUpHandler].bind(this)
|
|
57
|
-
this[mouseDownHandler] = this[mouseDownHandler].bind(this)
|
|
58
|
-
this[mouseMoveHandler] = this[mouseMoveHandler].bind(this)
|
|
59
|
-
this[connectedValue] = false
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
connect(): void {
|
|
63
|
-
this.target.addEventListener('mousedown', this[mouseDownHandler])
|
|
64
|
-
document.body.addEventListener('mouseup', this[mouseUpHandler])
|
|
65
|
-
document.body.addEventListener('mousemove', this[mouseMoveHandler])
|
|
66
|
-
this[connectedValue] = true
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
disconnect(): void {
|
|
70
|
-
this.target.removeEventListener('mousedown', this[mouseDownHandler])
|
|
71
|
-
document.body.removeEventListener('mouseup', this[mouseUpHandler])
|
|
72
|
-
document.body.removeEventListener('mousemove', this[mouseMoveHandler])
|
|
73
|
-
this[connectedValue] = false
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
reset(): void {
|
|
77
|
-
this.startPoint = null
|
|
78
|
-
this.delta = null
|
|
79
|
-
this.selectionZone = null
|
|
80
|
-
this.selecting = false
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
[mouseDownHandler](e: MouseEvent): void {
|
|
84
|
-
if (e.target !== this.target || e.button !== 0) {
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
// e.preventDefault();
|
|
88
|
-
this.selecting = true
|
|
89
|
-
this.startPoint = this.pointFromEvent(e)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
[mouseMoveHandler](e: MouseEvent): void {
|
|
93
|
-
if (!this.selecting) {
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
if (!this.selectionZone) {
|
|
97
|
-
this.appendSelectionZone(this.startPoint!)
|
|
98
|
-
}
|
|
99
|
-
const current = this.pointFromEvent(e)
|
|
100
|
-
this.updateSelectionSize(current)
|
|
101
|
-
// // See notes in this function.
|
|
102
|
-
this.detectEdges(e)
|
|
103
|
-
this.detectSelected()
|
|
104
|
-
e.preventDefault()
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
[mouseUpHandler](e: MouseEvent): void {
|
|
108
|
-
if (!this.selecting) {
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
this.clearWorkspace()
|
|
112
|
-
this.reset()
|
|
113
|
-
e.preventDefault()
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Removes the selection rectangle from the workspace
|
|
118
|
-
*/
|
|
119
|
-
clearWorkspace(): void {
|
|
120
|
-
const target = this.target.canvas!
|
|
121
|
-
const nodes = target.querySelectorAll(`.${CLS}`)
|
|
122
|
-
Array.from(nodes).forEach((n) => target.removeChild(n))
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Handles the drop event on one of the children.
|
|
127
|
-
* @returns coordinates of the click on the workspace as it would be
|
|
128
|
-
* not scaled.
|
|
129
|
-
*/
|
|
130
|
-
pointFromEvent(e: MouseEvent): Point {
|
|
131
|
-
const { clientX, clientY } = e
|
|
132
|
-
return getRelativeClickPoint(clientX, clientY, this.target)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Adds a selection box in the place of the click.
|
|
137
|
-
* @param position The starting position of the element.
|
|
138
|
-
*/
|
|
139
|
-
appendSelectionZone(position: Point): void {
|
|
140
|
-
const selectionZone = document.createElement('div')
|
|
141
|
-
selectionZone.classList.add(CLS)
|
|
142
|
-
const { x, y } = position
|
|
143
|
-
selectionZone.style.top = `${y}px`
|
|
144
|
-
selectionZone.style.left = `${x}px`
|
|
145
|
-
this.target.canvas!.append(selectionZone)
|
|
146
|
-
this.selectionZone = selectionZone
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Moves the workspace if needed.
|
|
151
|
-
*/
|
|
152
|
-
detectEdges(e: MouseEvent): void {
|
|
153
|
-
const { clientX, clientY } = e
|
|
154
|
-
this.target.scrollIfNeeded(clientX, clientY)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Redraws the selection rectangle to current point
|
|
159
|
-
* @param {Point} current
|
|
160
|
-
*/
|
|
161
|
-
updateSelectionSize(current: Point): void {
|
|
162
|
-
const { x: x1, y: y1 } = this.startPoint!
|
|
163
|
-
const { x: x2, y: y2 } = current
|
|
164
|
-
const dx = x2 - x1
|
|
165
|
-
const dy = y2 - y1
|
|
166
|
-
if (dx >= 0) {
|
|
167
|
-
this.selectionZone!.style.width = `${dx}px`
|
|
168
|
-
} else {
|
|
169
|
-
this.selectionZone!.style.width = `${Math.abs(dx)}px`
|
|
170
|
-
const xPos = x1 + dx
|
|
171
|
-
this.selectionZone!.style.left = `${xPos}px`
|
|
172
|
-
}
|
|
173
|
-
if (dy >= 0) {
|
|
174
|
-
this.selectionZone!.style.height = `${dy}px`
|
|
175
|
-
} else {
|
|
176
|
-
this.selectionZone!.style.height = `${Math.abs(dy)}px`
|
|
177
|
-
const yPos = y1 + dy
|
|
178
|
-
this.selectionZone!.style.top = `${yPos}px`
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
detectSelected(): void {
|
|
183
|
-
const selectionManager = this.target.selection
|
|
184
|
-
const items = selectionManager.selectable
|
|
185
|
-
if (!items.length) {
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
const selected: Element[] = []
|
|
189
|
-
const rect = this.getSelectionRect()
|
|
190
|
-
items.forEach((node) => {
|
|
191
|
-
const box = getObjectBoundingClientRect(node, this.target)
|
|
192
|
-
if (this.collide(rect, box)) {
|
|
193
|
-
selected.push(node)
|
|
194
|
-
}
|
|
195
|
-
})
|
|
196
|
-
const targetSelected: Element[] = []
|
|
197
|
-
selectionManager.selected.forEach((i) => {
|
|
198
|
-
if (selectionManager.isSelectable(i.node)) {
|
|
199
|
-
targetSelected.push(i.node)
|
|
200
|
-
}
|
|
201
|
-
})
|
|
202
|
-
if (selected.length === targetSelected.length) {
|
|
203
|
-
// This is a possible optimization to reduce number of computations.
|
|
204
|
-
// Assumption is being made that the actual change can only be made
|
|
205
|
-
// when adding or removing a selection (one by one) as the selection
|
|
206
|
-
// would have to at the same time select a rectangle and deselect another
|
|
207
|
-
// which probably is impossible (?).
|
|
208
|
-
return
|
|
209
|
-
}
|
|
210
|
-
if (selected.length > 0) {
|
|
211
|
-
targetSelected.forEach((node) => {
|
|
212
|
-
if (!selected.includes(node) && selectionManager.isSelected(node)) {
|
|
213
|
-
selectionManager.setUnselected(node)
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
selected.forEach((node) => {
|
|
217
|
-
if (!selectionManager.isSelected(node)) {
|
|
218
|
-
selectionManager.setSelected(node)
|
|
219
|
-
}
|
|
220
|
-
})
|
|
221
|
-
} else if (targetSelected.length) {
|
|
222
|
-
targetSelected.forEach((node) => selectionManager.setUnselected(node))
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Reads scaled selection rectangle
|
|
228
|
-
* @return A DOMRect object for the selection rectangle
|
|
229
|
-
*/
|
|
230
|
-
getSelectionRect(): DOMRect {
|
|
231
|
-
const node = this.selectionZone!
|
|
232
|
-
const top = this.getSafeStyleValue(node, 'top')
|
|
233
|
-
const left = this.getSafeStyleValue(node, 'left')
|
|
234
|
-
const width = this.getSafeStyleValue(node, 'width')
|
|
235
|
-
const height = this.getSafeStyleValue(node, 'height')
|
|
236
|
-
return new DOMRect(left, top, width, height)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* @param node The node to read the style property from.
|
|
241
|
-
* @param prop The name of the css property to read
|
|
242
|
-
* @returns The value of the property or 0 if not found.
|
|
243
|
-
*/
|
|
244
|
-
getSafeStyleValue(node: HTMLElement, prop: string): number {
|
|
245
|
-
let value = node.style.getPropertyValue(prop)
|
|
246
|
-
if (!value) {
|
|
247
|
-
return 0
|
|
248
|
-
}
|
|
249
|
-
value = value.replace('px', '')
|
|
250
|
-
const result = Number(value)
|
|
251
|
-
if (Number.isNaN(result)) {
|
|
252
|
-
return 0
|
|
253
|
-
}
|
|
254
|
-
return result
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Tests whether a current node collides with the selection rectangle.
|
|
259
|
-
* @param selectionRect The selection computed rectangle
|
|
260
|
-
* @param rect The Rect of the target element.
|
|
261
|
-
* @returns True if the selection rectangle collides with `node`
|
|
262
|
-
*/
|
|
263
|
-
collide(selectionRect: DOMRect, rect: DOMRect): boolean {
|
|
264
|
-
const { x: x1, y: y1, width: w1, height: h1 } = selectionRect
|
|
265
|
-
const { x: x2, y: y2, width: w2, height: h2 } = rect
|
|
266
|
-
if (x1 < x2 + w2 && x1 + w1 > x2 && y1 < y2 + h2 && y1 + h1 > y2) {
|
|
267
|
-
return true
|
|
268
|
-
}
|
|
269
|
-
return false
|
|
270
|
-
}
|
|
271
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
-
import { type Graph } from '@api-client/graph/graph/Graph.js'
|
|
3
|
-
import layout from '@api-client/graph/layout/layout.js'
|
|
4
|
-
import { type EdgeConfig, type GraphLabel, type NodeConfig } from '@api-client/graph/layout/types.js'
|
|
5
|
-
import { LayoutWeight, type PositioningResult, type PositionResult, WorkspaceLayout } from './WorkspaceLayout.js'
|
|
6
|
-
import { type DataModel } from '@api-client/core/legacy.js'
|
|
7
|
-
|
|
8
|
-
export class DataModelLayout extends WorkspaceLayout {
|
|
9
|
-
layout(model: DataModel): PositioningResult | null {
|
|
10
|
-
const { entities } = model
|
|
11
|
-
if (!entities.length) {
|
|
12
|
-
return null
|
|
13
|
-
}
|
|
14
|
-
this.readPositions = {}
|
|
15
|
-
const g = this.initGraph()
|
|
16
|
-
|
|
17
|
-
const selfEntities = entities.map((i) => i.key)
|
|
18
|
-
const addedEntities: string[] = []
|
|
19
|
-
|
|
20
|
-
// parents first
|
|
21
|
-
entities.forEach((entity) => {
|
|
22
|
-
if (!this.ensureAddEntity(g, entity.key)) {
|
|
23
|
-
return
|
|
24
|
-
}
|
|
25
|
-
addedEntities.push(entity.key)
|
|
26
|
-
entity.parents.forEach((id) => {
|
|
27
|
-
if (selfEntities.includes(id) || addedEntities.includes(id) || g.node(id)) {
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
this.ensureAddEntity(g, id)
|
|
31
|
-
const config: EdgeConfig = {
|
|
32
|
-
minLen: 1,
|
|
33
|
-
weight: LayoutWeight.Parent,
|
|
34
|
-
}
|
|
35
|
-
g.setEdge(entity.key, id, config)
|
|
36
|
-
})
|
|
37
|
-
entity.associations.forEach((item) => {
|
|
38
|
-
const targets = item.getTargets()
|
|
39
|
-
if (!targets.length) {
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
if (targets.length === 1) {
|
|
43
|
-
// classic association
|
|
44
|
-
const [target] = targets
|
|
45
|
-
this.ensureAddEntity(g, target.key)
|
|
46
|
-
addedEntities.push(target.key)
|
|
47
|
-
// TODO: Union layout.
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
// once all entities are set we can add edges
|
|
52
|
-
entities.forEach((entity) => {
|
|
53
|
-
entity.associations.forEach((item) => {
|
|
54
|
-
const targets = item.getTargets()
|
|
55
|
-
if (!targets.length) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
if (targets.length === 1) {
|
|
59
|
-
// classic association
|
|
60
|
-
const [target] = targets
|
|
61
|
-
const isSelf = target === entity
|
|
62
|
-
const config: EdgeConfig = {
|
|
63
|
-
minLen: 2,
|
|
64
|
-
weight: isSelf ? LayoutWeight.Self : LayoutWeight.Internal,
|
|
65
|
-
}
|
|
66
|
-
g.setEdge(entity.key, target.key, config)
|
|
67
|
-
} else {
|
|
68
|
-
// TODO: Union layout.
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
layout(g)
|
|
74
|
-
|
|
75
|
-
const nodes: PositionResult[] = []
|
|
76
|
-
g.nodes().forEach((id) => {
|
|
77
|
-
const def = g.node(id)!
|
|
78
|
-
if (!def) {
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
const result: NodeConfig = { ...def }
|
|
82
|
-
result.x! -= Math.round(result.width! / 2)
|
|
83
|
-
result.y! -= Math.round(result.height! / 2)
|
|
84
|
-
nodes.push({
|
|
85
|
-
id,
|
|
86
|
-
node: result,
|
|
87
|
-
})
|
|
88
|
-
})
|
|
89
|
-
return {
|
|
90
|
-
graph: g,
|
|
91
|
-
nodes,
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
addEntityNode(graph: Graph<GraphLabel, NodeConfig, EdgeConfig>, key: string, rect: DOMRect): void {
|
|
96
|
-
const { width, height } = rect
|
|
97
|
-
graph.setNode(key, {
|
|
98
|
-
width,
|
|
99
|
-
height,
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
ensureAddEntity(graph: Graph<GraphLabel, NodeConfig, EdgeConfig>, entityKey: string): boolean {
|
|
104
|
-
if (graph.node(entityKey)) {
|
|
105
|
-
return false
|
|
106
|
-
}
|
|
107
|
-
const position = this.readDimensions(entityKey)
|
|
108
|
-
if (!position) {
|
|
109
|
-
return false
|
|
110
|
-
}
|
|
111
|
-
this.addEntityNode(graph, entityKey, position)
|
|
112
|
-
return true
|
|
113
|
-
}
|
|
114
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { Graph } from '@api-client/graph/graph/Graph.js'
|
|
2
|
-
import type {
|
|
3
|
-
EdgeConfig,
|
|
4
|
-
NodeConfig,
|
|
5
|
-
GraphLabel,
|
|
6
|
-
RankDirOptions,
|
|
7
|
-
AlignOptions,
|
|
8
|
-
RankerOptions,
|
|
9
|
-
AcyclicerOptions,
|
|
10
|
-
} from '@api-client/graph/layout/types.js'
|
|
11
|
-
import VizWorkspaceElement from '../../elements/VizWorkspaceElement.js'
|
|
12
|
-
import { getObjectBoundingClientRect } from '../../lib/PositionUtils.js'
|
|
13
|
-
|
|
14
|
-
export interface PositionedEdge {
|
|
15
|
-
/**
|
|
16
|
-
* The width of the label
|
|
17
|
-
*/
|
|
18
|
-
width?: number
|
|
19
|
-
/**
|
|
20
|
-
* The height of the label
|
|
21
|
-
*/
|
|
22
|
-
height?: number
|
|
23
|
-
/**
|
|
24
|
-
* The Id of the originating node
|
|
25
|
-
*/
|
|
26
|
-
id: string
|
|
27
|
-
/**
|
|
28
|
-
* The id of the target node
|
|
29
|
-
*/
|
|
30
|
-
target: string
|
|
31
|
-
/**
|
|
32
|
-
* Edge's weight, if possible to determine
|
|
33
|
-
*/
|
|
34
|
-
weight?: number
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface PositionResult {
|
|
38
|
-
id: string
|
|
39
|
-
node: NodeConfig
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface PositioningResult {
|
|
43
|
-
graph: Graph<GraphLabel, NodeConfig, EdgeConfig>
|
|
44
|
-
nodes: PositionResult[]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// 01 - external association
|
|
48
|
-
// 10 - association (internal)
|
|
49
|
-
// 20 - parent association
|
|
50
|
-
// 40 - self association
|
|
51
|
-
export enum LayoutWeight {
|
|
52
|
-
External = 1,
|
|
53
|
-
Internal = 10,
|
|
54
|
-
Parent = 40,
|
|
55
|
-
Self = 80,
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* A helper library that computes positioning of a data model
|
|
60
|
-
* in the visualization workspace.
|
|
61
|
-
*/
|
|
62
|
-
export class WorkspaceLayout {
|
|
63
|
-
readPositions: Record<string, DOMRect> = {}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Direction for rank nodes. Can be TB, BT, LR, or RL, where T = top, B = bottom, L = left, and R = right.
|
|
67
|
-
*/
|
|
68
|
-
rankDir?: RankDirOptions
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Alignment for rank nodes. Can be UL, UR, DL, or DR, where U = up, D = down, L = left, and R = right.
|
|
72
|
-
*/
|
|
73
|
-
align?: AlignOptions
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Type of algorithm to assign a rank to each node in the input graph.
|
|
77
|
-
*/
|
|
78
|
-
ranker?: RankerOptions
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* If set to greedy, uses a greedy heuristic for finding a feedback arc set for a graph.
|
|
82
|
-
* A feedback arc set is a set of edges that can be removed to make a graph acyclic.
|
|
83
|
-
*/
|
|
84
|
-
acyclicer?: AcyclicerOptions
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Number of pixels that separate edges horizontally in the layout.
|
|
88
|
-
*/
|
|
89
|
-
edgeSeparation = 20
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Number of pixels between each rank in the layout.
|
|
93
|
-
*/
|
|
94
|
-
rankSeparation = 60 // 80
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Number of pixels that separate nodes horizontally in the layout.
|
|
98
|
-
*/
|
|
99
|
-
nodeSeparation = 60 // 80
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Graph margin LR
|
|
103
|
-
*/
|
|
104
|
-
marginX = 40
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Graph margin TB
|
|
108
|
-
*/
|
|
109
|
-
marginY = 40
|
|
110
|
-
|
|
111
|
-
constructor(public workspace: VizWorkspaceElement) {}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Reads workspace object dimensions
|
|
115
|
-
* @param {string} id Domain id of the object
|
|
116
|
-
* @returns {DOMRect}
|
|
117
|
-
*/
|
|
118
|
-
readDimensions(id: string): DOMRect | undefined {
|
|
119
|
-
if (this.readPositions[id]) {
|
|
120
|
-
return this.readPositions[id]
|
|
121
|
-
}
|
|
122
|
-
const element = this.workspace.querySelector(`[data-key="${id}"]`)
|
|
123
|
-
if (!element) {
|
|
124
|
-
return undefined
|
|
125
|
-
}
|
|
126
|
-
const rect = getObjectBoundingClientRect(element, this.workspace)
|
|
127
|
-
this.readPositions[id] = rect
|
|
128
|
-
return rect
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
initGraph(): Graph<GraphLabel, NodeConfig, EdgeConfig> {
|
|
132
|
-
const g = new Graph<GraphLabel, NodeConfig, EdgeConfig>()
|
|
133
|
-
const { rankDir, align, ranker, acyclicer, edgeSeparation, rankSeparation, nodeSeparation, marginX, marginY } = this
|
|
134
|
-
g.setGraph({
|
|
135
|
-
edgeSeparation,
|
|
136
|
-
rankSeparation,
|
|
137
|
-
nodeSeparation,
|
|
138
|
-
rankDir,
|
|
139
|
-
align,
|
|
140
|
-
ranker,
|
|
141
|
-
acyclicer,
|
|
142
|
-
marginX,
|
|
143
|
-
marginY,
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
// g.setDefaultEdgeLabel(() => { return {}; });
|
|
147
|
-
return g
|
|
148
|
-
}
|
|
149
|
-
}
|
package/test/env.d.ts
DELETED