1#include "EKeyboard.hpp"
10EKeyboard::EKeyboard(std::function<
void(
char)> typeAction)
13 this->y = SCREEN_HEIGHT - 420;
15 this->
width = SCREEN_WIDTH - 380;
17 this->typeAction = typeAction;
20 this->isAbsolute =
true;
28 if (
hidden || immersiveMode)
31 CST_Rect dimens = { this->x, this->y, this->
width + 305, this->height + 140 };
33 auto renderer = getRenderer();
35 CST_SetDrawColor(renderer, { 0xf9, 0xf9, 0xf9, 0xFF });
37 CST_SetDrawColor(renderer, { 0xdd, 0xdd, 0xdd, 0xFF });
42 dimens.w = RootDisplay::screenWidth;
45 CST_FillRect(renderer, &dimens);
47 for (
int y = 0; y < rowCount(); y++)
48 for (
int x = 0; x < rowLength(y) + 1; x++)
50 CST_Rect dimens2 = { this->x + kXPad + x * kXOff + y * yYOff, this->y + kYPad + y * ySpacing, keyWidth, keyWidth };
51 if (this->hasRoundedKeys) {
52 CST_roundedBoxRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0xee, 0xee, 0xee, 0xff);
54 CST_SetDrawColor(renderer, { 0xf4, 0xf4, 0xf4, 0xff });
55 CST_FillRect(renderer, &dimens2);
60 char curChar = rows[y]->at(x*2);
61 auto curCharStr = std::string(1, curChar);
62 int fHeight = CST_GetFontHeight(roundKeyFont, curCharStr.c_str());
63 int fWidth = CST_GetFontWidth(roundKeyFont, curCharStr.c_str());
67 dimens2.x + dimens2.w/2 - fWidth/2,
68 dimens2.y + dimens2.h/2 - fHeight/2,
74 CST_Rect dimensSpace = { this->x + sPos, this->y + dHeight, sWidth, textSize };
75 CST_Rect dimensEnter = { this->x + enterPos, this->y + enterHeight, enterWidth, (int)(1.5 * textSize) };
76 CST_Rect dimensTab = { this->x + dPos, this->y + enterHeight, enterWidth, (int)(1.5 * textSize) };
79 if (curRow >= 0 || index >= 0)
81 CST_Rect dimens2 = { this->x + kXPad + index * kXOff + curRow * yYOff, this->y + kYPad + curRow * ySpacing, keyWidth, keyWidth };
83 if (curRow >= rowCount())
92 dimens2 = dimensSpace;
96 dimens2 = dimensEnter;
104 if (touchMode && !isTouchDrag)
106 if (hasRoundedKeys) {
107 CST_roundedBoxRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0xad, 0xd8, 0xe6, 0x90);
108 CST_roundedRectangleRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0x66, 0x7c, 0x89, 0xff);
110 CST_SetDrawColor(renderer, { 0xad, 0xd8, 0xe6, 0x90 });
111 CST_FillRect(renderer, &dimens2);
114 else if (hasRoundedKeys) {
115 CST_roundedBoxRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0xad, 0xd8, 0xe6, 0x90);
116 CST_roundedRectangleRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0x66, 0x7c, 0x89, 0xff);
119 CST_SetDrawColor(renderer, { 0xff, 0xff, 0xff, 0xff });
120 CST_FillRect(renderer, &dimens2);
123 for (
int z = 4; z >= 0; z--)
130 CST_SetDrawColor(renderer, { 0x66 - z * 10, 0x7c + z * 20, 0x89 + z * 10, 0xFF });
131 CST_DrawRect(renderer, &dimens2);
136 if (hasRoundedKeys) {
137 CST_roundedBoxRGBA(renderer, dimensSpace.x, dimensSpace.y, dimensSpace.x + dimensSpace.w, dimensSpace.y + dimensSpace.h, 20, 0xee, 0xee, 0xee, 0xff);
138 CST_roundedBoxRGBA(renderer, dimensEnter.x, dimensEnter.y, dimensEnter.x + dimensEnter.w, dimensEnter.y + dimensEnter.h, 20, 0xee, 0xee, 0xee, 0xff);
139 CST_roundedBoxRGBA(renderer, dimensTab.x, dimensTab.y, dimensTab.x + dimensTab.w, dimensTab.y + dimensTab.h, 20, 0xee, 0xee, 0xee, 0xff);
141 CST_SetDrawColor(renderer, { 0xf4, 0xf4, 0xf4, 0xff });
142 CST_FillRect(renderer, &dimensSpace);
144 if (!preventEnterAndTab) {
145 CST_FillRect(renderer, &dimensEnter);
146 CST_FillRect(renderer, &dimensTab);
155 InputEvents::bypassKeyEvents =
false;
162 InputEvents::bypassKeyEvents =
true;
164 if (event->type == SDL_KEYDOWN)
165 return listenForPhysicalKeys(event);
166 if (event->type == SDL_KEYUP && (event->keyCode == SDLK_LSHIFT ||
167 event->keyCode == SDLK_RSHIFT ||
168 event->keyCode == SDLK_CAPSLOCK)) {
175 if (immersiveMode)
return false;
177 if (event->isTouchDown())
184 if (event->isKeyDown())
190 auto prevTouchDrag = isTouchDrag;
191 isTouchDrag = (
event->isTouchDrag() && (!touchMode || (curRow < 0 && index < 0))) || isTouchDrag;
192 if (prevTouchDrag != isTouchDrag && isTouchDrag) {
194 CST_LowRumble(event, 200);
198 if (!touchMode && !isTouchDrag)
200 if (curRow < 0 && index < 0)
208 if (event->isKeyDown())
210 int lastRow = curRow;
211 curRow += (
event->held(DOWN_BUTTON) -
event->held(UP_BUTTON));
212 index += (
event->held(RIGHT_BUTTON) -
event->held(LEFT_BUTTON));
214 if (curRow < 0) curRow = 0;
215 if (index < 0) index = 0;
216 if (curRow >= rowCount() + 1) curRow = rowCount();
217 if (curRow == rowCount())
220 if (lastRow < curRow && index > 0 && index < rowLength(lastRow))
226 if (index < 0) index = 0;
229 if (index > 2) index = 2;
233 if (index > rowLength(curRow))
234 index = rowLength(curRow);
236 if (lastRow == rowCount()) {
244 index = rowLength(curRow) / 2;
248 index = rowLength(curRow);
256 if (event->
held(A_BUTTON))
259 if (curRow >= rowCount())
288 int extWidth =
width + 305;
290 if ((event->isTouchDown() || event->isTouchDrag()) && event->
touchIn(this->x, this->y, extWidth, height + 200))
292 for (
int y = 0; y < rowCount(); y++)
293 for (
int x = 0; x < rowLength(y) + 1; x++) {
294 auto xStart = this->x + kXPad + x * kXOff + y * yYOff;
295 auto yStart = this->y + kYPad + y * ySpacing;
296 if (event->
touchIn(xStart, yStart, keyWidth, keyWidth))
306 if (event->isTouchUp())
313 if (event->
touchIn(this->x, this->y, extWidth, height + 200))
316 for (
int y = 0; y < rowCount(); y++)
317 for (
int x = 0; x < rowLength(y) + 1; x++)
318 if (event->
touchIn(this->x + kXPad + x * kXOff + y * yYOff, this->y + kYPad + y * ySpacing, keyWidth, keyWidth))
324 if (event->
touchIn(this->x + dPos, this->y + enterHeight, enterWidth, textSize))
330 if (event->
touchIn(this->x + sPos, this->y + dHeight, sWidth, textSize))
336 if (event->
touchIn(this->x + enterPos, this->y + enterHeight, enterWidth, textSize))
354bool EKeyboard::listenForPhysicalKeys(
InputEvents* e)
359 auto keyCode = e->keyCode;
363 if (keyCode == SDLK_LSHIFT || keyCode == SDLK_RSHIFT || keyCode == SDLK_CAPSLOCK) {
369 if (keyCode == SDLK_TAB) {
373 if (keyCode == SDLK_SPACE) {
377 if (keyCode == SDLK_RETURN && !preventEnterAndTab) {
383 if (keyCode == SDLK_LALT || keyCode == SDLK_RALT) {
384 immersiveMode = !immersiveMode;
389 auto roundedOffset = hasRoundedKeys ? 1 : 0;
390 for (
int x=roundedOffset; x<KEYCODE_COUNT; x++)
393 int topRowOffset = curBreak == 0 ? roundedOffset : 0;
395 if (keyCode == usbKeys[x])
399 type(curBreak, xx - topRowOffset);
401 index = xx - topRowOffset;
405 if (xx + 1 >= breaks[curBreak]) {
415 if (keyCode == SDLK_BACKSPACE) {
421 if (keyCode == SDLK_RETURN && preventEnterAndTab) {
425 sdlevent.type = SDL_JOYBUTTONDOWN;
426 sdlevent.jbutton.button = SDL_X;
427 SDL_PushEvent(&sdlevent);
431 if (keyCode == SDLK_ESCAPE) {
434 sdlevent.type = SDL_JOYBUTTONDOWN;
435 sdlevent.jbutton.button = SDL_Y;
436 SDL_PushEvent(&sdlevent);
443void EKeyboard::updateSize()
448 this->height = (304 / 900.0) *
width;
452 this->keyWidth = (int)(0.08 *
width);
453 this->padding = keyWidth / 2.0;
456 kXPad = (int)((23 / 400.0) *
width);
457 kXOff = (int)((36.5 / 400.0) *
width) + (900.0 /
width) * ( 900.0 !=
width);
458 yYOff = (int)((22 / 400.0) *
width);
459 kYPad = (int)((17 / 135.0) * height);
460 ySpacing = (int)((33 / 400.0) *
width);
462 if (hasRoundedKeys) {
465 kXOff = (int)((38 / 400.0) *
width) + (900.0 /
width) * ( 900.0 !=
width);
466 yYOff = (int)((10 / 400.0) *
width);
467 kYPad = (int)((0 / 135.0) * height);
468 ySpacing = (int)((37 / 400.0) *
width);
474 int kXPad = (int)((30 / 400.0) *
width);
475 int kXOff = (int)((22 / 400.0) *
width);
479 int kYPad = (int)((14 / 400.0) *
width);
481 int kYOff = (int)((33 / 400.0) *
width);
483 this->textSize = 0.9375 * keyWidth;
486 dPos = (int)((13 / 400.0) *
width);
487 dHeight = (int)((85 / 135.0) * height) + 145;
488 sPos = (int)((150 / 400.0) *
width);
489 enterPos = dPos + 1000;
490 enterHeight = dHeight - 34;
492 dWidth = (int)(1.4125 * textSize);
493 sWidth = (int)(7.5 * textSize);
494 enterWidth = (int)(2.25 * textSize);
499 CST_Color gray = { 0x52, 0x52, 0x52, 0xff };
501 int targetHeight = -1;
504 if (!hasRoundedKeys) {
505 for (
int x = 0; x < rowCount(); x++)
509 if (targetHeight < 0) {
510 targetHeight = rowText->height;
513 rowText->
position(kXPad + x * kXOff, kYPad + x * kYOff + targetHeight/2 - rowText->height/2);
519 CST_Color grayish = { 0x55, 0x55, 0x55, 0xff };
521 CST_Rect d4 = { this->x + sPos, this->y + dHeight, sWidth, textSize };
522 spaceText->
position(d4.x + d4.w / 2 - spaceText->
width / 2 - 15, 345);
523 this->
elements.push_back(spaceText);
525 if (!preventEnterAndTab)
528 CST_Rect d3 = { this->x + enterPos, this->y + enterHeight, enterWidth, textSize };
529 enterText->
position(d3.x + d3.w / 2 - enterText->
width / 2 - 30, 327);
530 this->
elements.push_back(enterText);
533 CST_Rect d5 = { this->x + dPos, this->y + enterHeight, enterWidth, textSize };
534 symText->
position(d5.x + d5.w / 2 - symText->
width / 2 - 30, 327);
540void EKeyboard::type(
int y,
int x)
542 const char input = (*(rows[y]))[x * 2];
547void EKeyboard::just_type(
const char input)
549 if (preventEnterAndTab && (input ==
'\n' || input ==
'\t'))
554 textInput.push_back(input);
557 if (typeAction != NULL) {
563void EKeyboard::generateEKeyboard()
569 keys = string((shiftOn || capsOn) ? upper_keys : lower_keys);
575 int offset = 47 * (mode - 1) + 0x00a1;
576 char chars[47 + (mode == 2)];
577 for (
int x = 0; x < 47 + (mode == 2); x++)
579 chars[x] = offset + x;
582 keys = string(chars);
585 breaks[3] += (mode == 2);
587 for (
int& end : breaks)
589 auto roundedOffset = (hasRoundedKeys && count == 0) ? 1 : 0;
590 string* row =
new string(keys.substr(count + roundedOffset, end - roundedOffset));
591 for (
int x = 1; x < (int)row->size(); x += 2)
593 row->insert(row->begin() + x,
' ');
600 if (hasRoundedKeys && roundKeyFont == NULL) {
602 roundKeyFont = CST_CreateFont();
603 auto fontPath = RAMFS
"res/lightsans.ttf";
604 auto renderer = getRenderer();
605 CST_LoadFont(roundKeyFont, renderer, fontPath, 40, CST_MakeColor(0,0,0,255), TTF_STYLE_NORMAL);
609void EKeyboard::backspace()
613 if (!textInput.empty())
614 textInput.pop_back();
623 sdlevent.type = SDL_JOYBUTTONDOWN;
624 sdlevent.jbutton.button = SDL_B;
625 SDL_PushEvent(&sdlevent);
628const std::string& EKeyboard::getTextInput()
633EKeyboard::~EKeyboard()
635 InputEvents::bypassKeyEvents =
false;
void render(Element *parent)
display the current state of the display
bool process(InputEvents *event)
process any input that is received for this element
bool hidden
whether this element should skip rendering or not
virtual void render(Element *parent)
display the current state of the display
void position(int x, int y)
position the element
int width
width and height of this element (must be manually set, isn't usually calculated (but is in some case...
std::vector< Element * > elements
visible GUI child elements of this element
void update(bool forceUpdate=false)
update TextElement with changes