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
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 )
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+ ]
121 : checkmark-vertices ( dim -- vertices )
122 checkmark-points concat >float-array ;
126 M: checkmark-paint recompute-pen
127 swap dim>> checkmark-vertices >>last-vertices drop ;
129 M: checkmark-paint draw-interior
132 [ last-vertices>> gl-vertex-pointer ] tri
133 GL_LINES 0 4 glDrawArrays ;
135 : checkmark-theme ( gadget -- gadget )
139 black <checkmark-paint>
140 <button-paint> >>interior
141 black <solid> >>boundary ;
143 : <checkmark> ( -- gadget )
148 : toggle-model ( model -- )
149 [ not ] change-model ;
151 : checkbox-theme ( gadget -- gadget )
156 TUPLE: checkbox < button ;
158 : <checkbox> ( model label -- checkbox )
159 <checkmark> label-on-right checkbox-theme
160 [ model>> toggle-model ]
165 M: checkbox model-changed
166 swap value>> >>selected? relayout-1 ;
168 TUPLE: radio-paint < caching-pen color interior-vertices boundary-vertices ;
170 : <radio-paint> ( color -- paint ) radio-paint new swap >>color ;
178 M: radio-paint recompute-pen
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
186 : (radio-paint) ( gadget paint -- )
187 [ compute-pen ] [ color>> gl-color ] bi ;
191 M: radio-paint draw-interior
192 [ (radio-paint) ] [ interior-vertices>> gl-vertex-pointer ] bi
193 GL_POLYGON 0 circle-steps glDrawArrays ;
195 M: radio-paint draw-boundary
196 [ (radio-paint) ] [ boundary-vertices>> gl-vertex-pointer ] bi
197 GL_LINE_STRIP 0 circle-steps 1+ glDrawArrays ;
199 :: radio-knob-theme ( gadget -- gadget )
200 [let | radio-paint [ black <radio-paint> ] |
202 f f radio-paint radio-paint <button-paint> >>interior
203 radio-paint >>boundary
207 : <radio-knob> ( -- gadget )
208 <gadget> radio-knob-theme ;
210 TUPLE: radio-control < button value ;
212 : <radio-control> ( value model label -- control )
213 [ [ value>> ] keep set-control-value ]
214 radio-control new-button
219 M: radio-control model-changed
221 over value>> = >>selected?
224 : <radio-controls> ( assoc model parent quot: ( value model label -- ) -- parent )
225 '[ _ swap _ call add-gadget ] assoc-each ; inline
227 : radio-button-theme ( gadget -- gadget )
231 : <radio-button> ( value model label -- gadget )
232 <radio-knob> label-on-right radio-button-theme <radio-control> ;
234 : <radio-buttons> ( model assoc -- gadget )
236 spin [ <radio-button> ] <radio-controls>
239 : <toggle-button> ( value model label -- gadget )
240 <radio-control> bevel-button-theme ;
242 : <toggle-buttons> ( model assoc -- gadget )
244 spin [ <toggle-button> ] <radio-controls> ;
246 : command-button-quot ( target command -- quot )
247 '[ _ _ invoke-command drop ] ;
249 : <command-button> ( target gesture command -- button )
250 [ command-string swap ] keep command-button-quot <bevel-button> ;
252 : <toolbar> ( target -- toolbar )
255 "toolbar" over class command-map commands>> swap
256 '[ [ _ ] 2dip <command-button> add-gadget ] assoc-each ;
258 : add-toolbar ( track -- track )
259 dup <toolbar> f track-add ;