@zenfg/inspector 0.1.0-beta.2 → 0.1.0-beta.4
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/GUIDE.md +182 -0
- package/README.md +60 -26
- package/THEMING.md +124 -0
- package/dist/FrameGraphInspector.d.ts +24 -8
- package/dist/FrameGraphInspector.d.ts.map +1 -1
- package/dist/FrameGraphInspector.js +151 -65
- package/dist/FrameGraphInspector.js.map +1 -1
- package/dist/capture.d.ts +5 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +2 -0
- package/dist/capture.js.map +1 -0
- package/dist/debugCaptureModel.d.ts +28 -4
- package/dist/debugCaptureModel.d.ts.map +1 -1
- package/dist/debugCaptureModel.js +72 -16
- package/dist/debugCaptureModel.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/panelAliasAnalysis.d.ts +1 -0
- package/dist/panelAliasAnalysis.d.ts.map +1 -1
- package/dist/panelAliasAnalysis.js +23 -54
- package/dist/panelAliasAnalysis.js.map +1 -1
- package/dist/panelCytoscapeGraphRenderer.d.ts +18 -3
- package/dist/panelCytoscapeGraphRenderer.d.ts.map +1 -1
- package/dist/panelCytoscapeGraphRenderer.js +183 -41
- package/dist/panelCytoscapeGraphRenderer.js.map +1 -1
- package/dist/panelDetailLayout.d.ts +27 -0
- package/dist/panelDetailLayout.d.ts.map +1 -0
- package/dist/panelDetailLayout.js +174 -0
- package/dist/panelDetailLayout.js.map +1 -0
- package/dist/panelDetailStyles.d.ts +2 -0
- package/dist/panelDetailStyles.d.ts.map +1 -0
- package/dist/panelDetailStyles.js +57 -0
- package/dist/panelDetailStyles.js.map +1 -0
- package/dist/panelDiagnosticsView.d.ts +10 -1
- package/dist/panelDiagnosticsView.d.ts.map +1 -1
- package/dist/panelDiagnosticsView.js +167 -58
- package/dist/panelDiagnosticsView.js.map +1 -1
- package/dist/panelDomHelpers.d.ts.map +1 -1
- package/dist/panelDomHelpers.js +6 -5
- package/dist/panelDomHelpers.js.map +1 -1
- package/dist/panelGraphLayout.d.ts +3 -2
- package/dist/panelGraphLayout.d.ts.map +1 -1
- package/dist/panelGraphLayout.js +20 -5
- package/dist/panelGraphLayout.js.map +1 -1
- package/dist/panelGraphRenderer.d.ts +10 -0
- package/dist/panelGraphRenderer.d.ts.map +1 -1
- package/dist/panelGraphRenderer.js.map +1 -1
- package/dist/panelGraphScene.d.ts +15 -26
- package/dist/panelGraphScene.d.ts.map +1 -1
- package/dist/panelGraphScene.js +191 -208
- package/dist/panelGraphScene.js.map +1 -1
- package/dist/panelGraphSearch.d.ts +16 -0
- package/dist/panelGraphSearch.d.ts.map +1 -0
- package/dist/panelGraphSearch.js +93 -0
- package/dist/panelGraphSearch.js.map +1 -0
- package/dist/panelGraphView.d.ts +82 -0
- package/dist/panelGraphView.d.ts.map +1 -1
- package/dist/panelGraphView.js +42 -9
- package/dist/panelGraphView.js.map +1 -1
- package/dist/panelGraphVisuals.d.ts +18 -6
- package/dist/panelGraphVisuals.d.ts.map +1 -1
- package/dist/panelGraphVisuals.js +156 -116
- package/dist/panelGraphVisuals.js.map +1 -1
- package/dist/panelInspectorView.d.ts +13 -0
- package/dist/panelInspectorView.d.ts.map +1 -1
- package/dist/panelInspectorView.js +326 -46
- package/dist/panelInspectorView.js.map +1 -1
- package/dist/panelListStyles.d.ts +3 -0
- package/dist/panelListStyles.d.ts.map +1 -0
- package/dist/panelListStyles.js +155 -0
- package/dist/panelListStyles.js.map +1 -0
- package/dist/panelMemoryStyles.d.ts +3 -0
- package/dist/panelMemoryStyles.d.ts.map +1 -0
- package/dist/panelMemoryStyles.js +42 -0
- package/dist/panelMemoryStyles.js.map +1 -0
- package/dist/panelMemoryView.d.ts +13 -1
- package/dist/panelMemoryView.d.ts.map +1 -1
- package/dist/panelMemoryView.js +161 -41
- package/dist/panelMemoryView.js.map +1 -1
- package/dist/panelPassesView.d.ts +15 -0
- package/dist/panelPassesView.d.ts.map +1 -1
- package/dist/panelPassesView.js +202 -72
- package/dist/panelPassesView.js.map +1 -1
- package/dist/panelRawView.d.ts +15 -0
- package/dist/panelRawView.d.ts.map +1 -0
- package/dist/panelRawView.js +105 -0
- package/dist/panelRawView.js.map +1 -0
- package/dist/panelResourcesView.d.ts +8 -0
- package/dist/panelResourcesView.d.ts.map +1 -1
- package/dist/panelResourcesView.js +62 -31
- package/dist/panelResourcesView.js.map +1 -1
- package/dist/panelSelection.d.ts +9 -1
- package/dist/panelSelection.d.ts.map +1 -1
- package/dist/panelSelection.js +36 -6
- package/dist/panelSelection.js.map +1 -1
- package/dist/panelTheme.d.ts +13 -0
- package/dist/panelTheme.d.ts.map +1 -0
- package/dist/panelTheme.js +104 -0
- package/dist/panelTheme.js.map +1 -0
- package/dist/panelTypes.d.ts +18 -4
- package/dist/panelTypes.d.ts.map +1 -1
- package/dist/panelTypes.js.map +1 -1
- package/dist/panelVisualTheme.d.ts +176 -71
- package/dist/panelVisualTheme.d.ts.map +1 -1
- package/dist/panelVisualTheme.js +34 -36
- package/dist/panelVisualTheme.js.map +1 -1
- package/dist/panelWorkbenchHelpers.d.ts +12 -1
- package/dist/panelWorkbenchHelpers.d.ts.map +1 -1
- package/dist/panelWorkbenchHelpers.js +63 -2
- package/dist/panelWorkbenchHelpers.js.map +1 -1
- package/dist/panelWorkbenchStyles.d.ts +2 -0
- package/dist/panelWorkbenchStyles.d.ts.map +1 -0
- package/dist/panelWorkbenchStyles.js +101 -0
- package/dist/panelWorkbenchStyles.js.map +1 -0
- package/dist/panelWorkbenchView.d.ts +16 -0
- package/dist/panelWorkbenchView.d.ts.map +1 -1
- package/dist/panelWorkbenchView.js +228 -50
- package/dist/panelWorkbenchView.js.map +1 -1
- package/dist/query.js.map +1 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +161 -205
- package/dist/styles.js.map +1 -1
- package/dist/theme.d.ts +22 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +10 -0
- package/dist/theme.js.map +1 -0
- package/dist/themeDefinitions.d.ts +251 -0
- package/dist/themeDefinitions.d.ts.map +1 -0
- package/dist/themeDefinitions.js +96 -0
- package/dist/themeDefinitions.js.map +1 -0
- package/dist/themePalette.d.ts +66 -0
- package/dist/themePalette.d.ts.map +1 -0
- package/dist/themePalette.js +37 -0
- package/dist/themePalette.js.map +1 -0
- package/dist/themes.css +165 -0
- package/package.json +44 -10
- package/src/FrameGraphInspector.ts +145 -68
- package/src/capture.ts +4 -0
- package/src/debugCaptureModel.ts +97 -21
- package/src/index.ts +6 -2
- package/src/panelAliasAnalysis.ts +24 -70
- package/src/panelCytoscapeGraphRenderer.ts +177 -40
- package/src/panelDetailLayout.ts +155 -0
- package/src/panelDetailStyles.ts +56 -0
- package/src/panelDiagnosticsView.ts +167 -86
- package/src/panelDomHelpers.ts +4 -5
- package/src/panelGraphLayout.ts +20 -5
- package/src/panelGraphRenderer.ts +7 -0
- package/src/panelGraphScene.ts +204 -292
- package/src/panelGraphSearch.ts +96 -0
- package/src/panelGraphView.ts +41 -9
- package/src/panelGraphVisuals.ts +152 -118
- package/src/panelInspectorView.ts +315 -48
- package/src/panelListStyles.ts +154 -0
- package/src/panelMemoryStyles.ts +41 -0
- package/src/panelMemoryView.ts +178 -53
- package/src/panelPassesView.ts +190 -137
- package/src/panelRawView.ts +99 -0
- package/src/panelResourcesView.ts +69 -56
- package/src/panelSelection.ts +39 -7
- package/src/panelTheme.ts +85 -0
- package/src/panelTypes.ts +16 -4
- package/src/panelVisualTheme.ts +38 -38
- package/src/panelWorkbenchHelpers.ts +62 -4
- package/src/panelWorkbenchStyles.ts +100 -0
- package/src/panelWorkbenchView.ts +201 -52
- package/src/query.ts +11 -11
- package/src/styles.ts +162 -205
- package/src/theme.ts +24 -0
- package/src/themeDefinitions.ts +103 -0
- package/src/themePalette.ts +44 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { GRAPH_VISUAL_THEME } from "./panelVisualTheme.js";
|
|
1
2
|
import { applyGraphLayout, layoutGraphScene, syncExpandedGroupLabelGeometry, } from "./panelGraphLayout.js";
|
|
2
3
|
import { selectionKey, } from "./panelGraphScene.js";
|
|
3
|
-
import { createGraphStyles, expandedGroupLabelMaxWidth, GRAPH_GEOMETRY, graphEdgeDisplayLabel, graphLayoutGeometryKey, isOverviewGraphScale, nodeDimensions, } from "./panelGraphVisuals.js";
|
|
4
|
+
import { createGraphStyles, fitGraphLabel, fitCollapsedGroupLabel, graphLabelFontSize, expandedGroupLabelMaxWidth, GRAPH_GEOMETRY, graphEdgeDisplayLabel, graphLayoutGeometryKey, isOverviewGraphScale, nodeDimensions, } from "./panelGraphVisuals.js";
|
|
4
5
|
export class CytoscapeGraphRenderer {
|
|
5
6
|
host;
|
|
6
7
|
environment;
|
|
@@ -10,6 +11,9 @@ export class CytoscapeGraphRenderer {
|
|
|
10
11
|
statusMessage;
|
|
11
12
|
retryButton;
|
|
12
13
|
resizeSubscription;
|
|
14
|
+
theme = GRAPH_VISUAL_THEME;
|
|
15
|
+
geometryRevision = 0;
|
|
16
|
+
wasVisible = false;
|
|
13
17
|
core;
|
|
14
18
|
elk;
|
|
15
19
|
loading;
|
|
@@ -25,15 +29,30 @@ export class CytoscapeGraphRenderer {
|
|
|
25
29
|
anchorTargetContentKey;
|
|
26
30
|
failedSceneContentKey;
|
|
27
31
|
overview = false;
|
|
28
|
-
|
|
32
|
+
dragPanning = false;
|
|
33
|
+
pointerInside = false;
|
|
34
|
+
pointerOverElement = false;
|
|
35
|
+
cancelPointerInteraction = () => {
|
|
36
|
+
this.dragPanning = false;
|
|
37
|
+
this.cancelGroupTap();
|
|
38
|
+
this.clearHover();
|
|
39
|
+
};
|
|
40
|
+
pendingReveal;
|
|
41
|
+
pendingGroupTap;
|
|
29
42
|
constructor(host, environment = browserGraphRendererEnvironment) {
|
|
30
43
|
this.host = host;
|
|
31
44
|
this.environment = environment;
|
|
32
45
|
this.canvasHost = environment.createElement('div');
|
|
33
46
|
this.canvasHost.className = 'zenfg-inspector-graph-canvas';
|
|
47
|
+
this.updateCursor();
|
|
34
48
|
this.tooltip = environment.createElement('div');
|
|
35
49
|
this.tooltip.className = 'zenfg-inspector-graph-tooltip';
|
|
36
50
|
this.tooltip.hidden = true;
|
|
51
|
+
// Cytoscape's node mouseout is not guaranteed when leaving its canvas directly.
|
|
52
|
+
this.canvasHost.addEventListener('pointerenter', () => { this.pointerInside = true; });
|
|
53
|
+
this.canvasHost.addEventListener('pointerleave', () => { this.pointerInside = false; this.clearHover(); });
|
|
54
|
+
this.canvasHost.addEventListener('pointercancel', this.cancelPointerInteraction);
|
|
55
|
+
this.canvasHost.ownerDocument?.defaultView?.addEventListener('blur', this.cancelPointerInteraction);
|
|
37
56
|
this.status = environment.createElement('div');
|
|
38
57
|
this.status.className = 'zenfg-inspector-graph-status';
|
|
39
58
|
this.status.hidden = true;
|
|
@@ -47,12 +66,36 @@ export class CytoscapeGraphRenderer {
|
|
|
47
66
|
this.retryButton.addEventListener('click', () => this.relayout());
|
|
48
67
|
this.status.append(this.statusMessage, this.retryButton);
|
|
49
68
|
this.host.replaceChildren(this.canvasHost, this.status, this.tooltip);
|
|
50
|
-
this.resizeSubscription = environment.observeResize?.(host, () =>
|
|
69
|
+
this.resizeSubscription = environment.observeResize?.(host, () => {
|
|
70
|
+
const visible = host.clientWidth > 0 && host.clientHeight > 0;
|
|
71
|
+
if (visible && !this.wasVisible)
|
|
72
|
+
this.latestRequest?.onVisible?.();
|
|
73
|
+
this.wasVisible = visible;
|
|
74
|
+
this.core?.resize();
|
|
75
|
+
});
|
|
51
76
|
}
|
|
52
77
|
render(request) {
|
|
53
78
|
if (this.destroyed)
|
|
54
79
|
return;
|
|
80
|
+
if (request.theme)
|
|
81
|
+
this.setTheme(request.theme);
|
|
82
|
+
if (this.latestRequest?.scene !== request.scene
|
|
83
|
+
|| (this.latestRequest?.selected && selectionKey(this.latestRequest.selected)) !== (request.selected && selectionKey(request.selected))) {
|
|
84
|
+
this.cancelGroupTap();
|
|
85
|
+
}
|
|
86
|
+
if ((!request.hovered && !this.tooltip.hidden) || this.latestRequest?.scene.contentKey !== request.scene.contentKey) {
|
|
87
|
+
this.hideTooltip();
|
|
88
|
+
this.core?.elements().removeClass('semantic-hover');
|
|
89
|
+
}
|
|
55
90
|
this.latestRequest = request;
|
|
91
|
+
if (request.reveal) {
|
|
92
|
+
this.pendingReveal = { request: request.reveal, contentKey: request.scene.contentKey, captureRevision: request.captureRevision };
|
|
93
|
+
}
|
|
94
|
+
else if (this.pendingReveal && (this.pendingReveal.captureRevision !== request.captureRevision
|
|
95
|
+
|| this.pendingReveal.contentKey !== request.scene.contentKey
|
|
96
|
+
|| !request.selected || selectionKey(request.selected) !== selectionKey(this.pendingReveal.request.selection))) {
|
|
97
|
+
this.pendingReveal = undefined;
|
|
98
|
+
}
|
|
56
99
|
if (request.fit) {
|
|
57
100
|
this.fitTargetContentKey = request.scene.contentKey;
|
|
58
101
|
}
|
|
@@ -82,14 +125,46 @@ export class CytoscapeGraphRenderer {
|
|
|
82
125
|
this.syncInteraction(request);
|
|
83
126
|
this.consumeFitIfCurrentTarget();
|
|
84
127
|
this.consumeAnchorIfCurrentTarget();
|
|
128
|
+
this.consumeReveal();
|
|
85
129
|
this.processedVersion = version;
|
|
86
130
|
return;
|
|
87
131
|
}
|
|
88
132
|
this.scheduleProcessing();
|
|
89
133
|
}
|
|
134
|
+
setTheme(theme) {
|
|
135
|
+
if (this.destroyed || JSON.stringify(theme) === JSON.stringify(this.theme))
|
|
136
|
+
return;
|
|
137
|
+
const typographyChanged = theme.fontFamily !== this.theme.fontFamily || theme.fontSize !== this.theme.fontSize;
|
|
138
|
+
this.theme = theme;
|
|
139
|
+
this.core?.style().fromJson(createGraphStyles(theme)).update();
|
|
140
|
+
if (!typographyChanged)
|
|
141
|
+
return;
|
|
142
|
+
this.geometryRevision++;
|
|
143
|
+
if (this.core && this.latestRequest && this.appliedScene) {
|
|
144
|
+
const selected = this.core.nodes('.semantic-selected').first();
|
|
145
|
+
const center = this.core.extent();
|
|
146
|
+
const target = selected.nonempty() ? selected : this.core.nodes().filter(node => !node.isParent()).sort((a, b) => {
|
|
147
|
+
const distance = (node) => Math.hypot(node.position('x') - center.x1 - center.w / 2, node.position('y') - center.y1 - center.h / 2);
|
|
148
|
+
return distance(a) - distance(b);
|
|
149
|
+
}).first();
|
|
150
|
+
if (target.nonempty()) {
|
|
151
|
+
this.anchorElementId = target.id();
|
|
152
|
+
this.anchorTargetContentKey = this.latestRequest.scene.contentKey;
|
|
153
|
+
}
|
|
154
|
+
this.forceRelayout = true;
|
|
155
|
+
++this.requestVersion;
|
|
156
|
+
this.scheduleProcessing();
|
|
157
|
+
}
|
|
158
|
+
this.updateSemanticZoom(true);
|
|
159
|
+
}
|
|
90
160
|
resize() {
|
|
91
161
|
this.core?.resize();
|
|
92
162
|
}
|
|
163
|
+
cancelReveal() {
|
|
164
|
+
this.pendingReveal = undefined;
|
|
165
|
+
this.cancelGroupTap();
|
|
166
|
+
this.clearHover();
|
|
167
|
+
}
|
|
93
168
|
fit() {
|
|
94
169
|
const targetContentKey = this.latestRequest?.scene.contentKey;
|
|
95
170
|
if (targetContentKey)
|
|
@@ -105,6 +180,7 @@ export class CytoscapeGraphRenderer {
|
|
|
105
180
|
relayout() {
|
|
106
181
|
if (!this.latestRequest || this.destroyed)
|
|
107
182
|
return;
|
|
183
|
+
this.cancelGroupTap();
|
|
108
184
|
this.failedSceneContentKey = undefined;
|
|
109
185
|
this.forceRelayout = true;
|
|
110
186
|
this.fitTargetContentKey = this.latestRequest.scene.contentKey;
|
|
@@ -118,8 +194,10 @@ export class CytoscapeGraphRenderer {
|
|
|
118
194
|
if (this.destroyed)
|
|
119
195
|
return;
|
|
120
196
|
this.destroyed = true;
|
|
197
|
+
this.cancelGroupTap();
|
|
121
198
|
this.requestVersion++;
|
|
122
199
|
this.resizeSubscription?.disconnect();
|
|
200
|
+
this.canvasHost.ownerDocument?.defaultView?.removeEventListener('blur', this.cancelPointerInteraction);
|
|
123
201
|
this.hideTooltip();
|
|
124
202
|
this.core?.destroy();
|
|
125
203
|
this.core = undefined;
|
|
@@ -153,7 +231,7 @@ export class CytoscapeGraphRenderer {
|
|
|
153
231
|
if (request.scene.nodes.length === 0) {
|
|
154
232
|
this.hideTooltip();
|
|
155
233
|
if (this.core)
|
|
156
|
-
replaceElements(this.core, request.scene);
|
|
234
|
+
replaceElements(this.core, request.scene, this.theme);
|
|
157
235
|
this.appliedScene = request.scene;
|
|
158
236
|
this.forceRelayout = false;
|
|
159
237
|
if (this.fitTargetContentKey === request.scene.contentKey)
|
|
@@ -178,6 +256,7 @@ export class CytoscapeGraphRenderer {
|
|
|
178
256
|
this.syncInteraction(request);
|
|
179
257
|
this.consumeFitIfCurrentTarget();
|
|
180
258
|
this.consumeAnchorIfCurrentTarget();
|
|
259
|
+
this.consumeReveal();
|
|
181
260
|
this.hideStatus();
|
|
182
261
|
this.processedVersion = version;
|
|
183
262
|
continue;
|
|
@@ -196,20 +275,23 @@ export class CytoscapeGraphRenderer {
|
|
|
196
275
|
let laidOut = false;
|
|
197
276
|
if (geometryChanged || this.forceRelayout) {
|
|
198
277
|
this.showStatus('layout', 'Laying out graph…');
|
|
199
|
-
const
|
|
278
|
+
const geometryRevision = this.geometryRevision;
|
|
279
|
+
const result = await this.environment.layoutScene(this.elk, request.scene, this.theme);
|
|
280
|
+
if (geometryRevision !== this.geometryRevision)
|
|
281
|
+
continue;
|
|
200
282
|
const layoutRequest = this.resolveCurrentRequest(version, request.scene.contentKey);
|
|
201
283
|
if (!layoutRequest)
|
|
202
284
|
continue;
|
|
203
285
|
({ version, request } = layoutRequest);
|
|
204
286
|
if (topologyChanged || !this.appliedScene)
|
|
205
|
-
replaceElements(core, request.scene);
|
|
287
|
+
replaceElements(core, request.scene, this.theme);
|
|
206
288
|
else
|
|
207
|
-
updateElementData(core, request.scene);
|
|
289
|
+
updateElementData(core, request.scene, this.theme);
|
|
208
290
|
applyGraphLayout(core, request.scene, result);
|
|
209
291
|
laidOut = true;
|
|
210
292
|
}
|
|
211
293
|
else {
|
|
212
|
-
updateElementData(core, request.scene);
|
|
294
|
+
updateElementData(core, request.scene, this.theme);
|
|
213
295
|
}
|
|
214
296
|
syncExpandedGroupLabelGeometry(core);
|
|
215
297
|
this.appliedScene = request.scene;
|
|
@@ -231,6 +313,7 @@ export class CytoscapeGraphRenderer {
|
|
|
231
313
|
restoreViewport(core, previousViewport);
|
|
232
314
|
}
|
|
233
315
|
this.consumeAnchorIfCurrentTarget();
|
|
316
|
+
this.consumeReveal();
|
|
234
317
|
this.updateSemanticZoom(true);
|
|
235
318
|
this.hideStatus();
|
|
236
319
|
this.processedVersion = version;
|
|
@@ -266,7 +349,7 @@ export class CytoscapeGraphRenderer {
|
|
|
266
349
|
this.core = runtime.createCore({
|
|
267
350
|
container: this.canvasHost,
|
|
268
351
|
elements: [],
|
|
269
|
-
style: createGraphStyles(),
|
|
352
|
+
style: createGraphStyles(this.theme),
|
|
270
353
|
layout: { name: 'preset' },
|
|
271
354
|
minZoom: 0.03,
|
|
272
355
|
maxZoom: 4,
|
|
@@ -284,29 +367,38 @@ export class CytoscapeGraphRenderer {
|
|
|
284
367
|
return;
|
|
285
368
|
const id = event.target.id();
|
|
286
369
|
const selection = request.scene.interaction.selectionByElementId.get(id);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
370
|
+
const doubleTap = this.pendingGroupTap?.id === id;
|
|
371
|
+
this.cancelGroupTap();
|
|
372
|
+
if (selection?.kind !== 'group') {
|
|
373
|
+
if (selection)
|
|
374
|
+
request.onSelect(selection);
|
|
375
|
+
}
|
|
376
|
+
else if (doubleTap) {
|
|
291
377
|
request.onToggleGroup(selection.pathKey);
|
|
292
|
-
this.lastTap = undefined;
|
|
293
378
|
}
|
|
294
379
|
else {
|
|
295
|
-
|
|
380
|
+
// Defer group selection so expansion does not replace the inspected resource.
|
|
381
|
+
this.pendingGroupTap = { id, timer: setTimeout(() => {
|
|
382
|
+
this.pendingGroupTap = undefined;
|
|
383
|
+
this.interactiveRequest()?.onSelect(selection);
|
|
384
|
+
}, 350) };
|
|
296
385
|
}
|
|
297
386
|
};
|
|
298
387
|
core.on('tap', 'node', selectElement);
|
|
299
388
|
core.on('tap', 'edge', selectElement);
|
|
300
389
|
core.on('tap', (event) => {
|
|
301
390
|
if (event.target === core)
|
|
302
|
-
this.
|
|
391
|
+
this.cancelGroupTap();
|
|
303
392
|
});
|
|
304
393
|
const hoverElement = (event) => {
|
|
305
394
|
const request = this.interactiveRequest();
|
|
306
|
-
if (!request)
|
|
395
|
+
if (!request || this.dragPanning)
|
|
307
396
|
return;
|
|
308
397
|
const id = event.target.id();
|
|
309
398
|
const selection = request.scene.interaction.selectionByElementId.get(id);
|
|
399
|
+
this.pointerInside = true;
|
|
400
|
+
this.pointerOverElement = !!selection;
|
|
401
|
+
this.updateCursor();
|
|
310
402
|
if (selection)
|
|
311
403
|
request.onHover(selection);
|
|
312
404
|
const title = event.target.data('tooltip');
|
|
@@ -321,12 +413,22 @@ export class CytoscapeGraphRenderer {
|
|
|
321
413
|
const moveTooltip = (event) => this.positionTooltip(event.renderedPosition);
|
|
322
414
|
core.on('mousemove', 'node', moveTooltip);
|
|
323
415
|
core.on('mousemove', 'edge', moveTooltip);
|
|
324
|
-
const clearHover = () =>
|
|
325
|
-
this.hideTooltip();
|
|
326
|
-
this.latestRequest?.onHover(undefined);
|
|
327
|
-
};
|
|
416
|
+
const clearHover = () => this.clearHover();
|
|
328
417
|
core.on('mouseout', 'node', clearHover);
|
|
329
418
|
core.on('mouseout', 'edge', clearHover);
|
|
419
|
+
core.on('dragpan', () => {
|
|
420
|
+
if (this.dragPanning)
|
|
421
|
+
return;
|
|
422
|
+
this.dragPanning = true;
|
|
423
|
+
this.cancelGroupTap();
|
|
424
|
+
this.clearHover();
|
|
425
|
+
});
|
|
426
|
+
core.on('tapend', (event) => {
|
|
427
|
+
this.dragPanning = false;
|
|
428
|
+
this.pointerOverElement = this.pointerInside && event.target !== core
|
|
429
|
+
&& !!this.interactiveRequest()?.scene.interaction.selectionByElementId.get(event.target.id());
|
|
430
|
+
this.updateCursor();
|
|
431
|
+
});
|
|
330
432
|
core.on('zoom', () => this.updateSemanticZoom());
|
|
331
433
|
}
|
|
332
434
|
interactiveRequest() {
|
|
@@ -340,7 +442,7 @@ export class CytoscapeGraphRenderer {
|
|
|
340
442
|
core.batch(() => {
|
|
341
443
|
core.elements().removeClass('semantic-selected semantic-hover');
|
|
342
444
|
if (request.hovered) {
|
|
343
|
-
for (const id of request.scene.interaction.
|
|
445
|
+
for (const id of request.scene.interaction.hoverElementIdsBySelection.get(selectionKey(request.hovered)) ?? []) {
|
|
344
446
|
core.getElementById(id).addClass('semantic-hover');
|
|
345
447
|
}
|
|
346
448
|
}
|
|
@@ -370,6 +472,27 @@ export class CytoscapeGraphRenderer {
|
|
|
370
472
|
this.anchorElementId = undefined;
|
|
371
473
|
this.anchorTargetContentKey = undefined;
|
|
372
474
|
}
|
|
475
|
+
consumeReveal() {
|
|
476
|
+
const pending = this.pendingReveal;
|
|
477
|
+
const request = this.latestRequest;
|
|
478
|
+
if (!pending || !request || !this.core || this.targetNeedsApply())
|
|
479
|
+
return;
|
|
480
|
+
this.pendingReveal = undefined;
|
|
481
|
+
if (pending.captureRevision !== request.captureRevision || pending.contentKey !== request.scene.contentKey)
|
|
482
|
+
return;
|
|
483
|
+
const ids = request.scene.interaction.primaryElementIdsBySelection.get(selectionKey(pending.request.selection)) ?? [];
|
|
484
|
+
const targets = this.core.collection();
|
|
485
|
+
for (const id of ids)
|
|
486
|
+
targets.merge(this.core.getElementById(id));
|
|
487
|
+
if (!targets.length)
|
|
488
|
+
return;
|
|
489
|
+
this.core.resize();
|
|
490
|
+
this.core.fit(targets, 64);
|
|
491
|
+
if (this.core.zoom() > 1.2)
|
|
492
|
+
this.core.zoom(1.2);
|
|
493
|
+
this.core.center(targets);
|
|
494
|
+
this.updateSemanticZoom();
|
|
495
|
+
}
|
|
373
496
|
targetNeedsApply() {
|
|
374
497
|
const target = this.latestRequest?.scene;
|
|
375
498
|
if (!target || !this.appliedScene)
|
|
@@ -380,7 +503,7 @@ export class CytoscapeGraphRenderer {
|
|
|
380
503
|
const core = this.core;
|
|
381
504
|
if (!core)
|
|
382
505
|
return;
|
|
383
|
-
const overview = isOverviewGraphScale(core.zoom());
|
|
506
|
+
const overview = isOverviewGraphScale(core.zoom(), this.theme);
|
|
384
507
|
if (!force && overview === this.overview)
|
|
385
508
|
return;
|
|
386
509
|
this.overview = overview;
|
|
@@ -402,7 +525,20 @@ export class CytoscapeGraphRenderer {
|
|
|
402
525
|
hideTooltip() {
|
|
403
526
|
this.tooltip.hidden = true;
|
|
404
527
|
this.tooltip.textContent = '';
|
|
405
|
-
|
|
528
|
+
}
|
|
529
|
+
cancelGroupTap() {
|
|
530
|
+
if (this.pendingGroupTap)
|
|
531
|
+
clearTimeout(this.pendingGroupTap.timer);
|
|
532
|
+
this.pendingGroupTap = undefined;
|
|
533
|
+
}
|
|
534
|
+
clearHover() {
|
|
535
|
+
this.pointerOverElement = false;
|
|
536
|
+
this.updateCursor();
|
|
537
|
+
this.hideTooltip();
|
|
538
|
+
this.latestRequest?.onHover(undefined);
|
|
539
|
+
}
|
|
540
|
+
updateCursor() {
|
|
541
|
+
this.canvasHost.style.cursor = this.dragPanning ? 'grabbing' : this.pointerOverElement ? 'pointer' : 'grab';
|
|
406
542
|
}
|
|
407
543
|
showStatus(kind, message, retry = false) {
|
|
408
544
|
this.status.dataset.state = kind;
|
|
@@ -466,9 +602,9 @@ const browserGraphRendererEnvironment = {
|
|
|
466
602
|
};
|
|
467
603
|
},
|
|
468
604
|
};
|
|
469
|
-
function replaceElements(core, scene) {
|
|
605
|
+
function replaceElements(core, scene, theme = GRAPH_VISUAL_THEME) {
|
|
470
606
|
const definitions = [
|
|
471
|
-
...scene.nodes.map(nodeDefinition),
|
|
607
|
+
...scene.nodes.map(node => nodeDefinition(node, theme)),
|
|
472
608
|
...scene.edges.map(edgeDefinition),
|
|
473
609
|
];
|
|
474
610
|
core.startBatch();
|
|
@@ -476,12 +612,12 @@ function replaceElements(core, scene) {
|
|
|
476
612
|
core.add(definitions);
|
|
477
613
|
core.endBatch();
|
|
478
614
|
}
|
|
479
|
-
export function updateElementData(core, scene) {
|
|
615
|
+
export function updateElementData(core, scene, theme = GRAPH_VISUAL_THEME) {
|
|
480
616
|
core.batch(() => {
|
|
481
617
|
for (const node of scene.nodes) {
|
|
482
618
|
const element = core.getElementById(node.id);
|
|
483
619
|
if (element.nonempty())
|
|
484
|
-
element.data(nodeRenderableData(node));
|
|
620
|
+
element.data(nodeRenderableData(node, theme));
|
|
485
621
|
}
|
|
486
622
|
for (const edge of scene.edges) {
|
|
487
623
|
const element = core.getElementById(edge.id);
|
|
@@ -490,31 +626,40 @@ export function updateElementData(core, scene) {
|
|
|
490
626
|
}
|
|
491
627
|
});
|
|
492
628
|
}
|
|
493
|
-
function nodeDefinition(node) {
|
|
629
|
+
function nodeDefinition(node, theme) {
|
|
494
630
|
return {
|
|
495
631
|
group: 'nodes',
|
|
632
|
+
pannable: true,
|
|
496
633
|
data: {
|
|
497
634
|
id: node.id,
|
|
498
635
|
parent: node.parentId,
|
|
499
|
-
...nodeRenderableData(node),
|
|
636
|
+
...nodeRenderableData(node, theme),
|
|
500
637
|
},
|
|
501
638
|
};
|
|
502
639
|
}
|
|
503
|
-
function nodeRenderableData(node) {
|
|
504
|
-
const dimensions = nodeDimensions(node);
|
|
640
|
+
function nodeRenderableData(node, theme) {
|
|
641
|
+
const dimensions = nodeDimensions(node, theme);
|
|
505
642
|
const labelMaxWidth = node.kind === 'group' && node.collapsed
|
|
506
643
|
? expandedGroupLabelMaxWidth(dimensions.width)
|
|
507
|
-
: 160;
|
|
644
|
+
: 160 * theme.fontSize / GRAPH_GEOMETRY.baseFontSize;
|
|
645
|
+
const fitLabel = (label) => node.kind !== 'group'
|
|
646
|
+
? fitGraphLabel(label, labelMaxWidth, theme)
|
|
647
|
+
: node.collapsed ? fitCollapsedGroupLabel(label, labelMaxWidth, theme) : label;
|
|
648
|
+
const detailLabel = fitLabel(node.label);
|
|
649
|
+
const labelFontSize = node.kind === 'group' && !node.collapsed
|
|
650
|
+
? theme.fontSize * 1.2
|
|
651
|
+
: graphLabelFontSize(detailLabel, labelMaxWidth, dimensions.height - 12 * theme.fontSize / GRAPH_GEOMETRY.baseFontSize, theme);
|
|
508
652
|
return {
|
|
509
653
|
kind: node.kind,
|
|
510
|
-
passKind: node.kind === 'pass'
|
|
511
|
-
resourceKind: node.kind === 'resource' ? node.resourceKind : undefined,
|
|
654
|
+
passKind: node.kind === 'pass' ? node.passKind : undefined,
|
|
655
|
+
resourceKind: (node.kind === 'resource' || node.kind === 'root') ? node.resourceKind : undefined,
|
|
512
656
|
collapsed: node.kind === 'group' && node.collapsed ? 1 : 0,
|
|
513
657
|
hasCulled: node.kind === 'group' && node.culledNodeCount > 0 ? 1 : 0,
|
|
514
658
|
depthBand: node.kind === 'group' ? node.depthBand : undefined,
|
|
515
|
-
detailLabel
|
|
516
|
-
|
|
517
|
-
|
|
659
|
+
detailLabel,
|
|
660
|
+
labelFontSize,
|
|
661
|
+
overviewLabel: fitLabel(node.overviewLabel),
|
|
662
|
+
displayLabel: detailLabel,
|
|
518
663
|
tooltip: node.title,
|
|
519
664
|
labelMaxWidth,
|
|
520
665
|
width: dimensions.width,
|
|
@@ -536,9 +681,6 @@ function edgeRenderableData(edge) {
|
|
|
536
681
|
const detailLabel = graphEdgeDisplayLabel(edge);
|
|
537
682
|
return {
|
|
538
683
|
kind: edge.kind,
|
|
539
|
-
dependencyKind: edge.kind === 'dependency' ? edge.dependencyKind : undefined,
|
|
540
|
-
accessMode: edge.kind === 'access' ? edge.accessMode : undefined,
|
|
541
|
-
dashed: edge.kind === 'access' && edge.dashed ? 1 : 0,
|
|
542
684
|
detailLabel,
|
|
543
685
|
displayLabel: detailLabel,
|
|
544
686
|
tooltip: edge.title,
|