1 #include "container.qh"
2 #ifndef ITEM_CONTAINER_H
3 #define ITEM_CONTAINER_H
6 METHOD(Container, draw, void(entity));
7 METHOD(Container, keyUp, float(entity, float, float, float));
8 METHOD(Container, keyDown, float(entity, float, float, float));
9 METHOD(Container, mouseMove, float(entity, vector));
10 METHOD(Container, mousePress, float(entity, vector));
11 METHOD(Container, mouseDrag, float(entity, vector));
12 METHOD(Container, mouseRelease, float(entity, vector));
13 METHOD(Container, focusLeave, void(entity));
14 METHOD(Container, resizeNotify, void(entity, vector, vector, vector, vector));
15 METHOD(Container, resizeNotifyLie, void(entity, vector, vector, vector, vector, .vector, .vector, .vector));
16 METHOD(Container, addItem, void(entity, entity, vector, vector, float));
17 METHOD(Container, addItemCentered, void(entity, entity, vector, float));
18 METHOD(Container, addItemRightCentered, void(entity, entity, vector, float));
19 METHOD(Container, moveItemAfter, void(entity, entity, entity));
20 METHOD(Container, removeItem, void(entity, entity));
21 METHOD(Container, setFocus, void(entity, entity));
22 METHOD(Container, saveFocus, void(entity));
23 METHOD(Container, setAlphaOf, void(entity, entity, float));
24 METHOD(Container, itemFromPoint, entity(entity, vector));
25 METHOD(Container, showNotify, void(entity));
26 METHOD(Container, hideNotify, void(entity));
27 METHOD(Container, preferredFocusedGrandChild, entity(entity));
28 ATTRIB(Container, focusable, float, 0)
29 ATTRIB(Container, firstChild, entity, NULL)
30 ATTRIB(Container, lastChild, entity, NULL)
31 ATTRIB(Container, focusedChild, entity, NULL)
32 ATTRIB(Container, savedFocus, entity, NULL)
33 ATTRIB(Container, shown, float, 0)
35 METHOD(Container, enterSubitem, void(entity, entity));
36 METHOD(Container, enterLieSubitem, void(entity, vector, vector, vector, float));
37 METHOD(Container, leaveSubitem, void(entity));
42 .vector Container_origin;
43 .vector Container_size;
44 .vector Container_fontscale;
45 .float Container_alpha;
46 .vector Container_save_shift;
47 .vector Container_save_scale;
48 .vector Container_save_fontscale;
49 .float Container_save_alpha;
53 void Container_enterSubitem(entity me, entity sub)
55 me.enterLieSubitem(me, sub.Container_origin, sub.Container_size, sub.Container_fontscale, sub.Container_alpha);
58 void Container_enterLieSubitem(entity me, vector o, vector s, vector f, float a)
60 me.Container_save_shift = draw_shift;
61 me.Container_save_scale = draw_scale;
62 me.Container_save_alpha = draw_alpha;
63 me.Container_save_fontscale = draw_fontscale;
65 draw_shift = boxToGlobal(o, draw_shift, draw_scale);
66 draw_scale = boxToGlobalSize(s, draw_scale);
67 if (f != '0 0 0') draw_fontscale = boxToGlobalSize(f, draw_fontscale);
71 void Container_leaveSubitem(entity me)
73 draw_shift = me.Container_save_shift;
74 draw_scale = me.Container_save_scale;
75 draw_alpha = me.Container_save_alpha;
76 draw_fontscale = me.Container_save_fontscale;
79 void Container_showNotify(entity me)
84 for (e = me.firstChild; e; e = e.nextSibling)
85 if (e.Container_alpha > 0) e.showNotify(e);
88 void Container_hideNotify(entity me)
91 if (!me.shown) return;
93 for (e = me.firstChild; e; e = e.nextSibling)
94 if (e.Container_alpha > 0) e.hideNotify(e);
97 void Container_setAlphaOf(entity me, entity other, float theAlpha)
101 if (other.Container_alpha > 0) other.hideNotify(other);
105 if (other.Container_alpha <= 0) other.showNotify(other);
107 other.Container_alpha = theAlpha;
110 void Container_resizeNotifyLie(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize, .vector originField, .vector sizeField, .vector fontScaleField)
115 for (e = me.firstChild; e; e = e.nextSibling)
119 me.enterLieSubitem(me, o, s, e.(fontScaleField), e.Container_alpha);
120 e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
126 for (e = me.firstChild; e; e = e.nextSibling)
133 me.enterLieSubitem(me, o, s, e.(fontScaleField), e.Container_alpha);
134 e.resizeNotify(e, o, s, boxToGlobal(o, absOrigin, absSize), boxToGlobalSize(s, absSize));
139 SUPER(Container).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
142 void Container_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
144 me.resizeNotifyLie(me, relOrigin, relSize, absOrigin, absSize, Container_origin, Container_size, Container_fontscale);
147 entity Container_itemFromPoint(entity me, vector pos)
151 for (e = me.lastChild; e; e = e.prevSibling)
153 o = e.Container_origin;
154 s = e.Container_size;
155 if (pos.x < o.x) continue;
156 if (pos.y < o.y) continue;
157 if (pos.x >= o.x + s.x) continue;
158 if (pos.y >= o.y + s.y) continue;
164 void Container_draw(entity me)
169 for (e = me.firstChild; e; e = e.nextSibling)
171 if (e.focusable) me.focusable += 1;
172 if (e.Container_alpha < 0.003) // can't change color values anyway
174 me.enterSubitem(me, e);
179 SUPER(Container).draw(me);
182 void Container_focusLeave(entity me)
184 me.setFocus(me, NULL);
187 float Container_keyUp(entity me, float scan, float ascii, float shift)
194 me.enterSubitem(me, f);
195 r = f.keyUp(f, scan, ascii, shift);
202 float Container_keyDown(entity me, float scan, float ascii, float shift)
209 me.enterSubitem(me, f);
210 r = f.keyDown(f, scan, ascii, shift);
217 float Container_mouseMove(entity me, vector pos)
224 me.enterSubitem(me, f);
225 r = f.mouseMove(f, globalToBox(pos, f.Container_origin, f.Container_size));
231 float Container_mousePress(entity me, vector pos)
238 me.enterSubitem(me, f);
239 r = f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size));
245 float Container_mouseDrag(entity me, vector pos)
252 me.enterSubitem(me, f);
253 r = f.mouseDrag(f, globalToBox(pos, f.Container_origin, f.Container_size));
259 float Container_mouseRelease(entity me, vector pos)
266 me.enterSubitem(me, f);
267 r = f.mouseRelease(f, globalToBox(pos, f.Container_origin, f.Container_size));
274 void Container_addItemCentered(entity me, entity other, vector theSize, float theAlpha)
276 me.addItem(me, other, '0.5 0.5 0' - 0.5 * theSize, theSize, theAlpha);
279 void Container_addItemRightCentered(entity me, entity other, vector theSize, float theAlpha)
281 me.addItem(me, other, '1 0.5 0' - 0.5 * theSize, theSize, theAlpha);
284 void Container_addItem(entity me, entity other, vector theOrigin, vector theSize, float theAlpha)
286 if (other.parent) error("Can't add already added item!");
288 if (other.focusable) me.focusable += 1;
292 theOrigin.x -= 0.5 * (theSize.x - 1);
297 theOrigin.y -= 0.5 * (theSize.y - 1);
300 theOrigin.x = bound(0, theOrigin.x, 1 - theSize.x);
301 theOrigin.y = bound(0, theOrigin.y, 1 - theSize.y);
304 other.Container_origin = theOrigin;
305 other.Container_size = theSize;
307 // don't call setAlphaOf, it would uneccessarily trigger showNotify
308 //me.setAlphaOf(me, other, theAlpha);
309 other.Container_alpha = theAlpha;
314 if (l) l.nextSibling = other;
315 else me.firstChild = other;
317 other.prevSibling = l;
318 other.nextSibling = NULL;
319 me.lastChild = other;
322 void Container_removeItem(entity me, entity other)
324 if (other.parent != me) error("Can't remove from wrong container!");
326 if (other.focusable) me.focusable -= 1;
331 n = other.nextSibling;
332 p = other.prevSibling;
334 if (p) p.nextSibling = n;
335 else me.firstChild = n;
337 if (n) n.prevSibling = p;
338 else me.lastChild = p;
341 void Container_setFocus(entity me, entity other)
343 if (me.focusedChild == other) return;
347 me.focusedChild.focused = 0;
348 me.focusedChild.focusLeave(me.focusedChild);
349 me.focusedChild = NULL;
354 if (!me.focused) error("Trying to set focus in a non-focused control!");
358 me.focusedChild = me.savedFocus;
359 me.savedFocus = NULL;
360 me.focusedChild.focused = 1;
361 me.focusedChild.focusEnter(me.focusedChild);
363 if (me.focusedChild.instanceOfContainer) me.focusedChild.setFocus(me.focusedChild, me.focusedChild.savedFocus);
367 me.focusedChild = other;
368 me.focusedChild.focused = 1;
369 me.focusedChild.focusEnter(me.focusedChild);
374 void Container_saveFocus(entity me)
376 me.savedFocus = me.focusedChild;
378 if (me.focusedChild.instanceOfContainer) me.focusedChild.saveFocus(me.focusedChild);
381 void Container_moveItemAfter(entity me, entity other, entity dest)
383 // first: remove other from the chain
386 if (other.parent != me) error("Can't move in wrong container!");
388 n = other.nextSibling;
389 p = other.prevSibling;
391 if (p) p.nextSibling = n;
392 else me.firstChild = n;
394 if (n) n.prevSibling = p;
395 else me.lastChild = p;
397 // now other got removed. Insert it behind dest now.
398 other.prevSibling = dest;
399 if (dest) other.nextSibling = dest.nextSibling;
400 else other.nextSibling = me.firstChild;
402 if (dest) dest.nextSibling = other;
403 else me.firstChild = other;
405 if (other.nextSibling) other.nextSibling.prevSibling = other;
406 else me.lastChild = other;
409 entity Container_preferredFocusedGrandChild(entity me)
416 for (e = me.firstChild; e; e = e.nextSibling)
418 if (e.instanceOfContainer)
420 e2 = e.preferredFocusedGrandChild(e);
422 if (!best || best.preferredFocusPriority < e2.preferredFocusPriority) best = e2;
425 if (!best || best.preferredFocusPriority < e.preferredFocusPriority) best = e;