Skip to content

Commit 0bb5df1

Browse files
author
Sjoerd Visscher
committed
Switch to purescript-vec
Fixes #32
1 parent 6a33d68 commit 0bb5df1

File tree

6 files changed

+58
-47
lines changed

6 files changed

+58
-47
lines changed

packages.dhall

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ let additions = {
88
{ dependencies = [ "prelude", "halogen", "strings", "web-uievents", "effect" ]
99
, repo = "https://github.com/statebox/purescript-halogen-svg.git"
1010
, version = "d0a4cbc79b5513296cb746576824dce967aedbab"
11+
},
12+
vec =
13+
{ dependencies = [ "foldable-traversable" ]
14+
, repo = "https://github.com/statebox/purescript-vec.git"
15+
, version = "c7c8486a4e36ed37baf67cbe026d42acd4aa9b02"
1116
}
1217
}
1318

spago.dhall

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
, "psci-support"
1515
, "strings"
1616
, "variant"
17+
, "vec"
1718
]
1819
, packages =
1920
./packages.dhall

src/Bricks.purs

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import Data.List (snoc) as L
88
import Data.Maybe (Maybe(..), fromMaybe, maybe)
99
import Data.Newtype (alaF)
1010
import Data.Ord.Max (Max(..))
11-
import Data.Tuple (fst, snd)
1211
import Data.Tuple.Nested (type (/\), (/\))
12+
import Data.Vec3 (vec2, _x, _y)
1313

1414
import Model
1515
import Common ((..<), Fix(..), Ann(..), Disc2)
@@ -38,7 +38,7 @@ fromPixels inp isHole = let term /\ boxes = findCuts false false 0 0 width heigh
3838
hCuts = 1 ..< height <#> \y -> 0 ..< width <#> \x -> at x (y - 1) `canCut` at x y
3939

4040
toTerm :: Boolean -> Int -> Int -> Int -> Int -> Term AnnPos (Brick bid) /\ Array (Brick bid)
41-
toTerm false x0 y0 x1 y1 = let box = { topLeft: { x: x0, y: y0 }, bottomRight: { x: x1, y: y1 } } in at x0 y0
41+
toTerm false x0 y0 x1 y1 = let box = { topLeft: vec2 x0 y0, bottomRight: vec2 x1 y1 } in at x0 y0
4242
# maybe (tunit /\ []) (\bid -> let brick = { bid, box } in tbox brick /\ [brick])
4343
toTerm true y0 x0 y1 x1 = toTerm false x0 y0 x1 y1
4444

@@ -52,8 +52,8 @@ fromPixels inp isHole = let term /\ boxes = findCuts false false 0 0 width heigh
5252
isCut y = and $ slice x0 x1 $ fromMaybe [] $ (if xySwapped then vCuts else hCuts) !! (y - 1)
5353

5454
toSelection :: bid. Box -> Term AnnPos (Brick bid) -> Path -> Selection
55-
toSelection box (Fix (Ann ann (TC ts))) p = toSelection' box ts ann p _.x
56-
toSelection box (Fix (Ann ann (TT ts))) p = toSelection' box ts ann p _.y
55+
toSelection box (Fix (Ann ann (TC ts))) p = toSelection' box ts ann p _x
56+
toSelection box (Fix (Ann ann (TT ts))) p = toSelection' box ts ann p _y
5757
toSelection _ _ path = { path, count: 1 }
5858

5959
toSelection'

src/Common.purs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ import Data.Array (range)
77
import Data.Bifunctor
88
import Data.Bitraversable
99
import Data.Traversable
10-
10+
import Data.Vec3
1111

1212
data VoidF a
1313

14-
type Vec2 a = { x :: a, y :: a }
1514
type Disc2 = Vec2 Int
1615
type Cont2 = Vec2 Number
1716

src/View/App.purs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ appView =
8383
}
8484

8585
initialState :: Input -> State
86-
initialState input = { input, selectionBox: { topLeft: { x: 0, y: 0 }, bottomRight: { x: 0, y: 0 } } }
86+
initialState input = { input, selectionBox: { topLeft: zero, bottomRight: zero } }
8787

8888
render :: m. MonadEffect m => State -> H.ComponentHTML Action ChildSlots m
8989
render st = div [ classes [ ClassName "app" ] ]

src/View/Bricks.purs

+46-40
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Data.Set as Set
1717
import Data.Set (Set)
1818
import Data.Symbol (SProxy(..))
1919
import Data.Tuple.Nested (type (/\), (/\))
20+
import Data.Vec3 (vec2, _x, _y, binOp)
2021
import Effect.Class (class MonadEffect, liftEffect)
2122
import Halogen as H
2223
import Halogen.HTML hiding (code, head, prop, map)
@@ -83,8 +84,8 @@ initialState :: Input -> State
8384
initialState 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 } =
148149
renderBrick _ Nothing _ = { className: "box", content: [] }
149150

150151
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 } =
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

163165
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 =
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

171174
type LineSettings =
172175
{ toBox :: Boolean
@@ -182,7 +185,7 @@ cupcapLineSettings :: LineSettings
182185
cupcapLineSettings = { toBox: false, cpxf: \dx -> 0.0, cpyf: \dy -> 0.0 }
183186

184187
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 } =
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

246253
sideClassName :: Side -> ClassName
@@ -253,11 +260,10 @@ objectClassNames { validity, center } =
253260
] <> if center then [ClassName "centered"] else []
254261

255262
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+
}
261267

262268

263269
handleAction :: 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

307313
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
309315

310316
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
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

318324
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)
324330
, S.rx 0.07
325331
, svgClasses [ ClassName cls ]
326332
]
327333

328334
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)
331337

332338
svgClasses :: r i. Array (ClassName) -> IProp r i
333339
svgClasses 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

Comments
 (0)