aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/frontend/src/graph/DotGraphVisualizer.tsx')
-rw-r--r--subprojects/frontend/src/graph/DotGraphVisualizer.tsx35
1 files changed, 32 insertions, 3 deletions
diff --git a/subprojects/frontend/src/graph/DotGraphVisualizer.tsx b/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
index 7c25488a..29e750f5 100644
--- a/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
+++ b/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
@@ -14,6 +14,7 @@ import { useRootStore } from '../RootStoreProvider';
14import type { SemanticsSuccessResult } from '../xtext/xtextServiceResults'; 14import type { SemanticsSuccessResult } from '../xtext/xtextServiceResults';
15 15
16import GraphTheme from './GraphTheme'; 16import GraphTheme from './GraphTheme';
17import { FitZoomCallback } from './ZoomCanvas';
17import postProcessSvg from './postProcessSVG'; 18import postProcessSvg from './postProcessSVG';
18 19
19function toGraphviz( 20function toGraphviz(
@@ -72,7 +73,20 @@ function toGraphviz(
72 return lines.join('\n'); 73 return lines.join('\n');
73} 74}
74 75
75export default function DotGraphVisualizer(): JSX.Element { 76function ptToPx(pt: number): number {
77 return (pt * 4) / 3;
78}
79
80export default function DotGraphVisualizer({
81 fitZoom,
82 transitionTime,
83}: {
84 fitZoom?: FitZoomCallback;
85 transitionTime?: number;
86}): JSX.Element {
87 const transitionTimeOrDefault =
88 transitionTime ?? DotGraphVisualizer.defaultProps.transitionTime;
89
76 const { editorStore } = useRootStore(); 90 const { editorStore } = useRootStore();
77 const disposerRef = useRef<IReactionDisposer | undefined>(); 91 const disposerRef = useRef<IReactionDisposer | undefined>();
78 const graphvizRef = useRef< 92 const graphvizRef = useRef<
@@ -104,12 +118,13 @@ export default function DotGraphVisualizer(): JSX.Element {
104 renderer.tweenShapes(false); 118 renderer.tweenShapes(false);
105 renderer.convertEqualSidedPolygons(false); 119 renderer.convertEqualSidedPolygons(false);
106 const transition = () => 120 const transition = () =>
107 d3.transition().duration(300).ease(d3.easeCubic); 121 d3.transition().duration(transitionTimeOrDefault).ease(d3.easeCubic);
108 /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument, 122 /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument,
109 @typescript-eslint/no-explicit-any -- 123 @typescript-eslint/no-explicit-any --
110 Workaround for error in `@types/d3-graphviz`. 124 Workaround for error in `@types/d3-graphviz`.
111 */ 125 */
112 renderer.transition(transition as any); 126 renderer.transition(transition as any);
127 let newViewBox = { width: 0, height: 0 };
113 renderer.on( 128 renderer.on(
114 'postProcessSVG', 129 'postProcessSVG',
115 // @ts-expect-error Custom `d3-graphviz` hook not covered by typings. 130 // @ts-expect-error Custom `d3-graphviz` hook not covered by typings.
@@ -119,9 +134,18 @@ export default function DotGraphVisualizer(): JSX.Element {
119 const svg = svgSelection.node(); 134 const svg = svgSelection.node();
120 if (svg !== null) { 135 if (svg !== null) {
121 postProcessSvg(svg); 136 postProcessSvg(svg);
137 newViewBox = {
138 width: ptToPx(svg.viewBox.baseVal.width),
139 height: ptToPx(svg.viewBox.baseVal.height),
140 };
141 } else {
142 newViewBox = { width: 0, height: 0 };
122 } 143 }
123 }, 144 },
124 ); 145 );
146 if (fitZoom !== undefined) {
147 renderer.on('transitionStart', () => fitZoom(newViewBox));
148 }
125 disposerRef.current = reaction( 149 disposerRef.current = reaction(
126 () => editorStore?.semantics, 150 () => editorStore?.semantics,
127 (semantics) => { 151 (semantics) => {
@@ -135,8 +159,13 @@ export default function DotGraphVisualizer(): JSX.Element {
135 graphvizRef.current = renderer; 159 graphvizRef.current = renderer;
136 } 160 }
137 }, 161 },
138 [editorStore], 162 [editorStore, fitZoom, transitionTimeOrDefault],
139 ); 163 );
140 164
141 return <GraphTheme ref={setElement} />; 165 return <GraphTheme ref={setElement} />;
142} 166}
167
168DotGraphVisualizer.defaultProps = {
169 fitZoom: undefined,
170 transitionTime: 250,
171};