]> gitweb.factorcode.org Git - factor.git/blob - basis/ui/gadgets/buttons/buttons.factor
Merge branch 'master' into experimental (untested!)
[factor.git] / basis / ui / gadgets / buttons / buttons.factor
1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays kernel math models namespaces sequences
4 strings quotations assocs combinators classes colors
5 classes.tuple opengl opengl.gl math.vectors ui.commands ui.gadgets
6 ui.gadgets.borders ui.gadgets.labels ui.gadgets.theme
7 ui.gadgets.tracks ui.gadgets.packs ui.gadgets.worlds ui.gestures
8 ui.render math.geometry.rect locals alien.c-types
9 specialized-arrays.float fry ;
10 IN: ui.gadgets.buttons
11
12 TUPLE: button < border pressed? selected? quot ;
13
14 : buttons-down? ( -- ? )
15     hand-buttons get-global empty? not ;
16
17 : button-rollover? ( button -- ? )
18     hand-gadget get-global child? ;
19
20 : mouse-clicked? ( gadget -- ? )
21     hand-clicked get-global child? ;
22
23 : button-update ( button -- )
24     dup mouse-clicked?
25     over button-rollover? and
26     buttons-down? and
27     >>pressed?
28     relayout-1 ;
29
30 : if-clicked ( button quot -- )
31     [ dup button-update dup button-rollover? ] dip [ drop ] if ;
32
33 : button-clicked ( button -- ) dup quot>> if-clicked ;
34
35 button H{
36     { T{ button-up } [ button-clicked ] }
37     { T{ button-down } [ button-update ] }
38     { T{ mouse-leave } [ button-update ] }
39     { T{ mouse-enter } [ button-update ] }
40 } set-gestures
41
42 : new-button ( label quot class -- button )
43     [ swap >label ] dip new-border swap >>quot ; inline
44
45 : <button> ( label quot -- button )
46     button new-button ;
47
48 TUPLE: button-paint plain rollover pressed selected ;
49
50 C: <button-paint> button-paint
51
52 : find-button ( gadget -- button )
53     [ button? ] find-parent ;
54
55 : button-paint ( button paint -- button paint )
56     over find-button {
57         { [ dup pressed?>> ] [ drop pressed>> ] }
58         { [ dup selected?>> ] [ drop selected>> ] }
59         { [ dup button-rollover? ] [ drop rollover>> ] }
60         [ drop plain>> ]
61     } cond ;
62
63 M: button-paint draw-interior
64     button-paint dup [ draw-interior ] [ 2drop ] if ;
65
66 M: button-paint draw-boundary
67     button-paint dup [ draw-boundary ] [ 2drop ] if ;
68
69 : align-left ( button -- button )
70     { 0 1/2 } >>align ; inline
71
72 : roll-button-theme ( button -- button )
73     f black <solid> dup f <button-paint> >>boundary
74     f f pressed-gradient f <button-paint> >>interior
75     align-left ; inline
76
77 : <roll-button> ( label quot -- button )
78     <button> roll-button-theme ;
79
80 : <bevel-button-paint> ( -- paint )
81     plain-gradient
82     rollover-gradient
83     pressed-gradient
84     selected-gradient
85     <button-paint> ;
86
87 : bevel-button-theme ( gadget -- gadget )
88     <bevel-button-paint> >>interior
89     { 5 5 } >>size
90     faint-boundary ; inline
91
92 : <bevel-button> ( label quot -- button )
93     <button> bevel-button-theme ;
94
95 TUPLE: repeat-button < button ;
96
97 repeat-button H{
98     { T{ drag } [ button-clicked ] }
99 } set-gestures
100
101 : <repeat-button> ( label quot -- button )
102     #! Button that calls the quotation every 100ms as long as
103     #! the mouse is held down.
104     repeat-button new-button bevel-button-theme ;
105
106 TUPLE: checkmark-paint < caching-pen color last-vertices ;
107
108 : <checkmark-paint> ( color -- paint )
109     checkmark-paint new swap >>color ;
110
111 <PRIVATE
112
113 : checkmark-points ( dim -- points )
114     {
115         [ { 0 0 } v* { 0.5 0.5 } v+ ]
116         [ { 1 1 } v* { 0.5 0.5 } v+ ]
117         [ { 1 0 } v* { -0.3 0.5 } v+ ]
118         [ { 0 1 } v* { -0.3 0.5 } v+ ]
119     } cleave 4array ;
120
121 : checkmark-vertices ( dim -- vertices )
122     checkmark-points concat >float-array ;
123
124 PRIVATE>
125
126 M: checkmark-paint recompute-pen
127     swap dim>> checkmark-vertices >>last-vertices drop ;
128
129 M: checkmark-paint draw-interior
130     [ compute-pen ]
131     [ color>> gl-color ]
132     [ last-vertices>> gl-vertex-pointer ] tri
133     GL_LINES 0 4 glDrawArrays ;
134
135 : checkmark-theme ( gadget -- gadget )
136     f
137     f
138     black <solid>
139     black <checkmark-paint>
140     <button-paint> >>interior
141     black <solid> >>boundary ;
142
143 : <checkmark> ( -- gadget )
144     <gadget>
145     checkmark-theme
146     { 14 14 } >>dim ;
147
148 : toggle-model ( model -- )
149     [ not ] change-model ;
150
151 : checkbox-theme ( gadget -- gadget )
152     f >>interior
153     { 5 5 } >>gap
154     1/2 >>align ; inline
155
156 TUPLE: checkbox < button ;
157
158 : <checkbox> ( model label -- checkbox )
159     <checkmark> label-on-right checkbox-theme
160     [ model>> toggle-model ]
161     checkbox new-button
162         swap >>model
163         align-left ;
164
165 M: checkbox model-changed
166     swap value>> >>selected? relayout-1 ;
167
168 TUPLE: radio-paint < caching-pen color interior-vertices boundary-vertices ;
169
170 : <radio-paint> ( color -- paint ) radio-paint new swap >>color ;
171
172 <PRIVATE
173
174 : circle-steps 8 ;
175
176 PRIVATE>
177
178 M: radio-paint recompute-pen
179     swap dim>>
180     [ { 4 4 } swap { 9 9 } v- circle-steps fill-circle-vertices >>interior-vertices ]
181     [ { 1 1 } swap { 3 3 } v- circle-steps circle-vertices >>boundary-vertices ] bi
182     drop ;
183
184 <PRIVATE
185
186 : (radio-paint) ( gadget paint -- )
187     [ compute-pen ] [ color>> gl-color ] bi ;
188
189 PRIVATE>
190
191 M: radio-paint draw-interior
192     [ (radio-paint) ] [ interior-vertices>> gl-vertex-pointer ] bi
193     GL_POLYGON 0 circle-steps glDrawArrays ;
194
195 M: radio-paint draw-boundary
196     [ (radio-paint) ] [ boundary-vertices>> gl-vertex-pointer ] bi
197     GL_LINE_STRIP 0 circle-steps 1+ glDrawArrays ;
198
199 :: radio-knob-theme ( gadget -- gadget )
200     [let | radio-paint [ black <radio-paint> ] |
201         gadget
202         f f radio-paint radio-paint <button-paint> >>interior
203         radio-paint >>boundary
204         { 16 16 } >>dim
205     ] ;
206
207 : <radio-knob> ( -- gadget )
208     <gadget> radio-knob-theme ;
209
210 TUPLE: radio-control < button value ;
211
212 : <radio-control> ( value model label -- control )
213     [ [ value>> ] keep set-control-value ]
214     radio-control new-button
215         swap >>model
216         swap >>value
217         align-left ; inline
218
219 M: radio-control model-changed
220     swap value>>
221     over value>> = >>selected?
222     relayout-1 ;
223
224 : <radio-controls> ( assoc model parent quot: ( value model label -- ) -- parent )
225     '[ _ swap _ call add-gadget ] assoc-each ; inline
226
227 : radio-button-theme ( gadget -- gadget )
228     { 5 5 } >>gap
229     1/2 >>align ; inline
230
231 : <radio-button> ( value model label -- gadget )
232     <radio-knob> label-on-right radio-button-theme <radio-control> ;
233
234 : <radio-buttons> ( model assoc -- gadget )
235     <filled-pile>
236         spin [ <radio-button> ] <radio-controls>
237         { 5 5 } >>gap ;
238
239 : <toggle-button> ( value model label -- gadget )
240     <radio-control> bevel-button-theme ;
241
242 : <toggle-buttons> ( model assoc -- gadget )
243     <shelf>
244         spin [ <toggle-button> ] <radio-controls> ;
245
246 : command-button-quot ( target command -- quot )
247     '[ _ _ invoke-command drop ] ;
248
249 : <command-button> ( target gesture command -- button )
250     [ command-string swap ] keep command-button-quot <bevel-button> ;
251
252 : <toolbar> ( target -- toolbar )
253     <shelf>
254         swap
255         "toolbar" over class command-map commands>> swap
256         '[ [ _ ] 2dip <command-button> add-gadget ] assoc-each ;
257
258 : add-toolbar ( track -- track )
259     dup <toolbar> f track-add ;