2006-03-24 19:26:06 -05:00
|
|
|
! Copyright (C) 2005, 2006 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2005-01-31 22:32:06 -05:00
|
|
|
IN: gadgets
|
2006-07-19 17:00:57 -04:00
|
|
|
USING: generic hashtables kernel math models namespaces queues
|
|
|
|
sequences words ;
|
2005-02-05 11:52:24 -05:00
|
|
|
|
2006-07-19 17:00:57 -04:00
|
|
|
: (gestures) ( gadget -- )
|
|
|
|
[
|
2006-07-19 19:30:02 -04:00
|
|
|
dup delegate (gestures)
|
|
|
|
class "gestures" word-prop [ , ] when*
|
2006-07-19 17:00:57 -04:00
|
|
|
] when* ;
|
2005-02-05 11:52:24 -05:00
|
|
|
|
2006-07-19 17:00:57 -04:00
|
|
|
: gestures ( gadget -- seq ) [ (gestures) ] { } make ;
|
|
|
|
|
|
|
|
: set-gestures ( class hash -- ) "gestures" set-word-prop ;
|
2005-10-07 20:26:21 -04:00
|
|
|
|
2006-05-26 17:40:41 -04:00
|
|
|
: handle-gesture* ( gesture gadget -- )
|
2006-07-19 17:00:57 -04:00
|
|
|
tuck gestures hash-stack [ call f ] [ drop t ] if* ;
|
2005-01-31 22:32:06 -05:00
|
|
|
|
2005-02-12 21:15:30 -05:00
|
|
|
: handle-gesture ( gesture gadget -- ? )
|
2005-01-31 22:32:06 -05:00
|
|
|
#! If a gadget's handle-gesture* generic returns t, the
|
|
|
|
#! event was not consumed and is passed on to the gadget's
|
2005-02-12 21:15:30 -05:00
|
|
|
#! parent. This word returns t if no gadget handled the
|
|
|
|
#! gesture, otherwise returns f.
|
|
|
|
[ dupd handle-gesture* ] each-parent nip ;
|
|
|
|
|
2006-03-22 17:22:05 -05:00
|
|
|
: user-input ( str gadget -- )
|
|
|
|
[ dupd user-input* ] each-parent 2drop ;
|
2005-02-01 20:14:03 -05:00
|
|
|
|
2006-05-18 22:01:38 -04:00
|
|
|
! Gesture objects
|
|
|
|
TUPLE: motion ;
|
|
|
|
TUPLE: drag # ;
|
|
|
|
TUPLE: button-up # ;
|
|
|
|
TUPLE: button-down # ;
|
|
|
|
TUPLE: wheel-up ;
|
|
|
|
TUPLE: wheel-down ;
|
|
|
|
TUPLE: mouse-enter ;
|
|
|
|
TUPLE: mouse-leave ;
|
|
|
|
TUPLE: lose-focus ;
|
|
|
|
TUPLE: gain-focus ;
|
|
|
|
|
2006-06-03 02:41:28 -04:00
|
|
|
! Higher-level actions
|
|
|
|
TUPLE: cut-action ;
|
|
|
|
TUPLE: copy-action ;
|
|
|
|
TUPLE: paste-action ;
|
|
|
|
TUPLE: delete-action ;
|
2006-07-19 02:27:37 -04:00
|
|
|
TUPLE: select-all-action ;
|
2006-06-03 02:41:28 -04:00
|
|
|
|
|
|
|
: handle-action ( gadget constructor -- )
|
|
|
|
execute swap handle-gesture drop ; inline
|
|
|
|
|
2006-05-18 22:01:38 -04:00
|
|
|
GENERIC: with-button ( button# tuple -- tuple )
|
|
|
|
|
|
|
|
M: drag with-button drop <drag> ;
|
|
|
|
M: button-up with-button drop <button-up> ;
|
|
|
|
M: button-down with-button drop <button-down> ;
|
|
|
|
|
|
|
|
! Modifiers
|
|
|
|
SYMBOL: C+
|
|
|
|
SYMBOL: A+
|
|
|
|
SYMBOL: M+
|
|
|
|
SYMBOL: S+
|
|
|
|
|
|
|
|
TUPLE: key-down mods sym ;
|
|
|
|
TUPLE: key-up mods sym ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
! Hand state
|
|
|
|
|
|
|
|
! Note that these are only really useful inside an event
|
|
|
|
! handler, and that the locations hand-loc and hand-click-loc
|
|
|
|
! are in the co-ordinate system of the world which contains
|
|
|
|
! the gadget in question.
|
|
|
|
SYMBOL: hand-gadget
|
|
|
|
SYMBOL: hand-loc
|
2006-06-23 00:06:53 -04:00
|
|
|
{ 0 0 } hand-loc set-global
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
SYMBOL: hand-clicked
|
|
|
|
SYMBOL: hand-click-loc
|
|
|
|
|
|
|
|
SYMBOL: hand-buttons
|
|
|
|
V{ } clone hand-buttons set-global
|
|
|
|
|
2006-03-25 17:01:39 -05:00
|
|
|
: button-gesture ( button gesture -- )
|
2006-05-24 03:23:45 -04:00
|
|
|
#! Send a gesture like T{ button-down f 2 }; if nobody
|
2006-05-18 22:01:38 -04:00
|
|
|
#! handles it, send T{ button-down }.
|
|
|
|
hand-clicked get-global
|
|
|
|
3dup >r with-button r> handle-gesture
|
|
|
|
[ handle-gesture 2drop ] [ 3drop ] if ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: drag-gesture ( -- )
|
2006-05-24 03:23:45 -04:00
|
|
|
#! Send a gesture like T{ drag f 2 }; if nobody handles it,
|
2006-05-18 22:01:38 -04:00
|
|
|
#! send T{ drag }.
|
|
|
|
hand-buttons get-global first T{ drag } button-gesture ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: fire-motion ( -- )
|
|
|
|
#! Fire a motion gesture to the gadget underneath the hand,
|
|
|
|
#! and if a mouse button is down, fire a drag gesture to the
|
|
|
|
#! gadget that was clicked.
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ motion } hand-gadget get-global handle-gesture drop
|
2006-03-24 19:26:06 -05:00
|
|
|
hand-buttons get-global empty? [ drag-gesture ] unless ;
|
|
|
|
|
|
|
|
: each-gesture ( gesture seq -- )
|
|
|
|
[ handle-gesture* drop ] each-with ;
|
|
|
|
|
|
|
|
: hand-gestures ( new old -- )
|
2006-05-14 23:25:34 -04:00
|
|
|
drop-prefix <reversed>
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ mouse-leave } swap each-gesture
|
2006-03-24 19:26:06 -05:00
|
|
|
fire-motion
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ mouse-enter } swap each-gesture ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
2006-06-03 01:53:34 -04:00
|
|
|
: forget-rollover ( -- )
|
|
|
|
#! After we restore the UI, send mouse leave events to all
|
|
|
|
#! gadgets that were under the mouse at the time of the
|
|
|
|
#! save, since the mouse is in a different location now.
|
|
|
|
f hand-gadget [ get-global ] 2keep set-global
|
|
|
|
parents hand-gestures ;
|
|
|
|
|
2006-03-24 19:26:06 -05:00
|
|
|
: focus-gestures ( new old -- )
|
2006-05-14 23:25:34 -04:00
|
|
|
drop-prefix <reversed>
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ lose-focus } swap each-gesture
|
|
|
|
T{ gain-focus } swap each-gesture ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
2006-06-09 19:58:11 -04:00
|
|
|
: focus-receiver ( world -- seq )
|
|
|
|
#! If the world is not focused, we want focus-gestures to
|
|
|
|
#! only send focus-lost and not focus-gained.
|
|
|
|
dup world-focused? [ focused-ancestors ] [ drop f ] if ;
|
|
|
|
|
2006-03-24 19:26:06 -05:00
|
|
|
: request-focus* ( gadget world -- )
|
|
|
|
dup focused-ancestors >r
|
|
|
|
[ set-world-focus ] keep
|
2006-06-09 19:58:11 -04:00
|
|
|
focus-receiver r> focus-gestures ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: request-focus ( gadget -- )
|
|
|
|
dup focusable-child swap find-world request-focus* ;
|
|
|
|
|
|
|
|
: modifier ( mod modifiers -- seq )
|
|
|
|
[ second swap bitand 0 > ] subset-with
|
2006-05-18 22:01:38 -04:00
|
|
|
[ first ] map f like ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: drag-loc ( -- loc )
|
|
|
|
hand-loc get-global hand-click-loc get-global v- ;
|
|
|
|
|
2006-07-12 15:58:05 -04:00
|
|
|
: hand-rel ( gadget -- loc )
|
|
|
|
hand-loc get-global relative-loc ;
|
|
|
|
|
2006-03-24 19:26:06 -05:00
|
|
|
: hand-click-rel ( gadget -- loc )
|
|
|
|
hand-click-loc get-global relative-loc ;
|
|
|
|
|
|
|
|
: relevant-help ( seq -- help )
|
|
|
|
[ gadget-help ] map [ ] find nip ;
|
|
|
|
|
2006-06-27 03:26:52 -04:00
|
|
|
: show-message ( string/f world -- )
|
2006-03-24 19:26:06 -05:00
|
|
|
#! Show a message in the status bar.
|
2006-06-27 03:26:52 -04:00
|
|
|
world-status set-model ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: update-help ( -- )
|
|
|
|
#! Update mouse-over help message.
|
|
|
|
hand-gadget get-global parents [ relevant-help ] keep
|
|
|
|
dup empty? [ 2drop ] [ peek show-message ] if ;
|
|
|
|
|
|
|
|
: under-hand ( -- seq )
|
|
|
|
#! A sequence whose first element is the world and last is
|
|
|
|
#! the current gadget, with all parents in between.
|
2006-05-14 23:25:34 -04:00
|
|
|
hand-gadget get-global parents <reversed> ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: move-hand ( loc world -- )
|
|
|
|
under-hand >r over hand-loc set-global
|
|
|
|
pick-up hand-gadget set-global
|
|
|
|
under-hand r> hand-gestures update-help ;
|
|
|
|
|
|
|
|
: update-clicked ( loc world -- )
|
|
|
|
move-hand
|
|
|
|
hand-gadget get-global hand-clicked set-global
|
|
|
|
hand-loc get-global hand-click-loc set-global ;
|
|
|
|
|
|
|
|
: send-button-down ( button# loc world -- )
|
|
|
|
update-clicked
|
|
|
|
dup hand-buttons get-global push
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ button-down } button-gesture ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
2006-03-25 17:01:39 -05:00
|
|
|
: send-button-up ( button# loc world -- )
|
2006-03-24 19:26:06 -05:00
|
|
|
move-hand
|
2006-03-25 17:41:40 -05:00
|
|
|
dup hand-buttons get-global delete
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ button-up } button-gesture ;
|
2006-03-24 19:26:06 -05:00
|
|
|
|
|
|
|
: send-wheel ( up/down loc world -- )
|
|
|
|
move-hand
|
2006-05-18 22:01:38 -04:00
|
|
|
T{ wheel-up } T{ wheel-down } ?
|
2006-03-24 19:26:06 -05:00
|
|
|
hand-gadget get-global handle-gesture drop ;
|
2006-07-19 02:37:59 -04:00
|
|
|
|
|
|
|
: send-action ( world gesture -- ? )
|
|
|
|
swap world-focus handle-gesture ;
|
|
|
|
|
2006-07-19 17:00:57 -04:00
|
|
|
world H{
|
|
|
|
{ T{ key-down f { C+ } "x" } [ T{ cut-action } send-action ] }
|
|
|
|
{ T{ key-down f { C+ } "c" } [ T{ copy-action } send-action ] }
|
|
|
|
{ T{ key-down f { C+ } "v" } [ T{ paste-action } send-action ] }
|
|
|
|
{ T{ key-down f { C+ } "a" } [ T{ select-all-action } send-action ] }
|
|
|
|
} set-gestures
|