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
35 ATTRIB(InputBox, enableClearButton, float, 1)
36 ATTRIB(InputBox, clearButton, entity, NULL)
37 ATTRIB(InputBox, cb_width, float, 0)
38 ATTRIB(InputBox, cb_pressed, float, 0)
39 ATTRIB(InputBox, cb_focused, float, 0)
40 ATTRIB(InputBox, cb_color, vector, '1 1 1')
41 ATTRIB(InputBox, cb_colorF, vector, '1 1 1')
42 ATTRIB(InputBox, cb_colorC, vector, '1 1 1')
47 void InputBox_configureInputBox(entity me, string theText, float theCursorPos, float theFontSize, string gfx)
49 SUPER(InputBox).configureLabel(me, theText, theFontSize, 0.0);
51 me.cursorPos = theCursorPos;
53 void InputBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
55 SUPER(InputBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
56 if (me.enableClearButton)
58 me.cb_width = absSize.y / absSize.x;
59 me.cb_offset = bound(-1, me.cb_offset, 0) * me.cb_width; // bound to range -1, 0
60 me.keepspaceRight = me.keepspaceRight - me.cb_offset + me.cb_width;
64 void InputBox_setText(entity me, string txt)
66 if (me.text) strunzone(me.text);
67 SUPER(InputBox).setText(me, strzone(txt));
70 float over_ClearButton(entity me, vector pos)
72 if (pos.x >= 1 + me.cb_offset - me.cb_width)
73 if (pos.x < 1 + me.cb_offset)
75 if (pos.y < 1) return 1;
79 float InputBox_mouseMove(entity me, vector pos)
81 if (me.enableClearButton)
83 if (over_ClearButton(me, pos))
93 float InputBox_mouseDrag(entity me, vector pos)
98 me.dragScrollPos = pos;
99 p = me.scrollPos + pos.x - me.keepspaceLeft;
100 me.cursorPos = draw_TextLengthUpToWidth(me.text, p, 0, me.realFontSize);
101 me.lastChangeTime = time;
103 else if (me.enableClearButton)
105 if (over_ClearButton(me, pos))
115 float InputBox_mousePress(entity me, vector pos)
117 if (me.enableClearButton)
118 if (over_ClearButton(me, pos))
123 me.dragScrollTimer = time;
125 return InputBox_mouseDrag(me, pos);
128 float InputBox_mouseRelease(entity me, vector pos)
131 if (over_ClearButton(me, pos))
133 m_play_click_sound(MENU_SOUND_CLEAR);
138 float r = InputBox_mouseDrag(me, pos);
139 // reset cb_pressed after mouseDrag, mouseDrag could set cb_pressed in this case:
140 // mouse press out of the clear button, drag and then mouse release over the clear button
146 void InputBox_enterText(entity me, string ch)
149 for (i = 0; i < strlen(ch); ++i)
150 if (strstrofs(me.forbiddenCharacters, substring(ch, i, 1), 0) > -1) return;
151 if (me.maxLength > 0)
153 if (strlen(ch) + strlen(me.text) > me.maxLength) return;
155 else if (me.maxLength < 0)
157 if (u8_strsize(ch) + u8_strsize(me.text) > -me.maxLength) return;
159 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), ch, substring(me.text, me.cursorPos, strlen(me.text) - me.cursorPos)));
160 me.cursorPos += strlen(ch);
163 float InputBox_keyDown(entity me, float key, float ascii, float shift)
165 me.lastChangeTime = time;
166 me.dragScrollTimer = time;
167 if (ascii >= 32 && ascii != 127)
169 me.enterText(me, chr(ascii));
178 case K_KP_RIGHTARROW:
188 me.cursorPos = strlen(me.text);
191 if (me.cursorPos > 0)
194 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
201 m_play_click_sound(MENU_SOUND_CLEAR);
206 me.setText(me, strcat(substring(me.text, 0, me.cursorPos), substring(me.text, me.cursorPos + 1, strlen(me.text) - me.cursorPos - 1)));
213 void InputBox_draw(entity me)
216 float cursorPosInWidths, totalSizeInWidths;
218 if (me.pressed) me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
220 if (me.recalcPos) me.recalcPositionWithText(me, me.text);
222 me.focusable = !me.disabled;
223 if (me.disabled) draw_alpha *= me.disabledAlpha;
227 if (me.focused && !me.disabled) draw_ButtonPicture('0 0 0', strcat(me.src, "_f"), '1 1 0', me.colorF, 1);
228 else draw_ButtonPicture('0 0 0', strcat(me.src, "_n"), '1 1 0', me.color, 1);
231 me.cursorPos = bound(0, me.cursorPos, strlen(me.text));
232 cursorPosInWidths = draw_TextWidth(substring(me.text, 0, me.cursorPos), 0, me.realFontSize);
233 totalSizeInWidths = draw_TextWidth(strcat(me.text, CURSOR), 0, me.realFontSize);
235 if (me.dragScrollTimer < time)
239 me.scrollPos = bound(cursorPosInWidths - (0.875 - me.keepspaceLeft - me.keepspaceRight), me.scrollPos, cursorPosInWidths - 0.125);
240 if (me.scrollPos != save) me.dragScrollTimer = time + 0.2;
242 me.scrollPos = min(me.scrollPos, totalSizeInWidths - (1 - me.keepspaceRight - me.keepspaceLeft));
243 me.scrollPos = max(0, me.scrollPos);
245 draw_SetClipRect(eX * me.keepspaceLeft, eX * (1 - me.keepspaceLeft - me.keepspaceRight) + eY);
246 if (me.editColorCodes)
251 float theAlpha; // float theVariableAlpha;
256 p = me.realOrigin - eX * me.scrollPos;
258 theAlpha = 1; // theVariableAlpha = 1; // changes when ^ax found
261 for (i = 0; i < n; ++i)
263 ch = substring(me.text, i, 1);
267 ch2 = substring(me.text, i + 1, 1);
268 w = draw_TextWidth(strcat(ch, ch2), 0, me.realFontSize);
271 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
272 draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
274 else if (ch2 == "0" || stof(ch2)) // digit?
278 case 0: theColor = '0 0 0';
281 case 1: theColor = '1 0 0';
284 case 2: theColor = '0 1 0';
287 case 3: theColor = '1 1 0';
290 case 4: theColor = '0 0 1';
293 case 5: theColor = '0 1 1';
296 case 6: theColor = '1 0 1';
299 case 7: theColor = '1 1 1';
302 case 8: theColor = '1 1 1';
305 case 9: theColor = '0.5 0.5 0.5';
309 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
310 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
312 else if (ch2 == "x") // ^x found
316 component = HEXDIGIT_TO_DEC(substring(me.text, i + 2, 1));
317 if (component >= 0) // ^xr found
319 theTempColor.x = component / 15;
321 component = HEXDIGIT_TO_DEC(substring(me.text, i + 3, 1));
322 if (component >= 0) // ^xrg found
324 theTempColor.y = component / 15;
326 component = HEXDIGIT_TO_DEC(substring(me.text, i + 4, 1));
327 if (component >= 0) // ^xrgb found
329 theTempColor.z = component / 15;
330 theColor = theTempColor;
331 w = draw_TextWidth(substring(me.text, i, 5), 0, me.realFontSize);
333 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
334 draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0); // theVariableAlpha instead of 1 using alpha tags ^ax
340 w = draw_TextWidth(substring(me.text, i, 4), 0, me.realFontSize);
341 draw_Fill(p, eX * w + eY * me.realFontSize.y, eZ, 0.5);
342 draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
349 w = draw_TextWidth(substring(me.text, i, 3), 0, me.realFontSize);
350 draw_Fill(p, eX * w + eY * me.realFontSize.y, eY, 0.5);
351 draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
358 // w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
359 draw_Fill(p, eX * w + eY * me.realFontSize.y, eX, 0.5);
360 draw_Text(p, substring(me.text, i, 2), me.realFontSize, '1 1 1', theAlpha, 0);
365 draw_Fill(p, eX * w + eY * me.realFontSize.y, '1 1 1', 0.5);
366 draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
372 draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
373 p += eX * draw_TextWidth(ch, 0, me.realFontSize);
378 draw_Text(me.realOrigin - eX * me.scrollPos, me.text, me.realFontSize, '1 1 1', 1, 0);
381 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);
385 if (me.enableClearButton)
388 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);
389 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);
390 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);
393 // skipping SUPER(InputBox).draw(me);
397 void InputBox_showNotify(entity me)
399 me.focusable = !me.disabled;