Merge commit 'origin/master' into diabolik/nexmodel
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / inputcontainer.c
1 #ifdef INTERFACE
2 CLASS(InputContainer) EXTENDS(Container)
3         METHOD(InputContainer, keyDown, float(entity, float, float, float))
4         METHOD(InputContainer, mouseMove, float(entity, vector))
5         METHOD(InputContainer, mousePress, float(entity, vector))
6         METHOD(InputContainer, mouseRelease, float(entity, vector))
7         METHOD(InputContainer, mouseDrag, float(entity, vector))
8         METHOD(InputContainer, focusLeave, void(entity))
9         METHOD(InputContainer, resizeNotify, void(entity, vector, vector, vector, vector))
10
11         METHOD(InputContainer, _changeFocusXY, float(entity, vector))
12         ATTRIB(InputContainer, mouseFocusedChild, entity, NULL)
13         ATTRIB(InputContainer, isTabRoot, float, 0)
14 ENDCLASS(InputContainer)
15 #endif
16
17 #ifdef IMPLEMENTATION
18 void InputContainer_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
19 {
20         SUPER(InputContainer).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
21         /*
22         if(me.parent.instanceOfInputContainer)
23                 me.isTabRoot = 0;
24         else
25                 me.isTabRoot = 1;
26         */
27 }
28
29 void InputContainer_focusLeave(entity me)
30 {
31         SUPER(InputContainer).focusLeave(me);
32         me.mouseFocusedChild = NULL;
33 }
34
35 float InputContainer_keyDown(entity me, float scan, float ascii, float shift)
36 {
37         entity f, ff;
38         if(SUPER(InputContainer).keyDown(me, scan, ascii, shift))
39                 return 1;
40         if(scan == K_ESCAPE)
41         {
42                 f = me.focusedChild;
43                 if(f)
44                 {
45                         me.setFocus(me, NULL);
46                         return 1;
47                 }
48                 return 0;
49         }
50         if(scan == K_TAB)
51         {
52                 f = me.focusedChild;
53                 if(shift & S_SHIFT)
54                 {
55                         if(f)
56                         {
57                                 for(ff = f.prevSibling; ff; ff = ff.prevSibling)
58                                 {
59                                         if not(ff.focusable)
60                                                 continue;
61                                         me.setFocus(me, ff);
62                                         return 1;
63                                 }
64                         }
65                         if(!f || me.isTabRoot)
66                         {
67                                 for(ff = me.lastChild; ff; ff = ff.prevSibling)
68                                 {
69                                         if not(ff.focusable)
70                                                 continue;
71                                         me.setFocus(me, ff);
72                                         return 1;
73                                 }
74                                 return 0; // AIIIIEEEEE!
75                         }
76                 }
77                 else
78                 {
79                         if(f)
80                         {
81                                 for(ff = f.nextSibling; ff; ff = ff.nextSibling)
82                                 {
83                                         if not(ff.focusable)
84                                                 continue;
85                                         me.setFocus(me, ff);
86                                         return 1;
87                                 }
88                         }
89                         if(!f || me.isTabRoot)
90                         {
91                                 for(ff = me.firstChild; ff; ff = ff.nextSibling)
92                                 {
93                                         if not(ff.focusable)
94                                                 continue;
95                                         me.setFocus(me, ff);
96                                         return 1;
97                                 }
98                                 return 0; // AIIIIEEEEE!
99                         }
100                 }
101         }
102         return 0;
103 }
104
105 float InputContainer__changeFocusXY(entity me, vector pos)
106 {
107         entity e, ne;
108         e = me.mouseFocusedChild;
109         ne = me.itemFromPoint(me, pos);
110         if(ne)
111                 if not(ne.focusable)
112                         ne = NULL;
113         me.mouseFocusedChild = ne;
114         if(ne)
115                 if(ne != e)
116                 {
117                         me.setFocus(me, ne);
118                         if(ne.instanceOfInputContainer)
119                         {
120                                 ne.focusedChild = NULL;
121                                 ne._changeFocusXY(e, globalToBox(pos, ne.Container_origin, ne.Container_size));
122                         }
123                 }
124         return (ne != NULL);
125 }
126
127 float InputContainer_mouseDrag(entity me, vector pos)
128 {
129         if(SUPER(InputContainer).mouseDrag(me, pos))
130                 return 1;
131         if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
132                 return 1;
133         return 0;
134 }
135 float InputContainer_mouseMove(entity me, vector pos)
136 {
137         if(me._changeFocusXY(me, pos))
138                 if(SUPER(InputContainer).mouseMove(me, pos))
139                         return 1;
140         if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
141                 return 1;
142         return 0;
143 }
144 float InputContainer_mousePress(entity me, vector pos)
145 {
146         me.mouseFocusedChild = NULL; // force focusing
147         if(me._changeFocusXY(me, pos))
148                 if(SUPER(InputContainer).mousePress(me, pos))
149                         return 1;
150         if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
151                 return 1;
152         return 0;
153 }
154 float InputContainer_mouseRelease(entity me, vector pos)
155 {
156         float r;
157         r = SUPER(InputContainer).mouseRelease(me, pos);
158         if(me.focused) // am I still eligible for this? (UGLY HACK, but a mouse event could have changed focus away)
159                 if(me._changeFocusXY(me, pos))
160                         return 1;
161         if(pos_x >= 0 && pos_y >= 0 && pos_x < 1 && pos_y < 1)
162                 return 1;
163         return 0;
164 }
165 #endif