on master help sign in
Start using new Input type everywhere!
0018d32Evan Czaplicki
libraries/Graphics/Input.elm+67−58
@@ -1,22 +1,22 @@
1module Graphics.Input where
1module Graphics.Input where
2{-| This module is for creating standard input widgets such as buttons and
2{-| This module is for creating standard input widgets such as buttons and
3−text fields. All functions in this library follow this general pattern:
3+text fields. All functions in this library follow a general pattern in which
4+you create an `Input` that many elements can report to:
4
5
5```haskell
6```haskell
6−-- (Signal (), SignalID ())
7+clicks : Input ()
7−(clicks, clickID) = input ()
8+clicks = input ()
8
9
9clickableYogi : Element
10clickableYogi : Element
10−clickableYogi = clickable clickID () (image 40 40 "/yogi.jpg")
11+clickableYogi = clickable clicks.handle () (image 40 40 "/yogi.jpg")
11```
12```
12
13
13−Whenever the user clicks on the resulting `clickableYogi` element, it sends a
14+Whenever the user clicks on the resulting `clickableYogi` element, it sends an
14−`()` to the `clicks` signal. Typically, you would create all your input signals
15+update to the `clicks` input. You will see this pattern again and again in
15−when setting up the signal graph, so then your graphics code can refer to them
16+examples in this library, so just read on to get a better idea of how it works!
16−easily.
17
17
18# Creating Inputs
18# Creating Inputs
19−@docs input
19+@docs Input, input
20
20
21# Basic Input Elements
21# Basic Input Elements
22Text fields come later.
22Text fields come later.
@@ -33,46 +33,55 @@ import Signal (Signal)
33import Graphics.Element (Element)
33import Graphics.Element (Element)
34import Native.Graphics.Input
34import Native.Graphics.Input
35
35
36−data SignalID a = SignalID
36+data Handle a = Handle
37
37
38−{-| This function is the key to using this library. It creates a signal that
38+{-| This is the key abstraction of this library. An `Input` is a record
39−input elements (buttens, checkboxes, etc.) can report to. It also create a
39+of two fields:
40−unique `SignalID` that allows input elements to refer to this particular
41−signal. It may be best to look at examples in the rest of the docs and return
42−to this function.
43
40
41+ 1. `signal` — all values coming to this input from “the world”
42+ 2. `handle` — a way to refer to this particular input and send it values
43+
44+This will make more sense as you see more examples.
45+-}
46+type Input a = { signal : Signal a, handle : Handle a }
47+
48+{-| Create a new `Input`. You just give the initial value for the
49+input’s `signal`.
50+
44−Note: creating an input signal is an inherently imperative action, so this is
51+Note for Advanced Users: creating an `Input` is an inherently imperative
45−one of very few impure functions in Elm. It is designed such that it can only
52+action, so this is one of very few impure functions in Elm. That means
53+`(input ())` and `(input ())` are actually two different inputs with different
54+signals and handles. By design, Elm’s impure functions can only be useful
46−be used as you build your signal graph at startup, keeping Elm pure at runtime.
55+as you build your signal graph at startup, so Elm is still pure at runtime.
47-}
56-}
48−input : a -> (Signal a, SignalID a)
57+input : a -> Input a
49input = Native.Graphics.Input.input
58input = Native.Graphics.Input.input
50
59
51{-| Create a standard button. The following example begins making a basic
60{-| Create a standard button. The following example begins making a basic
52calculator:
61calculator:
53
62
54− data Input = Number Int | Plus | Minus | Clear
63+ data Keys = Number Int | Plus | Minus | Clear
55
64
56− -- (Signal Input, SignalID Input)
65+ keys : Input Keys
57− (calcInput, pressID) = input Clear
66+ keys = input Clear
58
67
59− buttons : Element
68+ calculator : Element
60− buttons =
69+ calculator =
61− flow right [ button pressID (Number 1) "1"
70+ flow right [ button keys.handle (Number 1) "1"
62− , button pressID (Number 2) "2"
71+ , button keys.handle (Number 2) "2"
63− , button pressID Plus "+"
72+ , button keys.handle Plus "+"
64 ]
73 ]
65
74
66−If the user presses the "plus" button, the `calcInput` signal will update to
75+If the user presses the "+" button, `keys.signal` will update to `Plus`. If the
67−`Plus`. If the users presses "2", `calcInput` will update to `(Number 2)`.
76+users presses "2", `keys.signal` will update to `(Number 2)`.
68-}
77-}
69−button : SignalID a -> a -> String -> Element
78+button : Handle a -> a -> String -> Element
70button = Native.Graphics.Input.button
79button = Native.Graphics.Input.button
71
80
72−customButton : SignalID a -> a -> Element -> Element -> Element -> Element
81+customButton : Handle a -> a -> Element -> Element -> Element -> Element
73customButton = Native.Graphics.Input.customButton
82customButton = Native.Graphics.Input.customButton
74
83
75−checkbox : SignalID a -> (Bool -> a) -> Bool -> Element
84+checkbox : Handle a -> (Bool -> a) -> Bool -> Element
76checkbox = Native.Graphics.Input.checkbox
85checkbox = Native.Graphics.Input.checkbox
77
86
78{-| Create a drop-down menu. The following drop-down lets you choose your
87{-| Create a drop-down menu. The following drop-down lets you choose your
@@ -80,38 +89,38 @@ favorite British sport:
80
89
81 data Sport = Football | Cricket | Snooker
90 data Sport = Football | Cricket | Snooker
82
91
83− -- (Signal (Maybe Sport), SignalID (Maybe Sport))
92+ sport : Input Sport
84− (dropStatus, dropID) = input Nothing
93+ sport = input Nothing
85
94
86 sportDropDown : Element
95 sportDropDown : Element
87 sportDropDown =
96 sportDropDown =
88− dropDown dropID
97+ dropDown sport.handle
89 [ ("" , Nothing)
98 [ ("" , Nothing)
90 , ("Football", Just Football)
99 , ("Football", Just Football)
91 , ("Cricket" , Just Cricket)
100 , ("Cricket" , Just Cricket)
92 , ("Snooker" , Just Snooker)
101 , ("Snooker" , Just Snooker)
93 ]
102 ]
94
103
95−If the user selects "Football" from the drop down menue, the `dropStatus`
104+If the user selects "Football" from the drop down menue, `sport.signal`
96−signal will update to `Just Football`.
105+will update to `Just Football`.
97-}
106-}
98−dropDown : SignalID a -> [(String,a)] -> Element
107+dropDown : Handle a -> [(String,a)] -> Element
99dropDown = Native.Graphics.Input.dropDown
108dropDown = Native.Graphics.Input.dropDown
100
109
101{-| Detect mouse hovers over a specific `Element`. In the following example,
110{-| Detect mouse hovers over a specific `Element`. In the following example,
102we will create a hoverable picture called `cat`.
111we will create a hoverable picture called `cat`.
103
112
104− -- (Signal Bool, SignalID Bool)
113+ hover : Input Bool
105− (hover, hoverID) = input False
114+ hover = input False
106
115
107 cat : Element
116 cat : Element
108 cat = image 30 30 "/cat.jpg"
117 cat = image 30 30 "/cat.jpg"
109− |> hoverable hoverID (\hover -> hover)
118+ |> hoverable hover.handle id
110
119
111−When the mouse hovers above the `cat` element, the `hover` signal will become
120+When the mouse hovers above the `cat` element, `hover.signal` will become
112−`True`. When the mouse leaves it, `hover` will become `False`.
121+`True`. When the mouse leaves it, `hover.signal` will become `False`.
113-}
122-}
114−hoverable : SignalID a -> (Bool -> a) -> Element -> Element
123+hoverable : Handle a -> (Bool -> a) -> Element -> Element
115hoverable = Native.Graphics.Input.hoverable
124hoverable = Native.Graphics.Input.hoverable
116
125
117{-| Detect mouse clicks on a specific `Element`. In the following example,
126{-| Detect mouse clicks on a specific `Element`. In the following example,
@@ -119,24 +128,24 @@ we will create a clickable picture called `cat`.
119
128
120 data Picture = Cat | Hat
129 data Picture = Cat | Hat
121
130
122− -- (Signal Picture, SignalID Picture)
131+ picture : Input Picture
123− (click, clickID) = input Cat
132+ picture = input Cat
124
133
125 cat : Element
134 cat : Element
126 cat = image 30 30 "/cat.jpg"
135 cat = image 30 30 "/cat.jpg"
127− |> clickable clickID Cat
136+ |> clickable picture.handle Cat
128
137
129 hat : Element
138 hat : Element
130 hat = image 30 30 "/hat.jpg"
139 hat = image 30 30 "/hat.jpg"
131− |> clickable clickID Hat
140+ |> clickable picture.handle Hat
132
141
133−When the user clicks on the `cat` element, the `click` signal receives
142+When the user clicks on the `cat` element, `picture.signal` receives
134an update containing the value `Cat`. When the user clicks on the `hat` element,
143an update containing the value `Cat`. When the user clicks on the `hat` element,
135−the `click` signal receives an update containing the value `Hat`. This lets you
144+`picture.signal` receives an update containing the value `Hat`. This lets you
136distinguish which element was clicked. In a more complex example, they could be
145distinguish which element was clicked. In a more complex example, they could be
137distinguished with IDs or more complex data structures.
146distinguished with IDs or more complex data structures.
138-}
147-}
139−clickable : SignalID a -> a -> Element -> Element
148+clickable : Handle a -> a -> Element -> Element
140clickable = Native.Graphics.Input.clickable
149clickable = Native.Graphics.Input.clickable
141
150
142{-| Represents the current content of a text field. For example:
151{-| Represents the current content of a text field. For example:
@@ -170,25 +179,25 @@ noContent = FieldContent "" (Selection 0 0 Forward)
170called `nameField`. As the user types their name, the field will be updated
179called `nameField`. As the user types their name, the field will be updated
171to match what they have entered.
180to match what they have entered.
172
181
173− -- (Signal FieldContent, SignalID FieldContent)
182+ name : Input FieldContent
174− (nameContent,nameID) = input noContent
183+ name = input noContent
175
184
176 nameField : Signal Element
185 nameField : Signal Element
177− nameField = field nameID (\content -> content) "Name" <~ nameContent
186+ nameField = field name.handle (\content -> content) "Name" <~ nameContent
178-}
187-}
179−field : SignalID a -> (FieldContent -> a) -> String -> FieldContent -> Element
188+field : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
180field = Native.Graphics.Input.field
189field = Native.Graphics.Input.field
181
190
182{-| Same as `field` but the UI element blocks out each characters. -}
191{-| Same as `field` but the UI element blocks out each characters. -}
183−password : SignalID a -> (FieldContent -> a) -> String -> FieldContent -> Element
192+password : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
184password = Native.Graphics.Input.password
193password = Native.Graphics.Input.password
185
194
186{-| Same as `field` but it adds an annotation that this field is for email
195{-| Same as `field` but it adds an annotation that this field is for email
187addresses. This is helpful for auto-complete and for mobile users who may
196addresses. This is helpful for auto-complete and for mobile users who may
188get a custom keyboard with an `@` and `.com` button.
197get a custom keyboard with an `@` and `.com` button.
189-}
198-}
190−email : SignalID a -> (FieldContent -> a) -> String -> FieldContent -> Element
199+email : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
191email = Native.Graphics.Input.email
200email = Native.Graphics.Input.email
192
201
193−-- area : SignalID a -> (FieldContent -> a) -> SignalID b -> ((Int,Int) -> b) -> (Int,Int) -> String -> FieldContent -> Element
202+-- area : Handle a -> (FieldContent -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> FieldContent -> Element
194-- area = Native.Graphics.Input.area
203-- area = Native.Graphics.Input.area
libraries/Native/Graphics/Input.js+1−1
@@ -17,7 +17,7 @@ Elm.Native.Graphics.Input.make = function(elm) {
17
17
18 function input(initialValue) {
18 function input(initialValue) {
19 var sig = Signal.constant(initialValue);
19 var sig = Signal.constant(initialValue);
20− return Tuple2(sig, sig);
20+ return { _:{}, signal:sig, handle:sig };
21 }
21 }
22
22
23 function renderDropDown(signal, values) {
23 function renderDropDown(signal, values) {