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