on ab17521 help sign in
170 lines 6.5 kB history raw
1module Graphics.Input.Field where
2{-| This library provides an API for creating and updating text fields.
3Text fields use exactly the same approach as [`Graphics.Input`](Graphics-Input)
4for modelling user input, allowing you to keep track of new events and update
5text fields programmatically.
7# Create Fields
8@docs field, password, email
10# Field Content
11@docs Content, Selection, Direction, noContent
13# Field Style
14@docs Style, Outline, noOutline, Highlight, noHighlight, Dimensions, uniformly
15-}
17import Color (Color)
18import Color
19import Graphics.Element (Element)
20import Graphics.Input (Input, Handle)
21import Native.Graphics.Input
22import Text
24{-| Create uniform dimensions:
26 uniformly 4 == { left=4, right=4, top=4, bottom=4 }
28The following example creates an outline where the left, right, top, and bottom
29edges all have width 1:
31 Outline grey (uniformly 1) 4
32-}
33uniformly : Int -> Dimensions
34uniformly n = Dimensions n n n n
36{-| For setting dimensions of a fields padding or border. The left, right, top,
37and bottom may all have different sizes. The following example creates
38dimensions such that the left and right are twice as wide as the top and bottom:
40 myDimensions : Int -> Dimensions
41 myDimensions n = { left = 2 * n, right = 2 * n, top = n, bottom = n }
42-}
43type Dimensions = { left:Int, right:Int, top:Int, bottom:Int }
45{-| A field can have a outline around it. This lets you set its color, width,
46and radius. The radius allows you to round the corners of your field. Set the
47width to zero to make it invisible. Here is an example outline that is grey
48and thin with slightly rounded corners:
50 { color = grey, width = uniformly 1, radius = 4 }
51-}
52type Outline = { color:Color, width:Dimensions, radius:Int }
54{-| An outline with zero width, so you cannot see it. -}
55noOutline : Outline
56noOutline = Outline Color.grey (uniformly 0) 0
58{-| When a field has focus, it has a blue highlight around it by default. The
59`Highlight` lets you set the `color` and `width` of this highlight. Set the
60`width` to zero to turn the highlight off. Here is an example highlight that
61is blue and thin:
63 { color = blue, width = 1 }
64-}
65type Highlight = { color:Color, width:Int }
67{-| An highlight with zero width, so you cannot see it. -}
68noHighlight : Highlight
69noHighlight = Highlight Color.blue 0
71{-| Describe the style of a text box. `style` describes the style of the text
72itself using [`Text.Style`](/Text#Style). `outline` describes the glowing blue
73outline that shows up when the field has focus. `outline` describes the line
74surrounding the text field, and `padding` adds whitespace between the `outline`
75and the text.
77The width and height of the text box *includes* the `padding` and `outline`.
78Say we have a text box that is 40 pixels tall. It has a uniform outline of
791 pixel and a uniform padding of 5 pixels. Both of these must be subtracted
80from the total height to determine how much room there is for text. The
81`padding` and `outline` appear on the top and bottom, so there will be 28
82vertical pixels remaining for the text (40 - 1 - 5 - 5 - 1).
83-}
84type Style =
85 { padding : Dimensions
86 , outline : Outline
87 , highlight : Highlight
88 , style : Text.Style
89 }
91{-| The default style for a text field. The outline is `Color.grey` with width
921 and radius 2. The highlight is `Color.blue` with width 1, and the default
93text color is black.
94-}
95defaultStyle : Style
96defaultStyle =
97 { padding = uniformly 4
98 , outline = Outline Color.grey (uniformly 1) 2
99 , highlight = Highlight Color.blue 1
100 , style = Text.defaultStyle
101 }
103{-| Represents the current content of a text field. For example:
105 content = Content "She sells sea shells" (Selection 0 3 Backward)
107This means the user highlighted the substring `"She"` backwards. The value of
108`content.string` is `"She sells sea shells"`.
109-}
110type Content = { string:String, selection:Selection }
112{-| The selection within a text field. `start` is never greater than `end`:
114 Selection 0 0 Forward -- cursor precedes all characters
116 Selection 5 9 Backward -- highlighting characters starting after
117 -- the 5th and ending after the 9th
118-}
119type Selection = { start:Int, end:Int, direction:Direction }
121{-| The direction of selection. When the user highlights a selection in a text
122field, they must do it in a particular direction. This determines which end of
123the selection moves when they change the selection by pressing Shift-Left or
124Shift-Right.
125-}
126data Direction = Forward | Backward
128{-| A field with no content:
130 Content "" (Selection 0 0 Forward)
131-}
132noContent : Content
133noContent = Content "" (Selection 0 0 Forward)
135{-| Create a text field. The following example creates a time-varying element
136called `nameField`. As the user types their name, the field will be updated
137to match what they have entered.
139 name : Input Content
140 name = input noContent
142 nameField : Signal Element
143 nameField = field defaultStyle name.handle id "Name" <~ name.signal
145When we use the `field` function, we first give it a visual style. This is
146the first argument so that it is easier to define your own custom field
147(`myField = field myStyle`). The next two arguments are a `Handle` and a
148handler function that processes or augments events before sending them along
149to the associated `Input`. In the example above we use the `id` function to
150pass events along unchanged to the `name` `Input`. We then provide the
151place-holder message to use when no input has been provided yet. Finally,
152we give the current `Content` of the field. This argument is last because
153it is most likely to change frequently, making function composition easier.
154-}
155field : Style -> Handle a -> (Content -> a) -> String -> Content -> Element
156field = Native.Graphics.Input.field
158{-| Same as `field` but the UI element blocks out each characters. -}
159password : Style -> Handle a -> (Content -> a) -> String -> Content -> Element
160password = Native.Graphics.Input.password
162{-| Same as `field` but it adds an annotation that this field is for email
163addresses. This is helpful for auto-complete and for mobile users who may
164get a custom keyboard with an `@` and `.com` button.
165-}
166email : Style -> Handle a -> (Content -> a) -> String -> Content -> Element
167email = Native.Graphics.Input.email
169-- area : Handle a -> (Content -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> Content -> Element
170-- area = Native.Graphics.Input.area