Skip to content

Commit 75bdb42

Browse files
authored
Merge pull request #131 from statebox/79/dont-hardcode-svg-element
79/dont hardcode svg element
2 parents acc5778 + c9007e4 commit 75bdb42

File tree

7 files changed

+43
-52
lines changed

7 files changed

+43
-52
lines changed

src/Svg/Util.js

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,19 @@ exports._beginElements = function (cssSelectorStr) {
2121
};
2222
}
2323

24-
var svg;
24+
exports.domToSvgCoordinates = function (svg) {
25+
return function (point) {
26+
const svgPoint = svg.createSVGPoint();
2527

26-
exports.domToSvgCoordinates = function (point) {
27-
if (typeof svg === 'undefined') {
28-
svg = document.getElementsByTagName('svg')[0];
29-
}
28+
svgPoint.x = point.x;
29+
svgPoint.y = point.y;
3030

31-
const svgPoint = svg.createSVGPoint();
31+
const svgCoordPoint = svgPoint.matrixTransform(svg.getScreenCTM().inverse());
3232

33-
svgPoint.x = point.x;
34-
svgPoint.y = point.y;
35-
36-
const svgCoordPoint = svgPoint.matrixTransform(svg.getScreenCTM().inverse());
37-
38-
return {
39-
x: svgCoordPoint.x,
40-
y: svgCoordPoint.y,
41-
z: 0
33+
return {
34+
x: svgCoordPoint.x,
35+
y: svgCoordPoint.y,
36+
z: 0
37+
};
4238
};
4339
}

src/Svg/Util.purs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Data.Vec3 (Vec3)
44
import Prelude ((<<<))
55
import Effect.Aff (Aff)
66
import Effect.Aff.Compat (EffectFnAff, fromEffectFnAff)
7+
import Web.HTML (HTMLElement)
78

89
type CssSelector = String
910

@@ -12,4 +13,4 @@ foreign import _beginElements :: CssSelector -> EffectFnAff Int
1213
beginElements :: CssSelector -> Aff Int
1314
beginElements = fromEffectFnAff <<< _beginElements
1415

15-
foreign import domToSvgCoordinates :: Vec3 Int -> Vec3 Int
16+
foreign import domToSvgCoordinates :: HTMLElement -> Vec3 Int -> Vec3 Int

src/View/Diagram/DiagramEditor.purs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,25 @@ module View.Diagram.DiagramEditor where
22

33
import Prelude hiding (div)
44

5-
import Data.Bifunctor (bimap)
6-
import Data.Int (floor, round)
75
import Data.Maybe
86
import Data.Traversable (traverse)
97
import Data.Tuple.Nested ((/\))
10-
import Data.Vec3 (vec2, vec3)
11-
import Effect.Aff.Class (class MonadAff, liftAff)
12-
import Effect (Effect)
13-
import Foreign (Foreign)
8+
import Data.Vec3 (vec2)
9+
import Effect.Aff.Class (class MonadAff)
1410
import Halogen as H
1511
import Halogen (ComponentDSL, HalogenM)
1612
import Halogen.HTML as HH
17-
import Halogen.HTML (HTML, div, br)
13+
import Halogen.HTML (HTML, div)
1814
import Halogen.HTML.Core (ClassName(..))
1915
import Halogen.HTML.Events as HE
2016
import Halogen.HTML.Properties as HP
2117
import Halogen.HTML.Properties (classes)
22-
import Halogen.Query (getHTMLElementRef)
2318
import Svg.Elements as SE
2419
import Svg.Attributes as SA
2520
import Unsafe.Coerce (unsafeCoerce)
2621
import Web.DOM (Element)
2722
import Web.HTML.HTMLElement as HTMLElement
28-
import Web.HTML.HTMLElement (HTMLElement, DOMRect, getBoundingClientRect)
23+
import Web.HTML.HTMLElement (HTMLElement, getBoundingClientRect)
2924

3025
import View.Diagram.Model
3126
import View.Diagram.Update as Update
@@ -46,35 +41,27 @@ initialState ops =
4641
, dragStart: DragNotStarted
4742
}
4843
, msg: ""
49-
, boundingClientRectMaybe: Nothing
44+
, componentElemMaybe: Nothing
5045
}
5146

5247
ui :: m. MonadAff m => H.Component HTML Query Operators Msg m
53-
ui = H.component { initialState: initialState, render, eval, receiver: HE.input UpdateDiagram }
48+
ui = H.lifecycleComponent { initialState: initialState, render, eval, receiver: HE.input UpdateDiagram, initializer: Just (Initialize unit), finalizer: Nothing }
5449
where
5550
render :: State -> HTML Void (Query Unit)
5651
render state =
5752
div [ classes [ ClassName "css-diagram-editor" ] ]
5853
[ div [ classes [] ]
59-
[ View.diagramEditorSVG state.model <#> \msg -> MouseAction msg unit
54+
[ View.diagramEditorSVG state.componentElemMaybe state.model <#> \msg -> MouseAction msg unit
6055
, div [ classes [ ClassName "mt-4", ClassName "rb-2", ClassName "p-4", ClassName "bg-grey-lightest", ClassName "text-grey-dark", ClassName "rounded", ClassName "text-sm" ] ]
6156
[ Inspector.view state ]
6257
]
6358
]
6459

65-
-- TODO We shouldn't need to getBoundingClientRect on every single model update, that is incredibly inefficient.
66-
-- Doing it just on initialisation and window resizing/layout changes should do.
6760
eval :: Query ~> ComponentDSL State Query Msg m
6861
eval = case _ of
6962
MouseAction msg next -> do
70-
componentElemMaybe <- getHTMLElementRef' View.componentRefLabel
71-
boundingRectMaybe <- H.liftEffect $ getBoundingClientRect `traverse` componentElemMaybe
72-
7363
state <- H.get
74-
let updater = maybe (\ state -> state { msg = "Could not determine this component's boundingClientRect." })
75-
(\rect state -> state { model = evalModel msg state.model })
76-
boundingRectMaybe
77-
state' = (updater <<< _ { boundingClientRectMaybe = boundingRectMaybe }) state
64+
let state' = state { model = evalModel msg state.model }
7865

7966
isOperatorClicked = case msg of
8067
MouseUp _ -> true
@@ -96,6 +83,11 @@ ui = H.component { initialState: initialState, render, eval, receiver: HE.input
9683
H.modify_ \state -> state { model = state.model { ops = ops } }
9784
pure next
9885

86+
Initialize next -> do
87+
componentElemMaybe <- getHTMLElementRef' View.componentRefLabel
88+
H.modify_ \state -> state { componentElemMaybe = componentElemMaybe }
89+
pure next
90+
9991
-- TODO this is generally useful; move elsewhere
10092
-- This was made because the original implementation from Halogen.Query doesn't seem to work, at least in this case:
10193
-- getHTMLElementRef = map (HTMLElement.fromElement =<< _) <<< getRef

src/View/Diagram/Inspector.purs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ view state@{model} =
2828
, prop "valid" $ show $ isValidDrag model
2929
, prop "selectedOpId"$ show model.selectedOpId
3030
, code "-----------------------\n"
31-
, prop "bounds" $ maybe "Nothing" (\r -> "Just " <> viewRect r) state.boundingClientRectMaybe
3231
]
3332
where
3433
prop :: String -> String -> HTML Void (Query Unit)

src/View/Diagram/Model.purs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module View.Diagram.Model where
22

3-
import Prelude
43
import Data.Maybe
4+
import Prelude
5+
56
import Data.Tuple.Nested (type (/\), (/\))
67
import Data.Vec3 (Vec3, vec3, _x, _y)
78

src/View/Diagram/Update.purs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ module View.Diagram.Update where
33
import Prelude
44

55
import Data.Maybe
6-
import Data.Tuple.Nested (type (/\), (/\))
6+
import Data.Tuple.Nested ((/\))
77
import Data.Vec3 (Vec3, _x, _y, _z, vec3)
8+
import Web.HTML (HTMLElement)
89
import Web.HTML.HTMLElement (DOMRect)
910

1011
import View.Diagram.Model
@@ -13,11 +14,12 @@ import View.Diagram.Common (snap)
1314
type State =
1415
{ model :: Model -- TODO should perhaps be flattened into this record, ie State and Model should be unified
1516
, msg :: String
16-
, boundingClientRectMaybe :: Maybe DOMRect -- ^ Allows us to correct mouse coordinates for the component's position.
17+
, componentElemMaybe :: Maybe HTMLElement
1718
}
1819

1920
data Query a
20-
= MouseAction MouseMsg a
21+
= Initialize a
22+
| MouseAction MouseMsg a
2123
| UpdateDiagram Operators a
2224

2325
data MouseMsg

src/View/Diagram/View.purs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,32 @@ import Data.Monoid (guard)
88
import Data.Ord (abs)
99
import Data.Vec3 (Vec3, _x, _y, _z, vec2, vec3)
1010
import Halogen as H
11-
import Halogen.HTML (HTML, div, pre)
11+
import Halogen.HTML (HTML)
1212
import Halogen.HTML as HH
13-
import Halogen.HTML.Events (onMouseOver, onMouseOut)
1413
import Halogen.HTML.Events as HE
1514
import Halogen.HTML.Properties as HP
16-
import Svg.Attributes (Color(RGB, RGBA), FontSize(..), CSSLength(..))
15+
import Svg.Attributes (CSSLength(..))
1716
import Svg.Attributes as SA
1817
import Svg.Elements (rect)
1918
import Svg.Elements as SE
2019
import Svg.Util (domToSvgCoordinates)
21-
import View.Common (styleStr)
2220
import View.Diagram.Common
2321
import View.Diagram.Model
2422
import View.Diagram.Update
23+
import Web.HTML (HTMLElement)
2524
import Web.UIEvent.MouseEvent (clientX, clientY)
2625

2726
-- TODO eliminate?
2827
type Svg a = HTML Void a
2928

30-
diagramEditorSVG :: Model -> Svg MouseMsg
31-
diagramEditorSVG model =
29+
-- TODO: if there is no HTMLElement it does not make sense to draw anything
30+
diagramEditorSVG :: Maybe HTMLElement -> Model -> Svg MouseMsg
31+
diagramEditorSVG maybeElement model =
3232
SE.svg [ SA.viewBox sceneLeft sceneTop w h
3333
, HP.ref componentRefLabel
34-
, HE.onMouseMove $ \e -> Just $ MousePos (svg e)
35-
, HE.onMouseDown $ \e -> Just $ MouseDown (svg e)
36-
, HE.onMouseUp $ \e -> Just $ MouseUp (svg e)
34+
, HE.onMouseMove $ \e -> Just $ MousePos (svg e maybeElement)
35+
, HE.onMouseDown $ \e -> Just $ MouseDown (svg e maybeElement)
36+
, HE.onMouseUp $ \e -> Just $ MouseUp (svg e maybeElement)
3737
]
3838
(ghosts <> operators)
3939
where
@@ -42,7 +42,7 @@ diagramEditorSVG model =
4242
w = toNumber model.config.width
4343
h = toNumber model.config.height
4444
s = model.config.scale
45-
svg e = domToSvgCoordinates (vec2 (clientX e) (clientY e))
45+
svg e = maybe zero (\el -> domToSvgCoordinates el (vec2 (clientX e) (clientY e)))
4646

4747
-- TODO ???
4848
sceneLeft = zero

0 commit comments

Comments
 (0)