1 ! Copyright (C) 2005, 2007 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays assocs kernel math models namespaces queues
4 sequences words strings system hashtables math.parser
5 math.vectors tuples classes ui.gadgets timers ;
8 : set-gestures ( class hash -- ) "gestures" set-word-prop ;
10 GENERIC: handle-gesture* ( gadget gesture delegate -- ? )
12 : default-gesture-handler ( gadget gesture delegate -- ? )
13 class "gestures" word-prop at dup
14 [ call f ] [ 2drop t ] if ;
16 M: object handle-gesture* default-gesture-handler ;
18 : handle-gesture ( gesture gadget -- ? )
19 tuck delegates [ >r 2dup r> handle-gesture* ] all? 2nip ;
21 : send-gesture ( gesture gadget -- ? )
22 [ dupd handle-gesture ] each-parent nip ;
24 : user-input ( str gadget -- )
26 [ [ dupd user-input* ] each-parent ] unless
30 TUPLE: motion ; C: <motion> motion
31 TUPLE: drag # ; C: <drag> drag
32 TUPLE: button-up mods # ; C: <button-up> button-up
33 TUPLE: button-down mods # ; C: <button-down> button-down
34 TUPLE: mouse-scroll ; C: <mouse-scroll> mouse-scroll
35 TUPLE: mouse-enter ; C: <mouse-enter> mouse-enter
36 TUPLE: mouse-leave ; C: <mouse-leave> mouse-leave
37 TUPLE: lose-focus ; C: <lose-focus> lose-focus
38 TUPLE: gain-focus ; C: <gain-focus> gain-focus
40 ! Higher-level actions
41 TUPLE: cut-action ; C: <cut-action> cut-action
42 TUPLE: copy-action ; C: <copy-action> copy-action
43 TUPLE: paste-action ; C: <paste-action> paste-action
44 TUPLE: delete-action ; C: <delete-action> delete-action
45 TUPLE: select-all-action ; C: <select-all-action> select-all-action
47 : generalize-gesture ( gesture -- newgesture )
48 tuple>array 1 head* >tuple ;
56 TUPLE: key-down mods sym ;
58 : <key-gesture> ( mods sym action? class -- mods' sym' )
59 >r [ S+ rot remove swap ] unless r> construct-boa ; inline
61 : <key-down> ( mods sym action? -- key-down )
62 key-down <key-gesture> ;
64 TUPLE: key-up mods sym ;
66 : <key-up> ( mods sym action? -- key-up )
67 key-up <key-gesture> ;
71 ! Note that these are only really useful inside an event
72 ! handler, and that the locations hand-loc and hand-click-loc
73 ! are in the co-ordinate system of the world which contains
74 ! the gadget in question.
78 { 0 0 } hand-loc set-global
81 SYMBOL: hand-click-loc
83 SYMBOL: hand-last-button
84 SYMBOL: hand-last-time
85 0 hand-last-button set-global
86 0 hand-last-time set-global
89 V{ } clone hand-buttons set-global
91 SYMBOL: scroll-direction
92 { 0 0 } scroll-direction set-global
94 SYMBOL: double-click-timeout
95 300 double-click-timeout set-global
97 : hand-moved? ( -- ? )
98 hand-loc get hand-click-loc get = not ;
100 : button-gesture ( gesture -- )
101 hand-clicked get-global 2dup send-gesture [
102 >r generalize-gesture r> send-gesture drop
107 : drag-gesture ( -- )
108 hand-buttons get-global first <drag> button-gesture ;
112 M: drag-timer tick drop drag-gesture ;
114 drag-timer construct-empty drag-timer set-global
116 : start-drag-timer ( -- )
117 hand-buttons get-global empty? [
118 drag-timer get-global 100 100 add-timer
121 : stop-drag-timer ( -- )
122 hand-buttons get-global empty? [
123 drag-timer get-global remove-timer
127 hand-buttons get-global empty? [
128 T{ motion } hand-gadget get-global send-gesture drop
133 : each-gesture ( gesture seq -- )
134 [ handle-gesture drop ] curry* each ;
136 : hand-gestures ( new old -- )
137 drop-prefix <reversed>
138 T{ mouse-leave } swap each-gesture
139 T{ mouse-enter } swap each-gesture ;
141 : forget-rollover ( -- )
142 f hand-world set-global
143 hand-gadget get-global >r
144 f hand-gadget set-global
145 f r> parents hand-gestures ;
147 : send-lose-focus ( gadget -- )
148 T{ lose-focus } swap handle-gesture drop ;
150 : send-gain-focus ( gadget -- )
151 T{ gain-focus } swap handle-gesture drop ;
153 : focus-child ( child gadget ? -- )
159 dupd set-gadget-focus [
166 : modifier ( mod modifiers -- seq )
167 [ second swap bitand 0 > ] curry* subset
168 0 <column> prune dup empty? [ drop f ] [ >array ] if ;
170 : drag-loc ( -- loc )
171 hand-loc get-global hand-click-loc get-global v- ;
173 : hand-rel ( gadget -- loc )
174 hand-loc get-global swap screen-loc v- ;
176 : hand-click-rel ( gadget -- loc )
177 hand-click-loc get-global swap screen-loc v- ;
179 : multi-click? ( button -- ? )
180 millis hand-last-time get - double-click-timeout get <=
181 swap hand-last-button get = and ;
183 : update-click# ( button -- )
191 millis hand-last-time set
194 : update-clicked ( -- )
195 hand-gadget get-global hand-clicked set-global
196 hand-loc get-global hand-click-loc set-global ;
198 : under-hand ( -- seq )
199 hand-gadget get-global parents <reversed> ;
201 : move-hand ( loc world -- )
202 dup hand-world set-global
203 under-hand >r over hand-loc set-global
204 pick-up hand-gadget set-global
205 under-hand r> hand-gestures ;
207 : send-button-down ( gesture loc world -- )
211 dup update-click# hand-buttons get-global push
215 : send-button-up ( gesture loc world -- )
217 dup button-up-# hand-buttons get-global delete
221 : send-wheel ( direction loc world -- )
223 scroll-direction set-global
224 T{ mouse-scroll } hand-gadget get-global send-gesture
227 : world-focus ( world -- gadget )
228 dup gadget-focus [ world-focus ] [ ] ?if ;
230 : send-action ( world gesture -- )
231 swap world-focus send-gesture drop ;
233 : resend-button-down ( gesture world -- )
234 hand-loc get-global swap send-button-down ;
236 : resend-button-up ( gesture world -- )
237 hand-loc get-global swap send-button-up ;
239 GENERIC: gesture>string ( gesture -- string/f )
241 : modifiers>string ( modifiers -- string )
242 [ word-name ] map concat >string ;
244 M: key-down gesture>string
245 dup key-down-mods modifiers>string
246 swap key-down-sym append ;
248 M: button-up gesture>string
250 dup button-up-mods modifiers>string %
252 button-up-# [ " " % # ] when*
255 M: button-down gesture>string
257 dup button-down-mods modifiers>string %
259 button-down-# [ " " % # ] when*
262 M: object gesture>string drop f ;