simple_window.anubis
8.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
The Anubis/Paradize Project.
The simple window widget.
Copyright (c) Alain Prouté 2004-2005.
Authors: Alain Prouté
Olivier Duvernois
read tools/basis.anubis
read widget.anubis
This file defines simple 'nude' windows. If you need more sophisticated windows (with
boundary and/or scrollbars) see 'widgets3/window.anubis'.
A 'simple window' is a rectangular area which is able to show part of another widget
(its 'content') through itself:
+...........................+
: content :
: :
: :
: :
: +-------------+ :
: | window | :
: | | :
: | | :
: | | :
: | | :
: | | :
: +-------------+ :
: :
: :
+...........................+
The window has a position relative to its content. This position should not be confused
with the position of the window relative to its parent widget or relative to the host
window. Also a window may change its size.
The size of a window must eventually be coordinated with the size of another window. It
may be changed from outside the window, the position of the content may also be changed
or read from outside the window, for example by scrollbars. For these reasons, these
dimensions are stored in variables which must be provided at the creation.
A simple window widget is created by:
public define Widget
create_simple_window
(
Var(Int32) win_w, // width of window
Var(Int32) win_h, // height of window
Var(Int32) window_x_scroll, // position of window relative to its content
Var(Int32) window_y_scroll,
Widget content,
).
--- That's all for the public part ! --------------------------------------------------
If (cont_w,cont_h) is the size of the content, and (win_w,win_h) the size of the
window, we must always have:
0 =< window_x_scroll =< sup(0,cont_w - win_w)
0 =< window_y_scroll =< sup(0,cont_h - win_h)
In other words, 'window_x_scroll' is 0 when the window is wider than its content.
The window widget handles events as follows.
- keyboard event: do nothing,
- mouse move event:
- if mouse captured: change values of 'window_x_scroll' and 'window_y_scroll'
- otherwise: transmit to content,
- mouse click event:
- left down: if content does not handle, capture the mouse
- left up: if mouse captured, uncapture the mouse, otherwise transmit to content
- other: transmit to content
*** Managing window event
The function 'do_when_moved' is called at each mouse event when the mouse is captured
by the window.
define WidgetAnswer
do_when_moved
(
KeyboardState ks,
WidgetMouseCapturedEvent e,
Widget content,
Var(Int32) win_w,
Var(Int32) win_h,
Var(Int32) window_x_scroll,
Var(Int32) window_y_scroll,
Var((Int32,Int32)) move_ref
) =
if get_size(content)(unique) is (cont_w,cont_h) then
with xe = x(e), ye = y(e),
if *move_ref is (mrx,mry) then
window_x_scroll <- max(0,min(*window_x_scroll -xe+mrx,cont_w-*win_w));
window_y_scroll <- max(0,min(*window_y_scroll -ye+mry,cont_h-*win_h));
move_ref <- (xe,ye);
handled([rect(0,0,*win_w,*win_h)]).
if e is
{
moved(x,y) then
if *move_ref is (mrx,mry) then
window_x_scroll <- max(0,min(*window_x_scroll -x+mrx,cont_w-win_w));
window_y_scroll <- max(0,min(*window_y_scroll -y+mry,cont_h-win_h));
move_ref <- (x,y);
forget((WidgetPositionToolBox ptb) |->
set_position(content)(ptb,position(*window_x_scroll,*window_y_scroll)));
handled([rect(0,0,*win_w,*win_h)]),
liberated(x,y) then
if *move_ref is (mrx,mry) then
window_x_scroll <- max(0,min(*window_x_scroll -x+mrx,cont_w-win_w));
window_y_scroll <- max(0,min(*window_y_scroll -y+mry,cont_h-win_h));
move_ref <- (x,y);
forget((WidgetPositionToolBox ptb) |->
set_position(content)(ptb,position(*window_x_scroll,*window_y_scroll)));
handled([rect(0,0,*win_w,*win_h)]),
}.
define WidgetAnswer
manage_window_event
(
WidgetEventToolBox etb,
WidgetNormalEvent e,
Widget content,
Var(Int32) win_w,
Var(Int32) win_h,
Var(Int32) window_x_scroll,
Var(Int32) window_y_scroll,
Var((Int32,Int32)) move_ref
) =
if e is
{
mouse_gone then not_handled([]),
mouse_move(ks, x, y) then not_handled([]),
mouse_click(ks, mc, x, y) then
if mc is
{
left_down then
(move_ref <- (x,y));
forget(
capture_mouse
(etb,
(KeyboardState ks1, WidgetMouseCapturedEvent e1) |->
do_when_moved(ks1,e1,content,
win_w,win_h,
window_x_scroll,window_y_scroll,
move_ref)));
resized,
left_up then not_handled([]),
middle_down then not_handled([]),
middle_up then not_handled([]),
right_down then not_handled([]),
right_up then not_handled([]),
}
}.
*** Create Window
public define Widget
create_simple_window
(
Var(Int32) win_w, // width of window
Var(Int32) win_h, // height of window
Var(Int32) window_x_scroll, // position window relative to its content
Var(Int32) window_y_scroll,
Widget content,
) =
with move_ref = var(((Int32,Int32)) (0,0)),
monitor = (WidgetMonitoringToolBox mtb,
List(WidgetRectangle) -> One redraw) |->
redraw([rect(0,0,*win_w,*win_h)]),
create_widget
(
/* Set positions of childs */
(WidgetPositionToolBox ptb) |->
set_position(content)(ptb,position(-(*window_x_scroll),-(*window_y_scroll))),
/* Get size */
(One u) |-> (*win_w, *win_h),
/* Redraw the window */
(WidgetDrawToolBox dtb) |->
redraw(content)(dtb,rect(0,0,*win_w,*win_h)),
/* Duplicate */
(One u) |-> create_simple_window(win_w,win_h,window_x_scroll,window_y_scroll,
duplicate(content)(unique)),
/* Change size */
(Int32 w, Int32 h) |->
win_w <- max(10,w);
win_h <- max(10,h),
/* Handle normal events */
(WidgetEventToolBox etb, WidgetNormalEvent e) |->
if main_event_handler(content)(etb,e) is
{
not_handled(l) then join(not_handled(l), manage_window_event
(etb,
e,
content,
win_w,win_h,
window_x_scroll,window_y_scroll,
move_ref)),
handled(lwr) then handled(lwr),
resized then handled([rect(0,0,*win_w,*win_h)])
},
/* Register variables to monitor */
(List(WidgetRegistration))
[
register(win_w,monitor),
register(win_h,monitor),
register(window_x_scroll,monitor),
register(window_y_scroll,monitor),
]
).