Start using new Input type everywhere!

Whoo! :D
This commit is contained in:
Evan Czaplicki 2014-02-18 12:14:10 -05:00
parent 0c805d8c4f
commit 0018d32627
2 changed files with 68 additions and 59 deletions

View file

@ -1,22 +1,22 @@
module Graphics.Input where
{-| This module is for creating standard input widgets such as buttons and
text fields. All functions in this library follow this general pattern:
text fields. All functions in this library follow a general pattern in which
you create an `Input` that many elements can report to:
```haskell
-- (Signal (), SignalID ())
(clicks, clickID) = input ()
clicks : Input ()
clicks = input ()
clickableYogi : Element
clickableYogi = clickable clickID () (image 40 40 "/yogi.jpg")
clickableYogi = clickable clicks.handle () (image 40 40 "/yogi.jpg")
```
Whenever the user clicks on the resulting `clickableYogi` element, it sends a
`()` to the `clicks` signal. Typically, you would create all your input signals
when setting up the signal graph, so then your graphics code can refer to them
easily.
Whenever the user clicks on the resulting `clickableYogi` element, it sends an
update to the `clicks` input. You will see this pattern again and again in
examples in this library, so just read on to get a better idea of how it works!
# Creating Inputs
@docs input
@docs Input, input
# Basic Input Elements
Text fields come later.
@ -33,46 +33,55 @@ import Signal (Signal)
import Graphics.Element (Element)
import Native.Graphics.Input
data SignalID a = SignalID
data Handle a = Handle
{-| This function is the key to using this library. It creates a signal that
input elements (buttens, checkboxes, etc.) can report to. It also create a
unique `SignalID` that allows input elements to refer to this particular
signal. It may be best to look at examples in the rest of the docs and return
to this function.
{-| This is the key abstraction of this library. An `Input` is a record
of two fields:
Note: creating an input signal is an inherently imperative action, so this is
one of very few impure functions in Elm. It is designed such that it can only
be used as you build your signal graph at startup, keeping Elm pure at runtime.
1. `signal` — all values coming to this input from “the world”
2. `handle` — a way to refer to this particular input and send it values
This will make more sense as you see more examples.
-}
input : a -> (Signal a, SignalID a)
type Input a = { signal : Signal a, handle : Handle a }
{-| Create a new `Input`. You just give the initial value for the
input’s `signal`.
Note for Advanced Users: creating an `Input` is an inherently imperative
action, so this is one of very few impure functions in Elm. That means
`(input ())` and `(input ())` are actually two different inputs with different
signals and handles. By design, Elm’s impure functions can only be useful
as you build your signal graph at startup, so Elm is still pure at runtime.
-}
input : a -> Input a
input = Native.Graphics.Input.input
{-| Create a standard button. The following example begins making a basic
calculator:
data Input = Number Int | Plus | Minus | Clear
data Keys = Number Int | Plus | Minus | Clear
-- (Signal Input, SignalID Input)
(calcInput, pressID) = input Clear
keys : Input Keys
keys = input Clear
buttons : Element
buttons =
flow right [ button pressID (Number 1) "1"
, button pressID (Number 2) "2"
, button pressID Plus "+"
calculator : Element
calculator =
flow right [ button keys.handle (Number 1) "1"
, button keys.handle (Number 2) "2"
, button keys.handle Plus "+"
]
If the user presses the "plus" button, the `calcInput` signal will update to
`Plus`. If the users presses "2", `calcInput` will update to `(Number 2)`.
If the user presses the "+" button, `keys.signal` will update to `Plus`. If the
users presses "2", `keys.signal` will update to `(Number 2)`.
-}
button : SignalID a -> a -> String -> Element
button : Handle a -> a -> String -> Element
button = Native.Graphics.Input.button
customButton : SignalID a -> a -> Element -> Element -> Element -> Element
customButton : Handle a -> a -> Element -> Element -> Element -> Element
customButton = Native.Graphics.Input.customButton
checkbox : SignalID a -> (Bool -> a) -> Bool -> Element
checkbox : Handle a -> (Bool -> a) -> Bool -> Element
checkbox = Native.Graphics.Input.checkbox
{-| Create a drop-down menu. The following drop-down lets you choose your
@ -80,38 +89,38 @@ favorite British sport:
data Sport = Football | Cricket | Snooker
-- (Signal (Maybe Sport), SignalID (Maybe Sport))
(dropStatus, dropID) = input Nothing
sport : Input Sport
sport = input Nothing
sportDropDown : Element
sportDropDown =
dropDown dropID
dropDown sport.handle
[ ("" , Nothing)
, ("Football", Just Football)
, ("Cricket" , Just Cricket)
, ("Snooker" , Just Snooker)
]
If the user selects "Football" from the drop down menue, the `dropStatus`
signal will update to `Just Football`.
If the user selects "Football" from the drop down menue, `sport.signal`
will update to `Just Football`.
-}
dropDown : SignalID a -> [(String,a)] -> Element
dropDown : Handle a -> [(String,a)] -> Element
dropDown = Native.Graphics.Input.dropDown
{-| Detect mouse hovers over a specific `Element`. In the following example,
we will create a hoverable picture called `cat`.
-- (Signal Bool, SignalID Bool)
(hover, hoverID) = input False
hover : Input Bool
hover = input False
cat : Element
cat = image 30 30 "/cat.jpg"
|> hoverable hoverID (\hover -> hover)
|> hoverable hover.handle id
When the mouse hovers above the `cat` element, the `hover` signal will become
`True`. When the mouse leaves it, `hover` will become `False`.
When the mouse hovers above the `cat` element, `hover.signal` will become
`True`. When the mouse leaves it, `hover.signal` will become `False`.
-}
hoverable : SignalID a -> (Bool -> a) -> Element -> Element
hoverable : Handle a -> (Bool -> a) -> Element -> Element
hoverable = Native.Graphics.Input.hoverable
{-| Detect mouse clicks on a specific `Element`. In the following example,
@ -119,24 +128,24 @@ we will create a clickable picture called `cat`.
data Picture = Cat | Hat
-- (Signal Picture, SignalID Picture)
(click, clickID) = input Cat
picture : Input Picture
picture = input Cat
cat : Element
cat = image 30 30 "/cat.jpg"
|> clickable clickID Cat
|> clickable picture.handle Cat
hat : Element
hat = image 30 30 "/hat.jpg"
|> clickable clickID Hat
|> clickable picture.handle Hat
When the user clicks on the `cat` element, the `click` signal receives
When the user clicks on the `cat` element, `picture.signal` receives
an update containing the value `Cat`. When the user clicks on the `hat` element,
the `click` signal receives an update containing the value `Hat`. This lets you
`picture.signal` receives an update containing the value `Hat`. This lets you
distinguish which element was clicked. In a more complex example, they could be
distinguished with IDs or more complex data structures.
-}
clickable : SignalID a -> a -> Element -> Element
clickable : Handle a -> a -> Element -> Element
clickable = Native.Graphics.Input.clickable
{-| Represents the current content of a text field. For example:
@ -170,25 +179,25 @@ noContent = FieldContent "" (Selection 0 0 Forward)
called `nameField`. As the user types their name, the field will be updated
to match what they have entered.
-- (Signal FieldContent, SignalID FieldContent)
(nameContent,nameID) = input noContent
name : Input FieldContent
name = input noContent
nameField : Signal Element
nameField = field nameID (\content -> content) "Name" <~ nameContent
nameField = field name.handle (\content -> content) "Name" <~ nameContent
-}
field : SignalID a -> (FieldContent -> a) -> String -> FieldContent -> Element
field : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
field = Native.Graphics.Input.field
{-| Same as `field` but the UI element blocks out each characters. -}
password : SignalID a -> (FieldContent -> a) -> String -> FieldContent -> Element
password : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
password = Native.Graphics.Input.password
{-| Same as `field` but it adds an annotation that this field is for email
addresses. This is helpful for auto-complete and for mobile users who may
get a custom keyboard with an `@` and `.com` button.
-}
email : SignalID a -> (FieldContent -> a) -> String -> FieldContent -> Element
email : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
email = Native.Graphics.Input.email
-- area : SignalID a -> (FieldContent -> a) -> SignalID b -> ((Int,Int) -> b) -> (Int,Int) -> String -> FieldContent -> Element
-- area : Handle a -> (FieldContent -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> FieldContent -> Element
-- area = Native.Graphics.Input.area

View file

@ -17,7 +17,7 @@ Elm.Native.Graphics.Input.make = function(elm) {
function input(initialValue) {
var sig = Signal.constant(initialValue);
return Tuple2(sig, sig);
return { _:{}, signal:sig, handle:sig };
}
function renderDropDown(signal, values) {