]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/menu/item/container.c
merge trunk
[divverent/nexuiz.git] / data / qcsrc / menu / item / container.c
1 #ifdef INTERFACE
2 CLASS(Container) EXTENDS(Item)
3         METHOD(Container, draw, void(entity))
4         METHOD(Container, keyUp, float(entity, float, float, float))
5         METHOD(Container, keyDown, float(entity, float, float, float))
6         METHOD(Container, mouseMove, float(entity, vector))
7         METHOD(Container, mousePress, float(entity, vector))
8         METHOD(Container, mouseDrag, float(entity, vector))
9         METHOD(Container, mouseRelease, float(entity, vector))
10         METHOD(Container, focusLeave, void(entity))
11         METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector))
12         METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector))
13         METHOD(Container, addItem, void(entity, entity, vector, vector, float))
14         METHOD(Container, addItemCentered, void(entity, entity, vector, float))
15         METHOD(Container, moveItemAfter, void(entity, entity, entity))
16         METHOD(Container, removeItem, void(entity, entity))
17         METHOD(Container, setFocus, void(entity, entity))
18         METHOD(Container, setAlphaOf, void(entity, entity, float))
19         METHOD(Container, itemFromPoint, entity(entity, vector))
20         METHOD(Container, showNotify, void(entity))
21         METHOD(Container, hideNotify, void(entity))
22         ATTRIB(Container, focusable, float, 0)
23         ATTRIB(Container, firstChild, entity, NULL)
24         ATTRIB(Container, lastChild, entity, NULL)
25         ATTRIB(Container, focusedChild, entity, NULL)
26         ATTRIB(Container, shown, float, 0)
27 ENDCLASS(Container)
28 .entity nextSibling;
29 .entity prevSibling;
30 .float resized;
31 .vector Container_origin;
32 .vector Container_size;
33 .float Container_alpha;
34 #endif
35
36 #ifdef IMPLEMENTATION
37 void showNotifyContainer(entity me)
38 {
39         entity e;
40         if(me.shown)
41                 return;
42         me.shown = 1;
43         for(e = me.firstChild; e; e = e.nextSibling)
44                 if(e.Container_alpha > 0)
45                         e.showNotify(e);
46 }
47
48 void hideNotifyContainer(entity me)
49 {
50         entity e;
51         if not(me.shown)
52                 return;
53         me.shown = 0;
54         for(e = me.firstChild; e; e = e.nextSibling)
55                 if(e.Container_alpha > 0)
56                         e.hideNotify(e);
57 }
58
59 void setAlphaOfContainer(entity me, entity other, float theAlpha)
60 {
61         if(theAlpha <= 0)
62         {
63                 if(other.Container_alpha > 0)
64                         other.hideNotify(other);
65         }
66         else // value > 0
67         {
68                 if(other.Container_alpha <= 0)
69                         other.showNotify(other);
70         }
71         other.Container_alpha = theAlpha;
72 }
73
74 void resizeNotifyLieContainer(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize, .vector originField, .vector sizeField)
75 {
76         entity e;
77         vector o, s;
78         float d;
79         for(e = me.firstChild; e; e = e.nextSibling)
80         {
81                 o = e.originField;
82                 s = e.sizeField;
83                 e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
84         }
85         do
86         {
87                 d = 0;
88                 for(e = me.firstChild; e; e = e.nextSibling)
89                         if(e.resized)
90                         {
91                                 e.resized = 0;
92                                 d = 1;
93                                 o = e.originField;
94                                 s = e.sizeField;
95                                 e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
96                         }
97         }
98         while(d);
99         resizeNotifyItem(me, relOrigin, relSize, absOrigin, absSize);
100 }
101
102 void resizeNotifyContainer(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
103 {
104         me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, Container_origin, Container_size);
105 }
106
107 entity itemFromPointContainer(entity me, vector pos)
108 {
109         entity e;
110         vector o, s;
111         for(e = me.lastChild; e; e = e.prevSibling)
112         {
113                 o = e.Container_origin;
114                 s = e.Container_size;
115                 if(pos_x < o_x) continue;
116                 if(pos_y < o_y) continue;
117                 if(pos_x >= o_x + s_x) continue;
118                 if(pos_y >= o_y + s_y) continue;
119                 return e;
120         }
121         return NULL;
122 }
123
124 void drawContainer(entity me)
125 {
126         vector oldshift;
127         vector oldscale;
128         float oldalpha;
129         entity e;
130
131         oldshift = draw_shift;
132         oldscale = draw_scale;
133         oldalpha = draw_alpha;
134         me.focusable = 0;
135         for(e = me.firstChild; e; e = e.nextSibling)
136         {
137                 if(e.focusable)
138                         me.focusable += 1;
139                 if(e.Container_alpha < 0.003) // can't change color values anyway
140                         continue;
141                 draw_shift = boxToGlobal(e.Container_origin, oldshift, oldscale);
142                 draw_scale = boxToGlobalSize(e.Container_size, oldscale);
143                 draw_alpha *= e.Container_alpha;
144                 e.draw(e);
145                 draw_shift = oldshift;
146                 draw_scale = oldscale;
147                 draw_alpha = oldalpha;
148         }
149 };
150
151 void focusLeaveContainer(entity me)
152 {
153         me.setFocus(me, NULL);
154 }
155
156 float keyUpContainer(entity me, float scan, float ascii, float shift)
157 {
158         entity f;
159         f = me.focusedChild;
160         if(f)
161                 return f.keyUp(f, scan, ascii, shift);
162         return 0;
163 }
164
165 float keyDownContainer(entity me, float scan, float ascii, float shift)
166 {
167         entity f;
168         f = me.focusedChild;
169         if(f)
170                 return f.keyDown(f, scan, ascii, shift);
171         return 0;
172 }
173
174 float mouseMoveContainer(entity me, vector pos)
175 {
176         entity f;
177         f = me.focusedChild;
178         if(f)
179                 return f.mouseMove(f, globalToBox(pos, f.Container_origin, f.Container_size));
180         return 0;
181 }
182 float mousePressContainer(entity me, vector pos)
183 {
184         entity f;
185         f = me.focusedChild;
186         if(f)
187                 return f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size));
188         return 0;
189 }
190 float mouseDragContainer(entity me, vector pos)
191 {
192         entity f;
193         f = me.focusedChild;
194         if(f)
195                 return f.mouseDrag(f, globalToBox(pos, f.Container_origin, f.Container_size));
196         return 0;
197 }
198 float mouseReleaseContainer(entity me, vector pos)
199 {
200         entity f;
201         f = me.focusedChild;
202         if(f)
203                 return f.mouseRelease(f, globalToBox(pos, f.Container_origin, f.Container_size));
204         return 0;
205 }
206
207 void addItemCenteredContainer(entity me, entity other, vector theSize, float theAlpha)
208 {
209         me.addItem(me, other, '0.5 0.5 0' - 0.5 * theSize, theSize, theAlpha);
210 }
211
212 void addItemContainer(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
213 {
214         if(other.parent)
215                 error("Can't add already added item!");
216
217         if(other.focusable)
218                 me.focusable += 1;
219
220         if(theSize_x > 1)
221         {
222                 theOrigin_x -= 0.5 * (theSize_x - 1);
223                 theSize_x = 1;
224         }
225         if(theSize_y > 1)
226         {
227                 theOrigin_y -= 0.5 * (theSize_y - 1);
228                 theSize_y = 1;
229         }
230         theOrigin_x = bound(0, theOrigin_x, 1 - theSize_x);
231         theOrigin_y = bound(0, theOrigin_y, 1 - theSize_y);
232
233         other.parent = me;
234         other.Container_origin = theOrigin;
235         other.Container_size = theSize;
236         me.setAlphaOf(me, other, theAlpha);
237
238         entity f, l;
239         f = me.firstChild;
240         l = me.lastChild;
241
242         if(l)
243                 l.nextSibling = other;
244         else
245                 me.firstChild = other;
246
247         other.prevSibling = l;
248         other.nextSibling = NULL;
249         me.lastChild = other;
250
251         draw_NeedResizeNotify = 1;
252 }
253
254 void removeItemContainer(entity me, entity other)
255 {
256         if(other.parent != me)
257                 error("Can't remove from wrong container!");
258
259         if(other.focusable)
260                 me.focusable -= 1;
261
262         other.parent = NULL;
263
264         entity n, p, f, l;
265         f = me.firstChild;
266         l = me.lastChild;
267         n = other.nextSibling;
268         p = other.prevSibling;
269
270         if(p)
271                 p.nextSibling = n;
272         else
273                 me.firstChild = n;
274
275         if(n)
276                 n.prevSibling = p;
277         else
278                 me.lastChild = p;
279 }
280
281 void setFocusContainer(entity me, entity other)
282 {
283         if(other)
284                 if not(me.focused)
285                         error("Trying to set focus in a non-focused control!");
286         if(me.focusedChild == other)
287                 return;
288         //print(etos(me), ": focus changes from ", etos(me.focusedChild), " to ", etos(other), "\n");
289         if(me.focusedChild)
290         {
291                 me.focusedChild.focused = 0;
292                 me.focusedChild.focusLeave(me.focusedChild);
293         }
294         if(other)
295         {
296                 other.focused = 1;
297                 other.focusEnter(other);
298         }
299         me.focusedChild = other;
300 }
301
302 void moveItemAfterContainer(entity me, entity other, entity dest)
303 {
304         // first: remove other from the chain
305         entity n, p, f, l;
306
307         if(other.parent != me)
308                 error("Can't move in wrong container!");
309
310         f = me.firstChild;
311         l = me.lastChild;
312         n = other.nextSibling;
313         p = other.prevSibling;
314
315         if(p)
316                 p.nextSibling = n;
317         else
318                 me.firstChild = n;
319
320         if(n)
321                 n.prevSibling = p;
322         else
323                 me.lastChild = p;
324         
325         // now other got removed. Insert it behind dest now.
326         other.prevSibling = dest;
327         if(dest)
328                 other.nextSibling = dest.nextSibling;
329         else
330                 other.nextSibling = me.firstChild;
331
332         if(dest)
333                 dest.nextSibling = other;
334         else
335                 me.firstChild = other;
336
337         if(other.nextSibling)
338                 other.nextSibling.prevSibling = other;
339         else
340                 me.lastChild = other;
341 }
342 #endif