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 combinators.smart ;
10 IN: ui.gadgets.buttons
12 TUPLE: button < border pressed? selected? quot ;
14 : buttons-down? ( -- ? )
15 hand-buttons get-global empty? not ;
17 : button-rollover? ( button -- ? )
18 hand-gadget get-global child? ;
20 : mouse-clicked? ( gadget -- ? )
21 hand-clicked get-global child? ;
23 : button-update ( button -- )
25 over button-rollover? and
30 : if-clicked ( button quot -- )
31 [ dup button-update dup button-rollover? ] dip [ drop ] if ;
33 : button-clicked ( button -- ) dup quot>> if-clicked ;
36 { T{ button-up } [ button-clicked ] }
37 { T{ button-down } [ button-update ] }
38 { T{ mouse-leave } [ button-update ] }
39 { T{ mouse-enter } [ button-update ] }
42 : new-button ( label quot class -- button )
43 [ swap >label ] dip new-border swap >>quot ; inline
45 : <button> ( label quot -- button )
48 TUPLE: button-paint plain rollover pressed selected ;
50 C: <button-paint> button-paint
52 : find-button ( gadget -- button )
53 [ button? ] find-parent ;
55 : button-paint ( button paint -- button paint )
57 { [ dup pressed?>> ] [ drop pressed>> ] }
58 { [ dup selected?>> ] [ drop selected>> ] }
59 { [ dup button-rollover? ] [ drop rollover>> ] }
63 M: button-paint draw-interior
64 button-paint dup [ draw-interior ] [ 2drop ] if ;
66 M: button-paint draw-boundary
67 button-paint dup [ draw-boundary ] [ 2drop ] if ;
69 : align-left ( button -- button )
70 { 0 1/2 } >>align ; inline
72 : roll-button-theme ( button -- button )
73 f black <solid> dup f <button-paint> >>boundary
74 f f pressed-gradient f <button-paint> >>interior
77 : <roll-button> ( label quot -- button )
78 <button> roll-button-theme ;
80 : <bevel-button-paint> ( -- paint )
87 : bevel-button-theme ( gadget -- gadget )
88 <bevel-button-paint> >>interior
90 faint-boundary ; inline
92 : <bevel-button> ( label quot -- button )
93 <button> bevel-button-theme ;
95 TUPLE: repeat-button < button ;
98 { T{ drag } [ button-clicked ] }
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 ;
106 TUPLE: checkmark-paint < caching-pen color last-vertices ;
108 : <checkmark-paint> ( color -- paint )
109 checkmark-paint new swap >>color ;
113 : checkmark-points ( dim -- points )
116 [ { 0 0 } v* { 0.5 0.5 } v+ ]
117 [ { 1 1 } v* { 0.5 0.5 } v+ ]
118 [ { 1 0 } v* { -0.3 0.5 } v+ ]
119 [ { 0 1 } v* { -0.3 0.5 } v+ ]
123 : checkmark-vertices ( dim -- vertices )
124 checkmark-points concat >float-array ;
128 M: checkmark-paint recompute-pen
129 swap dim>> checkmark-vertices >>last-vertices drop ;
131 M: checkmark-paint draw-interior
134 [ last-vertices>> gl-vertex-pointer ] tri
135 GL_LINES 0 4 glDrawArrays ;
137 : checkmark-theme ( gadget -- gadget )
141 black <checkmark-paint>
142 <button-paint> >>interior
143 black <solid> >>boundary ;
145 : <checkmark> ( -- gadget )
150 : toggle-model ( model -- )
151 [ not ] change-model ;
153 : checkbox-theme ( gadget -- gadget )
158 TUPLE: checkbox < button ;
160 : <checkbox> ( model label -- checkbox )
161 <checkmark> label-on-right checkbox-theme
162 [ model>> toggle-model ]
167 M: checkbox model-changed
168 swap value>> >>selected? relayout-1 ;
170 TUPLE: radio-paint < caching-pen color interior-vertices boundary-vertices ;
172 : <radio-paint> ( color -- paint ) radio-paint new swap >>color ;
176 CONSTANT: circle-steps 8
180 M: radio-paint recompute-pen
182 [ { 4 4 } swap { 9 9 } v- circle-steps fill-circle-vertices >>interior-vertices ]
183 [ { 1 1 } swap { 3 3 } v- circle-steps circle-vertices >>boundary-vertices ] bi
188 : (radio-paint) ( gadget paint -- )
189 [ compute-pen ] [ color>> gl-color ] bi ;
193 M: radio-paint draw-interior
194 [ (radio-paint) ] [ interior-vertices>> gl-vertex-pointer ] bi
195 GL_POLYGON 0 circle-steps glDrawArrays ;
197 M: radio-paint draw-boundary
198 [ (radio-paint) ] [ boundary-vertices>> gl-vertex-pointer ] bi
199 GL_LINE_STRIP 0 circle-steps 1+ glDrawArrays ;
201 :: radio-knob-theme ( gadget -- gadget )
202 [let | radio-paint [ black <radio-paint> ] |
204 f f radio-paint radio-paint <button-paint> >>interior
205 radio-paint >>boundary
209 : <radio-knob> ( -- gadget )
210 <gadget> radio-knob-theme ;
212 TUPLE: radio-control < button value ;
214 : <radio-control> ( value model label -- control )
215 [ [ value>> ] keep set-control-value ]
216 radio-control new-button
221 M: radio-control model-changed
223 over value>> = >>selected?
226 : <radio-controls> ( assoc model parent quot: ( value model label -- ) -- parent )
227 '[ _ swap _ call add-gadget ] assoc-each ; inline
229 : radio-button-theme ( gadget -- gadget )
233 : <radio-button> ( value model label -- gadget )
234 <radio-knob> label-on-right radio-button-theme <radio-control> ;
236 : <radio-buttons> ( model assoc -- gadget )
238 spin [ <radio-button> ] <radio-controls>
241 : <toggle-button> ( value model label -- gadget )
242 <radio-control> bevel-button-theme ;
244 : <toggle-buttons> ( model assoc -- gadget )
246 spin [ <toggle-button> ] <radio-controls> ;
248 : command-button-quot ( target command -- quot )
249 '[ _ _ invoke-command drop ] ;
251 : <command-button> ( target gesture command -- button )
252 [ command-string swap ] keep command-button-quot <bevel-button> ;
254 : <toolbar> ( target -- toolbar )
257 "toolbar" over class command-map commands>> swap
258 '[ [ _ ] 2dip <command-button> add-gadget ] assoc-each ;
260 : add-toolbar ( track -- track )
261 dup <toolbar> f track-add ;