@hpcc-js/graph 2.83.1 → 2.83.2

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.
Files changed (55) hide show
  1. package/dist/index.es6.js +1139 -260
  2. package/dist/index.es6.js.map +1 -1
  3. package/dist/index.js +1139 -256
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.min.js +1 -1
  6. package/dist/index.min.js.map +1 -1
  7. package/package.json +8 -7
  8. package/src/__package__.ts +2 -2
  9. package/src/graph2/dataGraph.ts +27 -25
  10. package/src/graph2/edge.tsx +30 -0
  11. package/src/graph2/graph.ts +48 -1308
  12. package/src/graph2/graphReactT.ts +43 -0
  13. package/src/graph2/graphT.ts +1311 -0
  14. package/src/graph2/index.ts +4 -0
  15. package/src/graph2/layouts/dagre.ts +13 -1
  16. package/src/graph2/layouts/forceDirected.ts +2 -2
  17. package/src/graph2/layouts/graphvizWorker.ts +2 -2
  18. package/src/graph2/layouts/placeholders.ts +41 -32
  19. package/src/graph2/layouts/tree.ts +1 -1
  20. package/src/graph2/sankeyGraph.ts +8 -12
  21. package/src/graph2/subgraph.tsx +30 -0
  22. package/src/graph2/vertex.tsx +31 -0
  23. package/types/__package__.d.ts +2 -2
  24. package/types/graph2/dataGraph.d.ts +4 -4
  25. package/types/graph2/dataGraph.d.ts.map +1 -1
  26. package/types/graph2/edge.d.ts +9 -0
  27. package/types/graph2/edge.d.ts.map +1 -0
  28. package/types/graph2/graph.d.ts +26 -233
  29. package/types/graph2/graph.d.ts.map +1 -1
  30. package/types/graph2/graphReactT.d.ts +15 -0
  31. package/types/graph2/graphReactT.d.ts.map +1 -0
  32. package/types/graph2/graphT.d.ts +232 -0
  33. package/types/graph2/graphT.d.ts.map +1 -0
  34. package/types/graph2/index.d.ts +4 -0
  35. package/types/graph2/index.d.ts.map +1 -1
  36. package/types/graph2/layouts/dagre.d.ts.map +1 -1
  37. package/types/graph2/layouts/placeholders.d.ts +39 -32
  38. package/types/graph2/layouts/placeholders.d.ts.map +1 -1
  39. package/types/graph2/sankeyGraph.d.ts +5 -5
  40. package/types/graph2/sankeyGraph.d.ts.map +1 -1
  41. package/types/graph2/subgraph.d.ts +12 -0
  42. package/types/graph2/subgraph.d.ts.map +1 -0
  43. package/types/graph2/vertex.d.ts +13 -0
  44. package/types/graph2/vertex.d.ts.map +1 -0
  45. package/types-3.4/__package__.d.ts +2 -2
  46. package/types-3.4/graph2/dataGraph.d.ts +4 -4
  47. package/types-3.4/graph2/edge.d.ts +9 -0
  48. package/types-3.4/graph2/graph.d.ts +26 -233
  49. package/types-3.4/graph2/graphReactT.d.ts +15 -0
  50. package/types-3.4/graph2/graphT.d.ts +232 -0
  51. package/types-3.4/graph2/index.d.ts +4 -0
  52. package/types-3.4/graph2/layouts/placeholders.d.ts +42 -32
  53. package/types-3.4/graph2/sankeyGraph.d.ts +5 -5
  54. package/types-3.4/graph2/subgraph.d.ts +12 -0
  55. package/types-3.4/graph2/vertex.d.ts +13 -0
@@ -1,844 +1,25 @@
1
- import { d3Event, drag as d3Drag, Palette, select as d3Select, Selection, Spacer, SVGGlowFilter, SVGZoomWidget, ToggleButton, Utility, Widget } from "@hpcc-js/common";
2
- import { IconEx, Icons, React, render, Subgraph, Vertex, IVertex3, IVertex4Annotation, Icon } from "@hpcc-js/react";
3
- import { getScriptSrc, Graph2 as GraphCollection, hashSum } from "@hpcc-js/util";
4
- import { HTMLTooltip } from "@hpcc-js/html";
5
- import "d3-transition";
6
- import { Circle, Dagre, ForceDirected, ForceDirectedAnimated, Graphviz, ILayout, Null } from "./layouts/index";
7
- import { Options as FDOptions } from "./layouts/forceDirectedWorker";
8
- import type { IEdge, IGraphData2, IHierarchy, ISubgraph, IVertex } from "./layouts/placeholders";
9
- import { EdgePlaceholder, SubgraphPlaceholder, VertexPlaceholder } from "./layouts/placeholders";
10
- import { Engine, graphviz as gvWorker } from "./layouts/graphvizWorker";
11
- import { Tree, RadialTree, Dendrogram, RadialDendrogram } from "./layouts/tree";
1
+ import { SVGGlowFilter } from "@hpcc-js/common";
2
+ import { React, Subgraph, SubgraphProps, Vertex, VertexProps } from "@hpcc-js/react";
3
+ import { BasicEdge, BasicEdgeProps } from "./edge";
4
+ import { GraphReactT } from "./graphReactT";
12
5
 
13
- import "../../src/graph2/graph.css";
14
-
15
- const wasmFolder = `${getScriptSrc("/graph/lib-umd/graph2/graph") || getScriptSrc("/graph/dist/index") || "."}/graph/dist`;
16
-
17
- export {
18
- IGraphData2,
19
- ISubgraph,
20
- IVertex,
21
- IEdge,
22
- IHierarchy
23
- };
24
-
25
- type GraphLayoutType = "Hierarchy" | "DOT" | "Tree" | "Dendrogram" | "RadialTree" | "RadialDendrogram" | "ForceDirected" | "ForceDirected2" | "ForceDirectedHybrid" | "Neato" | "FDP" | "Circle" | "TwoPI" | "Circo" | "None";
26
- const GraphLayoutTypeSet = ["Hierarchy", "DOT", "Tree", "Dendrogram", "RadialTree", "RadialDendrogram", "ForceDirected", "ForceDirected2", "ForceDirectedHybrid", "Neato", "FDP", "Circle", "TwoPI", "Circo", "None"];
27
-
28
- const dragStart = (n: VertexPlaceholder) => {
29
- n.fx = n.sx = n.x;
30
- n.fy = n.sy = n.y;
31
- };
32
- const dragTick = (n: VertexPlaceholder, d: VertexPlaceholder) => {
33
- n.fx = n.sx + d.fx - d.sx;
34
- n.fy = n.sy + d.fy - d.sy;
35
- };
36
- const dragEnd = (n: VertexPlaceholder) => {
37
- n.x = n.fx;
38
- n.y = n.fy;
39
- n.fx = n.sx = undefined;
40
- n.fy = n.sy = undefined;
41
- };
42
-
43
- export class Graph2 extends SVGZoomWidget {
44
-
45
- private _toggleHierarchy = new ToggleButton().faChar("fa-sitemap").tooltip("Hierarchy").on("click", () => this.layoutClick("Hierarchy"));
46
- private _toggleForceDirected = new ToggleButton().faChar("fa-expand").tooltip("Force Directed").on("click", () => this.layoutClick("ForceDirected"));
47
- private _toggleForceDirected2 = new ToggleButton().faChar("fa-arrows").tooltip("Spring").on("click", () => this.layoutClick("ForceDirected2"));
48
- private _toggleCircle = new ToggleButton().faChar("fa-circle-o").tooltip("Circle").on("click", () => this.layoutClick("Circle"));
49
- private _toggleDot = new ToggleButton().faChar("fa-angle-double-down").tooltip("DOT").on("click", () => this.layoutClick("DOT"));
50
- private _toggleNeato = new ToggleButton().faChar("fa-sun-o").tooltip("Neato").on("click", () => this.layoutClick("Neato"));
51
- private _toggleFDP = new ToggleButton().faChar("fa-asterisk").tooltip("FDP").on("click", () => this.layoutClick("FDP"));
52
- private _toggleTwoPI = new ToggleButton().faChar("fa-bullseye").tooltip("TwoPI").on("click", () => this.layoutClick("TwoPI"));
53
- private _toggleCirco = new ToggleButton().faChar("fa-cogs").tooltip("Circo").on("click", () => this.layoutClick("Circo"));
54
- private _toggleT = new ToggleButton().faChar("fa-sitemap fa-rotate-270").tooltip("Tree").on("click", () => this.layoutClick("Tree"));
55
- private _toggleRT = new ToggleButton().faChar("fa-sun-o").tooltip("Radial Tree").on("click", () => this.layoutClick("RadialTree"));
56
- private _toggleD = new ToggleButton().faChar("fa-sitemap fa-rotate-270").tooltip("Dendrogram").on("click", () => this.layoutClick("Dendrogram"));
57
- private _toggleRD = new ToggleButton().faChar("fa-asterisk").tooltip("Radial Dendrogram").on("click", () => this.layoutClick("RadialDendrogram"));
58
-
59
- protected _graphData = new GraphCollection<VertexPlaceholder, EdgePlaceholder, SubgraphPlaceholder>()
60
- .idFunc(d => d.id)
61
- .sourceFunc(e => e.source.id)
62
- .targetFunc(e => e.target.id)
63
- .updateFunc((b: any, a: any) => {
64
- b.props = a.props;
65
- return b;
66
- })
67
- ;
68
-
69
- protected _prevDoClickTime: number = 0;
6
+ export class Graph2 extends GraphReactT<SubgraphProps, VertexProps, BasicEdgeProps> {
70
7
 
71
8
  protected _centroidFilter: SVGGlowFilter;
72
9
 
73
- protected _svgDefsAnn: any;
74
- protected _svgDefsCat: any;
75
- protected _subgraphG: Selection<SVGGElement, any, SVGGElement, any>;
76
- protected _edgeG: Selection<SVGGElement, any, SVGGElement, any>;
77
- protected _vertexG: Selection<SVGGElement, any, SVGGElement, any>;
78
-
79
- protected _tooltip: HTMLTooltip = new HTMLTooltip();
80
-
81
- protected _selection = new Utility.Selection(this);
82
- private _dragHandler = d3Drag<Element, VertexPlaceholder>();
83
-
84
- protected _catPalette = Palette.ordinal("hpcc10");
85
- _svgDefs: any;
86
-
87
10
  constructor() {
88
- super();
89
- const context = this;
90
- this._drawStartPos = "origin";
91
-
92
- const buttons: Widget[] = [
93
- this._toggleHierarchy,
94
- this._toggleForceDirected,
95
- this._toggleForceDirected2,
96
- this._toggleCircle,
97
- new Spacer(),
98
- this._toggleDot,
99
- this._toggleNeato,
100
- this._toggleFDP,
101
- this._toggleTwoPI,
102
- this._toggleCirco,
103
- new Spacer(),
104
- this._toggleT,
105
- this._toggleRT,
106
- this._toggleD,
107
- this._toggleRD,
108
- new Spacer()
109
- ];
110
- this._iconBar.buttons(buttons.concat(this._iconBar.buttons()));
111
-
112
- this._dragHandler
113
- .on("start", function (d) {
114
- if (context.allowDragging()) {
115
- d3Select(this).classed("grabbed", true);
116
- dragStart(d);
117
- Utility.safeRaise(this);
118
- context.moveVertexPlaceholder(d, false, true);
119
-
120
- const selection = context.selection();
121
- const isSelected = context.selected(d.props, selection as IVertex[]);
122
- if (isSelected) {
123
- selection
124
- .filter(v => v.id !== d.props.id)
125
- .forEach(v => {
126
- const n = context._graphData.vertex(v.id);
127
- dragStart(n);
128
- });
129
- } else if (context.dragSingleNeighbors()) {
130
- context._graphData.singleNeighbors(d.id).forEach(n => {
131
- dragStart(n);
132
- });
133
- }
134
- }
135
- })
136
- .on("drag", function (d) {
137
- if (context.allowDragging()) {
138
- d.fx = d.sx + context.rproject(d3Event().x - d.sx);
139
- d.fy = d.sy + context.rproject(d3Event().y - d.sy);
140
- context._graphData.vertexEdges(d.id).forEach(e => delete e.points);
141
- context.moveVertexPlaceholder(d, false, true);
142
- const selection = context.selection();
143
- const isSelected = context.selected(d.props, selection as IVertex[]);
144
-
145
- if (isSelected) {
146
- selection
147
- .filter(v => v.id !== d.props.id)
148
- .forEach(v => {
149
- const n = context._graphData.vertex(v.id);
150
- dragTick(n, d);
151
- context.moveVertexPlaceholder(n, false, true);
152
- });
153
- } else if (context.dragSingleNeighbors()) {
154
- context._graphData.singleNeighbors(d.id).forEach(n => {
155
- dragTick(n, d);
156
- context.moveVertexPlaceholder(n, false, true);
157
- });
158
- }
159
- }
160
- })
161
- .on("end", function (d) {
162
- let doClick = true;
163
- if (context.allowDragging()) {
164
- doClick = Math.abs(d.sx - d.fx) < 1 && Math.abs(d.sy - d.fy) < 1;
165
- dragEnd(d);
166
-
167
- const selection = context.selection();
168
- const isSelected = context.selected(d.props, selection as IVertex[]);
169
- if (isSelected) {
170
- selection
171
- .filter(v => v.id !== d.props.id)
172
- .forEach(v => {
173
- const n = context._graphData.vertex(v.id);
174
- dragEnd(n);
175
- });
176
- } else if (context.dragSingleNeighbors()) {
177
- context._graphData.singleNeighbors(d.id).forEach(dragEnd);
178
- }
179
-
180
- d3Select(this).classed("grabbed", false);
181
- }
182
- if (doClick) {
183
- context._selection.click({
184
- _id: d.id,
185
- element: () => d.element
186
- }, d3Event().sourceEvent);
187
- context.selectionChanged();
188
- const selected = d.element.classed("selected");
189
- const eventOrigin = context.resolveEventOrigin();
190
- context.vertex_click(d.props.origData || d.props, "", selected, eventOrigin);
191
- const doClickTime = Date.now();
192
- if (doClickTime - context._prevDoClickTime < context.doubleClickMaxDelay()) {
193
- context.vertex_dblclick(d.props.origData || d.props, "", selected, eventOrigin);
194
- }
195
- context._prevDoClickTime = doClickTime;
196
- }
197
- })
198
- .filter(() => true)
199
- ;
200
- this.zoomToFitLimit(1);
201
- }
202
-
203
- resolveEventOrigin(): { origin: string, data: undefined | IVertex4Annotation | Icon } {
204
- const d3evt = d3Event();
205
- const eventPath = d3evt?.sourceEvent?.path ?? d3evt?.path;
206
- const element = eventPath.find(n => n?.hasAttribute && n?.hasAttribute("data-click"));
207
- const origin = element ? element.getAttribute("data-click") : "";
208
- const dataStr = element ? element.getAttribute("data-click-data") : "";
209
- let data = undefined;
210
- if (dataStr) {
211
- try {
212
- data = JSON.parse(dataStr);
213
- } catch (e) {
214
- console.warn("Unexpected annotation data:", dataStr);
215
- }
216
- }
217
-
218
- return {
219
- origin,
220
- data
221
- };
222
- }
223
-
224
- iconBarButtons(): Widget[] {
225
- return this._iconBar.buttons();
226
- }
227
-
228
- protected _categories: IconEx[] = [];
229
- categories(): IconEx[];
230
- categories(_: IconEx[]): this;
231
- categories(_?: IconEx[]): IconEx[] | this {
232
- if (_ === void 0) return this._categories;
233
- this._categories = _;
234
- return this;
235
- }
236
-
237
- protected _annotations: IconEx[] = [];
238
- annotations(): IconEx[];
239
- annotations(_: IconEx[]): this;
240
- annotations(_?: IconEx[]): IconEx[] | this {
241
- if (_ === void 0) return this._annotations;
242
- this._annotations = _;
243
- return this;
244
- }
245
-
246
- private _origData: IGraphData2 = {
247
- subgraphs: [],
248
- vertices: [],
249
- edges: [],
250
- hierarchy: []
251
- };
252
- data(): IGraphData2;
253
- data(_: IGraphData2, merge?: boolean): this;
254
- data(_?: IGraphData2, merge?: boolean): IGraphData2 | this {
255
- if (_ === void 0) return this._origData;
256
- this._origData = _;
257
-
258
- this._graphData.mergeSubgraphs((_.subgraphs || []).map(sg => ({
259
- id: sg.id,
260
- props: sg
261
- })));
262
-
263
- this._graphData.mergeVertices((_.vertices || []).map(v => ({
264
- id: v.id,
265
- centroid: v.centroid,
266
- props: v
267
- })));
268
-
269
- this._graphData.mergeEdges(
270
- (_.edges || [])
271
- .filter(e => {
272
- return this._graphData.vertexExists(e.source.id) && this._graphData.vertexExists(e.target.id);
273
- })
274
- .map(e => ({
275
- id: e.id,
276
- props: e,
277
- source: this._graphData.vertex(e.source.id),
278
- target: this._graphData.vertex(e.target.id)
279
- }))
280
- );
281
-
282
- this._graphData.clearParents();
283
- (_.hierarchy ? _.hierarchy : []).forEach(h => {
284
- if (this._graphData.subgraphExists(h.child.id)) {
285
- this._graphData.subgraphParent(h.child.id, h.parent.id);
286
- } else if (this._graphData.vertexExists(h.child.id)) {
287
- this._graphData.vertexParent(h.child.id, h.parent.id);
288
- }
289
- });
290
-
291
- return this;
292
- }
293
-
294
- selected(vertex: IVertex, _?: Array<IVertex>): boolean {
295
- return (_ || this.selection()).some(n => n.id === vertex.id);
296
- }
297
-
298
- selection(_: Array<IVertex | ISubgraph | IEdge>): this;
299
- selection(): Array<IVertex | ISubgraph | IEdge>;
300
- selection(_?: Array<IVertex | ISubgraph | IEdge>): Array<IVertex | ISubgraph | IEdge> | this {
301
- if (!arguments.length) return this._selection.get().map(item => this._graphData.item(item._id).props);
302
- this._selection.set(_.map(item => {
303
- const vp = this._graphData.item(item.id);
304
- return {
305
- _id: vp.id,
306
- element: () => vp.element
307
- };
308
- }));
309
- return this;
310
- }
311
-
312
- graphData(): GraphCollection<VertexPlaceholder, EdgePlaceholder> {
313
- return this._graphData;
314
- }
315
-
316
- resetLayout() {
317
- delete this._prevLayout;
318
- return this;
319
- }
320
-
321
- layoutRunning() {
322
- return this._layoutAlgo && this._layoutAlgo.running();
323
- }
324
-
325
- protected _layoutAlgo: ILayout = new Null(this);
326
- layoutAlgo(layout: ILayout) {
327
- if (this._layoutAlgo) {
328
- this._layoutAlgo.stop();
329
- }
330
- this._layoutAlgo = layout;
331
- return this._layoutAlgo.start().then(() => {
332
- this.updateIconBar();
333
- if (this.applyScaleOnLayout()) {
334
- // Wait for any transitions to finish ---
335
- setTimeout(() => {
336
- this.zoomToFit();
337
- }, this.transitionDuration());
338
- }
11
+ super(Subgraph, Vertex, BasicEdge);
12
+ this._reactCentroidRenderer = Vertex;
13
+ this._reactVertexRenderer2 = Vertex;
14
+ super.vertexRenderer((props) => {
15
+ return props.centroid ? this._reactCentroidRenderer(props) : this._reactVertexRenderer2(props);
339
16
  });
340
17
  }
341
18
 
342
- layoutClick(layout: GraphLayoutType) {
343
- if (this.layoutRunning()) {
344
- this._layoutAlgo.stop();
345
- this.updateIconBar();
346
- } else {
347
- delete this._prevLayout;
348
- this
349
- .layout(layout)
350
- .render()
351
- ;
352
- }
353
- }
354
-
355
- updateIconBarItem(tb: ToggleButton, tbLayout: GraphLayoutType) {
356
- const layout = this.layout();
357
- const running = this._layoutAlgo && this._layoutAlgo.running();
358
- tb.enabled(!running || layout === tbLayout).selected(running && layout === tbLayout).render();
359
- }
360
-
361
- updateIconBar() {
362
- super.updateIconBar();
363
- this.updateIconBarItem(this._toggleHierarchy, "Hierarchy");
364
- this.updateIconBarItem(this._toggleDot, "DOT");
365
- this.updateIconBarItem(this._toggleForceDirected, "ForceDirected");
366
- this.updateIconBarItem(this._toggleNeato, "Neato");
367
- this.updateIconBarItem(this._toggleFDP, "FDP");
368
- this.updateIconBarItem(this._toggleForceDirected2, "ForceDirected2");
369
- this.updateIconBarItem(this._toggleCircle, "Circle");
370
- this.updateIconBarItem(this._toggleTwoPI, "TwoPI");
371
- this.updateIconBarItem(this._toggleCirco, "Circo");
372
- this.updateIconBarItem(this._toggleT, "Tree");
373
- this.updateIconBarItem(this._toggleRT, "RadialTree");
374
- this.updateIconBarItem(this._toggleD, "Dendrogram");
375
- this.updateIconBarItem(this._toggleRD, "RadialDendrogram");
376
- }
377
-
378
- getNeighborMap(vertex: VertexPlaceholder) {
379
- const vertices = {};
380
- const edges = {};
381
-
382
- if (vertex) {
383
- const nedges = this._graphData.vertexEdges(vertex.id);
384
- for (let i = 0; i < nedges.length; ++i) {
385
- const edge = this._graphData.edge(nedges[i].id);
386
- edges[edge.id] = edge;
387
- if (edge.source.id !== vertex.id) {
388
- vertices[edge.source.id] = edge.source;
389
- }
390
- if (edge.target.id !== vertex.id) {
391
- vertices[edge.target.id] = edge.target;
392
- }
393
- }
394
- }
395
-
396
- return {
397
- vertices,
398
- edges
399
- };
400
- }
401
-
402
- centerOnItem(id: string) {
403
- const item = this._graphData.item(id);
404
- let x;
405
- let y;
406
- if (this._graphData.isSubgraph(item) || this._graphData.isVertex(item)) {
407
- x = item.x;
408
- y = item.y;
409
- }
410
- if (this._graphData.isEdge(item)) {
411
- [x, y] = [0, 0]; // center(item.points);
412
- }
413
- if (x !== undefined && y !== undefined) {
414
- const bbox = item.element.node().getBBox();
415
- if (this._graphData.isVertex(item)) {
416
- const proj = this.projectPlacholder(item);
417
- x = proj.x;
418
- y = proj.y;
419
- } else if (this._graphData.isSubgraph(item)) {
420
- x = this.project(item.x);
421
- y = this.project(item.y);
422
- }
423
- const deltaX = bbox.x + bbox.width / 2;
424
- const deltaY = bbox.y + bbox.height / 2;
425
- const itemBBox = {
426
- x: x + deltaX - bbox.width / 2,
427
- y: y + deltaY - bbox.height / 2,
428
- width: bbox.width,
429
- height: bbox.height
430
- };
431
- this.centerOnBBox(itemBBox);
432
- }
433
- }
434
-
435
- hideVertex(id: string): this {
436
- const item = this._graphData.item(id);
437
- if (this._graphData.isVertex(item)) {
438
- item.props.hidden = true;
439
- }
440
- return this;
441
- }
442
-
443
- showVertex(id: string): this {
444
- const item = this._graphData.item(id);
445
- if (this._graphData.isVertex(item)) {
446
- item.props.hidden = false;
447
- }
448
- return this;
449
- }
450
-
451
- protected highlight = {
452
- zoom: 1.1,
453
- opacity: 0.33,
454
- edge: "1.25px"
455
- };
456
-
457
- highlightVerticies(vertexMap?: { [id: string]: boolean }) {
458
- const context = this;
459
- const vertexElements = this._vertexG.selectAll<SVGGElement, VertexPlaceholder>(".graphVertex");
460
- const forceLabelOnHighlight = !context.showVertexLabels() && context.showVertexLabelsOnHighlight();
461
- vertexElements
462
- .classed("graphVertex-highlighted", d => !vertexMap || vertexMap[d.id])
463
- .style("filter", d => vertexMap && vertexMap[d.id] ? "url(#" + this.id() + "_glow)" : null)
464
- .each(function (d) {
465
- if (forceLabelOnHighlight) {
466
- const props = context.calcProps(
467
- d.centroid,
468
- {
469
- showLabel: !!(vertexMap && vertexMap[d.id]),
470
- ...context.vertexMapper(d.props, d.props.origData)
471
- }
472
- );
473
- render(
474
- d.centroid ? context._centroidRenderer : context._vertexRenderer,
475
- props,
476
- this
477
- );
478
- }
479
- })
480
- .transition().duration(this.transitionDuration())
481
- .on("end", function (d) {
482
- if (vertexMap && vertexMap[d.id]) {
483
- if (d.element.node() && d.element.node().parentNode) {
484
- d.element.node().parentNode.appendChild(d.element.node());
485
- }
486
- }
487
- })
488
- .style("opacity", function (d) {
489
- if (d.props.hidden) return 0;
490
- if (!vertexMap || vertexMap[d.id]) {
491
- return 1;
492
- }
493
- return context.highlight.opacity;
494
- })
495
- ;
496
- return this;
497
- }
498
-
499
- highlightEdges(edgeMap) {
500
- const context = this;
501
- const edgeElements = this._edgeG.selectAll<SVGGElement, EdgePlaceholder>(".graphEdge");
502
- edgeElements
503
- .classed("graphEdge-highlighted", function (d) { return !edgeMap || edgeMap[d.id]; })
504
- .style("stroke-width", function (o) {
505
- if (edgeMap && edgeMap[o.id]) {
506
- return context.highlight.edge;
507
- }
508
- return context.edgeStrokeWidth() + "px";
509
- }).transition().duration(this.transitionDuration())
510
- .style("opacity", function (o) {
511
- if (o.source.props.hidden || o.target.props.hidden) return 0;
512
- if (!edgeMap || edgeMap[o.id]) {
513
- return 1;
514
- }
515
- return context.highlight.opacity;
516
- })
517
- ;
518
- return this;
519
- }
520
-
521
- highlightVertex(_element, d: VertexPlaceholder) {
522
- if (this.highlightOnMouseOverVertex()) {
523
- if (d) {
524
- const highlight = this.getNeighborMap(d);
525
- highlight.vertices[d.id] = d;
526
- this.highlightVerticies(highlight.vertices);
527
- this.highlightEdges(highlight.edges);
528
- } else {
529
- this.highlightVerticies(null);
530
- this.highlightEdges(null);
531
- }
532
- }
533
- }
534
-
535
- highlightEdge(_element, d: EdgePlaceholder) {
536
- if (this.highlightOnMouseOverEdge()) {
537
- if (d) {
538
- const vertices = {};
539
- vertices[d.source.id] = d.source;
540
- vertices[d.target.id] = d.target;
541
- const edges = {};
542
- edges[d.id] = d;
543
- this.highlightVerticies(vertices);
544
- this.highlightEdges(edges);
545
- } else {
546
- this.highlightVerticies(null);
547
- this.highlightEdges(null);
548
- }
549
- }
550
- }
551
-
552
- moveSubgraphPlaceholder(sp: SubgraphPlaceholder, transition: boolean): this {
553
- const x = this.project(sp.x);
554
- const y = this.project(sp.y);
555
- const width = this.project(sp.props.width, true);
556
- const height = this.project(sp.props.height, true);
557
- if (sp.element) {
558
- // TODO: any should not be needed (tsc issue?)
559
- (transition ? sp.element.transition() as any : sp.element)
560
- .attr("transform", `translate(${x} ${y})`)
561
- .each(function (d) {
562
- render(Subgraph, { ...d.props, width, height }, this);
563
- })
564
- ;
565
- }
566
- return this;
567
- }
568
-
569
- moveEdgePlaceholder(ep: EdgePlaceholder, transition: boolean): this {
570
- const edgeLayout = this._layoutAlgo.edgePath(ep, this.edgeArcDepth());
571
- if (ep.elementPath) {
572
- // TODO: any should not be needed (tsc issue?)
573
- (transition ? ep.elementPath.transition() as any : ep.elementPath)
574
- .attr("d", edgeLayout.path)
575
- .attr("stroke-dasharray", d => d.props.strokeDasharray)
576
- ;
577
- }
578
-
579
- if (ep.elementText) {
580
- const lines = ep.props.label?.split("\n") ?? [];
581
- ep.elementText
582
- .selectAll(".textLine")
583
- .data(lines, (d: string) => d)
584
- .join(
585
- enter => enter.append("tspan")
586
- .attr("class", "textLine")
587
- .attr("x", 0),
588
- update => update
589
- .attr("dy", (d, i) => `${i}em`)
590
- .text(d => d),
591
- exit => exit.remove()
592
- )
593
- ;
594
- // TODO: any should not be needed (tsc issue?)
595
- (transition ? ep.elementText.transition() as any : ep.elementText)
596
- .attr("transform", `translate(${edgeLayout.labelPos[0]} ${edgeLayout.labelPos[1]})`)
597
- .attr("font-family", d => d.props.fontFamily || null)
598
- ;
599
- }
600
- return this;
601
- }
602
-
603
- moveVertexPlaceholder(vp: VertexPlaceholder, transition: boolean, moveNeighbours: boolean): this {
604
- const { x, y } = this.projectPlacholder(vp);
605
- vp.element && (transition ? vp.element.transition() as unknown as Selection<SVGPathElement, EdgePlaceholder, SVGGElement, any> : vp.element)
606
- .attr("transform", `translate(${x} ${y})`)
607
- ;
608
- if (moveNeighbours) {
609
- this._graphData.vertexEdges(vp.id).forEach(e => this.moveEdgePlaceholder(e, transition));
610
- }
611
- return this;
612
- }
613
-
614
- moveSubgraphs(transition: boolean): this {
615
- this._graphData.allSubgraphs().forEach(s => this.moveSubgraphPlaceholder(s, transition));
616
- return this;
617
- }
618
-
619
- moveEdges(transition: boolean): this {
620
- this._graphData.allEdges().forEach(e => this.moveEdgePlaceholder(e, transition));
621
- return this;
622
- }
623
-
624
- moveVertices(transition: boolean): this {
625
- this._graphData.allVertices().forEach(v => this.moveVertexPlaceholder(v, transition, false));
626
- return this;
627
- }
628
-
629
- project(pos: number, clip: boolean = false) {
630
- const rf = 10;
631
- pos = pos !== undefined ? pos : 0;
632
- let scale = this._transformScale;
633
- if (clip) {
634
- if (this._transformScale > this.maxScale() + (this._transformScale - this.maxScale()) / 2) {
635
- scale = this.maxScale() + (this._transformScale - this.maxScale()) / 2;
636
- } else if (this._transformScale < this.minScale() - (this._transformScale - this.minScale()) / 13) {
637
- // scale = this.minScale() - (this._transformScale - this.minScale()) / 13;
638
- }
639
- }
640
- return Math.round(pos * scale * rf) / rf;
641
- }
642
-
643
- rproject(pos: number) {
644
- const rf = 10;
645
- pos = pos !== undefined ? pos : 0;
646
- return Math.round(pos / this._transformScale * rf) / rf;
647
- }
648
-
649
- projectPlacholder(vp: VertexPlaceholder) {
650
- return {
651
- x: this.project(vp.fx !== undefined ? vp.fx : vp.x),
652
- y: this.project(vp.fy !== undefined ? vp.fy : vp.y)
653
- };
654
- }
655
-
656
- categoryID(id: string | number, prefix: "cat" | "ann" = "cat"): string {
657
- return id === undefined || id === "" ? "" : `${prefix}${this.id()}_${id}`;
658
- }
659
-
660
- updateCategories() {
661
- render(Icons, {
662
- icons: this._categories.map((c): IconEx => ({
663
- ...c,
664
- id: this.categoryID(c.id),
665
- fill: c.fill || "transparent",
666
- imageCharFill: c.imageCharFill || this._catPalette(c.id)
667
- }))
668
- }, this._svgDefsCat.node());
669
- }
670
-
671
- updateAnnotations() {
672
- render(Icons, {
673
- icons: this._annotations.map((c): IconEx => ({
674
- ...c,
675
- id: this.categoryID(c.id, "ann"),
676
- shape: c.shape || "square",
677
- height: c.height || 12,
678
- fill: c.fill || this._catPalette(c.id)
679
- }))
680
- }, this._svgDefsAnn.node());
681
- }
682
-
683
- updateEdges(): this {
684
- const context = this;
685
- this._edgeG.selectAll(".graphEdge")
686
- .data(this._graphData.allEdges(), (d: EdgePlaceholder) => d.id)
687
- .join(
688
- enter => enter.append("g")
689
- .attr("class", "graphEdge")
690
- .on("click.selectionBag", function (d) {
691
- context._selection.click({
692
- _id: d.id,
693
- element: () => d.element
694
- }, d3Event());
695
- context.selectionChanged();
696
- })
697
- .on("click", function (this: SVGElement, d) {
698
- const selected = d.element.classed("selected");
699
- context.edge_click(d.props.origData || d.props, "", selected);
700
- })
701
- .on("mouseover", function (d) {
702
- Utility.safeRaise(this);
703
- context.edge_mouseover(d3Select(this), d);
704
- })
705
- .on("mouseout", function (d) {
706
- context.edge_mouseout(d3Select(this), d);
707
- })
708
- .each(function (d) {
709
- d.element = d3Select(this);
710
- d.elementPath = d.element.append("path");
711
- d.elementText = d.element.append("text")
712
- .attr("text-anchor", "middle")
713
- ;
714
- })
715
- ,
716
- update => update
717
- .attr("opacity", d => d.source.props.hidden || d.target.props.hidden ? 0 : 1)
718
- .classed("hide-text", !context.showEdgeLabels())
719
- ,
720
- exit => exit
721
- .each(function (d) {
722
- delete d.element;
723
- })
724
- .remove()
725
- )
726
- .style("stroke", d => {
727
- return d.props?.color ?? this.edgeColor();
728
- })
729
- .style("stroke-width", this.edgeStrokeWidth() + "px")
730
- ;
731
- return this;
732
- }
733
-
734
- private _centroidRenderer: React.FunctionComponent<Vertex> = Vertex;
735
- centroidRenderer(): React.FunctionComponent;
736
- centroidRenderer(_: React.FunctionComponent): this;
737
- centroidRenderer(_?: React.FunctionComponent): this | React.FunctionComponent {
738
- if (!arguments.length) return this._centroidRenderer;
739
- this._centroidRenderer = _;
740
- return this;
741
- }
742
-
743
- private _vertexRenderer: React.FunctionComponent<Vertex> = Vertex;
744
- vertexRenderer(): React.FunctionComponent;
745
- vertexRenderer(_: React.FunctionComponent): this;
746
- vertexRenderer(_?: React.FunctionComponent): this | React.FunctionComponent {
747
- if (!arguments.length) return this._vertexRenderer;
748
- this._vertexRenderer = _;
749
- return this;
750
- }
751
-
752
- vertexMapper(props: IVertex, origRow: any): Vertex | IVertex3 {
753
- return {
754
- ...props,
755
- categoryID: this.categoryID(props.categoryID),
756
- annotationIDs: props.annotationIDs ? props.annotationIDs.map(a => this.categoryID(a, "ann")) : []
757
- };
758
- }
759
-
760
- updateVertices(): this {
761
- const context = this;
762
- this._vertexG.selectAll(".graphVertex")
763
- .data(this._graphData.allVertices(), (d: VertexPlaceholder) => d.id)
764
- .join(
765
- enter => enter.append("g")
766
- .attr("class", "graphVertex")
767
- .on("dblclick", function (this: SVGElement, d) {
768
- d3Event().stopPropagation();
769
- })
770
- .on("mousein", function (d) {
771
- Utility.safeRaise(this);
772
- context.highlightVertex(d3Select(this), d);
773
- const selected = d.element.classed("selected");
774
- const eventOrigin = context.resolveEventOrigin();
775
- context.vertex_mousein(d.props.origData || d.props, "", selected, eventOrigin);
776
- })
777
- .on("mouseover", function (d) {
778
- Utility.safeRaise(this);
779
- context.highlightVertex(d3Select(this), d);
780
- const selected = d.element.classed("selected");
781
- if (d.props.tooltip) {
782
- context._tooltip
783
- .tooltipHTML(context.tooltipHTML.bind(context))
784
- .triggerElement(d.element)
785
- .tooltipWidth(context.tooltipWidth())
786
- .tooltipHeight(context.tooltipHeight())
787
- .enablePointerEvents(context.enableTooltipPointerEvents())
788
- .closeDelay(context.tooltipCloseDelay())
789
- .direction("n")
790
- .data(d)
791
- .visible(true)
792
- .render()
793
- ;
794
- }
795
- const eventOrigin = context.resolveEventOrigin();
796
- context.vertex_mouseover(d.props.origData || d.props, "", selected, eventOrigin);
797
- })
798
- .on("mouseout", function (d) {
799
- context.highlightVertex(null, null);
800
- const selected = d.element.classed("selected");
801
- const eventOrigin = context.resolveEventOrigin();
802
- context.vertex_mouseout(d.props.origData || d.props, "", selected, eventOrigin);
803
- if (d.props.tooltip) {
804
- context._tooltip.mouseout();
805
- }
806
- })
807
- .call(this._dragHandler)
808
- .each(function (d) {
809
- d.element = d3Select(this);
810
- }),
811
- update => update,
812
- exit => exit
813
- .each(function (d) {
814
- delete d.element;
815
- })
816
- .remove()
817
- )
818
- .classed("centroid", d => d.centroid)
819
- .attr("opacity", d => d.props.hidden ? 0 : 1)
820
- .attr("filter", d => d.centroid ? "url(#" + this.id() + "_glow)" : null)
821
- .each(function (this: SVGGElement, d) {
822
- const props = context.calcProps(
823
- d.centroid,
824
- {
825
- showLabel: context.showVertexLabels(),
826
- ...context.vertexMapper(d.props, d.props.origData)
827
- }
828
- );
829
- render(
830
- d.centroid ? context._centroidRenderer : context._vertexRenderer,
831
- props,
832
- this
833
- );
834
- })
835
- ;
836
- return this;
837
- }
838
-
839
- calcProps(isCentroid: boolean, props) {
19
+ calcProps(_props: VertexProps): VertexProps {
20
+ const props = super.calcProps(_props);
840
21
  if (!props.icon) props.icon = {};
841
- if (isCentroid) {
22
+ if (props.centroid) {
842
23
  props.textHeight = props.textHeight ? props.textHeight : this.centroidTextHeight() * this.centroidScale();
843
24
  props.textPadding = props.textPadding ? props.textPadding : this.centroidTextPadding() * this.centroidScale();
844
25
  props.textFontFamily = props.textFontFamily ? props.textFontFamily : this.centroidLabelFontFamily();
@@ -864,338 +45,51 @@ export class Graph2 extends SVGZoomWidget {
864
45
  return props;
865
46
  }
866
47
 
867
- hasSubgraphs() {
868
- switch (this.layout()) {
869
- case "DOT":
870
- case "Hierarchy":
871
- return true;
872
- }
873
- return false;
48
+ protected _reactVertexRenderer2: React.FunctionComponent<VertexProps>;
49
+ vertexRenderer(): React.FunctionComponent<VertexProps>;
50
+ vertexRenderer(_: React.FunctionComponent<VertexProps>): this;
51
+ vertexRenderer(_?: React.FunctionComponent<VertexProps>): this | React.FunctionComponent<VertexProps> {
52
+ if (!arguments.length) return this._reactVertexRenderer2;
53
+ this._reactVertexRenderer2 = _;
54
+ return this;
874
55
  }
875
56
 
876
- updateSubgraphs(): this {
877
- const context = this;
878
- this._subgraphG.selectAll(".subgraphPlaceholder")
879
- .data(this.hasSubgraphs() ? this._graphData.allSubgraphs() : [], (d: SubgraphPlaceholder) => d.id)
880
- .join(
881
- enter => enter.append("g")
882
- .attr("class", "subgraphPlaceholder")
883
- .on("click.selectionBag", function (d) {
884
- context._selection.click({
885
- _id: d.id,
886
- element: () => d.element
887
- }, d3Event());
888
- context.selectionChanged();
889
- })
890
- .on("click", function (this: SVGElement, d) {
891
- const selected = d.element.classed("selected");
892
- context.subgraph_click(d.props.origData || d.props, "", selected);
893
- })
894
- .on("mouseover", function () {
895
- Utility.safeRaise(this);
896
- })
897
- .each(function (d) {
898
- d.element = d3Select(this);
899
- })
900
- ,
901
- update => update,
902
- exit => exit
903
- .each(function (d) {
904
- delete d.element;
905
- })
906
- .transition()
907
- .style("opacity", 0)
908
- .remove()
909
- )
910
- .each(function (d) {
911
- context.moveSubgraphPlaceholder(d, false);
912
- })
913
- ;
57
+ protected _reactCentroidRenderer: React.FunctionComponent<VertexProps>;
58
+ centroidRenderer(): React.FunctionComponent<VertexProps>;
59
+ centroidRenderer(_: React.FunctionComponent<VertexProps>): this;
60
+ centroidRenderer(_?: React.FunctionComponent<VertexProps>): this | React.FunctionComponent<VertexProps> {
61
+ if (!arguments.length) return this._reactCentroidRenderer;
62
+ this._reactCentroidRenderer = _;
914
63
  return this;
915
64
  }
916
65
 
917
66
  enter(domNode, element) {
918
67
  super.enter(domNode, element);
919
-
920
- const svg = this.locateSVGNode(domNode);
921
- this._svgDefs = d3Select(svg).select<SVGDefsElement>("defs");
922
68
  this._centroidFilter = new SVGGlowFilter(this._svgDefs, this._id + "_glow");
923
-
924
- this._svgDefsCat = this._svgDefs.append("g");
925
- this._svgDefsAnn = this._svgDefs.append("g");
926
- this._subgraphG = this._renderElement.append("g");
927
- this._edgeG = this._renderElement.append("g");
928
- this._vertexG = this._renderElement.append("g");
929
-
930
- this._tooltip.target(domNode);
931
-
932
- this.on("startMarqueeSelection", () => {
933
- }).on("updateMarqueeSelection", rect => {
934
- const vertices: VertexPlaceholder[] = this._graphData.allVertices().filter(v => v.x >= rect.x && v.x <= rect.x + rect.width && v.y >= rect.y && v.y <= rect.y + rect.height);
935
- this.selection(vertices.map(v => v.props));
936
- }).on("endMarqueeSelection", () => {
937
- this.selectionChanged();
938
- });
939
- }
940
-
941
- protected forceDirectedOptions(): FDOptions {
942
- return {
943
- alpha: this.forceDirectedAlpha(),
944
- alphaMin: this.forceDirectedAlphaMin(),
945
- alphaDecay: this.forceDirectedAlphaDecay(),
946
- velocityDecay: this.forceDirectedVelocityDecay(),
947
- repulsionStrength: this.forceDirectedRepulsionStrength(),
948
- iterations: this.forceDirectedIterations(),
949
- linkDistance: this.forceDirectedLinkDistance(),
950
- linkStrength: this.forceDirectedLinkStrength(),
951
- pinCentroid: this.forceDirectedPinCentroid(),
952
- forceStrength: this.forceDirectedForceStrength(),
953
- distanceMin: this.forceDirectedMinDistance(),
954
- distanceMax: this.forceDirectedMaxDistance(),
955
- };
956
- }
957
-
958
- private layoutOptions(layout: GraphLayoutType) {
959
- switch (layout) {
960
- case "ForceDirected":
961
- case "ForceDirected2":
962
- case "ForceDirectedHybrid":
963
- return this.forceDirectedOptions();
964
- case "Hierarchy":
965
- return {
966
- rankdir: this.hierarchyRankDirection(),
967
- nodesep: this.hierarchyNodeSeparation(),
968
- edgesep: this.hierarchyEdgeSeparation(),
969
- ranksep: this.hierarchyRankSeparation(),
970
- digraph: this.hierarchyDigraph()
971
- };
972
- case "Tree":
973
- case "Dendrogram":
974
- return { rankdir: this.treeRankDirection() };
975
- case "DOT":
976
- case "Neato":
977
- case "FDP":
978
- case "TwoPI":
979
- case "Circo":
980
- return this.wasmFolder() || wasmFolder;
981
- case "None":
982
- case "Circle":
983
- case "RadialTree":
984
- case "RadialDendrogram":
985
- default:
986
- return undefined;
987
- }
988
- }
989
-
990
- private _prevLayout: string;
991
- updateLayout() {
992
- const layout = this.layout();
993
- const options: any = this.layoutOptions(layout);
994
- const hash = hashSum([layout, options]);
995
- if (this._prevLayout !== hash) {
996
- this._prevLayout = hash;
997
- switch (layout) {
998
- case "None":
999
- this.layoutAlgo(new Null(this));
1000
- break;
1001
- case "Circle":
1002
- this.layoutAlgo(new Circle(this));
1003
- break;
1004
- case "ForceDirected":
1005
- this.layoutAlgo(new ForceDirected(this, options));
1006
- break;
1007
- case "ForceDirected2":
1008
- this.layoutAlgo(new ForceDirectedAnimated(this, options));
1009
- break;
1010
- case "ForceDirectedHybrid":
1011
- this.layoutAlgo(new ForceDirected(this, options)).then(() => {
1012
- this.layoutAlgo(new ForceDirectedAnimated(this, options));
1013
- });
1014
- break;
1015
- case "Hierarchy":
1016
- this.layoutAlgo(new Dagre(this, options));
1017
- break;
1018
- case "DOT":
1019
- this.layoutAlgo(new Graphviz(this, "dot", options));
1020
- break;
1021
- case "Tree":
1022
- this.layoutAlgo(new Tree(this, options));
1023
- break;
1024
- case "RadialTree":
1025
- this.layoutAlgo(new RadialTree(this));
1026
- break;
1027
- case "Dendrogram":
1028
- this.layoutAlgo(new Dendrogram(this, options));
1029
- break;
1030
- case "RadialDendrogram":
1031
- this.layoutAlgo(new RadialDendrogram(this));
1032
- break;
1033
- case "Neato":
1034
- this.layoutAlgo(new Graphviz(this, "neato", options));
1035
- break;
1036
- case "FDP":
1037
- this.layoutAlgo(new Graphviz(this, "fdp", options));
1038
- break;
1039
- case "TwoPI":
1040
- this.layoutAlgo(new Graphviz(this, "twopi", options));
1041
- break;
1042
- case "Circo":
1043
- this.layoutAlgo(new Graphviz(this, "circo", options));
1044
- break;
1045
- }
1046
- }
1047
69
  }
1048
70
 
1049
71
  update(domNode, element) {
1050
72
  super.update(domNode, element);
1051
-
1052
73
  this._centroidFilter.update(this.centroidColor());
1053
- this._renderElement.classed("allowDragging", this.allowDragging());
1054
-
1055
- this.updateCategories();
1056
- this.updateAnnotations();
1057
-
1058
- this.updateSubgraphs();
1059
- this.updateVertices();
1060
- this.updateEdges();
1061
-
1062
- this.updateLayout();
1063
-
1064
- this.updateIconBar();
1065
- }
1066
-
1067
- exit(domNode, element) {
1068
- super.exit(domNode, element);
1069
- this._tooltip.target(null);
1070
- }
1071
-
1072
- render(callback?: (w: Widget) => void): this {
1073
- this.progress("start");
1074
- super.render(w => {
1075
- this.progress("stop");
1076
- if (callback) {
1077
- callback(w);
1078
- }
1079
- });
1080
- return this;
1081
- }
1082
-
1083
- private _prevWidth;
1084
- private _prevHeight;
1085
- private _prevTransformScale;
1086
- private _transformScale = 1;
1087
- zoomed(transform) {
1088
- super.zoomed(transform);
1089
- const { width, height } = this.size();
1090
-
1091
- if (transform.k < this.minScale()) {
1092
- this._edgeG.attr("transform", `scale(${this.minScale() / transform.k})`);
1093
- this._subgraphG.attr("transform", `scale(${this.minScale() / transform.k})`);
1094
- this._vertexG.attr("transform", `scale(${this.minScale() / transform.k})`);
1095
- this._transformScale = transform.k / this.minScale();
1096
- } else if (transform.k > this.maxScale()) {
1097
- this._edgeG.attr("transform", `scale(${this.maxScale() / transform.k})`);
1098
- this._subgraphG.attr("transform", `scale(${this.maxScale() / transform.k})`);
1099
- this._vertexG.attr("transform", `scale(${this.maxScale() / transform.k})`);
1100
- this._transformScale = transform.k / this.maxScale();
1101
- } else {
1102
- this._transformScale = 1;
1103
- this._edgeG.attr("transform", null);
1104
- this._subgraphG.attr("transform", null);
1105
- this._vertexG.attr("transform", null);
1106
- }
1107
-
1108
- if (this._prevTransformScale !== this._transformScale ||
1109
- this._prevWidth !== width ||
1110
- this._prevHeight !== height) {
1111
- this._prevTransformScale = this._transformScale;
1112
- this._prevWidth = width;
1113
- this._prevHeight = height;
1114
- this
1115
- .moveSubgraphs(false)
1116
- .moveVertices(false)
1117
- .moveEdges(false)
1118
- ;
1119
- }
1120
- }
1121
-
1122
- // Events ---
1123
- centroids(): VertexPlaceholder[] {
1124
- return this._graphData.allVertices().filter(vp => !!vp.centroid);
1125
- }
1126
-
1127
- selectionChanged() {
1128
- if (this.highlightSelectedPathToCentroid()) {
1129
- const highlightedVertices = {};
1130
- this.centroids().forEach(centroid => {
1131
- this.selection().forEach(selection => {
1132
- const { ids, len } = this._graphData.dijkstra(centroid.id, selection.id);
1133
- if (len) {
1134
- ids.forEach(id => {
1135
- highlightedVertices[id] = true;
1136
- });
1137
- }
1138
- });
1139
- });
1140
- this._edgeG.selectAll(".graphEdge")
1141
- // .classed("shortest-path", d => highlightedEdges[d.id()] === true)
1142
- ;
1143
- }
1144
- }
1145
-
1146
- tooltipHTML(data) {
1147
- return data.props.tooltip;
1148
- }
1149
-
1150
- subgraph_click(row, _col, sel) {
1151
- }
1152
-
1153
- vertex_click(row, _col, sel, data) {
1154
- }
1155
-
1156
- vertex_dblclick(row, _col, sel, data) {
1157
- }
1158
-
1159
- vertex_mousein(row, _col, sel, data) {
1160
- }
1161
-
1162
- vertex_mouseover(row, _col, sel, data) {
1163
- }
1164
-
1165
- vertex_mouseout(row, _col, sel, data) {
1166
- }
1167
-
1168
- edge_click(row, _col, sel) {
1169
- }
1170
-
1171
- edge_mouseover(element, d) {
1172
- this.highlightEdge(element, d);
1173
- }
1174
-
1175
- edge_mouseout(_element, _d) {
1176
- this.highlightEdge(null, null);
1177
- }
1178
-
1179
- progress(what: "start" | "stop" | "layout-start" | "layout-tick" | "layout-stop") {
1180
74
  }
1181
75
  }
1182
76
  Graph2.prototype._class += " graph_Graph2";
1183
77
 
1184
78
  export interface Graph2 {
1185
- allowDragging(): boolean;
1186
- allowDragging(_: boolean): this;
1187
- dragSingleNeighbors(): boolean;
1188
- dragSingleNeighbors(_: boolean): this;
1189
- layout(): GraphLayoutType;
1190
- layout(_: GraphLayoutType): this;
1191
- applyScaleOnLayout(): boolean;
1192
- applyScaleOnLayout(_: boolean): this;
1193
- highlightOnMouseOverVertex(): boolean;
1194
- highlightOnMouseOverVertex(_: boolean): this;
1195
- highlightOnMouseOverEdge(): boolean;
1196
- highlightOnMouseOverEdge(_: boolean): this;
1197
- transitionDuration(): number;
1198
- transitionDuration(_: number): this;
79
+ vertexTextHeight(): number;
80
+ vertexTextHeight(_: number): this;
81
+ vertexTextPadding(): number;
82
+ vertexTextPadding(_: number): this;
83
+ vertexIconHeight(): number;
84
+ vertexIconHeight(_: number): this;
85
+ vertexIconPadding(): number;
86
+ vertexIconPadding(_: number): this;
87
+ vertexIconStrokeWidth(): number;
88
+ vertexIconStrokeWidth(_: number): this;
89
+ vertexIconFontFamily(): string;
90
+ vertexIconFontFamily(_: string): this;
91
+ vertexLabelFontFamily(): string;
92
+ vertexLabelFontFamily(_: string): this;
1199
93
 
1200
94
  centroidColor(): string;
1201
95
  centroidColor(_: string): this;
@@ -1215,120 +109,16 @@ export interface Graph2 {
1215
109
  centroidIconFontFamily(_: string): this;
1216
110
  centroidLabelFontFamily(): string;
1217
111
  centroidLabelFontFamily(_: string): this;
1218
- vertexTextHeight(): number;
1219
- vertexTextHeight(_: number): this;
1220
- vertexTextPadding(): number;
1221
- vertexTextPadding(_: number): this;
1222
- vertexIconHeight(): number;
1223
- vertexIconHeight(_: number): this;
1224
- vertexIconPadding(): number;
1225
- vertexIconPadding(_: number): this;
1226
- vertexIconStrokeWidth(): number;
1227
- vertexIconStrokeWidth(_: number): this;
1228
- vertexIconFontFamily(): string;
1229
- vertexIconFontFamily(_: string): this;
1230
- vertexLabelFontFamily(): string;
1231
- vertexLabelFontFamily(_: string): this;
1232
- highlightSelectedPathToCentroid(): boolean;
1233
- highlightSelectedPathToCentroid(_: boolean): this;
1234
- edgeArcDepth(): number;
1235
- edgeArcDepth(_: number): this;
1236
- minScale(): number;
1237
- minScale(_: number): this;
1238
- maxScale(): number;
1239
- maxScale(_: number): this;
1240
- showEdgeLabels(): boolean;
1241
- showEdgeLabels(_: boolean): this;
1242
- showEdgeLabelsOnHighlight(): boolean;
1243
- showEdgeLabelsOnHighlight(_: boolean): this;
1244
- showVertexLabels(): boolean;
1245
- showVertexLabels(_: boolean): this;
1246
- showVertexLabelsOnHighlight(): boolean;
1247
- showVertexLabelsOnHighlight(_: boolean): this;
1248
-
1249
- hierarchyRankDirection(): "TB" | "BT" | "LR" | "RL";
1250
- hierarchyRankDirection(_: "TB" | "BT" | "LR" | "RL"): this;
1251
- hierarchyNodeSeparation(): number;
1252
- hierarchyNodeSeparation(_: number): this;
1253
- hierarchyEdgeSeparation(): number;
1254
- hierarchyEdgeSeparation(_: number): this;
1255
- hierarchyRankSeparation(): number;
1256
- hierarchyRankSeparation(_: number): this;
1257
- hierarchyDigraph(): boolean;
1258
- hierarchyDigraph(_: boolean): this;
1259
-
1260
- forceDirectedAlpha(): number;
1261
- forceDirectedAlpha(_: number): this;
1262
- forceDirectedAlphaMin(): number;
1263
- forceDirectedAlphaMin(_: number): this;
1264
- forceDirectedAlphaDecay(): number;
1265
- forceDirectedAlphaDecay(_: number): this;
1266
- forceDirectedRepulsionStrength(): number;
1267
- forceDirectedRepulsionStrength(_: number): this;
1268
- forceDirectedVelocityDecay(): number;
1269
- forceDirectedVelocityDecay(_: number): this;
1270
- forceDirectedIterations(): number;
1271
- forceDirectedIterations(_: number): this;
1272
- forceDirectedLinkDistance(): number;
1273
- forceDirectedLinkDistance(_: number): this;
1274
- forceDirectedLinkStrength(): number;
1275
- forceDirectedLinkStrength(_: number): this;
1276
- forceDirectedPinCentroid(): boolean;
1277
- forceDirectedPinCentroid(_: boolean): this;
1278
- forceDirectedForceStrength(): number;
1279
- forceDirectedForceStrength(_: number): this;
1280
- forceDirectedMinDistance(): number;
1281
- forceDirectedMinDistance(_: number): this;
1282
- forceDirectedMaxDistance(): number;
1283
- forceDirectedMaxDistance(_: number): this;
1284
-
1285
- treeRankDirection(): "TB" | "LR";
1286
- treeRankDirection(_: "TB" | "LR"): this;
1287
-
1288
- edgeColor(): string;
1289
- edgeColor(_: string): this;
1290
- edgeStrokeWidth(): number;
1291
- edgeStrokeWidth(_: number): this;
1292
- tooltipWidth(): number;
1293
- tooltipWidth(_: number): this;
1294
- tooltipHeight(): number;
1295
- tooltipHeight(_: number): this;
1296
- enableTooltipPointerEvents(): boolean;
1297
- enableTooltipPointerEvents(_: boolean): this;
1298
- tooltipCloseDelay(): number;
1299
- tooltipCloseDelay(_: number): this;
1300
- doubleClickMaxDelay(): number;
1301
- doubleClickMaxDelay(_: number): this;
1302
-
1303
- wasmFolder(): string;
1304
- wasmFolder(_: string): this;
1305
112
  }
1306
113
 
1307
- Graph2.prototype.publish("allowDragging", true, "boolean", "Allow Dragging of Vertices");
1308
- Graph2.prototype.publish("dragSingleNeighbors", true, "boolean", "Dragging a Vertex also moves its singleton neighbors");
1309
- Graph2.prototype.publish("layout", "ForceDirectedHybrid", "set", "Default Layout", GraphLayoutTypeSet);
1310
- Graph2.prototype.publish("scale", "100%", "set", "Zoom Level", ["all", "width", "selection", "100%", "90%", "75%", "50%", "25%", "10%"]);
1311
- Graph2.prototype.publish("applyScaleOnLayout", false, "boolean", "Shrink to fit on Layout");
1312
- Graph2.prototype.publish("highlightOnMouseOverVertex", true, "boolean", "Highlight Vertex on Mouse Over");
1313
- Graph2.prototype.publish("highlightOnMouseOverEdge", true, "boolean", "Highlight Edge on Mouse Over");
1314
- Graph2.prototype.publish("transitionDuration", 250, "number", "Transition Duration");
1315
- Graph2.prototype.publish("showEdges", true, "boolean", "Show Edges");
1316
- Graph2.prototype.publish("showEdgeLabels", true, "boolean", "Show Edge labels");
1317
- Graph2.prototype.publish("showEdgeLabelsOnHighlight", true, "boolean", "Show Edge labels when highlighted");
1318
- Graph2.prototype.publish("showVertexLabels", true, "boolean", "Show Vertex labels");
1319
- Graph2.prototype.publish("showVertexLabelsOnHighlight", true, "boolean", "Show Vertex labels when highlighted");
1320
- Graph2.prototype.publish("snapToGrid", 0, "number", "Snap to Grid");
1321
- Graph2.prototype.publish("selectionClearOnBackgroundClick", false, "boolean", "Clear selection on background click");
1322
- Graph2.prototype.publish("edgeArcDepth", 8, "number", "Edge Arc Depth");
1323
- Graph2.prototype.publish("edgeColor", null, "html-color", "Edge line stroke color", null, { optional: true });
1324
- Graph2.prototype.publish("edgeStrokeWidth", 1, "number", "Edge line stroke width (pixels)");
1325
- Graph2.prototype.publish("minScale", 0.6, "number", "Min scale size for text");
1326
- Graph2.prototype.publish("maxScale", 1.0, "number", "Max scale size for text");
1327
- Graph2.prototype.publish("tooltipWidth", 256, "number", "Tooltip width (pixels)");
1328
- Graph2.prototype.publish("tooltipHeight", 128, "number", "Tooltip width (pixels)");
1329
- Graph2.prototype.publish("enableTooltipPointerEvents", false, "boolean", "If true, tooltip will use the style: 'pointer-events: all'");
1330
- Graph2.prototype.publish("tooltipCloseDelay", 0, "number", "Number of milliseconds to wait before closing tooltip (cancelled on tooltip mouseover event)");
1331
- Graph2.prototype.publish("doubleClickMaxDelay", 300, "number", "Number of milliseconds to wait before a subsequent click is not considered a double click");
114
+ Graph2.prototype.publish("vertexTextHeight", 10, "number", "Vertex Text Height");
115
+ Graph2.prototype.publish("vertexTextPadding", 4, "number", "Vertex Text Padding");
116
+ Graph2.prototype.publish("vertexIconHeight", 50, "number", "Vertex Icon Height");
117
+ Graph2.prototype.publish("vertexIconPadding", 10, "number", "Vertex Icon Padding");
118
+ Graph2.prototype.publish("vertexIconStrokeWidth", 0, "number", "Vertex Icon Stroke Width");
119
+ Graph2.prototype.publish("vertexIconFontFamily", "FontAwesome", "string", "Vertex Icon Font Family");
120
+ Graph2.prototype.publish("vertexLabelFontFamily", "Verdana", "string", "Vertex Label Font Family");
121
+ Graph2.prototype.publish("highlightSelectedPathToCentroid", true, "boolean", "Highlight path to Center Vertex (for selected vertices)");
1332
122
 
1333
123
  Graph2.prototype.publish("centroidColor", "#00A000", "html-color", "Centroid Glow Color");
1334
124
  Graph2.prototype.publish("centroidScale", 1, "number", "Centroid Scale");
@@ -1339,54 +129,4 @@ Graph2.prototype.publish("centroidIconPadding", 10, "number", "Centroid Icon Pad
1339
129
  Graph2.prototype.publish("centroidIconStrokeWidth", 4, "number", "Centroid Icon Stroke Width");
1340
130
  Graph2.prototype.publish("centroidIconFontFamily", "FontAwesome", "string", "Centroid Icon Font Family");
1341
131
  Graph2.prototype.publish("centroidLabelFontFamily", "Verdana", "string", "Centroid Label Font Family");
1342
- Graph2.prototype.publish("vertexTextHeight", 10, "number", "Vertex Text Height");
1343
- Graph2.prototype.publish("vertexTextPadding", 4, "number", "Vertex Text Padding");
1344
- Graph2.prototype.publish("vertexIconHeight", 50, "number", "Vertex Icon Height");
1345
- Graph2.prototype.publish("vertexIconPadding", 10, "number", "Vertex Icon Padding");
1346
- Graph2.prototype.publish("vertexIconStrokeWidth", 0, "number", "Vertex Icon Stroke Width");
1347
- Graph2.prototype.publish("vertexIconFontFamily", "FontAwesome", "string", "Vertex Icon Font Family");
1348
- Graph2.prototype.publish("vertexLabelFontFamily", "Verdana", "string", "Vertex Label Font Family");
1349
- Graph2.prototype.publish("highlightSelectedPathToCentroid", true, "boolean", "Highlight path to Center Vertex (for selected vertices)");
1350
-
1351
- Graph2.prototype.publish("hierarchyRankDirection", "TB", "set", "Direction for Rank Nodes", ["TB", "BT", "LR", "RL"], { disable: (w: Graph2) => w.layout() !== "Hierarchy" });
1352
- Graph2.prototype.publish("hierarchyNodeSeparation", 50, "number", "Number of pixels that separate nodes horizontally in the layout", null, { disable: (w: Graph2) => w.layout() !== "Hierarchy" });
1353
- Graph2.prototype.publish("hierarchyEdgeSeparation", 10, "number", "Number of pixels that separate edges horizontally in the layout", null, { disable: (w: Graph2) => w.layout() !== "Hierarchy" });
1354
- Graph2.prototype.publish("hierarchyRankSeparation", 50, "number", "Number of pixels between each rank in the layout", null, { disable: (w: Graph2) => w.layout() !== "Hierarchy" });
1355
- Graph2.prototype.publish("hierarchyDigraph", true, "boolean", "Directional Graph2", null, { disable: (w: Graph2) => w.layout() !== "Hierarchy" });
1356
-
1357
- Graph2.prototype.publish("forceDirectedAlpha", 1, "number", "Alpha", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1358
- Graph2.prototype.publish("forceDirectedAlphaMin", 0.001, "number", "Min Alpha", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1359
- Graph2.prototype.publish("forceDirectedAlphaDecay", 0.0228, "number", "Defaults to 1 - pow(alphaMin, 1 / 300)", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1360
- Graph2.prototype.publish("forceDirectedRepulsionStrength", -350, "number", "Charge strength ", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1361
- Graph2.prototype.publish("forceDirectedVelocityDecay", 0.4, "number", "Velocity Decay ", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1362
- Graph2.prototype.publish("forceDirectedIterations", 300, "number", "Iterations", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1363
- Graph2.prototype.publish("forceDirectedLinkDistance", 300, "number", "Target distance between linked nodes", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1364
- Graph2.prototype.publish("forceDirectedLinkStrength", 1, "number", "Strength (rigidity) of links", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1365
- Graph2.prototype.publish("forceDirectedPinCentroid", false, "boolean", "Pin centroid to center", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1366
- Graph2.prototype.publish("forceDirectedForceStrength", 0, "number", "Strength of center force", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1367
- Graph2.prototype.publish("forceDirectedMinDistance", 1, "number", "Min distance between nodes", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1368
- Graph2.prototype.publish("forceDirectedMaxDistance", Infinity, "number", "Max distance between nodes", null, { disable: (w: Graph2) => w.layout().indexOf("ForceDirected") !== 0 });
1369
-
1370
- Graph2.prototype.publish("treeRankDirection", "LR", "set", "Direction for Rank Nodes", ["TB", "LR"], { disable: (w: Graph2) => w.layout() !== "Tree" && w.layout() !== "Dendrogram" });
1371
132
 
1372
- Graph2.prototype.publish("wasmFolder", null, "string", "WASM Folder", null, { optional: true, disable: (w: Graph2) => ["DOT", "Neato", "FDP", "TwoPI", "Circo"].indexOf(w.layout()) < 0 });
1373
-
1374
- const _origScale = Graph2.prototype.scale;
1375
- Graph2.prototype.scale = function (_?, transitionDuration?) {
1376
- const retVal = _origScale.apply(this, arguments);
1377
- if (arguments.length) {
1378
- this.zoomTo(_, transitionDuration);
1379
- }
1380
- return retVal;
1381
- };
1382
-
1383
- export function graphviz(dot: string, engine: Engine = "dot", _wasmFolder: string = wasmFolder) {
1384
- return gvWorker({
1385
- items: [],
1386
- links: [],
1387
- raw: dot
1388
- }, {
1389
- engine: engine,
1390
- wasmFolder: _wasmFolder
1391
- });
1392
- }