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 (hasRoundedKeys) {
105 CST_roundedBoxRGBA(renderer, dimensSpace.x, dimensSpace.y, dimensSpace.x + dimensSpace.w, dimensSpace.y + dimensSpace.h, 20, 0xee, 0xee, 0xee, 0xff);
106 CST_roundedBoxRGBA(renderer, dimensEnter.x, dimensEnter.y, dimensEnter.x + dimensEnter.w, dimensEnter.y + dimensEnter.h, 20, 0xee, 0xee, 0xee, 0xff);
107 CST_roundedBoxRGBA(renderer, dimensTab.x, dimensTab.y, dimensTab.x + dimensTab.w, dimensTab.y + dimensTab.h, 20, 0xee, 0xee, 0xee, 0xff);
109 CST_SetDrawColor(renderer, { 0xf4, 0xf4, 0xf4, 0xff });
110 CST_FillRect(renderer, &dimensSpace);
112 if (!preventEnterAndTab) {
113 CST_FillRect(renderer, &dimensEnter);
114 CST_FillRect(renderer, &dimensTab);
119 if (touchMode && !isTouchDrag)
121 if (hasRoundedKeys) {
122 CST_roundedBoxRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0xad, 0xd8, 0xe6, 0x90);
123 CST_roundedRectangleRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0x66, 0x7c, 0x89, 0xff);
125 CST_SetDrawColor(renderer, { 0xad, 0xd8, 0xe6, 0x90 });
126 CST_FillRect(renderer, &dimens2);
129 else if (hasRoundedKeys) {
130 CST_roundedBoxRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0xad, 0xd8, 0xe6, 0x90);
131 CST_roundedRectangleRGBA(renderer, dimens2.x, dimens2.y, dimens2.x + dimens2.w, dimens2.y + dimens2.h, 20, 0x66, 0x7c, 0x89, 0xff);
134 CST_SetDrawColor(renderer, { 0xff, 0xff, 0xff, 0xff });
135 CST_FillRect(renderer, &dimens2);
139 for (
int x=-2; x<3; x++) {
140 CST_rectangleRGBA(renderer, d.x + x, d.y + x, d.x + d.w - x, d.y + d.h - x, 0x10, 0xD9, 0xD9, 0xff);
150 InputEvents::bypassKeyEvents =
false;
157 InputEvents::bypassKeyEvents =
true;
159 if (event->type == SDL_KEYDOWN)
160 return listenForPhysicalKeys(event);
161 if (event->type == SDL_KEYUP && (event->keyCode == SDLK_LSHIFT ||
162 event->keyCode == SDLK_RSHIFT ||
163 event->keyCode == SDLK_CAPSLOCK)) {
170 if (immersiveMode)
return false;
172 if (event->isTouchDown())
179 if (event->isKeyDown()) {
187 auto prevTouchDrag = isTouchDrag;
188 isTouchDrag = (
event->isTouchDrag() && (!touchMode || (curRow < 0 && index < 0))) || isTouchDrag;
189 if (prevTouchDrag != isTouchDrag && isTouchDrag) {
191 CST_LowRumble(event, 200);
195 if (!touchMode && !isTouchDrag)
197 if (curRow < 0 && index < 0)
205 if (event->isKeyDown())
207 int lastRow = curRow;
208 curRow += (
event->held(DOWN_BUTTON) -
event->held(UP_BUTTON));
209 index += (
event->held(RIGHT_BUTTON) -
event->held(LEFT_BUTTON));
211 if (curRow < 0) curRow = 0;
212 if (index < 0) index = 0;
213 if (curRow >= rowCount() + 1) curRow = rowCount();
214 if (curRow == rowCount())
217 if (lastRow < curRow && index > 0 && index < rowLength(lastRow))
223 if (index < 0) index = 0;
226 if (index > 2) index = 2;
230 if (index > rowLength(curRow))
231 index = rowLength(curRow);
233 if (lastRow == rowCount()) {
241 index = rowLength(curRow) / 2;
245 index = rowLength(curRow);
253 if (event->
held(A_BUTTON))
256 if (curRow >= rowCount())
285 int extWidth =
width + 305;
287 if ((event->isTouchDown() || event->isTouchDrag()) && event->
touchIn(this->x, this->y, extWidth, height + 200))
289 for (
int y = 0; y < rowCount(); y++)
290 for (
int x = 0; x < rowLength(y) + 1; x++) {
291 auto xStart = this->x + kXPad + x * kXOff + y * yYOff;
292 auto yStart = this->y + kYPad + y * ySpacing;
293 if (event->
touchIn(xStart, yStart, keyWidth, keyWidth))
303 if (event->isTouchUp())
310 if (event->
touchIn(this->x, this->y, extWidth, height + 200))
313 for (
int y = 0; y < rowCount(); y++)
314 for (
int x = 0; x < rowLength(y) + 1; x++)
315 if (event->
touchIn(this->x + kXPad + x * kXOff + y * yYOff, this->y + kYPad + y * ySpacing, keyWidth, keyWidth))
321 if (event->
touchIn(this->x + dPos, this->y + enterHeight, enterWidth, textSize))
327 if (event->
touchIn(this->x + sPos, this->y + dHeight, sWidth, textSize))
333 if (event->
touchIn(this->x + enterPos, this->y + enterHeight, enterWidth, textSize))
351bool EKeyboard::listenForPhysicalKeys(
InputEvents* e)
356 auto keyCode = e->keyCode;
360 if (keyCode == SDLK_LSHIFT || keyCode == SDLK_RSHIFT || keyCode == SDLK_CAPSLOCK) {
366 if (keyCode == SDLK_TAB) {
370 if (keyCode == SDLK_SPACE) {
374 if (keyCode == SDLK_RETURN && !preventEnterAndTab) {
380 if (keyCode == SDLK_LALT || keyCode == SDLK_RALT) {
381 immersiveMode = !immersiveMode;
386 auto roundedOffset = hasRoundedKeys ? 1 : 0;
387 for (
int x=roundedOffset; x<KEYCODE_COUNT; x++)
390 int topRowOffset = curBreak == 0 ? roundedOffset : 0;
392 if (keyCode == usbKeys[x])
396 type(curBreak, xx - topRowOffset);
398 index = xx - topRowOffset;
402 if (xx + 1 >= breaks[curBreak]) {
412 if (keyCode == SDLK_BACKSPACE) {
418 if (keyCode == SDLK_RETURN && preventEnterAndTab) {
422 sdlevent.type = SDL_JOYBUTTONDOWN;
423 sdlevent.jbutton.button = SDL_X;
424 SDL_PushEvent(&sdlevent);
428 if (keyCode == SDLK_ESCAPE) {
431 sdlevent.type = SDL_JOYBUTTONDOWN;
432 sdlevent.jbutton.button = SDL_Y;
433 SDL_PushEvent(&sdlevent);
440void EKeyboard::updateSize()
445 this->height = (304 / 900.0) *
width;
449 this->keyWidth = (int)(0.08 *
width);
450 this->padding = keyWidth / 2.0;
453 kXPad = (int)((23 / 400.0) *
width);
454 kXOff = (int)((36.5 / 400.0) *
width) + (900.0 /
width) * ( 900.0 !=
width);
455 yYOff = (int)((22 / 400.0) *
width);
456 kYPad = (int)((17 / 135.0) * height);
457 ySpacing = (int)((33 / 400.0) *
width);
459 if (hasRoundedKeys) {
462 kXOff = (int)((38 / 400.0) *
width) + (900.0 /
width) * ( 900.0 !=
width);
463 yYOff = (int)((10 / 400.0) *
width);
464 kYPad = (int)((0 / 135.0) * height);
465 ySpacing = (int)((37 / 400.0) *
width);
471 int kXPad = (int)((30 / 400.0) *
width);
472 int kXOff = (int)((22 / 400.0) *
width);
476 int kYPad = (int)((14 / 400.0) *
width);
478 int kYOff = (int)((33 / 400.0) *
width);
480 this->textSize = 0.9375 * keyWidth;
483 dPos = (int)((13 / 400.0) *
width);
484 dHeight = (int)((85 / 135.0) * height) + 145;
485 sPos = (int)((150 / 400.0) *
width);
486 enterPos = dPos + 1000;
487 enterHeight = dHeight - 34;
489 dWidth = (int)(1.4125 * textSize);
490 sWidth = (int)(7.5 * textSize);
491 enterWidth = (int)(2.25 * textSize);
496 CST_Color gray = { 0x52, 0x52, 0x52, 0xff };
498 int targetHeight = -1;
501 if (!hasRoundedKeys) {
502 for (
int x = 0; x < rowCount(); x++)
506 if (targetHeight < 0) {
507 targetHeight = rowText->height;
510 rowText->
position(kXPad + x * kXOff, kYPad + x * kYOff + targetHeight/2 - rowText->height/2);
516 CST_Color grayish = { 0x55, 0x55, 0x55, 0xff };
518 CST_Rect d4 = { this->x + sPos, this->y + dHeight, sWidth, textSize };
519 spaceText->
position(d4.x + d4.w / 2 - spaceText->
width / 2 - 15, 345);
520 this->
elements.push_back(spaceText);
522 if (!preventEnterAndTab)
525 CST_Rect d3 = { this->x + enterPos, this->y + enterHeight, enterWidth, textSize };
526 enterText->
position(d3.x + d3.w / 2 - enterText->
width / 2 - 30, 327);
527 this->
elements.push_back(enterText);
530 CST_Rect d5 = { this->x + dPos, this->y + enterHeight, enterWidth, textSize };
531 symText->
position(d5.x + d5.w / 2 - symText->
width / 2 - 30, 327);
537void EKeyboard::type(
int y,
int x)
539 const char input = (*(rows[y]))[x * 2];
544void EKeyboard::just_type(
const char input)
546 if (preventEnterAndTab && (input ==
'\n' || input ==
'\t'))
551 textInput.push_back(input);
554 if (typeAction != NULL) {
560void EKeyboard::generateEKeyboard()
566 keys = string((shiftOn || capsOn) ? upper_keys : lower_keys);
572 int offset = 47 * (mode - 1) + 0x00a1;
573 char chars[47 + (mode == 2)];
574 for (
int x = 0; x < 47 + (mode == 2); x++)
576 chars[x] = offset + x;
579 keys = string(chars);
582 breaks[3] += (mode == 2);
584 for (
int& end : breaks)
586 auto roundedOffset = (hasRoundedKeys && count == 0) ? 1 : 0;
587 string* row =
new string(keys.substr(count + roundedOffset, end - roundedOffset));
588 for (
int x = 1; x < (int)row->size(); x += 2)
590 row->insert(row->begin() + x,
' ');
597 if (hasRoundedKeys && roundKeyFont == NULL) {
599 roundKeyFont = CST_CreateFont();
600 auto fontPath = RAMFS
"res/lightsans.ttf";
601 auto renderer = getRenderer();
602 CST_LoadFont(roundKeyFont, renderer, fontPath, 40, CST_MakeColor(0,0,0,255), TTF_STYLE_NORMAL);
606void EKeyboard::backspace()
610 if (!textInput.empty())
611 textInput.pop_back();
620 sdlevent.type = SDL_JOYBUTTONDOWN;
621 sdlevent.jbutton.button = SDL_B;
622 SDL_PushEvent(&sdlevent);
625const std::string& EKeyboard::getTextInput()
630EKeyboard::~EKeyboard()
632 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