]> 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     {
99         [ reset-world ]
100         [ init-text-rendering ]
101         [ f >>images drop ]
102         [ restore-gadget ]
103     } cleave ;
104
105 : update-hand ( world -- )
106     dup hand-world get-global eq?
107     [ hand-loc get-global swap move-hand ] [ drop ] if ;
108
109 : layout-queued ( -- seq )
110     [
111         in-layout? on
112         layout-queue [
113             dup layout find-world [ , ] when*
114         ] slurp-deque
115     ] { } make prune ;
116
117 : redraw-worlds ( seq -- )
118     [ dup update-hand draw-world ] each ;
119
120 : send-queued-gestures ( -- )
121     gesture-queue [ send-queued-gesture notify-queued ] slurp-deque ;
122
123 : update-ui ( -- )
124     [
125         notify-queued
126         layout-queued
127         redraw-worlds
128         send-queued-gestures
129     ] [ ui-error ] recover ;
130
131 SYMBOL: ui-thread
132
133 : ui-running ( quot -- )
134     t \ ui-running set-global
135     [ f \ ui-running set-global ] [ ] cleanup ; inline
136
137 : ui-running? ( -- ? )
138     \ ui-running get-global ;
139
140 : update-ui-loop ( -- )
141     [ ui-running? ui-thread get-global self eq? and ]
142     [ ui-notify-flag get lower-flag update-ui ]
143     [ ] while ;
144
145 : start-ui-thread ( -- )
146     [ self ui-thread set-global update-ui-loop ]
147     "UI update" spawn drop ;
148
149 : open-world-window ( world -- )
150     dup pref-dim >>dim dup relayout graft ;
151
152 : open-window ( gadget title -- )
153     f <world> open-world-window ;
154
155 : set-fullscreen? ( ? gadget -- )
156     find-world set-fullscreen* ;
157
158 : fullscreen? ( gadget -- ? )
159     find-world fullscreen* ;
160
161 : raise-window ( gadget -- )
162     find-world raise-window* ;
163
164 HOOK: close-window ui-backend ( gadget -- )
165
166 M: object close-window
167     find-world [ ungraft ] when* ;
168
169 : start-ui ( quot -- )
170     call notify-ui-thread start-ui-thread ;
171
172 [
173     f \ ui-running set-global
174     <flag> ui-notify-flag set-global
175 ] "ui" add-init-hook
176
177 HOOK: (with-ui) ui-backend ( quot -- )
178
179 : restore-windows ( -- )
180     [
181         windows get [ values ] [ delete-all ] bi
182         [ restore-world ] each
183         forget-rollover
184     ] (with-ui) ;
185
186 : restore-windows? ( -- ? )
187     windows get empty? not ;
188
189 : with-ui ( quot -- )
190     ui-running? [ call ] [ '[ init-ui @ ] (with-ui) ] if ;
191
192 HOOK: beep ui-backend ( -- )