]> gitweb.factorcode.org Git - factor.git/blob - basis/ui/ui.factor
Fix conflict
[factor.git] / basis / ui / ui.factor
1 ! Copyright (C) 2006, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays assocs io kernel math models namespaces make dlists
4 deques sequences threads sequences words continuations init call
5 combinators hashtables concurrency.flags sets accessors calendar fry
6 destructors ui.gadgets ui.gadgets.private ui.gadgets.worlds
7 ui.gadgets.tracks ui.gestures ui.backend ui.render ui.text
8 ui.text.private ;
9 IN: ui
10
11 ! Assoc mapping aliens to gadgets
12 SYMBOL: windows
13
14 : window ( handle -- world ) windows get-global at ;
15
16 : window-focus ( handle -- gadget ) window world-focus ;
17
18 : register-window ( world handle -- )
19     #! Add the new window just below the topmost window. Why?
20     #! So that if the new window doesn't actually receive focus
21     #! (eg, we're using focus follows mouse and the mouse is not
22     #! in the new window when it appears) Factor doesn't get
23     #! confused and send workspace operations to the new window,
24     #! etc.
25     swap 2array windows get-global push
26     windows get-global dup length 1 >
27     [ [ length 1- dup 1- ] keep exchange ] [ drop ] if ;
28
29 : unregister-window ( handle -- )
30     windows global [ [ first = not ] with filter ] change-at ;
31
32 : raised-window ( world -- )
33     windows get-global
34     [ [ second eq? ] with find drop ] keep
35     [ nth ] [ delete-nth ] [ nip ] 2tri push ;
36
37 : focus-gestures ( new old -- )
38     drop-prefix <reversed>
39     lose-focus swap each-gesture
40     gain-focus swap each-gesture ;
41
42 : focus-world ( world -- )
43     t >>focused?
44     dup raised-window
45     focus-path f focus-gestures ;
46
47 : unfocus-world ( world -- )
48     f >>focused?
49     focus-path f swap focus-gestures ;
50
51 M: world graft*
52     [ (open-window) ]
53     [ [ title>> ] keep set-title ]
54     [ request-focus ] tri ;
55
56 : reset-world ( world -- )
57     #! This is used when a window is being closed, but also
58     #! when restoring saved worlds on image startup.
59     f >>handle unfocus-world ;
60
61 : (ungraft-world) ( world -- )
62     {
63         [ handle>> select-gl-context ]
64         [ text-handle>> dispose ]
65         [ images>> [ dispose ] when* ]
66         [ hand-clicked close-global ]
67         [ hand-gadget close-global ]
68     } cleave ;
69
70 M: world ungraft*
71     [ (ungraft-world) ]
72     [ handle>> (close-window) ]
73     [ reset-world ] tri ;
74
75 : find-window ( quot -- world )
76     windows get values
77     [ gadget-child swap call ] with find-last nip ; inline
78
79 : init-ui ( -- )
80     <dlist> \ graft-queue set-global
81     <dlist> \ layout-queue set-global
82     <dlist> \ gesture-queue set-global
83     V{ } clone windows set-global ;
84
85 : restore-gadget-later ( gadget -- )
86     dup graft-state>> {
87         { { f f } [ ] }
88         { { f t } [ ] }
89         { { t t } [ { f f } >>graft-state ] }
90         { { t f } [ dup unqueue-graft { f f } >>graft-state ] }
91     } case graft-later ;
92
93 : restore-gadget ( gadget -- )
94     dup restore-gadget-later
95     children>> [ restore-gadget ] each ;
96
97 : restore-world ( world -- )
98     [ reset-world ] [ init-text-rendering ] [ restore-gadget ] tri ;
99
100 : update-hand ( world -- )
101     dup hand-world get-global eq?
102     [ hand-loc get-global swap move-hand ] [ drop ] if ;
103
104 : layout-queued ( -- seq )
105     [
106         in-layout? on
107         layout-queue [
108             dup layout find-world [ , ] when*
109         ] slurp-deque
110     ] { } make prune ;
111
112 : redraw-worlds ( seq -- )
113     [ dup update-hand draw-world ] each ;
114
115 : send-queued-gestures ( -- )
116     gesture-queue [ send-queued-gesture notify-queued ] slurp-deque ;
117
118 : update-ui ( -- )
119     [
120         notify-queued
121         layout-queued
122         redraw-worlds
123         send-queued-gestures
124     ] [ ui-error ] recover ;
125
126 SYMBOL: ui-thread
127
128 : ui-running ( quot -- )
129     t \ ui-running set-global
130     [ f \ ui-running set-global ] [ ] cleanup ; inline
131
132 : ui-running? ( -- ? )
133     \ ui-running get-global ;
134
135 : update-ui-loop ( -- )
136     [ ui-running? ui-thread get-global self eq? and ]
137     [ ui-notify-flag get lower-flag update-ui ]
138     [ ] while ;
139
140 : start-ui-thread ( -- )
141     [ self ui-thread set-global update-ui-loop ]
142     "UI update" spawn drop ;
143
144 : open-world-window ( world -- )
145     dup pref-dim >>dim dup relayout graft ;
146
147 : open-window ( gadget title -- )
148     f <world> open-world-window ;
149
150 : set-fullscreen? ( ? gadget -- )
151     find-world set-fullscreen* ;
152
153 : fullscreen? ( gadget -- ? )
154     find-world fullscreen* ;
155
156 : raise-window ( gadget -- )
157     find-world raise-window* ;
158
159 HOOK: close-window ui-backend ( gadget -- )
160
161 M: object close-window
162     find-world [ ungraft ] when* ;
163
164 : start-ui ( quot -- )
165     call notify-ui-thread start-ui-thread ;
166
167 [
168     f \ ui-running set-global
169     <flag> ui-notify-flag set-global
170 ] "ui" add-init-hook
171
172 HOOK: (with-ui) ui-backend ( quot -- )
173
174 : restore-windows ( -- )
175     [
176         windows get [ values ] [ delete-all ] bi
177         [ restore-world ] each
178         forget-rollover
179     ] (with-ui) ;
180
181 : restore-windows? ( -- ? )
182     windows get empty? not ;
183
184 : with-ui ( quot -- )
185     ui-running? [ call ] [ '[ init-ui @ ] (with-ui) ] if ;
186
187 HOOK: beep ui-backend ( -- )