@davidsouther/agathon 0.0.0-stage → 0.0.0

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 (62) hide show
  1. package/package.json +19 -4
  2. package/src/assert.ts +67 -0
  3. package/src/geometry/box.ts +76 -0
  4. package/src/geometry/circle.ts +296 -0
  5. package/src/geometry/geometry.ts +318 -0
  6. package/src/geometry/path.ts +315 -0
  7. package/src/geometry/quadtree.ts +321 -0
  8. package/src/geometry/rectangle.ts +129 -0
  9. package/src/geometry/rngon.ts +132 -0
  10. package/src/geometry/types.ts +102 -0
  11. package/src/geometry.ts +61 -0
  12. package/src/highlight/highlight.ts +85 -0
  13. package/src/index.ts +5 -0
  14. package/src/layout/grid/manager.ts +55 -0
  15. package/src/layout/grid.ts +1 -0
  16. package/src/layout/hierarchic/README.md +21 -0
  17. package/src/layout/hierarchic/acyclic.ts +249 -0
  18. package/src/layout/hierarchic/children.ts +169 -0
  19. package/src/layout/hierarchic/debug.ts +186 -0
  20. package/src/layout/hierarchic/layout.ts +266 -0
  21. package/src/layout/hierarchic/manager.ts +65 -0
  22. package/src/layout/hierarchic/normalize.ts +177 -0
  23. package/src/layout/hierarchic/order.ts +321 -0
  24. package/src/layout/hierarchic/position.ts +514 -0
  25. package/src/layout/hierarchic/rank.ts +629 -0
  26. package/src/layout/hierarchic.ts +2 -0
  27. package/src/layout/hulls/arrange.ts +94 -0
  28. package/src/layout/hulls/hulls.ts +243 -0
  29. package/src/layout/hulls/segments.ts +174 -0
  30. package/src/layout/hulls.ts +3 -0
  31. package/src/layout/manager/child_manager.ts +42 -0
  32. package/src/layout/manager/drag_manager.ts +112 -0
  33. package/src/layout/manager/manager.ts +425 -0
  34. package/src/layout/manager/pan_manager.ts +146 -0
  35. package/src/layout/manager/visibility_manager.ts +84 -0
  36. package/src/layout/manager/zoom_manager.ts +263 -0
  37. package/src/layout/manager.ts +6 -0
  38. package/src/layout/properties/defaults.ts +99 -0
  39. package/src/layout/properties/symbol.ts +99 -0
  40. package/src/layout/properties/weak_map.ts +73 -0
  41. package/src/layout/properties.ts +111 -0
  42. package/src/layout/types.ts +470 -0
  43. package/src/layout/util.ts +444 -0
  44. package/src/layout.ts +6 -0
  45. package/src/samples/diff_graph.ts +15 -0
  46. package/src/samples/edge_cases.ts +168 -0
  47. package/src/samples/gansner_with_states.ts +67 -0
  48. package/src/samples/load_generator.ts +213 -0
  49. package/src/samples/search_graph.ts +35 -0
  50. package/src/tsabre/algo.ts +126 -0
  51. package/src/tsabre/builder.ts +97 -0
  52. package/src/tsabre/compress.ts +15 -0
  53. package/src/tsabre/dijkstra/dijkstra.ts +76 -0
  54. package/src/tsabre/dijkstra/heap.ts +83 -0
  55. package/src/tsabre/graph.ts +808 -0
  56. package/src/tsabre/parse.ts +634 -0
  57. package/src/tsabre/print.ts +188 -0
  58. package/src/tsabre/sourcebuilder/code_content_buffer.ts +275 -0
  59. package/src/tsabre/sourcebuilder/printable.ts +33 -0
  60. package/src/tsabre.ts +6 -0
  61. package/src/types.ts +424 -0
  62. package/README.md +0 -3
@@ -0,0 +1,470 @@
1
+ import type { Geometry } from "../geometry/types.ts";
2
+ import type {
3
+ AttributeSet,
4
+ Bounds,
5
+ Box,
6
+ DiffableGraphElement,
7
+ Edge,
8
+ Node,
9
+ NodeId,
10
+ Point,
11
+ ReadonlySmartGraph,
12
+ Segment,
13
+ SmartGraph,
14
+ } from "../types.ts";
15
+
16
+ /**
17
+ * Properties to store client configuration values for a LayoutGraph.
18
+ */
19
+ export interface LayoutGraphProperties {
20
+ layout?: Partial<GraphProperties>;
21
+ data?: AttributeSet;
22
+ }
23
+
24
+ /** Convenience type for a graph with an optional, partial property set. */
25
+ export interface LayoutGraph extends SmartGraph<LayoutNode, LayoutEdge>, LayoutGraphProperties {}
26
+
27
+ /**
28
+ * A ReadonlyLayoutGraph is a non-mutable interface for renderers, layouts, and
29
+ * other compute-only modules to use.
30
+ */
31
+ export interface ReadonlyLayoutGraph
32
+ extends ReadonlySmartGraph<Readonly<LayoutNode>, Readonly<LayoutEdge>>,
33
+ Readonly<LayoutGraphProperties> {}
34
+
35
+ /**
36
+ * Configuration settings for a force graph layout engine.
37
+ */
38
+ export interface ForceGraphConfig {
39
+ linkDistance: number;
40
+ linkStrength: number;
41
+ charge: number;
42
+ chargeDistance: number;
43
+ collisionStrength: number;
44
+ theta: number;
45
+ friction: number;
46
+ collapse: boolean;
47
+ center: number;
48
+ }
49
+
50
+ /** User-setable properties for node layout calculations. */
51
+ export interface NodeConfig {
52
+ /** Geometry of the node to cover during layout and rendering. */
53
+ geometry: Geometry;
54
+
55
+ // TODO: Refactor Hiererachical-specific properties
56
+
57
+ /** Rank is the row a node will get positioned on. */
58
+ rank: number;
59
+ /** When fixedRank is set, this node will not be adjusted during ranking. */
60
+ fixedRank: boolean;
61
+ /** Order specifies the order of nodes within a rank. */
62
+ order: number;
63
+ }
64
+
65
+ /**
66
+ * A NodeLayout contains all necessary internal information when calculating
67
+ * where to put a node in a particular layout.
68
+ */
69
+ export interface NodeProperties extends NodeConfig {
70
+ /**
71
+ * When computing ranks, low and lim will be used for building the feasible
72
+ * spanning tree. When initially creating the spanning tree, lim is the
73
+ * postorder traversal number of the tree, and low is the smallest lim of a
74
+ * node's descendants. This makes testing descendants in a tree a pair of
75
+ * integer comparisons.
76
+ *
77
+ * (1, 5)
78
+ * / \
79
+ * (1, 3) (4, 4)
80
+ * / \
81
+ * (1, 1) (2, 2)
82
+ *
83
+ * See [Gansner] Figure 2.5 for a larger example.
84
+ */
85
+ low: number;
86
+ lim: number;
87
+ /**
88
+ * Virtual indicates this node was created at some point during the layout
89
+ * process for internal processing, and will be removed before finishing.
90
+ */
91
+ virtual: boolean | "border" | "edge" | "root";
92
+ virtualEdge?: Edge;
93
+ virtualEdgeLayout?: EdgeProperties;
94
+ top?: NodeId;
95
+ bottom?: NodeId;
96
+
97
+ /* Properties for force graph simulation */
98
+ vx?: number; // the node's current x velocity
99
+ vy?: number; // the node's current y velocity
100
+
101
+ /* Properties to use when fixing position or dragged. */
102
+ fx?: number; // the node's fixed x position
103
+ fy?: number; // the node's fixed y position
104
+ dragging?: boolean; // the node is being actively dragged; unset is false
105
+ }
106
+
107
+ /** Convenience type for a node with an optional, partial property set. */
108
+ export interface LayoutNode extends Node, DiffableGraphElement {
109
+ expanded?: boolean;
110
+ layout?: Partial<NodeProperties>;
111
+ data?: AttributeSet;
112
+ }
113
+
114
+ /**
115
+ * User definable edge configuration properties.
116
+ */
117
+ export interface EdgeConfig {
118
+ /**
119
+ * The minimum number of ranks this Edge must span. Defaults to 1, but forcing
120
+ * some edges longer can create interesting layouts.
121
+ */
122
+ minLength: number;
123
+ /**
124
+ * The weight of an edge forces stronger vertical alignment of that node.
125
+ * Consider these
126
+ */
127
+ weight: number;
128
+ /**
129
+ * When calculating ranks, cutValue is used as a heuristic for which edges to
130
+ * attempt to remove first when creating a minimum spanning tree.
131
+ */
132
+ cutValue: number;
133
+ }
134
+
135
+ /**
136
+ * An EdgeLayout has all necessary information on an edge when calculating a
137
+ * layout.
138
+ */
139
+ export interface EdgeProperties extends EdgeConfig {
140
+ /** When removing cycles, some edges will get reversed. */
141
+ reversed: boolean;
142
+ /*
143
+ * When a node is reversed, this is the original edge to be restored.
144
+ */
145
+ original?: Edge;
146
+
147
+ /**
148
+ * As with virtual nodes, this edge was inserted by layout to normalize some
149
+ * operations.
150
+ */
151
+ nestingEdge: boolean;
152
+ points: Point[];
153
+ }
154
+
155
+ /** Convenience type for an edge with an optional, partial property set. */
156
+ export interface LayoutEdge extends Edge, DiffableGraphElement {
157
+ layout?: Partial<EdgeProperties>;
158
+ data?: AttributeSet;
159
+ }
160
+
161
+ interface SegmentLabel<V extends string | number> {
162
+ /**
163
+ * Metric along the segment's path.
164
+ */
165
+ forward?: V;
166
+
167
+ /**
168
+ * Metric in the opposite direction to the segment's path.
169
+ */
170
+ reverse?: V;
171
+ }
172
+
173
+ /**
174
+ * Data model representing a metrics flow along a segment, following its path
175
+ * direction or the opposite direction. Objects of this class are bound to a
176
+ * single line of a label attached to a segment and are used to aggregate
177
+ * values originating from multiple links.
178
+ */
179
+ export interface LabelAnnotation<T> {
180
+ rawValue: T;
181
+ formattedValue: string;
182
+ /** Whether the metric flows in the segment path direction. */
183
+ forward: boolean;
184
+ drawArrow: boolean;
185
+ }
186
+
187
+ /**
188
+ * User specified layout & rendering information for segments.
189
+ */
190
+ export interface SegmentConfig {
191
+ metrics: SegmentLabel<number>;
192
+
193
+ annotations: SegmentLabel<string>;
194
+ }
195
+
196
+ /**
197
+ * Layout & rendering information for segments.
198
+ */
199
+ export interface SegmentProperties extends SegmentConfig {
200
+ points: ReadonlyArray<Readonly<Point>>;
201
+
202
+ label: LabelProperties;
203
+ }
204
+
205
+ /**
206
+ * Properties to describe how to layout a label on a segment.
207
+ */
208
+ export interface LabelProperties {
209
+ /**
210
+ * Where to place the label of the node, in the same coordinate space as
211
+ * `points`.
212
+ */
213
+ position: Point;
214
+
215
+ /**
216
+ * What angle, in degrees, to rotate the label.
217
+ */
218
+ rotation: number;
219
+
220
+ /**
221
+ * Tells us whether the label has been rendered with an additional rotation
222
+ * by 180 degrees to prevent upside-down text.
223
+ */
224
+ flippedBy180: boolean;
225
+ }
226
+
227
+ /**
228
+ * User-definable graph configuration properties.
229
+ */
230
+ export interface GraphConfig {
231
+ /**
232
+ * The amount of separation between two ranks, in pixels. That is, a second
233
+ * row will be rankSep pixels below the bottom of the row above it.
234
+ */
235
+ rankSep: number;
236
+
237
+ /**
238
+ * The amount of separation between two nodes on the same rank, in pixels.
239
+ * That is, a second node will be nodeSep pixels after the node before it.
240
+ */
241
+ nodeSep: number;
242
+
243
+ /**
244
+ * The amount of "empty" space to leave for edges that span multiple ranks and
245
+ * cross between nodes.
246
+ */
247
+ edgeSep: number;
248
+
249
+ /**
250
+ * When laying out nodes, some minimum size is useful in several places.
251
+ */
252
+ baseRadius: number;
253
+
254
+ /**
255
+ * When laying out hulls, long labels can have improved overlap by providing
256
+ * some rotation. Specified in degrees.
257
+ */
258
+ hullRotation: number;
259
+
260
+ /**
261
+ * When laying out children, positions can either be absolute (default) or
262
+ * relative to the parent (with this flag).
263
+ */
264
+ childrenRelative: boolean;
265
+
266
+ /**
267
+ * Whether to bend long edges through virtual nodes, or make them always
268
+ * direct. Defaults to true.
269
+ */
270
+ bendLongEdges: boolean;
271
+
272
+ /**
273
+ * Number of items in a row before triggering staggered layout.
274
+ */
275
+ staggerRows: number;
276
+
277
+ /**
278
+ * When set, write timing information for each of the major steps to the
279
+ * console using `console.time`.
280
+ */
281
+ timing: boolean;
282
+
283
+ /**
284
+ * When set, write debugging information after each step of layout.
285
+ */
286
+ printDebug: boolean;
287
+ }
288
+
289
+ /**
290
+ * A GraphLayout has all necessary information on a graph when calculating a
291
+ * layout.
292
+ */
293
+ export interface GraphProperties extends GraphConfig {
294
+ /** The NodeId of the inserted virtual root */
295
+ root?: NodeId;
296
+
297
+ /** The NodeId of the inserted nesting root, to track */
298
+ nestingRoot?: NodeId;
299
+
300
+ /**
301
+ * When inserting virtual nodes, nodeRankFactor describes how many "virtual"
302
+ * ranks were inserted between each original set of ranks.
303
+ */
304
+ nodeRankFactor: number;
305
+
306
+ /**
307
+ * When calculating ordering cross-cutting, having consistent sized ranks is
308
+ * helpful. Between ranking and ordering, virtual nodes are inserted at each
309
+ * (rank, order) pair that does not already have a node in it. To clean these
310
+ * up later, each of the highest-ranked nodes are tracked to remove them when
311
+ * finished ordering.
312
+ */
313
+ virtualChains?: Set<NodeId>;
314
+
315
+ /**
316
+ * Cached value of FAS for decycling. Result of initial run of greedyFas() in
317
+ * acyclic.ts::decycle() is cached here, and subsequently accessed in the same
318
+ * function.
319
+ */
320
+ fas?: Edge[];
321
+
322
+ /**
323
+ * Cached layout positions of virtual nodes. Results of rank() and order()
324
+ * from layout()'s first run get cached in virtualNodeLayout, and then used as
325
+ * a part of simplified partialLayout() pipeline.
326
+ *
327
+ * virtualNodeLayout is initialized in
328
+ * layout() => virtualNodeLayoutCache(...,'write'), and subsequently accessed
329
+ * in partialLayout() => virtualNodeLayoutCache(..., 'read').
330
+ */
331
+ virtualNodeLayout?: Map<NodeId, { rank: number; order: number }>;
332
+ }
333
+
334
+ /**
335
+ * Rendeing layout position information for segments.
336
+ */
337
+ export interface SegmentPosition {
338
+ /**
339
+ * Points the segment must pass through. The first and last points are the
340
+ * coordinates on the edge of the source and target node foreground circles
341
+ * that are closest to the adjacent point in the array. Intermediate values
342
+ * are specific points the line segment should pass through.
343
+ *
344
+ * Set after layout is complete.
345
+ */
346
+ points: Point[];
347
+
348
+ label: LabelProperties;
349
+ }
350
+
351
+ /**
352
+ * PropertiesStrategy are a collection of functions which control how to access
353
+ * properties on an Agathon entity.
354
+ */
355
+ export interface PropertiesStrategy {
356
+ getNodeProps(obj: Node & { layout?: Partial<NodeProperties> }): NodeProperties;
357
+ getEdgeProps(obj: Edge & { layout?: Partial<EdgeProperties> }): EdgeProperties;
358
+ getSegmentProps(obj: Segment & { layout?: Partial<SegmentProperties> }): SegmentProperties;
359
+ getGraphProps(obj: SmartGraph<{}, {}> & { layout?: Partial<GraphProperties> }): GraphProperties;
360
+ clearNodeProps(obj: Node): void;
361
+ clearEdgeProps(obj: Edge): void;
362
+ clearSegmentProps(obj: Segment): void;
363
+ clearGraphProps(obj: SmartGraph<{}, {}>): void;
364
+ }
365
+
366
+ /**
367
+ * A GraphLayout is used by the Topology Graph renderer to decide where and how
368
+ * to position nodes and segments. The renderer uses a LayoutManager's run
369
+ * method to either update an existing or get a new instance of GraphLayout,
370
+ * which it then uses to set node and segment positions. The renderer will then
371
+ * call `run` with LayoutChange items to change, update, or otherwise modify the
372
+ * generated layout.
373
+ */
374
+ export interface GraphLayout {
375
+ readonly panOffset: Point;
376
+ readonly box: Box;
377
+ readonly zoomLevel: number;
378
+ readonly draggable: boolean;
379
+ readonly isDragging: boolean;
380
+
381
+ didUpdate(entity: NodeId | Segment<LayoutEdge>): boolean;
382
+ getNodePosition(node: NodeId): Geometry;
383
+ getSegmentPosition(segment: Segment<LayoutEdge>): SegmentPosition;
384
+
385
+ isNodeVisible(node: NodeId): boolean;
386
+ isSegmentVisible(segment: Segment<LayoutEdge>): boolean;
387
+ }
388
+
389
+ /**
390
+ * A LayoutManager is the client-created and configured class which provides a
391
+ * method, `run`, which takes a graph and collection of LayoutChanges to
392
+ * apply.
393
+ */
394
+ export interface LayoutManager {
395
+ /** Run layout calculations for a graph. */
396
+ run(graph: ReadonlyLayoutGraph): void;
397
+
398
+ /**
399
+ * Mark the layout as finished. Position will not change until the next run or
400
+ * update. Calls to didUpdate between runFinished and the next run or update
401
+ * will return false.
402
+ */
403
+ runFinished(): void;
404
+
405
+ /** An instance of the current layout. */
406
+ readonly layout: GraphLayout;
407
+
408
+ /**
409
+ * Mark the height and width of the primary viewport, which is assumed to
410
+ * always be rooted at <0, 0>. Using a Manager should only include one primary
411
+ * viewport.
412
+ */
413
+ setPageBounds(bounds: Bounds): void;
414
+
415
+ /** Increase the cumulative graph panning by `delta`. */
416
+ moveGraphBy(delta: Point): void;
417
+
418
+ /** Resets the graph panning to {0,0} */
419
+ resetGraphPan(): void;
420
+
421
+ /**
422
+ * Adjust pan so that given node is centered in the graph. If node is not
423
+ * renderable, or is not present, no change happens.
424
+ */
425
+ panToNode(id: NodeId): void;
426
+
427
+ /** Resets the graph zoom level to 0 */
428
+ resetGraphZoom(): void;
429
+
430
+ /**
431
+ * Indicate to the layout manager that the graph intends to start moving a
432
+ * node. Future calls to moveNodeBy should be against this node, until
433
+ * stopMovingNode is called. If no node is being moved, and moveNodeBy is
434
+ * called, startMovingNode is implicitly called. If moveNodeBy uses a node
435
+ * that isn't the currently moving node, stopMovingNode is called as well.
436
+ */
437
+ startMovingNode(id: NodeId): void;
438
+
439
+ /** Indicate that a node is finished moving. */
440
+ stopMovingNode(): void;
441
+
442
+ /** Move a node by a delta offset. */
443
+ moveNodeBy(id: NodeId, delta: Point): void;
444
+
445
+ /**
446
+ * Re-run the layout algorithm as if this node has just been expanded. Should
447
+ * be called after a node goes from being unexpanded to being expanded. This
448
+ * does NOT set the given node to be expanded if it is not already, it merely
449
+ * informs the layout algorithm to behave as if that node just became
450
+ * expanded.
451
+ */
452
+ runLayoutAfterNodeExpanded(id: NodeId): void;
453
+
454
+ /**
455
+ * Re-run the layout algorithm as if this node has just been collapsed. See
456
+ * runLayoutAfterNodeExpanded for more details.
457
+ */
458
+ runLayoutAfterNodeCollapsed(id: NodeId): void;
459
+
460
+ /**
461
+ * Apply fisheye zooming to all nodes. If not provided, uses the center of
462
+ * the visible graph as the target point.
463
+ */
464
+ zoomIn(center?: Point): void;
465
+ zoomOut(center?: Point): void;
466
+
467
+ /** LayoutManagers can inform listeners when the layout has been updated. */
468
+ registerUpdateCallback(cb: () => void): void;
469
+ unregisterUpdateCallback(cb: () => void): void;
470
+ }