tree_node.anubis
6.71 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
250
251
252
253
254
255
256
257
258
259
260
261
The Anubis Project.
A Widget System (4th version).
The 'tree node' widget.
Copyright (c) Alain Proute' 2005.
Authors: Alain Proute'
read tools/basis.anubis
read widget.anubis
A 'tree node' is made of a main widget and a list of widgets, which are displayed in
one of the following two ways:
folded: unfolded:
+ main_widget - main_widget
widget_1
widget_2
...
widget_n
public type WidgetFolded:
folded,
unfolded.
When the user clicks on the '+' he unfolds the tree node. When he clicks on the '-' he
folds the tree node.
public define Widget
tree_node
(
Widget main,
List(Widget) items,
Int32 down, // moves '+' and '-' that number of pixels down
WidgetFolded folded // starts either folded or unfolded
).
--- That's all for the public part ! --------------------------------------------------
read tools.anubis
define Int32 mw = 6.
*** [] Computing the size of the tree node.
define (Int32,Int32)
stack_size
(
List(Widget) l
) =
if l is
{
[ ] then (0,0),
[h . t] then
if size(h) is (w,h) then
if stack_size(t) is (iw,ih) then
(max(w,iw),h+ih)
}.
define One -> (Int32,Int32)
size
(
Var(Bool) folded_v,
Widget main,
List(Widget) items,
Int32 down
) =
with mw2 = mw+mw, mw4 = mw2+mw2,
(One u) |-> if *folded_v is
{
false then
if size(main) is (w,h) then
if stack_size(items) is (iw,ih) then
(max(mw2 + w, mw4 + iw), h + ih),
true then
if size(main) is (w,h) then
(mw2 + w, max(mw2,h))
}.
*** [] The draw method.
define One
draw_items
(
WidgetDrawToolBox dtb,
List(Widget) items,
Int32 h,
Int32 down,
Int32 mw,
Int32 mw4
) =
if items is
{
[ ] then unique,
[item_1 . others] then
if size(item_1) is (_,h1) then
draw(dtb)(rect(mw,h,mw+1,h+(if others is [] then mw+down else h1)),rgb(0,0,0));
draw(dtb)(rect(mw,h+mw+down,mw4+1,h+mw+down+1),rgb(0,0,0));
draw(dtb)(item_1,mw4,h);
draw_items(dtb,others,h+h1,down,mw,mw4)
}.
define WidgetDrawToolBox -> One
draw_method
(
Var(Bool) folded_v,
Widget main,
List(Widget) items,
Int32 down
) =
with black = rgb(0,0,0), mw2 = mw+mw, mw4 = mw2+mw2,
(WidgetDrawToolBox dtb) |->
draw_relief_edge(dtb,1,rect(1,1+down,mw2-1,mw2-1+down),black,black); // draw the small square
draw(dtb)(main,mw2,0);
if items is
{
[ ] then unique,
[_._] then
draw(dtb)(rect(3,mw-1+down,mw2-3,mw+1+down),black); // draw the '-' sign
(if *folded_v then draw(dtb)(rect(mw-1,3+down,mw+1,mw2-3+down),black) else unique); // '+' sign
(if *folded_v then unique else
if size(main) is (_,h) then
draw(dtb)(rect(mw,mw2-1+down,mw+1,h),rgb(0,0,0)); // start of line down
draw_items(dtb,items,h,down,mw,mw4)) // items
}.
*** [] The event handler.
define WidgetAnswer
merge_answers
(
WidgetAnswer a1,
WidgetAnswer a2
) =
if a1 is
{
not_handled(area1) then if a2 is
{
not_handled(area2) then not_handled(area1+area2),
handled(area2) then handled(area1+area2),
resized then resized,
ignored then a1
want_to_capture_mouse(_,_,_) then a2,
want_to_capture_keyboard(_,_) then a2
},
handled(area1) then if a2 is
{
not_handled(area2) then handled(area1+area2),
handled(area2) then handled(area1+area2),
resized then resized,
ignored then a1,
want_to_capture_mouse(_,_,_) then a2,
want_to_capture_keyboard(_,_) then a2
},
resized then resized,
ignored then a2,
want_to_capture_mouse(v,cf,area) then a1,
want_to_capture_keyboard(v,area) then a1,
}.
define WidgetAnswer
transmit
(
WidgetEventToolBox etb,
List(Widget) items,
Int32 h,
WidgetEvent e,
Int32 mw4
) =
if items is
{
[ ] then ignored,
[first . others] then
if size(first) is (_,h1) then
merge_answers(transmit(etb)(first,mw4,h,e),
transmit(etb,others,h+h1,e,mw4))
}.
define (WidgetEventToolBox,WidgetEvent) -> WidgetAnswer
event_handler
(
Var(Bool) folded_v,
Widget main,
List(Widget) items,
Int32 down
) =
with mw2 = mw+mw, mw4 = mw2+mw2,
(WidgetEventToolBox etb, WidgetEvent e) |->
if size(main) is (w,h) then
if e is mouse_click(ks,mc,x,y)
then
(
if (down =< x & x =< mw2+down & down =< y & y =< mw2+down & mc = left_down)
then
(
folded_v <- (if *folded_v then false else true);
resized
)
else
merge_answers(transmit(etb)(main,mw2,0,e),
transmit(etb,items,h,e,mw4))
)
else
(
merge_answers(transmit(etb)(main,mw2,0,e),
transmit(etb,items,h,e,mw4))
).
*** [] Creating the tree node.
public define Widget
tree_node
(
Widget main,
List(Widget) items,
Int32 down,
WidgetFolded fld
) =
with folded_v = var((Bool)fld=folded),
create_widget
(
size(folded_v,main,items,down),
draw_method(folded_v,main,items,down),
event_handler(folded_v,main,items,down),
(One u) |-> []
).