diff options
Diffstat (limited to 'subprojects/frontend/src/Refinery.tsx')
-rw-r--r-- | subprojects/frontend/src/Refinery.tsx | 142 |
1 files changed, 2 insertions, 140 deletions
diff --git a/subprojects/frontend/src/Refinery.tsx b/subprojects/frontend/src/Refinery.tsx index 099646f0..5ad16000 100644 --- a/subprojects/frontend/src/Refinery.tsx +++ b/subprojects/frontend/src/Refinery.tsx | |||
@@ -4,151 +4,13 @@ | |||
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | 6 | ||
7 | import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; | ||
8 | import MoreVertIcon from '@mui/icons-material/MoreVert'; | ||
9 | import Box from '@mui/material/Box'; | ||
10 | import Grow from '@mui/material/Grow'; | 7 | import Grow from '@mui/material/Grow'; |
11 | import Stack from '@mui/material/Stack'; | 8 | import Stack from '@mui/material/Stack'; |
12 | import { alpha, useTheme } from '@mui/material/styles'; | ||
13 | import { SnackbarProvider } from 'notistack'; | 9 | import { SnackbarProvider } from 'notistack'; |
14 | import { memo, useRef, useState } from 'react'; | ||
15 | import { useResizeDetector } from 'react-resize-detector'; | ||
16 | 10 | ||
17 | import TopBar from './TopBar'; | 11 | import TopBar from './TopBar'; |
18 | import UpdateNotification from './UpdateNotification'; | 12 | import UpdateNotification from './UpdateNotification'; |
19 | import EditorPane from './editor/EditorPane'; | 13 | import WorkArea from './WorkArea'; |
20 | import GraphPane from './graph/GraphPane'; | ||
21 | |||
22 | const DirectionalSplitPane = memo(function SplitPanel({ | ||
23 | horizontalSplit, | ||
24 | }: { | ||
25 | horizontalSplit: boolean; | ||
26 | }): JSX.Element { | ||
27 | const theme = useTheme(); | ||
28 | const stackRef = useRef<HTMLDivElement>(null); | ||
29 | const sliderRef = useRef<HTMLDivElement>(null); | ||
30 | const [resizing, setResizing] = useState(false); | ||
31 | const [fraction, setFraction] = useState(0.5); | ||
32 | |||
33 | const direction = horizontalSplit ? 'column' : 'row'; | ||
34 | const axis = horizontalSplit ? 'height' : 'width'; | ||
35 | const primarySize = `calc(${fraction * 100}% - 0.5px)`; | ||
36 | const secondarySize = `calc(${(1 - fraction) * 100}% - 0.5px)`; | ||
37 | |||
38 | return ( | ||
39 | <Stack direction={direction} height="100%" overflow="hidden" ref={stackRef}> | ||
40 | <Box {...{ [axis]: primarySize }}> | ||
41 | <EditorPane /> | ||
42 | </Box> | ||
43 | <Box | ||
44 | sx={{ | ||
45 | overflow: 'visible', | ||
46 | position: 'relative', | ||
47 | [axis]: '0px', | ||
48 | display: 'flex', | ||
49 | flexDirection: direction, | ||
50 | [horizontalSplit | ||
51 | ? 'borderBottom' | ||
52 | : 'borderRight']: `1px solid ${theme.palette.outer.border}`, | ||
53 | }} | ||
54 | > | ||
55 | <Box | ||
56 | ref={sliderRef} | ||
57 | sx={{ | ||
58 | display: 'flex', | ||
59 | position: 'absolute', | ||
60 | [axis]: theme.spacing(2), | ||
61 | ...(horizontalSplit | ||
62 | ? { | ||
63 | top: theme.spacing(-1), | ||
64 | left: 0, | ||
65 | right: 0, | ||
66 | transform: 'translateY(0.5px)', | ||
67 | } | ||
68 | : { | ||
69 | left: theme.spacing(-1), | ||
70 | top: 0, | ||
71 | bottom: 0, | ||
72 | transform: 'translateX(0.5px)', | ||
73 | }), | ||
74 | zIndex: 999, | ||
75 | alignItems: 'center', | ||
76 | justifyContent: 'center', | ||
77 | color: theme.palette.text.secondary, | ||
78 | cursor: horizontalSplit ? 'ns-resize' : 'ew-resize', | ||
79 | '.MuiSvgIcon-root': { | ||
80 | opacity: resizing ? 1 : 0, | ||
81 | }, | ||
82 | ...(resizing | ||
83 | ? { | ||
84 | background: alpha( | ||
85 | theme.palette.text.primary, | ||
86 | theme.palette.action.activatedOpacity, | ||
87 | ), | ||
88 | } | ||
89 | : { | ||
90 | '&:hover': { | ||
91 | background: alpha( | ||
92 | theme.palette.text.primary, | ||
93 | theme.palette.action.hoverOpacity, | ||
94 | ), | ||
95 | '.MuiSvgIcon-root': { | ||
96 | opacity: 1, | ||
97 | }, | ||
98 | }, | ||
99 | }), | ||
100 | }} | ||
101 | onPointerDown={(event) => { | ||
102 | if (event.button !== 0) { | ||
103 | return; | ||
104 | } | ||
105 | sliderRef.current?.setPointerCapture(event.pointerId); | ||
106 | setResizing(true); | ||
107 | }} | ||
108 | onPointerUp={(event) => { | ||
109 | if (event.button !== 0) { | ||
110 | return; | ||
111 | } | ||
112 | sliderRef.current?.releasePointerCapture(event.pointerId); | ||
113 | setResizing(false); | ||
114 | }} | ||
115 | onPointerMove={(event) => { | ||
116 | if (!resizing) { | ||
117 | return; | ||
118 | } | ||
119 | const container = stackRef.current; | ||
120 | if (container === null) { | ||
121 | return; | ||
122 | } | ||
123 | const rect = container.getBoundingClientRect(); | ||
124 | const newFraction = horizontalSplit | ||
125 | ? (event.clientY - rect.top) / rect.height | ||
126 | : (event.clientX - rect.left) / rect.width; | ||
127 | setFraction(Math.min(0.9, Math.max(0.1, newFraction))); | ||
128 | }} | ||
129 | onDoubleClick={() => setFraction(0.5)} | ||
130 | > | ||
131 | {horizontalSplit ? <MoreHorizIcon /> : <MoreVertIcon />} | ||
132 | </Box> | ||
133 | </Box> | ||
134 | <Box {...{ [axis]: secondarySize }}> | ||
135 | <GraphPane /> | ||
136 | </Box> | ||
137 | </Stack> | ||
138 | ); | ||
139 | }); | ||
140 | |||
141 | function SplitPane(): JSX.Element { | ||
142 | const { ref, width, height } = useResizeDetector(); | ||
143 | const horizontalSplit = | ||
144 | width !== undefined && height !== undefined && height > width; | ||
145 | |||
146 | return ( | ||
147 | <Box height="100%" overflow="auto" ref={ref}> | ||
148 | <DirectionalSplitPane horizontalSplit={horizontalSplit} /> | ||
149 | </Box> | ||
150 | ); | ||
151 | } | ||
152 | 14 | ||
153 | export default function Refinery(): JSX.Element { | 15 | export default function Refinery(): JSX.Element { |
154 | return ( | 16 | return ( |
@@ -156,7 +18,7 @@ export default function Refinery(): JSX.Element { | |||
156 | <UpdateNotification /> | 18 | <UpdateNotification /> |
157 | <Stack direction="column" height="100%" overflow="auto"> | 19 | <Stack direction="column" height="100%" overflow="auto"> |
158 | <TopBar /> | 20 | <TopBar /> |
159 | <SplitPane /> | 21 | <WorkArea /> |
160 | </Stack> | 22 | </Stack> |
161 | </SnackbarProvider> | 23 | </SnackbarProvider> |
162 | ); | 24 | ); |