-- Look at DragAndDrop first! -- StayInTouch -- Example of using Dictionary updates, dragging, getting values out of a dictionary. -- We need this as the first comment line, because we use the Dict module -- Functions starting with Dict. are from that module. See -- https://package.elm-lang.org/packages/elm/core/latest/Dict import Dict exposing (Dict) myShapes model = [ text "Drag me!" |> centered |> filled black |> move (0,-55) , polygon (Dict.values model.points) |> outlined (solid 1) black ] ++ Dict.foldl drawAt [] model.points ++ -- what we draw depends on the state, this code generated by PALDraw case model.state of Waiting -> -- apply drawWord to two inputs, the index in list, and the value in the wordList [] Dragging (idx,(x0,y0)) (dx,dy) (lx,ly) -> [ circle 5 |> outlined (solid 2) purple |> move ( x0 + lx - dx , y0 + ly - dy) , rect 191 127 |> filled (rgba 0 0 255 0.01) |> notifyMouseUpAt MUp |> notifyMouseMoveAt MMove |> notifyLeaveAt MUp ] -- draws one point and attaches a notification to it drawAt : Int -> (Float,Float) -> List (Shape Msg) -> List (Shape Msg) drawAt idx pos shapes = ( circle 5 |> filled red |> move pos |> notifyMouseDownAt (MDown (idx,pos) ) ) :: shapes type Msg = Tick Float GetKeyState | MDown (Int,(Float,Float)) ( Float, Float ) | MMove ( Float, Float ) | MUp ( Float, Float ) type State = Waiting | Dragging ( Int, ( Float, Float ) ) ( Float, Float ) ( Float, Float ) update : Msg -> Model -> Model update msg model = case msg of Tick t _ -> case model.state of Waiting -> { model | time = t } Dragging draggable downPos lastPos -> { model | time = t } MDown draggable newPos -> case model.state of Waiting -> { model | state = Dragging draggable newPos newPos } otherwise -> model MMove newPos -> case model.state of Dragging (idx,(x,y)) (lx,ly) (cx,cy) -> { model | state = Dragging (idx,(x+cx-lx,y+cy-ly)) (cx,cy) newPos , points = Dict.update idx (mvPoint (lx,ly) (cx,cy)) model.points } otherwise -> model MUp newPos -> case model.state of Dragging (idx,pos) last current -> { model | state = Waiting , points = Dict.update idx (mvPoint last current) model.points } otherwise -> model mvPoint : (Float,Float) -> (Float,Float) -> Maybe (Float,Float) -> Maybe (Float,Float) mvPoint (lx,ly) (cx,cy) mPoint = case mPoint of Just (x,y) -> Just (x + cx - lx, y + cy - ly) Nothing -> Nothing type alias Model = { time : Float , state : State -- a Dict lets us look up values, like a normal dictionary, but with any values, not just definitions , points : Dict Int (Float,Float) } init : Model init = { time = 0 , state = Waiting -- creates a Dict from a list of pairs of indices and points , points = Dict.fromList <| List.map ( \ idx -> (idx, (cos (toFloat idx * 0.1 * pi) , sin (toFloat idx * 0.1 * pi))) ) (List.range 0 20) }