diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-08-24 17:12:16 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-08-24 17:44:34 +0200 |
commit | f20474c728e97af79a6d63783619c2515549b107 (patch) | |
tree | 2650578c70ecd6bad730086fdfdcf3a6387106ec /subprojects/frontend/src/graph/DotGraphVisualizer.tsx | |
parent | chore: clarify permissing licensing (diff) | |
download | refinery-f20474c728e97af79a6d63783619c2515549b107.tar.gz refinery-f20474c728e97af79a6d63783619c2515549b107.tar.zst refinery-f20474c728e97af79a6d63783619c2515549b107.zip |
feat(frontend): automatic fit zoom
Diffstat (limited to 'subprojects/frontend/src/graph/DotGraphVisualizer.tsx')
-rw-r--r-- | subprojects/frontend/src/graph/DotGraphVisualizer.tsx | 35 |
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'; | |||
14 | import type { SemanticsSuccessResult } from '../xtext/xtextServiceResults'; | 14 | import type { SemanticsSuccessResult } from '../xtext/xtextServiceResults'; |
15 | 15 | ||
16 | import GraphTheme from './GraphTheme'; | 16 | import GraphTheme from './GraphTheme'; |
17 | import { FitZoomCallback } from './ZoomCanvas'; | ||
17 | import postProcessSvg from './postProcessSVG'; | 18 | import postProcessSvg from './postProcessSVG'; |
18 | 19 | ||
19 | function toGraphviz( | 20 | function toGraphviz( |
@@ -72,7 +73,20 @@ function toGraphviz( | |||
72 | return lines.join('\n'); | 73 | return lines.join('\n'); |
73 | } | 74 | } |
74 | 75 | ||
75 | export default function DotGraphVisualizer(): JSX.Element { | 76 | function ptToPx(pt: number): number { |
77 | return (pt * 4) / 3; | ||
78 | } | ||
79 | |||
80 | export 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 | |||
168 | DotGraphVisualizer.defaultProps = { | ||
169 | fitZoom: undefined, | ||
170 | transitionTime: 250, | ||
171 | }; | ||