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