1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs kernel math models namespaces
4 sequences words strings system hashtables math.parser
5 math.vectors classes.tuple classes ui.gadgets boxes
6 calendar alarms symbols combinators sets columns ;
9 : set-gestures ( class hash -- ) "gestures" set-word-prop ;
11 GENERIC: handle-gesture* ( gadget gesture delegate -- ? )
13 : default-gesture-handler ( gadget gesture delegate -- ? )
14 class "gestures" word-prop at dup
15 [ call f ] [ 2drop t ] if ;
17 M: object handle-gesture* default-gesture-handler ;
19 : handle-gesture ( gesture gadget -- ? )
20 tuck delegates [ >r 2dup r> handle-gesture* ] all? 2nip ;
22 : send-gesture ( gesture gadget -- ? )
23 [ dupd handle-gesture ] each-parent nip ;
25 : user-input ( str gadget -- )
27 [ [ dupd user-input* ] each-parent ] unless
31 TUPLE: motion ; C: <motion> motion
32 TUPLE: drag # ; C: <drag> drag
33 TUPLE: button-up mods # ; C: <button-up> button-up
34 TUPLE: button-down mods # ; C: <button-down> button-down
35 TUPLE: mouse-scroll ; C: <mouse-scroll> mouse-scroll
36 TUPLE: mouse-enter ; C: <mouse-enter> mouse-enter
37 TUPLE: mouse-leave ; C: <mouse-leave> mouse-leave
38 TUPLE: lose-focus ; C: <lose-focus> lose-focus
39 TUPLE: gain-focus ; C: <gain-focus> gain-focus
41 ! Higher-level actions
42 TUPLE: cut-action ; C: <cut-action> cut-action
43 TUPLE: copy-action ; C: <copy-action> copy-action
44 TUPLE: paste-action ; C: <paste-action> paste-action
45 TUPLE: delete-action ; C: <delete-action> delete-action
46 TUPLE: select-all-action ; C: <select-all-action> select-all-action
48 TUPLE: left-action ; C: <left-action> left-action
49 TUPLE: right-action ; C: <right-action> right-action
50 TUPLE: up-action ; C: <up-action> up-action
51 TUPLE: down-action ; C: <down-action> down-action
53 TUPLE: zoom-in-action ; C: <zoom-in-action> zoom-in-action
54 TUPLE: zoom-out-action ; C: <zoom-out-action> zoom-out-action
56 : generalize-gesture ( gesture -- newgesture )
57 tuple>array but-last >tuple ;
60 SYMBOLS: C+ A+ M+ S+ ;
62 TUPLE: key-down mods sym ;
64 : <key-gesture> ( mods sym action? class -- mods' sym' )
65 >r [ S+ rot remove swap ] unless r> boa ; inline
67 : <key-down> ( mods sym action? -- key-down )
68 key-down <key-gesture> ;
70 TUPLE: key-up mods sym ;
72 : <key-up> ( mods sym action? -- key-up )
73 key-up <key-gesture> ;
77 ! Note that these are only really useful inside an event
78 ! handler, and that the locations hand-loc and hand-click-loc
79 ! are in the co-ordinate system of the world which contains
80 ! the gadget in question.
84 { 0 0 } hand-loc set-global
87 SYMBOL: hand-click-loc
89 SYMBOL: hand-last-button
90 SYMBOL: hand-last-time
91 0 hand-last-button set-global
92 0 hand-last-time set-global
95 V{ } clone hand-buttons set-global
97 SYMBOL: scroll-direction
98 { 0 0 } scroll-direction set-global
100 SYMBOL: double-click-timeout
101 300 double-click-timeout set-global
103 : hand-moved? ( -- ? )
104 hand-loc get hand-click-loc get = not ;
106 : button-gesture ( gesture -- )
107 hand-clicked get-global 2dup send-gesture [
108 >r generalize-gesture r> send-gesture drop
113 : drag-gesture ( -- )
114 hand-buttons get-global
115 dup empty? [ drop ] [ first <drag> button-gesture ] if ;
119 <box> drag-timer set-global
121 : start-drag-timer ( -- )
122 hand-buttons get-global empty? [
124 300 milliseconds from-now
126 add-alarm drag-timer get-global >box
129 : stop-drag-timer ( -- )
130 hand-buttons get-global empty? [
131 drag-timer get-global ?box
132 [ cancel-alarm ] [ drop ] if
136 hand-buttons get-global empty? [
137 T{ motion } hand-gadget get-global send-gesture drop
142 : each-gesture ( gesture seq -- )
143 [ handle-gesture drop ] with each ;
145 : hand-gestures ( new old -- )
146 drop-prefix <reversed>
147 T{ mouse-leave } swap each-gesture
148 T{ mouse-enter } swap each-gesture ;
150 : forget-rollover ( -- )
151 f hand-world set-global
152 hand-gadget get-global >r
153 f hand-gadget set-global
154 f r> parents hand-gestures ;
156 : send-lose-focus ( gadget -- )
157 T{ lose-focus } swap handle-gesture drop ;
159 : send-gain-focus ( gadget -- )
160 T{ gain-focus } swap handle-gesture drop ;
162 : focus-child ( child gadget ? -- )
168 dupd set-gadget-focus [
175 : modifier ( mod modifiers -- seq )
176 [ second swap bitand 0 > ] with filter
177 0 <column> prune dup empty? [ drop f ] [ >array ] if ;
179 : drag-loc ( -- loc )
180 hand-loc get-global hand-click-loc get-global v- ;
182 : hand-rel ( gadget -- loc )
183 hand-loc get-global swap screen-loc v- ;
185 : hand-click-rel ( gadget -- loc )
186 hand-click-loc get-global swap screen-loc v- ;
188 : multi-click-timeout? ( -- ? )
189 millis hand-last-time get - double-click-timeout get <= ;
191 : multi-click-button? ( button -- button ? )
192 dup hand-last-button get = ;
194 : multi-click-position? ( -- ? )
195 hand-loc get hand-click-loc get v- norm 10 <= ;
197 : multi-click? ( button -- ? )
199 { [ multi-click-timeout? not ] [ f ] }
200 { [ multi-click-button? not ] [ f ] }
201 { [ multi-click-position? not ] [ f ] }
202 { [ multi-click-position? not ] [ f ] }
206 : update-click# ( button -- )
214 millis hand-last-time set
217 : update-clicked ( -- )
218 hand-gadget get-global hand-clicked set-global
219 hand-loc get-global hand-click-loc set-global ;
221 : under-hand ( -- seq )
222 hand-gadget get-global parents <reversed> ;
224 : move-hand ( loc world -- )
225 dup hand-world set-global
226 under-hand >r over hand-loc set-global
227 pick-up hand-gadget set-global
228 under-hand r> hand-gestures ;
230 : send-button-down ( gesture loc world -- )
234 dup update-click# hand-buttons get-global push
238 : send-button-up ( gesture loc world -- )
240 dup button-up-# hand-buttons get-global delete
244 : send-wheel ( direction loc world -- )
246 scroll-direction set-global
247 T{ mouse-scroll } hand-gadget get-global send-gesture
250 : world-focus ( world -- gadget )
251 dup gadget-focus [ world-focus ] [ ] ?if ;
253 : send-action ( world gesture -- )
254 swap world-focus send-gesture drop ;
256 : resend-button-down ( gesture world -- )
257 hand-loc get-global swap send-button-down ;
259 : resend-button-up ( gesture world -- )
260 hand-loc get-global swap send-button-up ;
262 GENERIC: gesture>string ( gesture -- string/f )
264 : modifiers>string ( modifiers -- string )
265 [ name>> ] map concat >string ;
267 M: key-down gesture>string
268 dup key-down-mods modifiers>string
269 swap key-down-sym append ;
271 M: button-up gesture>string
273 dup button-up-mods modifiers>string %
275 button-up-# [ " " % # ] when*
278 M: button-down gesture>string
280 dup button-down-mods modifiers>string %
282 button-down-# [ " " % # ] when*
285 M: left-action gesture>string drop "Swipe left" ;
287 M: right-action gesture>string drop "Swipe right" ;
289 M: up-action gesture>string drop "Swipe up" ;
291 M: down-action gesture>string drop "Swipe down" ;
293 M: zoom-in-action gesture>string drop "Zoom in" ;
295 M: zoom-out-action gesture>string drop "Zoom out (pinch)" ;
297 M: object gesture>string drop f ;