2 #ifndef ITEM_INPUTBOX_H
3 #define ITEM_INPUTBOX_H
6 METHOD(InputBox, configureInputBox, void(entity, string, float, float, string));
7 METHOD(InputBox, draw, void(entity));
8 METHOD(InputBox, setText, void(entity, string));
9 METHOD(InputBox, enterText, void(entity, string));
10 METHOD(InputBox, keyDown, float(entity, float, float, float));
11 METHOD(InputBox, mouseMove, float(entity, vector));
12 METHOD(InputBox, mouseRelease, float(entity, vector));
13 METHOD(InputBox, mousePress, float(entity, vector));
14 METHOD(InputBox, mouseDrag, float(entity, vector));
15 METHOD(InputBox, showNotify, void(entity));
16 METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector));
18 ATTRIB(InputBox, src, string, string_null)
20 ATTRIB(InputBox, cursorPos, float, 0) // characters
21 ATTRIB(InputBox, scrollPos, float, 0) // widths
23 ATTRIB(InputBox, focusable, float, 1)
24 ATTRIB(InputBox, allowFocusSound, float, 1)
25 ATTRIB(InputBox, disabled, float, 0)
26 ATTRIB(InputBox, lastChangeTime, float, 0)
27 ATTRIB(InputBox, dragScrollTimer, float, 0)
28 ATTRIB(InputBox, dragScrollPos, vector, '0 0 0')
29 ATTRIB(InputBox, pressed, float, 0)
30 ATTRIB(InputBox, editColorCodes, float, 1)
31 ATTRIB(InputBox, forbiddenCharacters, string, "")
32 ATTRIB(InputBox, color, vector, '1 1 1')
33 ATTRIB(InputBox, colorF, vector, '1 1 1')
34 ATTRIB(InputBox, maxLength, float, 255) // if negative, it counts bytes, not chars
35 ATTRIB(InputBox, applyButton, entity, NULL)
37 ATTRIB(InputBox, enableClearButton, float, 1)
38 ATTRIB(InputBox, clearButton, entity, NULL)
39 ATTRIB(InputBox, cb_width, float, 0)
40 ATTRIB(InputBox, cb_pressed, float, 0)
41 ATTRIB(InputBox, cb_focused, float, 0)
42 ATTRIB(InputBox, cb_color, vector, '1 1 1')
43 ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
44 ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
49 void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
51 SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
53 me.cursorPos = theCursorPos;
55 void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
57 SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
58 if (me.enableClearButton)
60 me.cb_width = absSize.y / absSize.x;
61 me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0
62 me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
66 void InputBox_setText(entity me, string txt)
68 if (me.text) strunzone(me.text);
69 SUPER(InputBox).setText(me, strzone(txt));
72 float over_ClearButton(entity me, vector pos)
74 if (pos.x >= 1 + me.cb_offset - me.cb_width)
75 if (pos.x < 1 + me.cb_offset)
77 if (pos.y < 1) return 1;
81 float InputBox_mouseMove(entity me, vector pos)
83 if (me.enableClearButton)
85 if (over_ClearButton(me, pos))
95 float InputBox_mouseDrag(entity me, vector pos)
100 me.dragScrollPos = pos;
101 p = me.scrollPos + pos.x - me.keepspaceLeft;
102 me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
103 me.lastChangeTime = time;
105 else if (me.enableClearButton)
107 if (over_ClearButton(me, pos))
117 float InputBox_mousePress(entity me, vector pos)
119 if (me.enableClearButton)
120 if (over_ClearButton(me, pos))
125 me.dragScrollTimer = time;
127 return InputBox_mouseDrag(me, pos);
130 float InputBox_mouseRelease(entity me, vector pos)
133 if (over_ClearButton(me, pos))
135 m_play_click_sound(MENU_SOUND_CLEAR);
138 me.applyButton.disabled = false;
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
150 void InputBox_enterText(entity me, string ch)
153 for (i = 0; i < strlen(ch); ++i)
154 if (strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1) return;
155 if (me.maxLength > 0)
157 if (strlen(ch) + strlen(me.text) > me.maxLength) return;
159 else if (me.maxLength < 0)
161 if (u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength) return;
163 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
164 me.cursorPos += strlen(ch);
167 float InputBox_keyDown(entity me, float key, float ascii, float shift)
169 me.lastChangeTime = time;
170 me.dragScrollTimer = time;
171 if (ascii >= 32 && ascii != 127)
173 me.enterText(me, chr(ascii));
175 me.applyButton.disabled = false;
184 case K_KP_RIGHTARROW:
194 me.cursorPos = strlen(me.text);
197 if (me.cursorPos > 0)
200 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
202 me.applyButton.disabled = false;
209 m_play_click_sound(MENU_SOUND_CLEAR);
213 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
215 me.applyButton.disabled = false;
221 void InputBox_draw(entity me)
224 float cursorPosInWidths, totalSizeInWidths;
226 if (me.pressed) me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
228 if (me.recalcPos) me.recalcPositionWithText(me, me.text);
230 me.focusable = !me.disabled;
231 if (me.disabled) draw_alpha *= me.disabledAlpha;
235 if (me.focused && !me.disabled) draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
236 else draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
239 me.cursorPos = bound(0, me.cursorPos, strlen(me.text));
240 cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize);
241 totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize);
243 if (me.dragScrollTimer < time)
247 me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
248 if (me.scrollPos != save) me.dragScrollTimer = time + 0.2;
250 me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
251 me.scrollPos = max(0, me.scrollPos);
253 draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
254 if (me.editColorCodes)
259 float theAlpha; // float theVariableAlpha;
264 p = me.realOrigin - eX * me.scrollPos;
266 theAlpha = 1; // theVariableAlpha = 1; // changes when ^ax found
269 for (i = 0; i < n; ++i)
271 ch = substring(me.text, i, 1);
275 ch2 = substring(me.text, i + 1, 1);
276 w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
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);
282 else if (ch2 == "0" || stof(ch2)) // digit?
286 case 0: theColor = '0 0 0';
289 case 1: theColor = '1 0 0';
292 case 2: theColor = '0 1 0';
295 case 3: theColor = '1 1 0';
298 case 4: theColor = '0 0 1';
301 case 5: theColor = '0 1 1';
304 case 6: theColor = '1 0 1';
307 case 7: theColor = '1 1 1';
310 case 8: theColor = '1 1 1';
313 case 9: theColor = '0.5 0.5 0.5';
317 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
318 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
320 else if (ch2 == "x") // ^x found
324 component = HEXDIGIT_TO_DEC(substring(me.text, i + 2, 1));
325 if (component >= 0) // ^xr found
327 theTempColor.x = component / 15;
329 component = HEXDIGIT_TO_DEC(substring(me.text, i + 3, 1));
330 if (component >= 0) // ^xrg found
332 theTempColor.y = component / 15;
334 component = HEXDIGIT_TO_DEC(substring(me.text, i + 4, 1));
335 if (component >= 0) // ^xrgb found
337 theTempColor.z = component / 15;
338 theColor = theTempColor;
339 w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
341 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
342 draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0); // theVariableAlpha instead of 1 using alpha tags ^ax
348 w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
349 draw_Fill(p, eX * w + eY * me.realFontSize.y, eZ, 0.5);
350 draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
357 w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
358 draw_Fill(p, eX * w + eY * me.realFontSize.y, eY, 0.5);
359 draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
366 // w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
367 draw_Fill(p, eX * w + eY * me.realFontSize.y, eX, 0.5);
368 draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
373 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
374 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
380 draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
381 p += eX * draw_TextWidth(ch, 0, me.realFontSize);
386 draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
389 if (!me.focused || (time - me.lastChangeTime) < floor(time - me.lastChangeTime) + 0.5) draw_Text(me.realOrigin + eX * (cursorPosInWidths - me.scrollPos), CURSOR, me.realFontSize, '1 1 1', 1, 0);
393 if (me.enableClearButton)
396 if (me.focused && me.cb_pressed) draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_c"), eX * me.cb_width + eY, me.cb_colorC, 1);
397 else if (me.focused && me.cb_focused) draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_f"), eX * me.cb_width + eY, me.cb_colorF, 1);
398 else draw_Picture(eX * (1 + me.cb_offset - me.cb_width), strcat(me.cb_src, "_n"), eX * me.cb_width + eY, me.cb_color, 1);
401 // skipping SUPER(InputBox).draw(me);
405 void InputBox_showNotify(entity me)
407 me.focusable = !me.disabled;