import Graphics.Collage exposing (..) import Graphics.Element exposing (..) import Graphics.Input exposing (..) import Color exposing (..) import Signal exposing (..) import Text import List import Mouse -------- -- Model -------- type alias Cell = { position : { x : Float, y : Float } , dimensions : { width : Float, height : Float } , isHoveredOver : Bool } type alias Grid = List Cell type alias Model = { grid : Grid } grid : (Int, Int) -> (Float, Float) -> (Float, Float) -> Float -> Grid grid (rows, columns) (width, height) (offsetX, offsetY) margin = if rows <= 0 || columns <= 0 then [] else let gridIter : List (Int, List Int) gridIter = List.map (\x -> (x, [1..columns])) [1..rows] makeCell : (Int, Int) -> Cell makeCell (row, column) = { position = { x = offsetX + toFloat (column) * width + (margin * toFloat column) , y = offsetY + toFloat (row) * height + (margin * toFloat row) } , dimensions = { width = width , height = height } , isHoveredOver = False } makeRow : (Int, List Int) -> List Cell makeRow (row, columns) = List.map (\column -> makeCell (row, column)) columns makeGrid : List (Int, List Int) -> Grid makeGrid = List.concat << List.map makeRow in makeGrid gridIter initialModel : Model initialModel = { grid = grid (10,10) (20,20) (-50, -100) 2 } ------- -- View ------- drawCell : Cell -> Form drawCell cell = let cellColor = if cell.isHoveredOver then blue else red in move (cell.position.x, cell.position.y) <| filled cellColor <| rect cell.dimensions.width cell.dimensions.height drawGrid : Grid -> List Form drawGrid grid = List.map drawCell grid view : Model -> Element view model = collage 400 400 (drawGrid model.grid) -------- -- Input -------- type alias Input = { mousePosition : (Int, Int) } convertToViewCoordinates (x,y) = Input (x - 200, 200 - y) input : Signal Input input = Signal.map convertToViewCoordinates Mouse.position --------- -- Update --------- stepCell : Input -> Cell -> Cell stepCell input cell = let (mouseX, mouseY) = input.mousePosition in if toFloat mouseX > cell.position.x - cell.dimensions.width / 2 && toFloat mouseX < cell.position.x + cell.dimensions.width / 2 && toFloat mouseY > cell.position.y - cell.dimensions.height / 2 && toFloat mouseY < cell.position.y + cell.dimensions.height / 2 then { cell | isHoveredOver = True } else { cell | isHoveredOver = False } step : Input -> Model -> Model step input model = { model | grid = List.map (stepCell input) model.grid } ------- -- Main ------- main : Signal Element main = Signal.map view <| foldp step initialModel input