1 ! Copyright (C) 2005, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays ascii assocs boxes calendar classes columns
4 combinators combinators.short-circuit deques fry kernel make math
5 math.order math.parser math.vectors namespaces sequences sets system
6 timers ui.gadgets ui.gadgets.private words locals ;
9 : get-gesture-handler ( gesture gadget -- quot )
10 class-of superclasses-of [ "gestures" word-prop ] map assoc-stack ;
12 GENERIC: handle-gesture ( gesture gadget -- ? )
14 M: object handle-gesture
16 [ get-gesture-handler ] 2bi
17 dup [ call( gadget -- ) f ] [ 2drop t ] if ;
19 GENERIC: handles-gesture? ( gesture gadget -- ? )
21 M: object handles-gesture? ( gesture gadget -- ? )
22 get-gesture-handler >boolean ;
24 : parents-handle-gesture? ( gesture gadget -- ? )
25 [ handles-gesture? not ] with each-parent not ;
27 : set-gestures ( class hash -- ) "gestures" set-word-prop ;
29 : gesture-queue ( -- deque ) \ gesture-queue get ;
31 GENERIC: send-queued-gesture ( request -- )
33 TUPLE: send-gesture-tuple gesture gadget ;
35 M: send-gesture-tuple send-queued-gesture
36 [ gesture>> ] [ gadget>> ] bi handle-gesture drop ;
38 : queue-gesture ( ... class -- )
39 boa gesture-queue push-front notify-ui-thread ; inline
41 : send-gesture ( gesture gadget -- )
42 \ send-gesture-tuple queue-gesture ;
44 : each-gesture ( gesture seq -- ) [ send-gesture ] with each ;
46 TUPLE: propagate-gesture-tuple gesture gadget ;
48 : resend-gesture ( gesture gadget -- ? )
49 [ handle-gesture ] with each-parent ;
51 M: propagate-gesture-tuple send-queued-gesture
52 [ gesture>> ] [ gadget>> ] bi resend-gesture drop ;
54 : propagate-gesture ( gesture gadget -- )
55 \ propagate-gesture-tuple queue-gesture ;
57 TUPLE: propagate-key-gesture-tuple gesture world ;
59 : world-focus ( world -- gadget )
60 dup focus>> [ world-focus ] [ ] ?if ;
62 M: propagate-key-gesture-tuple send-queued-gesture
63 [ gesture>> ] [ world>> world-focus ] bi
64 [ handle-gesture ] with each-parent drop ;
66 GENERIC: preedit? ( gadget -- ? )
68 M: gadget preedit? drop f ;
70 :: propagate-key-gesture ( gesture world -- )
71 world world-focus preedit? [
72 gesture world \ propagate-key-gesture-tuple queue-gesture
75 TUPLE: user-input-tuple string world ;
77 M: user-input-tuple send-queued-gesture
78 [ string>> ] [ world>> world-focus ] bi
79 [ user-input* ] with each-parent drop ;
81 : user-input ( string world -- )
82 '[ _ \ user-input-tuple queue-gesture ] unless-empty ;
85 TUPLE: drag # ; C: <drag> drag
86 TUPLE: button-up mods # ; C: <button-up> button-up
87 TUPLE: button-down mods # ; C: <button-down> button-down
88 TUPLE: file-drop mods ; C: <file-drop> file-drop
95 mouse-enter mouse-leave
96 lose-focus gain-focus ;
98 ! Higher-level actions
100 undo-action redo-action
101 cut-action copy-action paste-action
102 delete-action select-all-action
103 left-action right-action up-action down-action
104 zoom-in-action zoom-out-action
105 new-action open-action save-action save-as-action
106 revert-action close-action ;
109 undo-action redo-action
110 cut-action copy-action paste-action
111 delete-action select-all-action
112 left-action right-action up-action down-action
113 zoom-in-action zoom-out-action
114 new-action open-action save-action save-as-action
115 revert-action close-action ;
117 CONSTANT: action-gestures
124 { "a" select-all-action }
128 { "S" save-as-action }
133 SYMBOLS: C+ A+ M+ S+ ;
135 TUPLE: key-gesture mods sym ;
137 TUPLE: key-down < key-gesture ;
139 : new-key-gesture ( mods sym action? class -- key-gesture )
140 [ [ [ S+ swap remove f like ] dip ] unless ] dip boa ; inline
142 : <key-down> ( mods sym action? -- key-down )
143 key-down new-key-gesture ;
145 TUPLE: key-up < key-gesture ;
147 : <key-up> ( mods sym action? -- key-up )
148 key-up new-key-gesture ;
152 ! Note that these are only really useful inside an event
153 ! handler, and that the locations hand-loc and hand-click-loc
154 ! are in the co-ordinate system of the world which contains
155 ! the gadget in question.
159 { 0 0 } hand-loc set-global
162 SYMBOL: hand-click-loc
164 SYMBOL: hand-last-button
165 SYMBOL: hand-last-time
166 0 hand-last-button set-global
167 0 hand-last-time set-global
170 V{ } clone hand-buttons set-global
172 SYMBOL: scroll-direction
173 { 0 0 } scroll-direction set-global
175 SYMBOL: double-click-timeout
176 300 milliseconds double-click-timeout set-global
178 : hand-moved? ( -- ? )
179 hand-loc get-global hand-click-loc get-global = not ;
181 : button-gesture ( gesture -- )
182 hand-clicked get-global propagate-gesture ;
184 : drag-gesture ( -- )
185 hand-buttons get-global
186 [ first <drag> button-gesture ] unless-empty ;
190 <box> drag-timer set-global
192 : start-drag-timer ( -- )
193 hand-buttons get-global empty? [
198 [ drag-timer get-global >box ]
202 : stop-drag-timer ( -- )
203 hand-buttons get-global empty? [
204 drag-timer get-global ?box
205 [ stop-timer ] [ drop ] if
209 hand-buttons get-global empty? [
210 motion hand-gadget get-global propagate-gesture
215 : hand-gestures ( new old -- )
216 drop-prefix <reversed>
217 mouse-leave swap each-gesture
218 mouse-enter swap each-gesture ;
220 : forget-rollover ( -- )
221 f hand-world set-global
222 hand-gadget get-global
223 [ f hand-gadget set-global f ] dip
224 parents hand-gestures ;
226 : send-lose-focus ( gadget -- )
227 lose-focus swap send-gesture ;
229 : send-gain-focus ( gadget -- )
230 gain-focus swap send-gesture ;
232 : focus-child ( child gadget ? -- )
245 : modifier ( mod modifiers -- seq )
246 [ second swap bitand 0 > ] with filter
247 0 <column> members [ f ] [ >array ] if-empty ;
249 : drag-loc ( -- loc )
250 hand-loc get-global hand-click-loc get-global v- ;
252 : hand-rel ( gadget -- loc )
253 hand-loc get-global swap screen-loc v- ;
255 : hand-click-rel ( gadget -- loc )
256 hand-click-loc get-global swap screen-loc v- ;
258 : multi-click-timeout? ( -- ? )
259 nano-count hand-last-time get - nanoseconds
260 double-click-timeout get before=? ;
262 : multi-click-button? ( button -- button ? )
263 dup hand-last-button get = ;
265 : multi-click-position? ( -- ? )
266 hand-loc get-global hand-click-loc get-global distance 10 <= ;
268 : multi-click? ( button -- ? )
270 [ multi-click-timeout? ]
271 [ multi-click-button? ]
272 [ multi-click-position? ]
275 : update-click# ( button -- )
280 1 hand-click# namespaces:set
282 hand-last-button namespaces:set
283 nano-count hand-last-time namespaces:set
286 : update-clicked ( -- )
287 hand-gadget get-global hand-clicked set-global
288 hand-loc get-global hand-click-loc set-global ;
290 : under-hand ( -- seq )
291 hand-gadget get-global parents <reversed> ;
293 : move-hand ( loc world -- )
294 dup hand-world set-global
296 over hand-loc set-global
297 pick-up hand-gadget set-global
299 ] dip hand-gestures ;
301 : send-button-down ( gesture loc world -- )
305 dup update-click# hand-buttons get-global push
309 : send-button-up ( gesture loc world -- )
311 dup #>> hand-buttons get-global remove! drop
315 : send-scroll ( direction loc world -- )
317 scroll-direction set-global
318 mouse-scroll hand-gadget get-global propagate-gesture ;
320 : send-action ( world gesture -- )
321 swap world-focus propagate-gesture ;
323 GENERIC: gesture>string ( gesture -- string/f )
325 HOOK: modifiers>string os ( modifiers -- string )
327 M: macosx modifiers>string
330 { A+ [ "\u002318" ] }
331 { M+ [ "\u002325" ] }
332 { S+ [ "\u0021e7" ] }
333 { C+ [ "\u002303" ] }
337 M: object modifiers>string
338 [ name>> ] map "" concat-as ;
340 HOOK: keysym>string os ( keysym -- string )
342 M: macosx keysym>string >upper ;
344 M: object keysym>string dup length 1 = [ >lower ] when ;
346 M: key-down gesture>string
347 [ mods>> ] [ sym>> ] bi
349 { [ dup { [ length 1 = ] [ first LETTER? ] } 1&& ] [ [ S+ prefix ] dip ] }
350 { [ dup " " = ] [ drop "SPACE" ] }
353 [ modifiers>string ] [ keysym>string ] bi* append ;
355 M: button-up gesture>string
357 dup mods>> modifiers>string %
359 #>> [ " " % # ] when*
362 M: button-down gesture>string
364 dup mods>> modifiers>string %
366 #>> [ " " % # ] when*
369 M: file-drop gesture>string drop "Drop files" ;
371 M: left-action gesture>string drop "Swipe left" ;
373 M: right-action gesture>string drop "Swipe right" ;
375 M: up-action gesture>string drop "Swipe up" ;
377 M: down-action gesture>string drop "Swipe down" ;
379 M: zoom-in-action gesture>string drop "Zoom in" ;
381 M: zoom-out-action gesture>string drop "Zoom out (pinch)" ;
383 HOOK: action-modifier os ( -- mod )
385 M: object action-modifier C+ ;
386 M: macosx action-modifier A+ ;
388 M: action gesture>string
389 action-gestures value-at
390 action-modifier 1array
391 swap f <key-down> gesture>string ;
393 M: object gesture>string drop f ;