]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/item/inputbox.qc
Replace more `vector_[xyz]` with `vector.[xyz]`
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / item / inputbox.qc
1 #ifdef INTERFACE
2 CLASS(InputBox) EXTENDS(Label)
3         METHOD(InputBox, configureInputBox, void(entity, string, float, float, string))
4         METHOD(InputBox, draw, void(entity))
5         METHOD(InputBox, setText, void(entity, string))
6         METHOD(InputBox, enterText, void(entity, string))
7         METHOD(InputBox, keyDown, float(entity, float, float, float))
8         METHOD(InputBox, mouseMove, float(entity, vector))
9         METHOD(InputBox, mouseRelease, float(entity, vector))
10         METHOD(InputBox, mousePress, float(entity, vector))
11         METHOD(InputBox, mouseDrag, float(entity, vector))
12         METHOD(InputBox, showNotify, void(entity))
13         METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector))
14
15         ATTRIB(InputBox, src, string, string_null)
16
17         ATTRIB(InputBox, cursorPos, float, 0) // characters
18         ATTRIB(InputBox, scrollPos, float, 0) // widths
19
20         ATTRIB(InputBox, focusable, float, 1)
21         ATTRIB(InputBox, disabled, float, 0)
22         ATTRIB(InputBox, lastChangeTime, float, 0)
23         ATTRIB(InputBox, dragScrollTimer, float, 0)
24         ATTRIB(InputBox, dragScrollPos, vector, '0 0 0')
25         ATTRIB(InputBox, pressed, float, 0)
26         ATTRIB(InputBox, editColorCodes, float, 1)
27         ATTRIB(InputBox, forbiddenCharacters, string, "")
28         ATTRIB(InputBox, color, vector, '1 1 1')
29         ATTRIB(InputBox, colorF, vector, '1 1 1')
30         ATTRIB(InputBox, maxLength, float, 255) // if negative, it counts bytes, not chars
31
32         ATTRIB(InputBox, enableClearButton, float, 1)
33         ATTRIB(InputBox, clearButton, entity, NULL)
34         ATTRIB(InputBox, cb_width, float, 0)
35         ATTRIB(InputBox, cb_pressed, float, 0)
36         ATTRIB(InputBox, cb_focused, float, 0)
37         ATTRIB(InputBox, cb_color, vector, '1 1 1')
38         ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
39         ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
40 ENDCLASS(InputBox)
41 void InputBox_Clear_Click(entity btn, entity me);
42 #endif
43
44 #ifdef IMPLEMENTATION
45 void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
46 {
47         SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
48         me.src = gfx;
49         me.cursorPos = theCursorPos;
50 }
51 void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
52 {
53         SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
54         if (me.enableClearButton)
55         {
56                 me.cb_width = absSize.y / absSize.x;
57                 me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0
58                 me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
59         }
60 }
61
62 void InputBox_setText(entity me, string txt)
63 {
64         if(me.text)
65                 strunzone(me.text);
66         SUPER(InputBox).setText(me, strzone(txt));
67 }
68
69 void InputBox_Clear_Click(entity btn, entity me)
70 {
71         me.setText(me, "");
72 }
73
74 float over_ClearButton(entity me, vector pos)
75 {
76         if (pos.x >= 1 + me.cb_offset - me.cb_width)
77         if (pos.x < 1 + me.cb_offset)
78         if (pos.y >= 0)
79         if (pos.y < 1)
80                 return 1;
81         return 0;
82 }
83
84 float InputBox_mouseMove(entity me, vector pos)
85 {
86         if (me.enableClearButton)
87         {
88                 if (over_ClearButton(me, pos))
89                 {
90                         me.cb_focused = 1;
91                         return 1;
92                 }
93                 me.cb_focused = 0;
94         }
95         return 1;
96 }
97
98 float InputBox_mouseDrag(entity me, vector pos)
99 {
100         float p;
101         if(me.pressed)
102         {
103                 me.dragScrollPos = pos;
104                 p = me.scrollPos + pos.x - me.keepspaceLeft;
105                 me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
106                 me.lastChangeTime = time;
107         }
108         else if (me.enableClearButton)
109         {
110                 if (over_ClearButton(me, pos))
111                 {
112                         me.cb_pressed = 1;
113                         return 1;
114                 }
115         }
116         me.cb_pressed = 0;
117         return 1;
118 }
119
120 float InputBox_mousePress(entity me, vector pos)
121 {
122         if (me.enableClearButton)
123         if (over_ClearButton(me, pos))
124         {
125                 me.cb_pressed = 1;
126                 return 1;
127         }
128         me.dragScrollTimer = time;
129         me.pressed = 1;
130         return InputBox_mouseDrag(me, pos);
131 }
132
133 float InputBox_mouseRelease(entity me, vector pos)
134 {
135         if(me.cb_pressed)
136         if (over_ClearButton(me, pos))
137         {
138                 me.cb_pressed = 0;
139                 InputBox_Clear_Click(world, me);
140                 return 1;
141         }
142         float r = InputBox_mouseDrag(me, pos);
143         //reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case:
144         //mouse press out of the clear button, drag and then mouse release over the clear button
145         me.cb_pressed = 0;
146         me.pressed = 0;
147         return r;
148 }
149
150 void InputBox_enterText(entity me, string ch)
151 {
152         float i;
153         for(i = 0; i < strlen(ch); ++i)
154                 if(strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1)
155                         return;
156         if(me.maxLength > 0)
157         {
158                 if(strlen(ch) + strlen(me.text) > me.maxLength)
159                         return;
160         }
161         else if(me.maxLength < 0)
162         {
163                 if(u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength)
164                         return;
165         }
166         me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
167         me.cursorPos += strlen(ch);
168 }
169
170 float InputBox_keyDown(entity me, float key, float ascii, float shift)
171 {
172         me.lastChangeTime = time;
173         me.dragScrollTimer = time;
174         if(ascii >= 32 && ascii != 127)
175         {
176                 me.enterText(me, chr(ascii));
177                 return 1;
178         }
179         switch(key)
180         {
181                 case K_KP_LEFTARROW:
182                 case K_LEFTARROW:
183                         me.cursorPos -= 1;
184                         return 1;
185                 case K_KP_RIGHTARROW:
186                 case K_RIGHTARROW:
187                         me.cursorPos += 1;
188                         return 1;
189                 case K_KP_HOME:
190                 case K_HOME:
191                         me.cursorPos = 0;
192                         return 1;
193                 case K_KP_END:
194                 case K_END:
195                         me.cursorPos = strlen(me.text);
196                         return 1;
197                 case K_BACKSPACE:
198                         if(me.cursorPos > 0)
199                         {
200                                 me.cursorPos -= 1;
201                                 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
202                         }
203                         return 1;
204                 case K_KP_DEL:
205                 case K_DEL:
206                         if(shift & S_CTRL)
207                                 me.setText(me, "");
208                         else
209                                 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
210                         return 1;
211         }
212         return 0;
213 }
214
215 void InputBox_draw(entity me)
216 {
217         string CURSOR = "_";
218         float cursorPosInWidths, totalSizeInWidths;
219
220         if(me.pressed)
221                 me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
222
223         if(me.recalcPos)
224                 me.recalcPositionWithText(me, me.text);
225
226         me.focusable = !me.disabled;
227         if(me.disabled)
228                 draw_alpha *= me.disabledAlpha;
229
230         if(me.src)
231         {
232                 if(me.focused && !me.disabled)
233                         draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
234                 else
235                         draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
236         }
237
238         me.cursorPos = bound(0, me.cursorPos, strlen(me.text));
239         cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize);
240         totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize);
241
242         if(me.dragScrollTimer < time)
243         {
244                 float save;
245                 save = me.scrollPos;
246                 me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
247                 if(me.scrollPos != save)
248                         me.dragScrollTimer = time + 0.2;
249         }
250         me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
251         me.scrollPos = max(0, me.scrollPos);
252
253         draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
254         if(me.editColorCodes)
255         {
256                 string ch, ch2;
257                 float i, n;
258                 vector theColor;
259                 float theAlpha;    //float theVariableAlpha;
260                 vector p;
261                 vector theTempColor;
262                 float component;
263
264                 p = me.realOrigin - eX * me.scrollPos;
265                 theColor = '1 1 1';
266                 theAlpha = 1;    //theVariableAlpha = 1; // changes when ^ax found
267
268                 n = strlen(me.text);
269                 for(i = 0; i < n; ++i)
270                 {
271                         ch = substring(me.text, i, 1);
272                         if(ch == "^")
273                         {
274                                 float w;
275                                 ch2 = substring(me.text, i+1, 1);
276                                 w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
277                                 if(ch2 == "^")
278                                 {
279                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
280                                         draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
281                                 }
282                                 else if(ch2 == "0" || stof(ch2)) // digit?
283                                 {
284                                         switch(stof(ch2))
285                                         {
286                                                 case 0: theColor = '0 0 0'; theAlpha = 1; break;
287                                                 case 1: theColor = '1 0 0'; theAlpha = 1; break;
288                                                 case 2: theColor = '0 1 0'; theAlpha = 1; break;
289                                                 case 3: theColor = '1 1 0'; theAlpha = 1; break;
290                                                 case 4: theColor = '0 0 1'; theAlpha = 1; break;
291                                                 case 5: theColor = '0 1 1'; theAlpha = 1; break;
292                                                 case 6: theColor = '1 0 1'; theAlpha = 1; break;
293                                                 case 7: theColor = '1 1 1'; theAlpha = 1; break;
294                                                 case 8: theColor = '1 1 1'; theAlpha = 0.5; break;
295                                                 case 9: theColor = '0.5 0.5 0.5'; theAlpha = 1; break;
296                                         }
297                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
298                                         draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
299                                 }
300                                 else if(ch2 == "x") // ^x found
301                                 {
302                                         theColor = '1 1 1';
303
304                                         component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1));
305                                         if (component >= 0) // ^xr found
306                                         {
307                                                 theTempColor.x = component/15;
308
309                                                 component = HEXDIGIT_TO_DEC(substring(me.text, i+3, 1));
310                                                 if (component >= 0) // ^xrg found
311                                                 {
312                                                         theTempColor.y = component/15;
313
314                                                         component = HEXDIGIT_TO_DEC(substring(me.text, i+4, 1));
315                                                         if (component >= 0) // ^xrgb found
316                                                         {
317                                                                 theTempColor.z = component/15;
318                                                                 theColor = theTempColor;
319                                                                 w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
320
321                                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
322                                                                 draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0);    // theVariableAlpha instead of 1 using alpha tags ^ax
323                                                                 i += 3;
324                                                         }
325                                                         else
326                                                         {
327                                                                 // blue missing
328                                                                 w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
329                                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, eZ, 0.5);
330                                                                 draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
331                                                                 i += 2;
332                                                         }
333                                                 }
334                                                 else
335                                                 {
336                                                         // green missing
337                                                         w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
338                                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, eY, 0.5);
339                                                         draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
340                                                         i += 1;
341                                                 }
342                                         }
343                                         else
344                                         {
345                                                 // red missing
346                                                 //w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
347                                                 draw_Fill(p, eX * w + eY * me.realFontSize.y, eX, 0.5);
348                                                 draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
349                                         }
350                                 }
351                                 else
352                                 {
353                                         draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
354                                         draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
355                                 }
356                                 p += w * eX;
357                                 ++i;
358                                 continue;
359                         }
360                         draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
361                         p += eX * draw_TextWidth(ch, 0, me.realFontSize);
362                 }
363         }
364         else
365                 draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
366
367         if(!me.focused || (time - me.lastChangeTime) < floor(time - me.lastChangeTime) + 0.5)
368                 draw_Text(me.realOrigin + eX * (cursorPosInWidths - me.scrollPos), CURSOR, me.realFontSize, '1 1 1', 1, 0);
369
370         draw_ClearClip();
371
372         if (me.enableClearButton)
373         if (me.text != "")
374         {
375                 if(me.focused && me.cb_pressed)
376                         draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_c"), eX * me.cb_width + eY, me.cb_colorC, 1);
377                 else if(me.focused && me.cb_focused)
378                         draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_f"), eX * me.cb_width + eY, me.cb_colorF, 1);
379                 else
380                         draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_n"), eX * me.cb_width + eY, me.cb_color, 1);
381         }
382
383         // skipping SUPER(InputBox).draw(me);
384         Item_draw(me);
385 }
386
387 void InputBox_showNotify(entity me)
388 {
389         me.focusable = !me.disabled;
390 }
391 #endif