@@ -17,6 +17,7 @@ import Data.Set as Set
1717import Data.Set (Set )
1818import Data.Symbol (SProxy (..))
1919import Data.Tuple.Nested (type (/\), (/\))
20+ import Data.Vec3 (vec2 , _x , _y , binOp )
2021import Effect.Class (class MonadEffect , liftEffect )
2122import Halogen as H
2223import Halogen.HTML hiding (code , head , prop , map )
@@ -83,8 +84,8 @@ initialState :: Input -> State
8384initialState input =
8485 { input
8586 , selection:
86- { topLeft: { x: 0 , y: 0 }
87- , bottomRight: { x: 0 , y: 0 }
87+ { topLeft: zero
88+ , bottomRight: zero
8889 }
8990 , mouseDownFrom: Nothing
9091 , showWires: false
@@ -98,7 +99,7 @@ render { input: { bricks: { width, height, boxes }, matches, context, selectedBo
9899 , onKeyDown (Just <<< OnKeyDown )
99100 , onMouseUp (const $ Just $ OnMouseUp )
100101 ]
101- [ S .svg [ viewBox { topLeft: { x: 0 , y: 0 } , bottomRight: { x: width, y: height } } ] $
102+ [ S .svg [ viewBox { topLeft: vec2 0 0 , bottomRight: vec2 width height } ] $
102103 foldMap (\b@{ bid, box } -> let { className, content } = renderBrick (matchesToIO matches) (lookup bid context) b in [ S .g
103104 [ svgClasses [ ClassName className, ClassName $ if Set .member b selectedBoxes then " selected" else " " ]
104105 , onMouseDown (const $ Just $ OnMouseDown box)
@@ -148,25 +149,27 @@ renderBrick io (Just { type: Cap }) b@{ box } =
148149renderBrick _ Nothing _ = { className: " box" , content: [] }
149150
150151renderBox :: ∀ m . String -> Box -> Array (H.ComponentHTML Action () m )
151- renderBox name { topLeft: { x: xl, y: yt }, bottomRight: { x: xr, y: yb } } =
152+ renderBox name { topLeft, bottomRight } =
152153 [ S .rect [ S .x (mx - 0.18 ), S .y (my - 0.25 ), S .width 0.36 , S .height 0.5 , svgClasses [ ClassName " inner-box" ] ]
153154 , S .text
154155 [ S .x mx, S .y (my + 0.12 )
155156 , S .attr (AttrName " text-anchor" ) " middle"
156157 , svgClasses [ ClassName " inner-box-text" ]
157- ] [ text name, sub_ [ text " 1 " ] ]
158+ ] [ text name ]
158159 ]
159160 where
160- mx = (toNumber xl + toNumber xr) / 2.0
161- my = (toNumber yt + toNumber yb) / 2.0
161+ center = map toNumber (topLeft + bottomRight) / pure 2.0
162+ mx = _x center
163+ my = _y center
162164
163165renderNode :: ∀ m . Brick String -> Color -> Array (H.ComponentHTML Action () m )
164- renderNode { bid, box: { topLeft: { x: xl, y: yt }, bottomRight: { x: xr, y: yb } } } color =
166+ renderNode { bid, box: { topLeft, bottomRight } } color =
165167 [ S .circle [ S .cx mx, S .cy my, S .r 0.05 , svgClasses [ ClassName " node" , ClassName (show color) ] ]
166168 ]
167169 where
168- mx = (toNumber xl + toNumber xr) / 2.0
169- my = (toNumber yt + toNumber yb) / 2.0
170+ center = map toNumber (topLeft + bottomRight) / pure 2.0
171+ mx = _x center
172+ my = _y center
170173
171174type LineSettings =
172175 { toBox :: Boolean
@@ -182,7 +185,7 @@ cupcapLineSettings :: LineSettings
182185cupcapLineSettings = { toBox: false , cpxf: \dx -> 0.0 , cpyf: \dy -> 0.0 }
183186
184187renderLines :: ∀ m . LineSettings -> Side -> Brick String -> Match String -> Array (H.ComponentHTML Action () m )
185- renderLines { toBox, cpxf, cpyf } side { box: { topLeft: { x: xl, y: yt }, bottomRight: { x: xr, y: yb } } } m@{ y } =
188+ renderLines { toBox, cpxf, cpyf } side { box: { topLeft, bottomRight } } m@{ y } =
186189 [ S .g [ svgClasses (objectClassNames m) ] $
187190 (if not toBox && m.center then [] else renderObject side x m) <>
188191 [ S .path
@@ -195,10 +198,14 @@ renderLines { toBox, cpxf, cpyf } side { box: { topLeft: { x: xl, y: yt }, botto
195198 ]
196199 ]
197200 where
198- x = toNumber $ if side == Input then xl else xr
199- mx = (toNumber xl + toNumber xr) / 2.0 + if toBox then if side == Input then -0.18 else 0.18 else 0.0
200- my = (toNumber yt + toNumber yb) / 2.0
201- height = toNumber yb - toNumber yt
201+ xl = toNumber (_x topLeft)
202+ yt = toNumber (_y topLeft)
203+ xr = toNumber (_x bottomRight)
204+ yb = toNumber (_y bottomRight)
205+ x = if side == Input then xl else xr
206+ mx = (xl + xr) / 2.0 + if toBox then if side == Input then -0.18 else 0.18 else 0.0
207+ my = (yt + yb) / 2.0
208+ height = yb - yt
202209 cpx = mx + cpxf (x - mx)
203210 cpy = my + cpyf ((y - my) / height)
204211
@@ -239,8 +246,8 @@ renderPerm io { box: b } perm =
239246 ] <> (if ml.center then [] else renderObject Input xln ml) <> (if mr.center then [] else renderObject Output xrn mr)
240247 _, _ -> []
241248 where
242- xln = toNumber b.topLeft.x
243- xrn = toNumber b.bottomRight.x
249+ xln = toNumber (_x b.topLeft)
250+ xrn = toNumber (_x b.bottomRight)
244251 cpx = (xln + xrn) / 2.0
245252
246253sideClassName :: Side -> ClassName
@@ -253,11 +260,10 @@ objectClassNames { validity, center } =
253260 ] <> if center then [ClassName " centered" ] else []
254261
255262selectionBox :: Box -> Box
256- selectionBox selection = { topLeft, bottomRight }
257- where
258- { topLeft: { x: x0, y: y0 }, bottomRight: { x: x1, y: y1 } } = selection
259- topLeft = { x: min x0 x1, y: min y0 y1 }
260- bottomRight = { x: max x0 x1 + 1 , y: max y0 y1 + 1 }
263+ selectionBox { topLeft, bottomRight } =
264+ { topLeft: binOp min topLeft bottomRight
265+ , bottomRight: binOp max topLeft bottomRight + vec2 1 1
266+ }
261267
262268
263269handleAction :: ∀ m . MonadEffect m => Action -> H.HalogenM State Action () Output m Unit
@@ -272,7 +278,7 @@ handleAction = case _ of
272278 , bottomRight: moveCursor d sel.bottomRight sel.topLeft
273279 }
274280 MoveCursorEnd d -> updateSelection (_bottomRight +~ d)
275- OnKeyDown k -> let act dx dy = handleAction $ (if shiftKey k then MoveCursorEnd else MoveCursorStart ) { x: dx, y: dy } in
281+ OnKeyDown k -> let act dx dy = handleAction $ (if shiftKey k then MoveCursorEnd else MoveCursorStart ) (vec2 dx dy) in
276282 case code k of
277283 " ArrowLeft" -> act (-1 ) 0
278284 " ArrowUp" -> act 0 (-1 )
@@ -283,15 +289,15 @@ handleAction = case _ of
283289 x -> trace x pure
284290 OnMouseDown b@{ topLeft, bottomRight } -> do
285291 H .modify_ \st -> st { mouseDownFrom = Just b }
286- updateSelection \_ -> { topLeft, bottomRight: bottomRight - { x: 1 , y: 1 } }
292+ updateSelection \_ -> { topLeft, bottomRight: bottomRight - vec2 1 1 }
287293 OnMouseMove b1 -> do
288294 mb0 <- H .gets _.mouseDownFrom
289295 case mb0 of
290296 Nothing -> pure unit
291297 Just b0 -> do
292298 updateSelection \_ ->
293- { topLeft: { x: min b0.topLeft.x b1.topLeft.x, y: min b0.topLeft.y b1.topLeft.y }
294- , bottomRight: { x: max b0.bottomRight.x b1.bottomRight.x - 1 , y: max b0.bottomRight.y b1.bottomRight.y - 1 }
299+ { topLeft: binOp min b0.topLeft b1.topLeft
300+ , bottomRight: binOp max b0.bottomRight b1.bottomRight - vec2 1 1
295301 }
296302 OnMouseUp ->
297303 H .modify_ $ \st -> st { mouseDownFrom = Nothing }
@@ -305,29 +311,29 @@ updateSelection f = do
305311 H .raise (SelectionChanged $ selectionBox selection')
306312
307313clamp2d :: Int -> Int -> Disc2 -> Disc2
308- clamp2d width height { x, y }= { x: clamp 0 (width - 1 ) x, y: clamp 0 (height - 1 ) y }
314+ clamp2d width height p = clamp <$> pure 0 <*> vec2 (width - 1 ) (height - 1 ) <*> p
309315
310316moveCursor :: Disc2 -> Disc2 -> Disc2 -> Disc2
311- moveCursor d2 p0 p1 = { x: move d2.x p0.x p1.x, y: move d2.y p0.y p1.y }
317+ moveCursor d2 p0 p1 = move <$> d2 <*> p0 <*> p1
312318 where
313319 move d a b | a == b = a + d
314320 move -1 a b = min a b
315321 move 1 a b = max a b
316322 move _ a _ = a
317323
318324rect :: ∀ m . Box -> String -> H.ComponentHTML Action () m
319- rect { topLeft: { x: x0, y: y0 }, bottomRight: { x: x1, y: y1 } } cls = S .rect $
320- [ S .x (toNumber x0 + 0.005 )
321- , S .y (toNumber y0 + 0.005 )
322- , S .width (toNumber (x1 - x0 ) - 0.01 )
323- , S .height (toNumber (y1 - y0 ) - 0.01 )
325+ rect { topLeft: p0, bottomRight: p1 } cls = let dp = p1 - p0 in S .rect $
326+ [ S .x (toNumber (_x p0) + 0.005 )
327+ , S .y (toNumber (_y p0) + 0.005 )
328+ , S .width (toNumber (_x dp ) - 0.01 )
329+ , S .height (toNumber (_y dp ) - 0.01 )
324330 , S .rx 0.07
325331 , svgClasses [ ClassName cls ]
326332 ]
327333
328334viewBox :: ∀ r i . Box -> IProp (viewBox :: String | r ) i
329- viewBox { topLeft : { x : x0 , y : y0 } , bottomRight : { x : x1 , y : y1 } } =
330- S.viewBox (toNumber x0 - 0.01) (toNumber y0 - 0.01) (toNumber (x1 - x0 ) + 0.02) (toNumber (y1 - y0 ) + 0.02)
335+ viewBox { topLeft : p0 , bottomRight : p1 } = let dp = p1 - p0 in
336+ S.viewBox (toNumber ( _x p0 ) - 0.01) (toNumber ( _y p0 ) - 0.01) (toNumber (_x dp ) + 0.02) (toNumber (_y dp ) + 0.02)
331337
332338svgClasses :: ∀ r i . Array (ClassName ) -> IProp r i
333339svgClasses arr = S .attr (AttrName " class" ) $ intercalate " " $ map (\(ClassName s) -> s) arr
@@ -351,8 +357,8 @@ matchesToIO = foldMap matchesToIO' >>> foldr (Map.unionWith (<>)) Map.empty
351357 _ /\ lvar /\ rvar = head nonEmpty
352358 lBox = lvar.box
353359 rBox = rvar.box
354- y0 = toNumber $ max lBox.topLeft.y rBox.topLeft.y
355- y1 = toNumber $ min lBox.bottomRight.y rBox.bottomRight.y
360+ y0 = toNumber $ max (_y lBox.topLeft) (_y rBox.topLeft)
361+ y1 = toNumber $ min (_y lBox.bottomRight) (_y rBox.bottomRight)
356362 n = toNumber (length nonEmpty)
357363 leftObjects /\ rightObjects = nonEmpty # foldMapWithIndex \i (b /\ l /\ r) ->
358364 let y = y0 + (y1 - y0) * (0.5 + toNumber i) / n in
@@ -365,9 +371,9 @@ matchesToIO = foldMap matchesToIO' >>> foldr (Map.unionWith (<>)) Map.empty
365371 toMismatch validity side nonEmpty = Map .singleton (b /\ side) objects
366372 where
367373 b = (head nonEmpty).box
368- x = if side == Input then b.topLeft.x else b.bottomRight.x
369- y0 = toNumber $ b.topLeft.y
370- y1 = toNumber $ b.bottomRight.y
374+ x = _x ( if side == Input then b.topLeft else b.bottomRight)
375+ y0 = toNumber $ _y b.topLeft
376+ y1 = toNumber $ _y b.bottomRight
371377 n = toNumber (length nonEmpty)
372378 objects = nonEmpty # foldMapWithIndex \i v -> [{ validity, y: y0 + (y1 - y0) * (0.5 + toNumber i) / n, object: getObject v, center: false }]
373379 getObject { var: BoundVar bv } = bv
0 commit comments