1 #ifndef ITEM_INPUTBOX_H
2 #define ITEM_INPUTBOX_H
5 METHOD(InputBox, configureInputBox, void(entity, string, float, float, string));
6 METHOD(InputBox, draw, void(entity));
7 METHOD(InputBox, setText, void(entity, string));
8 METHOD(InputBox, enterText, void(entity, string));
9 METHOD(InputBox, keyDown, float(entity, float, float, float));
10 METHOD(InputBox, mouseMove, float(entity, vector));
11 METHOD(InputBox, mouseRelease, float(entity, vector));
12 METHOD(InputBox, mousePress, float(entity, vector));
13 METHOD(InputBox, mouseDrag, float(entity, vector));
14 METHOD(InputBox, showNotify, void(entity));
15 METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector));
17 ATTRIB(InputBox, src, string, string_null)
19 ATTRIB(InputBox, cursorPos, float, 0) // characters
20 ATTRIB(InputBox, scrollPos, float, 0) // widths
22 ATTRIB(InputBox, focusable, float, 1)
23 ATTRIB(InputBox, allowFocusSound, float, 1)
24 ATTRIB(InputBox, disabled, float, 0)
25 ATTRIB(InputBox, lastChangeTime, float, 0)
26 ATTRIB(InputBox, dragScrollTimer, float, 0)
27 ATTRIB(InputBox, dragScrollPos, vector, '0 0 0')
28 ATTRIB(InputBox, pressed, float, 0)
29 ATTRIB(InputBox, editColorCodes, float, 1)
30 ATTRIB(InputBox, forbiddenCharacters, string, "")
31 ATTRIB(InputBox, color, vector, '1 1 1')
32 ATTRIB(InputBox, colorF, vector, '1 1 1')
33 ATTRIB(InputBox, maxLength, float, 255) // if negative, it counts bytes, not chars
34 ATTRIB(InputBox, applyButton, entity, NULL)
36 ATTRIB(InputBox, enableClearButton, float, 1)
37 ATTRIB(InputBox, clearButton, entity, NULL)
38 ATTRIB(InputBox, cb_width, float, 0)
39 ATTRIB(InputBox, cb_pressed, float, 0)
40 ATTRIB(InputBox, cb_focused, float, 0)
41 ATTRIB(InputBox, cb_color, vector, '1 1 1')
42 ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
43 ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
48 void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
50 SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
52 me.cursorPos = theCursorPos;
54 void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
56 SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
57 if (me.enableClearButton)
59 me.cb_width = absSize.y / absSize.x;
60 me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0
61 me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
65 void InputBox_setText(entity me, string txt)
67 if (me.text) strunzone(me.text);
68 SUPER(InputBox).setText(me, strzone(txt));
71 float over_ClearButton(entity me, vector pos)
73 if (pos.x >= 1 + me.cb_offset - me.cb_width)
74 if (pos.x < 1 + me.cb_offset)
76 if (pos.y < 1) return 1;
80 float InputBox_mouseMove(entity me, vector pos)
82 if (me.enableClearButton)
84 if (over_ClearButton(me, pos))
94 float InputBox_mouseDrag(entity me, vector pos)
99 me.dragScrollPos = pos;
100 p = me.scrollPos + pos.x - me.keepspaceLeft;
101 me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
102 me.lastChangeTime = time;
104 else if (me.enableClearButton)
106 if (over_ClearButton(me, pos))
116 float InputBox_mousePress(entity me, vector pos)
118 if (me.enableClearButton)
119 if (over_ClearButton(me, pos))
124 me.dragScrollTimer = time;
126 return InputBox_mouseDrag(me, pos);
129 float InputBox_mouseRelease(entity me, vector pos)
132 if (over_ClearButton(me, pos))
134 m_play_click_sound(MENU_SOUND_CLEAR);
137 me.applyButton.disabled = false;
141 float r = InputBox_mouseDrag(me, pos);
142 // reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case:
143 // mouse press out of the clear button, drag and then mouse release over the clear button
149 void InputBox_enterText(entity me, string ch)
152 for (i = 0; i < strlen(ch); ++i)
153 if (strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1) return;
154 if (me.maxLength > 0)
156 if (strlen(ch) + strlen(me.text) > me.maxLength) return;
158 else if (me.maxLength < 0)
160 if (u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength) return;
162 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
163 me.cursorPos += strlen(ch);
166 float InputBox_keyDown(entity me, float key, float ascii, float shift)
168 me.lastChangeTime = time;
169 me.dragScrollTimer = time;
170 if (ascii >= 32 && ascii != 127)
172 me.enterText(me, chr(ascii));
174 me.applyButton.disabled = false;
183 case K_KP_RIGHTARROW:
193 me.cursorPos = strlen(me.text);
196 if (me.cursorPos > 0)
199 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
201 me.applyButton.disabled = false;
208 m_play_click_sound(MENU_SOUND_CLEAR);
212 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
214 me.applyButton.disabled = false;
220 void InputBox_draw(entity me)
223 float cursorPosInWidths, totalSizeInWidths;
225 if (me.pressed) me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
227 if (me.recalcPos) me.recalcPositionWithText(me, me.text);
229 me.focusable = !me.disabled;
230 if (me.disabled) draw_alpha *= me.disabledAlpha;
234 if (me.focused && !me.disabled) draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
235 else draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
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);
242 if (me.dragScrollTimer < time)
246 me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
247 if (me.scrollPos != save) me.dragScrollTimer = time + 0.2;
249 me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
250 me.scrollPos = max(0, me.scrollPos);
252 draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
253 if (me.editColorCodes)
258 float theAlpha; // float theVariableAlpha;
263 p = me.realOrigin - eX * me.scrollPos;
265 theAlpha = 1; // theVariableAlpha = 1; // changes when ^ax found
268 for (i = 0; i < n; ++i)
270 ch = substring(me.text, i, 1);
274 ch2 = substring(me.text, i + 1, 1);
275 w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
278 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
279 draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
281 else if (ch2 == "0" || stof(ch2)) // digit?
285 case 0: theColor = '0 0 0';
288 case 1: theColor = '1 0 0';
291 case 2: theColor = '0 1 0';
294 case 3: theColor = '1 1 0';
297 case 4: theColor = '0 0 1';
300 case 5: theColor = '0 1 1';
303 case 6: theColor = '1 0 1';
306 case 7: theColor = '1 1 1';
309 case 8: theColor = '1 1 1';
312 case 9: theColor = '0.5 0.5 0.5';
316 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
317 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
319 else if (ch2 == "x") // ^x found
323 component = HEXDIGIT_TO_DEC(substring(me.text, i + 2, 1));
324 if (component >= 0) // ^xr found
326 theTempColor.x = component / 15;
328 component = HEXDIGIT_TO_DEC(substring(me.text, i + 3, 1));
329 if (component >= 0) // ^xrg found
331 theTempColor.y = component / 15;
333 component = HEXDIGIT_TO_DEC(substring(me.text, i + 4, 1));
334 if (component >= 0) // ^xrgb found
336 theTempColor.z = component / 15;
337 theColor = theTempColor;
338 w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
340 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
341 draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0); // theVariableAlpha instead of 1 using alpha tags ^ax
347 w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
348 draw_Fill(p, eX * w + eY * me.realFontSize.y, eZ, 0.5);
349 draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
356 w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
357 draw_Fill(p, eX * w + eY * me.realFontSize.y, eY, 0.5);
358 draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
365 // w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
366 draw_Fill(p, eX * w + eY * me.realFontSize.y, eX, 0.5);
367 draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
372 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
373 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
379 draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
380 p += eX * draw_TextWidth(ch, 0, me.realFontSize);
385 draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
388 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);
392 if (me.enableClearButton)
395 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);
396 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);
397 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);
400 // skipping SUPER(InputBox).draw(me);
404 void InputBox_showNotify(entity me)
406 me.focusable = !me.disabled;