@@ -17,6 +17,7 @@ import Data.Set as Set
17
17
import Data.Set (Set )
18
18
import Data.Symbol (SProxy (..))
19
19
import Data.Tuple.Nested (type (/\), (/\))
20
+ import Data.Vec3 (vec2 , _x , _y , binOp )
20
21
import Effect.Class (class MonadEffect , liftEffect )
21
22
import Halogen as H
22
23
import Halogen.HTML hiding (code , head , prop , map )
@@ -83,8 +84,8 @@ initialState :: Input -> State
83
84
initialState input =
84
85
{ input
85
86
, selection:
86
- { topLeft: { x: 0 , y: 0 }
87
- , bottomRight: { x: 0 , y: 0 }
87
+ { topLeft: zero
88
+ , bottomRight: zero
88
89
}
89
90
, mouseDownFrom: Nothing
90
91
, showWires: false
@@ -98,7 +99,7 @@ render { input: { bricks: { width, height, boxes }, matches, context, selectedBo
98
99
, onKeyDown (Just <<< OnKeyDown )
99
100
, onMouseUp (const $ Just $ OnMouseUp )
100
101
]
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 } ] $
102
103
foldMap (\b@{ bid, box } -> let { className, content } = renderBrick (matchesToIO matches) (lookup bid context) b in [ S .g
103
104
[ svgClasses [ ClassName className, ClassName $ if Set .member b selectedBoxes then " selected" else " " ]
104
105
, onMouseDown (const $ Just $ OnMouseDown box)
@@ -148,25 +149,27 @@ renderBrick io (Just { type: Cap }) b@{ box } =
148
149
renderBrick _ Nothing _ = { className: " box" , content: [] }
149
150
150
151
renderBox :: ∀ 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 } =
152
153
[ S .rect [ S .x (mx - 0.18 ), S .y (my - 0.25 ), S .width 0.36 , S .height 0.5 , svgClasses [ ClassName " inner-box" ] ]
153
154
, S .text
154
155
[ S .x mx, S .y (my + 0.12 )
155
156
, S .attr (AttrName " text-anchor" ) " middle"
156
157
, svgClasses [ ClassName " inner-box-text" ]
157
- ] [ text name, sub_ [ text " 1 " ] ]
158
+ ] [ text name ]
158
159
]
159
160
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
162
164
163
165
renderNode :: ∀ 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 =
165
167
[ S .circle [ S .cx mx, S .cy my, S .r 0.05 , svgClasses [ ClassName " node" , ClassName (show color) ] ]
166
168
]
167
169
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
170
173
171
174
type LineSettings =
172
175
{ toBox :: Boolean
@@ -182,7 +185,7 @@ cupcapLineSettings :: LineSettings
182
185
cupcapLineSettings = { toBox: false , cpxf: \dx -> 0.0 , cpyf: \dy -> 0.0 }
183
186
184
187
renderLines :: ∀ 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 } =
186
189
[ S .g [ svgClasses (objectClassNames m) ] $
187
190
(if not toBox && m.center then [] else renderObject side x m) <>
188
191
[ S .path
@@ -195,10 +198,14 @@ renderLines { toBox, cpxf, cpyf } side { box: { topLeft: { x: xl, y: yt }, botto
195
198
]
196
199
]
197
200
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
202
209
cpx = mx + cpxf (x - mx)
203
210
cpy = my + cpyf ((y - my) / height)
204
211
@@ -239,8 +246,8 @@ renderPerm io { box: b } perm =
239
246
] <> (if ml.center then [] else renderObject Input xln ml) <> (if mr.center then [] else renderObject Output xrn mr)
240
247
_, _ -> []
241
248
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)
244
251
cpx = (xln + xrn) / 2.0
245
252
246
253
sideClassName :: Side -> ClassName
@@ -253,11 +260,10 @@ objectClassNames { validity, center } =
253
260
] <> if center then [ClassName " centered" ] else []
254
261
255
262
selectionBox :: 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
+ }
261
267
262
268
263
269
handleAction :: ∀ m . MonadEffect m => Action -> H.HalogenM State Action () Output m Unit
@@ -272,7 +278,7 @@ handleAction = case _ of
272
278
, bottomRight: moveCursor d sel.bottomRight sel.topLeft
273
279
}
274
280
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
276
282
case code k of
277
283
" ArrowLeft" -> act (-1 ) 0
278
284
" ArrowUp" -> act 0 (-1 )
@@ -283,15 +289,15 @@ handleAction = case _ of
283
289
x -> trace x pure
284
290
OnMouseDown b@{ topLeft, bottomRight } -> do
285
291
H .modify_ \st -> st { mouseDownFrom = Just b }
286
- updateSelection \_ -> { topLeft, bottomRight: bottomRight - { x: 1 , y: 1 } }
292
+ updateSelection \_ -> { topLeft, bottomRight: bottomRight - vec2 1 1 }
287
293
OnMouseMove b1 -> do
288
294
mb0 <- H .gets _.mouseDownFrom
289
295
case mb0 of
290
296
Nothing -> pure unit
291
297
Just b0 -> do
292
298
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
295
301
}
296
302
OnMouseUp ->
297
303
H .modify_ $ \st -> st { mouseDownFrom = Nothing }
@@ -305,29 +311,29 @@ updateSelection f = do
305
311
H .raise (SelectionChanged $ selectionBox selection')
306
312
307
313
clamp2d :: 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
309
315
310
316
moveCursor :: 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
312
318
where
313
319
move d a b | a == b = a + d
314
320
move -1 a b = min a b
315
321
move 1 a b = max a b
316
322
move _ a _ = a
317
323
318
324
rect :: ∀ 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 )
324
330
, S .rx 0.07
325
331
, svgClasses [ ClassName cls ]
326
332
]
327
333
328
334
viewBox :: ∀ 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 )
331
337
332
338
svgClasses :: ∀ r i . Array (ClassName ) -> IProp r i
333
339
svgClasses arr = S .attr (AttrName " class" ) $ intercalate " " $ map (\(ClassName s) -> s) arr
@@ -351,8 +357,8 @@ matchesToIO = foldMap matchesToIO' >>> foldr (Map.unionWith (<>)) Map.empty
351
357
_ /\ lvar /\ rvar = head nonEmpty
352
358
lBox = lvar.box
353
359
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)
356
362
n = toNumber (length nonEmpty)
357
363
leftObjects /\ rightObjects = nonEmpty # foldMapWithIndex \i (b /\ l /\ r) ->
358
364
let y = y0 + (y1 - y0) * (0.5 + toNumber i) / n in
@@ -365,9 +371,9 @@ matchesToIO = foldMap matchesToIO' >>> foldr (Map.unionWith (<>)) Map.empty
365
371
toMismatch validity side nonEmpty = Map .singleton (b /\ side) objects
366
372
where
367
373
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
371
377
n = toNumber (length nonEmpty)
372
378
objects = nonEmpty # foldMapWithIndex \i v -> [{ validity, y: y0 + (y1 - y0) * (0.5 + toNumber i) / n, object: getObject v, center: false }]
373
379
getObject { var: BoundVar bv } = bv
0 commit comments