-
Notifications
You must be signed in to change notification settings - Fork 1
/
redbox.elm
87 lines (70 loc) · 2.88 KB
/
redbox.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
module RedBox where
import Anima exposing (..)
import Graphics.Element as El
import Graphics.Collage as Co
import Graphics.Input as In
import Touch
import Color
import Window
import Signal
import Debug exposing (..)
import Time
import Automaton as Auto exposing ((>>>))
import Focus exposing ((=>))
{- A simple application that shows a red box that can be in one of two
positions within the window. Clicking within the window causes the
box to jump to the other position using a springy animation. -}
{- Our only input is a click within the box to switch its position. -}
type Input = Quiet | Click
{- Our only model state is a boolean - indicating whether the box
is on the left hand side or the right hand side. -}
type alias Model = {boxIsToTheLeft : Bool}
{- Given the position indication, the director decides a color for the box
and its actual stable position within the window. -}
type alias Direction = {color : Color.Color, x : Float}
{- The view state is structurally the same as the direction, except that the
meaning of the "x" field is "the position of the box right now" as opposed to
"the stable position of the box" as indicated by the direction. -}
type alias ViewState = Direction
clicks = Signal.mailbox Quiet
input = clicks.signal
initial =
{ model = { boxIsToTheLeft = False }
, direction = { color = Color.red, x = 256.0 }
, viewstate = { color = Color.red, x = 256.0 }
, view = El.show "initializing..."
}
app : OpinionatedApp Input Model Direction ViewState El.Element
app = {
{- The modeller responds to the input by flipping the position
of the box from left to right or vice versa. -}
modeller = \input model ->
case input of
Click -> { model | boxIsToTheLeft = not model.boxIsToTheLeft }
_ -> model
{- Based on the model, the director decides the stable position
of the box within the window, taking into account the window
environment. -}
, director = \(input, model) dir ->
let dx = 0.25 * toFloat dir.env.width
data = dir.data
in
{dir | data = { data | x = if model.boxIsToTheLeft then -dx else dx } }
{- The animator specifies how to achieve the position indicated
by the director. In this case, the indicated stable position is
to be reached using a springy animation. -}
, animator =
filterProp (data_ => x_) (springy 3.0 1.5 initial.direction.x)
{- The viewer takes the position indicated by the animator and renders
the box at that position. -}
, viewer = \(model, vs) ->
Co.collage vs.env.width vs.env.height [
Co.rect 100.0 100.0
|> Co.filled vs.data.color
|> Co.moveX vs.data.x
]
|> In.clickable (Signal.message clicks.address Click)
, initial =
initial
}
main = let (app', _) = Anima.runOpinionatedApp app input in app'