--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
P.S. Other folks on the list, this is maybe the most important kind of question on the list. These are the questions that will lead to success or failure, not speculative design discussions!!!
--
Kaspar, yes, of course! You don't make a language like Elm if you don't care about theory and design. I'm just pointing out that we need a balance. 40 comments on theory and 0 on examples is not a good balance.
--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/6nv1KkBs1a8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
Enter code here...
import Svg (Svg, circle, svg, g, line)import Svg.Attributes (cx, cy, r, fill, stroke, strokeWidth, x1, x2, y1, y2)import Html (Html)import Html.Attributes (style)
import Signal (Signal, map, foldp)import DragAndDrop (..)import List
type alias Vector = (Int, Int)
type alias Point = { position : Vector , selected : Bool , radius : Int }
type alias Triangle = (Point, Point, Point)
type alias Circle = (Point, Point)
type alias State = { triangles : List Triangle , circles : List Circle }
view : Model -> Html
view : State -> Htmlview {circles, triangles} = svg [ style [ ("border", "1px solid black") , ("width", "800px") , ("height", "600px")] ] ((List.map drawCircle circles) ++ (List.map drawTriangle triangles))
svg : List Html.Attribute -> List Svg -> List Html.Html
((List.map drawCircle circles) ++ (List.map drawTriangle triangles))
drawCircle : Circle -> SvgdrawCircle (center, edge) = let (x1', y1') = center.position radius = distance center.position edge.position in g [] [ drawPoint center , drawPoint edge , drawLine center.position edge.position , circle [ cx (toString x1') , cy (toString y1') , r (toString radius) , fill "rgba(255,0,0,0.1)" , stroke "black" , strokeWidth "2" ] [] ]
distanceSquared : Vector -> Vector -> IntdistanceSquared (ax, ay) (bx, by) = (ax - bx) * (ax - bx) + (ay - by) * (ay - by)
distance : Vector -> Vector -> Intdistance p q = round (sqrt (toFloat (distanceSquared p q)))
drawPoint : Point -> SvgdrawPoint {position, radius} = let (x,y) = position in circle [ cx (toString x) , cy (toString y) , r (toString radius) , fill "rgba(0, 0, 255, 1)" ] []
drawLine : Vector -> Vector -> SvgdrawLine (x1', y1') (x2', y2') = line [ stroke "black" , strokeWidth "2" , x1 (toString x1') , x2 (toString x2') , y1 (toString y1') , y2 (toString y2') ] []
drawCircle : Circle -> SvgdrawCircle (center, edge) = let (x1', y1') = center.position radius = distance center.position edge.position in g [] [ drawPoint center , drawPoint edge , drawLine center.position edge.position , circle [ cx (toString x1') , cy (toString y1') , r (toString radius) , fill "rgba(255,0,0,0.1)" , stroke "black" , strokeWidth "2" ] [] ]
drawTriangle : Triangle -> SvgdrawTriangle (a,b,c) = g [] [ drawPoint a , drawPoint b , drawPoint c , drawLine a.position b.position , drawLine b.position c.position , drawLine c.position a.position ]
view : State -> Htmlview {circles, triangles} = svg [ style [ ("border", "1px solid black") , ("width", "800px") , ("height", "600px")] ] ((List.map drawCircle circles) ++ (List.map drawTriangle triangles))
step : MouseEvent -> State -> State
step : MouseEvent -> State -> Statestep mouseEvent state = { state | circles <- List.map (stepCircle mouseEvent) state.circles , triangles <- List.map (stepTriangle mouseEvent) state.triangles }
stepTriangle : MouseEvent -> Triangle -> TrianglestepTriangle mouseEvent (a,b,c) = ( stepPoint mouseEvent a , stepPoint mouseEvent b , stepPoint mouseEvent c )
stepCircle : MouseEvent -> Circle -> CirclestepCircle mouseEvent (center, edge) = ( stepPoint mouseEvent center , stepPoint mouseEvent edge )
stepPoint : MouseEvent -> Point -> PointstepPoint mouseEvent point = case mouseEvent of StartAt start -> if start `within` point then { point | selected <- True , position <- start } else { point | selected <- False }
MoveFromTo origin destination -> if point.selected then { point | position <- destination } else point
EndAt destination -> if point.selected then { point | position <- destination , selected <- False } else point
type MouseEvent
= StartAt (Int,Int)
| MoveFromTo (Int,Int) (Int,Int)
| EndAt (Int,Int)
StartAt start -> if start `within` point
then { point | selected <- True , position <- start } else { point | selected <- False }
within : Vector -> Point -> Boolwithin vector point = distanceSquared vector point.position <= point.radius * point.radius
MoveFromTo origin destination -> if point.selected then { point | position <- destination } else point
EndAt destination -> if point.selected then { point | position <- destination , selected <- False } else point
main : Signal Htmlmain = map view (foldp step initialState mouseEvents)
initialState : StateinitialState = { triangles = [ initialTriangle ] , circles = [ initialCircle ] }
initialTriangle : TriangleinitialTriangle = (point 100 100, point 200 200, point 100 200)
initialCircle : CircleinitialCircle = (point 250 300, point 250 250)
point : Int -> Int -> Pointpoint x y = { position = (x,y) , selected = False , radius = 5 }
import Svg (Svg, circle, svg, g, line)import Svg.Attributes (cx, cy, r, fill, stroke, strokeWidth, x1, x2, y1, y2)import Html (Html)import Html.Attributes (style)
import Signal (Signal, map, foldp)import DragAndDrop (..)import List
--------------- Vector Type-------------type alias Vector = (Int, Int)
distanceSquared : Vector -> Vector -> IntdistanceSquared (ax, ay) (bx, by) = (ax - bx) * (ax - bx) + (ay - by) * (ay - by)
distance : Vector -> Vector -> Intdistance p q = round (sqrt (toFloat (distanceSquared p q)))
---------- Model--------
type alias Point = { position : Vector , selected : Bool , radius : Int }
within : Vector -> Point -> Boolwithin vector point = distanceSquared vector point.position <= point.radius * point.radius
type alias Triangle = (Point, Point, Point)
type alias Circle = (Point, Point)
type alias State = { triangles : List Triangle , circles : List Circle }
point : Int -> Int -> Pointpoint x y = { position = (x,y) , selected = False , radius = 5 }
initialTriangle : TriangleinitialTriangle = (point 100 100, point 200 200, point 100 200)
initialCircle : CircleinitialCircle = (point 250 300, point 250 250)
initialState : StateinitialState = { triangles = [ initialTriangle ] , circles = [ initialCircle ] }
--------- VIEW-------
drawPoint : Point -> SvgdrawPoint {position, radius} = let (x,y) = position in circle [ cx (toString x) , cy (toString y) , r (toString radius) , fill "rgba(0, 0, 255, 1)" ] []
drawLine : Vector -> Vector -> SvgdrawLine (x1', y1') (x2', y2') = line [ stroke "black" , strokeWidth "2" , x1 (toString x1') , x2 (toString x2') , y1 (toString y1') , y2 (toString y2') ] []
drawCircle : Circle -> SvgdrawCircle (center, edge) = let (x1', y1') = center.position radius = distance center.position edge.position in g [] [ drawPoint center , drawPoint edge , drawLine center.position edge.position , circle [ cx (toString x1') , cy (toString y1') , r (toString radius) , fill "rgba(255,0,0,0.1)" , stroke "black" , strokeWidth "2" ] [] ]
drawTriangle : Triangle -> SvgdrawTriangle (a,b,c) = g [] [ drawPoint a , drawPoint b , drawPoint c , drawLine a.position b.position , drawLine b.position c.position , drawLine c.position a.position ]
view : State -> Htmlview {circles, triangles} = svg [ style [ ("border", "1px solid black") , ("width", "800px") , ("height", "600px")] ] ((List.map drawCircle circles) ++ (List.map drawTriangle triangles))
----------- UPDATE---------
stepPoint : MouseEvent -> Point -> PointstepPoint mouseEvent point = case mouseEvent of StartAt start -> if start `within` point then { point | selected <- True , position <- start } else { point | selected <- False }
MoveFromTo origin destination -> if point.selected then { point | position <- destination } else point
EndAt destination -> if point.selected then { point | position <- destination , selected <- False } else point
stepTriangle : MouseEvent -> Triangle -> TrianglestepTriangle mouseEvent (a,b,c) = ( stepPoint mouseEvent a , stepPoint mouseEvent b , stepPoint mouseEvent c )
stepCircle : MouseEvent -> Circle -> CirclestepCircle mouseEvent (center, edge) = ( stepPoint mouseEvent center , stepPoint mouseEvent edge )
step : MouseEvent -> State -> Statestep mouseEvent state = { state | circles <- List.map (stepCircle mouseEvent) state.circles , triangles <- List.map (stepTriangle mouseEvent) state.triangles }
--------- MAIN-------
main : Signal Htmlmain = map view (foldp step initialState mouseEvents)
import Text
main = Text.asText "Hello World"
import Html
...
Thank you Evan. Running elm-reactor inside folder /1 solved my problem.
Wow, Hassan I am impressed with the detailedness of your answer.
Thank you very much.
I have further questions, but first,
I think that I need to explain why I asked this question.
I studied mathematics and I am working on logic and graph theory.
I don’t have much experience with programming languages
but it is not that difficult for me to understand purely functional languages.
Their source code is very near to how we write constructive proofs.
Graph theorists do not have good software for
drawing example graphs,
coloring and manipulating them,
partitioning the vertex-set,
visualizing steps of algorithms,
etc.
People have done some nice things like
visualgo.net
but what we need is something more powerful and open source.
Users (which will be mostly graph theorists)
should be able to construct graphs by writing algorithms.
They should be able
to download the entire program from github and easily extend the code.
So, together with the graph drawing tool,
we need a nice programming language
For sure, javascript is not an option.
Whenever mathematicians or computer scientists hear the word ‘javascript’
their faces are like
these.
I started building such a tool using plain javascript and D3.js but as my GUI got bigger, everything got messy.
So I gave up implementing a GUI.
I decided to let the user manipulate the graphs using the console of the browser.
Implementing “undo” is also a must for such a tool.
This is not easy without persistent data structures.
So, I should use those libraries of Facebook.
But I don’t want to learn thousand things only because of the shortcomings of javascript.
At the end, I realised that I need a good programming language to create this tool.
I do not want to deal with the problems of javascript.
I saw some videos of Evan
and I’ve got the impression that in elm,
visualising algorithms step by step is so simple
that it is almost like a built-in language feature.
So is undo.
My interest shifted from ClojureScript to elm.
(Of course this is not the only reason. In many aspects, elm seems to be the dream language for my purposes.)
Here is, why I think that using svg onMouseDown
instead of using elm-drag-and-drop
may be a better idea:
Every time the user clicks somewhere, you run over all the points to look for
whether that point is clicked.
Also during the drag, you run over all points.
If you have many points, this can cause a performance problem.
Here
is an example with 50 x 50 points.
Just download or clone the repo.
(I used your code to create this.)
If you drag a point slowly you will notice the problem.
But the biggest problem is the following.
What if, for example, the svg-elements are not circles but rectangles or worse, svg-paths.
It can get very difficult to find out, which element the user clicked on.
Another problem is that if you have, for example, two big overlapping circles
and you click on the area where they overlap,
you drag both.
The expected behavior would be dragging only the one which is on top.
Another issue is the “beaming” on mouseDown.
If you don’t click on the center of the element, the element jumps.
But solving this problem should be easy,
once you get the “center” (I mean the anchor-point) of the svg-element.
See
here
to see how Mike Bostock solved it for D3.
In a language like elm,
it should be possible to create a solution
which is at least as clean as in
this .
What I would like to have, is some function like
makeDraggable : Svg -> Svg
or
makeDraggable : (Int, Int) -> Svg -> Svg
where (Int, Int)
is used as the .origin
in Mike Bostock’s solution for the “beaming problem”.
I think that elm can a better alternative to D3 for visualising data.
But there is a lot to be done.
Thanks again for the help (and in the first place for creating elm).
...
...
...
step : Input -> Model -> Model
onMouseDown : Signal.Message -> Attribute
onMouseDown : (MouseEvent -> Signal.Message) -> Attribute
drawPoint point =
circle
[ cx (toString point.x)
, cy (toString point.y)
, r "5"
, onMouseDown (\{clientX, clientY} -> send mouseDrags (StartDrag point.id (clientX, clientY)))
] []
type MouseDrag
= StartDrag ID (Int, Int)
| DragFromTo ID (Int, Int) (Int, Int)
| EndDrag ID (Int, Int)
| NoDrag
mouseDrags : Channel MouseDrag
mouseDrags = channel NoDrag
type alias Graphic = Dict ID Shape
...