factor/basis/ui/ui.factor

200 lines
5.2 KiB
Factor
Raw Normal View History

! Copyright (C) 2006, 2009 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: arrays assocs io kernel math models namespaces make
dlists deques sequences threads sequences words continuations
init combinators hashtables concurrency.flags sets accessors
calendar fry ui.gadgets ui.gadgets.worlds ui.gadgets.tracks
ui.gestures ui.backend ui.render ui.text ui.text.private ;
2007-09-20 18:09:08 -04:00
IN: ui
! Assoc mapping aliens to gadgets
SYMBOL: windows
: window ( handle -- world ) windows get-global at ;
: window-focus ( handle -- gadget ) window world-focus ;
: register-window ( world handle -- )
#! Add the new window just below the topmost window. Why?
#! So that if the new window doesn't actually receive focus
#! (eg, we're using focus follows mouse and the mouse is not
#! in the new window when it appears) Factor doesn't get
#! confused and send workspace operations to the new window,
#! etc.
swap 2array windows get-global push
windows get-global dup length 1 >
[ [ length 1- dup 1- ] keep exchange ] [ drop ] if ;
: unregister-window ( handle -- )
windows global [ [ first = not ] with filter ] change-at ;
2007-09-20 18:09:08 -04:00
: raised-window ( world -- )
2008-05-06 10:16:48 -04:00
windows get-global
[ [ second eq? ] with find drop ] keep
[ nth ] [ delete-nth ] [ nip ] 2tri push ;
2007-09-20 18:09:08 -04:00
2007-11-22 01:40:17 -05:00
: focus-gestures ( new old -- )
drop-prefix <reversed>
T{ lose-focus } swap each-gesture
T{ gain-focus } swap each-gesture ;
2007-09-20 18:09:08 -04:00
: focus-world ( world -- )
t >>focused?
2007-09-20 18:09:08 -04:00
dup raised-window
focus-path f focus-gestures ;
: unfocus-world ( world -- )
f >>focused?
2007-09-20 18:09:08 -04:00
focus-path f swap focus-gestures ;
2007-11-22 01:40:17 -05:00
M: world graft*
[ (open-window) ]
[ [ title>> ] keep set-title ]
[ request-focus ] tri ;
2007-11-22 01:40:17 -05:00
2007-09-20 18:09:08 -04:00
: reset-world ( world -- )
2007-11-22 01:40:17 -05:00
#! This is used when a window is being closed, but also
#! when restoring saved worlds on image startup.
[ fonts>> clear-assoc ]
[ unfocus-world ]
[ f >>handle drop ] tri ;
: (ungraft-world) ( world -- )
{
[ handle>> select-gl-context ]
[ fonts>> free-fonts ]
[ hand-clicked close-global ]
[ hand-gadget close-global ]
} cleave ;
2007-09-20 18:09:08 -04:00
2007-11-22 01:40:17 -05:00
M: world ungraft*
[ (ungraft-world) ]
[ handle>> (close-window) ]
[ reset-world ] tri ;
2007-09-20 18:09:08 -04:00
: find-window ( quot -- world )
2007-11-16 01:19:13 -05:00
windows get values
2008-01-09 17:36:30 -05:00
[ gadget-child swap call ] with find-last nip ; inline
2007-09-20 18:09:08 -04:00
2007-11-22 01:40:17 -05:00
: init-ui ( -- )
<dlist> \ graft-queue set-global
<dlist> \ layout-queue set-global
<dlist> \ gesture-queue set-global
2007-11-22 01:40:17 -05:00
V{ } clone windows set-global ;
: restore-gadget-later ( gadget -- )
2008-08-29 19:44:19 -04:00
dup graft-state>> {
2007-11-22 01:40:17 -05:00
{ { f f } [ ] }
{ { f t } [ ] }
{ { t t } [ { f f } >>graft-state ] }
{ { t f } [ dup unqueue-graft { f f } >>graft-state ] }
2007-11-22 01:40:17 -05:00
} case graft-later ;
: restore-gadget ( gadget -- )
dup restore-gadget-later
2008-08-29 19:44:19 -04:00
children>> [ restore-gadget ] each ;
2007-11-22 01:40:17 -05:00
: restore-world ( world -- )
dup reset-world restore-gadget ;
2007-09-20 18:09:08 -04:00
: update-hand ( world -- )
dup hand-world get-global eq?
[ hand-loc get-global swap move-hand ] [ drop ] if ;
: layout-queued ( -- seq )
[
2007-11-16 01:19:13 -05:00
in-layout? on
layout-queue [
dup layout find-world [ , ] when*
2008-08-19 15:06:20 -04:00
] slurp-deque
2007-11-24 23:57:37 -05:00
] { } make prune ;
2007-09-20 18:09:08 -04:00
: redraw-worlds ( seq -- )
2007-11-23 17:23:53 -05:00
[ dup update-hand draw-world ] each ;
2007-09-20 18:09:08 -04:00
2007-11-16 01:19:13 -05:00
: notify ( gadget -- )
2008-08-29 19:44:19 -04:00
dup graft-state>>
2008-11-20 19:11:25 -05:00
[ first { f f } { t t } ? >>graft-state ] keep
{
{ { f t } [ dup activate-control graft* ] }
2008-01-29 03:04:14 -05:00
{ { t f } [ dup deactivate-control ungraft* ] }
} case ;
2007-11-16 01:19:13 -05:00
: notify-queued ( -- )
2008-08-19 15:06:20 -04:00
graft-queue [ notify ] slurp-deque ;
2007-11-16 01:19:13 -05:00
: send-queued-gestures ( -- )
gesture-queue [ send-queued-gesture notify-queued ] slurp-deque ;
2008-02-25 17:48:11 -05:00
: update-ui ( -- )
[
[
notify-queued
layout-queued
redraw-worlds
send-queued-gestures
] assert-depth
] [ ui-error ] recover ;
2007-09-20 18:09:08 -04:00
2008-02-25 20:37:43 -05:00
SYMBOL: ui-thread
2008-02-25 17:48:11 -05:00
: ui-running ( quot -- )
t \ ui-running set-global
[ f \ ui-running set-global ] [ ] cleanup ; inline
2008-02-25 20:37:43 -05:00
: ui-running? ( -- ? )
\ ui-running get-global ;
2008-02-25 17:48:11 -05:00
: update-ui-loop ( -- )
[ ui-running? ui-thread get-global self eq? and ]
[ ui-notify-flag get lower-flag update-ui ]
[ ] while ;
2008-02-25 17:48:11 -05:00
: start-ui-thread ( -- )
2008-02-25 20:37:43 -05:00
[ self ui-thread set-global update-ui-loop ]
"UI update" spawn drop ;
2008-02-25 17:48:11 -05:00
: open-world-window ( world -- )
dup pref-dim >>dim dup relayout graft ;
: open-window ( gadget title -- )
f <world> open-world-window ;
: set-fullscreen? ( ? gadget -- )
find-world set-fullscreen* ;
: fullscreen? ( gadget -- ? )
find-world fullscreen* ;
2008-02-21 00:13:31 -05:00
: raise-window ( gadget -- )
find-world raise-window* ;
HOOK: close-window ui-backend ( gadget -- )
M: object close-window
find-world [ ungraft ] when* ;
: start-ui ( quot -- )
call notify-ui-thread start-ui-thread ;
2007-09-20 18:09:08 -04:00
2008-02-25 20:37:43 -05:00
[
f \ ui-running set-global
<flag> ui-notify-flag set-global
] "ui" add-init-hook
2007-09-20 18:09:08 -04:00
HOOK: (with-ui) ui-backend ( quot -- )
2007-09-20 18:09:08 -04:00
: restore-windows ( -- )
[
windows get [ values ] [ delete-all ] bi
[ restore-world ] each
forget-rollover
] (with-ui) ;
: restore-windows? ( -- ? )
windows get empty? not ;
2007-09-20 18:09:08 -04:00
: with-ui ( quot -- )
ui-running? [ call ] [ '[ init-ui @ ] (with-ui) ] if ;
HOOK: beep ui-backend ( -- )