union-minui/other/DinguxCommander/src/keyboard.cpp
2023-04-15 10:36:01 +02:00

483 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include "keyboard.h"
#include "sdlutils.h"
#include "resourceManager.h"
#include "def.h"
#define KB_X 28
#define KB_Y 128
#define FIELD_Y 98
#define FIELD_W 258
CKeyboard::CKeyboard(const std::string &p_inputText):
CWindow(),
m_imageKeyboard(NULL),
m_textField(NULL),
m_inputText(p_inputText),
m_selected(0),
m_footer(NULL),
m_keySet(0),
m_font(CResourceManager::instance().getFont()),
m_font_sm(CResourceManager::instance().getSmallFont())
{
// Key sets
m_keySets[0] = "abcdefghijklmnopqrstuvwxyz0123456789., ";
m_keySets[1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789., ";
m_keySets[2] = "!#$%&'()[]{}+-;=@^_`´~¡¿¢£¤¥¦§«»±×÷©®° ";
m_keySets[3] = "áàäâãåéèëêæœçíìïîóòöôõðøñþúùüûýÿøßµ¹²³ ";
m_keySets[4] = "ÁÀÄÂÃÅÉÈËÊÆŒÇÍÌÏÎÓÒÖÔÕÐØÑÞÚÙÜÛÝŸØßµ¼½¾ ";
// Create keyboard image
{
SDL_Rect l_rect;
// Create keyboard image
m_imageKeyboard = SDL_utils::createImage(265, 84, SDL_MapRGB(Globals::g_screen->format, COLOR_BORDER));
l_rect.x = 2;
l_rect.y = 2;
l_rect.w = 261;
l_rect.h = 80;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BG_2));
// Keys
for (unsigned int l_y = 0; l_y < 3; ++l_y)
{
for (unsigned int l_x = 0; l_x < 13; ++l_x)
{
l_rect.x = 3 + 20 * l_x;
l_rect.y = 3 + 20 * l_y;
l_rect.w = 19;
l_rect.h = 18;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BORDER));
++l_rect.x;
++l_rect.y;
l_rect.w -= 2;
l_rect.h -= 2;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BG_1));
}
}
// Buttons Cancel and OK
l_rect.x = 3;
l_rect.y = 63;
l_rect.w = 129;
l_rect.h = 18;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BORDER));
l_rect.x = 133;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BORDER));
l_rect.w -= 2;
l_rect.h -= 2;
++l_rect.y;
l_rect.x = 4;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BG_1));
l_rect.x = 134;
SDL_FillRect(m_imageKeyboard, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BG_1));
// Create text field image
m_textField = SDL_utils::createImage(265, 19, SDL_MapRGB(Globals::g_screen->format, COLOR_BORDER));
l_rect.x = 2;
l_rect.y = 2;
l_rect.w = 261;
l_rect.h = 15;
SDL_FillRect(m_textField, &l_rect, SDL_MapRGB(m_imageKeyboard->format, COLOR_BG_1));
}
// Create footer
m_footer = SDL_utils::createImage(SCREEN_WIDTH, H_FOOTER, SDL_MapRGB(Globals::g_screen->format, COLOR_BORDER));
SDL_utils::applyText(SCREEN_WIDTH >> 1, 1, m_footer, m_font_sm, "A-Input B-Cancel START-OK L/R-Change Y-Backspace X-Space", Globals::g_colorTextTitle, SDL_utils::T_TEXT_ALIGN_CENTER);
}
CKeyboard::~CKeyboard(void)
{
// Free surfaces
if (m_imageKeyboard != NULL)
{
SDL_FreeSurface(m_imageKeyboard);
m_imageKeyboard = NULL;
}
if (m_textField != NULL)
{
SDL_FreeSurface(m_textField);
m_textField = NULL;
}
if (m_footer != NULL)
{
SDL_FreeSurface(m_footer);
m_footer = NULL;
}
}
void CKeyboard::render(const bool p_focus) const
{
INHIBIT(std::cout << "CKeyboard::render fullscreen: " << isFullScreen() << " focus: " << p_focus << std::endl;)
// Draw input text field
SDL_utils::applySurface(KB_X, FIELD_Y, m_textField, Globals::g_screen);
// Input text
if (!m_inputText.empty())
{
SDL_Surface *l_surfaceTmp = SDL_utils::renderText(m_font, m_inputText, Globals::g_colorTextNormal);
if (l_surfaceTmp->w > FIELD_W)
{
// Text is too big => clip it
SDL_Rect l_rect;
l_rect.x = l_surfaceTmp->w - FIELD_W;
l_rect.y = 0;
l_rect.w = FIELD_W;
l_rect.h = l_surfaceTmp->h;
SDL_utils::applySurface(KB_X + 5, FIELD_Y + 4 - Y_OFFSET, l_surfaceTmp, Globals::g_screen, &l_rect);
}
else
SDL_utils::applySurface(KB_X + 5, FIELD_Y + 4 - Y_OFFSET, l_surfaceTmp, Globals::g_screen);
}
// Draw keyboard
SDL_utils::applySurface(KB_X, KB_Y, m_imageKeyboard, Globals::g_screen);
// Cursor
{
SDL_Rect l_rect;
if (m_selected < 39)
{
// A letter is selected
l_rect.w = 17;
l_rect.h = 16;
l_rect.x = KB_X + 4;
if (m_selected >= 26)
{
l_rect.x = KB_X + 4 + (m_selected - 26) * 20;
l_rect.y = KB_Y + 44;
}
else if (m_selected >= 13)
{
l_rect.x = KB_X + 4 + (m_selected - 13) * 20;
l_rect.y = KB_Y + 24;
}
else
{
l_rect.x = KB_X + 4 + m_selected * 20;
l_rect.y = KB_Y + 4;
}
}
else
{
l_rect.w = 127;
l_rect.h = 16;
l_rect.x = KB_X + 4 + (m_selected == 40) * 130;
l_rect.y = KB_Y + 64;
}
SDL_FillRect(Globals::g_screen, &l_rect, SDL_MapRGB(Globals::g_screen->format, COLOR_CURSOR_1));
}
// Draw keys text
{
unsigned int l_i(0);
unsigned int l_x(0);
unsigned int l_y(0);
std::string l_text("");
for (l_y = 0; l_y < 3; ++l_y)
{
for (l_x = 0; l_x < 13; ++l_x)
{
if (utf8Code(m_keySets[m_keySet].at(l_i)))
{
l_text = m_keySets[m_keySet].substr(l_i, 2);
l_i += 2;
}
else
{
l_text = m_keySets[m_keySet].substr(l_i, 1);
l_i += 1;
}
SDL_utils::applyText(KB_X + 20 * l_x + 13, KB_Y + 7 + 20 * l_y - Y_OFFSET, Globals::g_screen, m_font, l_text, Globals::g_colorTextNormal, SDL_utils::T_TEXT_ALIGN_CENTER);
}
}
}
// Buttons text
SDL_utils::applyText(KB_X + 67, KB_Y + 67 - Y_OFFSET, Globals::g_screen, m_font, "Cancel", Globals::g_colorTextNormal, SDL_utils::T_TEXT_ALIGN_CENTER);
SDL_utils::applyText(KB_X + 197, KB_Y + 67 - Y_OFFSET, Globals::g_screen, m_font, "OK", Globals::g_colorTextNormal, SDL_utils::T_TEXT_ALIGN_CENTER);
// Draw footer
SDL_utils::applySurface(0, 227, m_footer, Globals::g_screen);
}
const bool CKeyboard::keyPress(const SDL_Event &p_event)
{
CWindow::keyPress(p_event);
bool l_ret(false);
switch (p_event.key.keysym.sym)
{
case MYKEY_PARENT:
// B => Cancel
m_retVal = -1;
l_ret = true;
break;
case MYKEY_UP:
l_ret = moveCursorUp(true);
break;
case MYKEY_DOWN:
l_ret = moveCursorDown(true);
break;
case MYKEY_LEFT:
l_ret = moveCursorLeft(true);
break;
case MYKEY_RIGHT:
l_ret = moveCursorRight(true);
break;
case MYKEY_SYSTEM:
// Y => Backspace
l_ret = backspace();
break;
case MYKEY_OPERATION:
// X => Space
l_ret = type(" ");
break;
case MYKEY_OPEN:
// A => Button pressed
if (m_selected == 39)
{
// Button Cancel
m_retVal = -1;
l_ret = true;
}
else if (m_selected == 40)
{
// Button OK
m_retVal = 1;
l_ret = true;
}
else
// A letter button
l_ret = type();
break;
case MYKEY_PAGEDOWN:
// R => Change keys forward
m_keySet = (m_keySet + 1) % NB_KEY_SETS;
l_ret = true;
break;
case MYKEY_PAGEUP:
// L => Change keys backward
m_keySet = m_keySet ? m_keySet - 1 : NB_KEY_SETS - 1;
l_ret = true;
break;
case MYKEY_TRANSFER:
// START => OK
m_retVal = 1;
l_ret = true;
default:
break;
}
return l_ret;
}
const bool CKeyboard::keyHold(void)
{
bool l_ret(false);
switch(m_lastPressed)
{
case MYKEY_UP:
if (tick(SDL_GetKeyState(NULL)[MYKEY_UP]))
l_ret = moveCursorUp(false);
break;
case MYKEY_DOWN:
if (tick(SDL_GetKeyState(NULL)[MYKEY_DOWN]))
l_ret = moveCursorDown(false);
break;
case MYKEY_LEFT:
if (tick(SDL_GetKeyState(NULL)[MYKEY_LEFT]))
l_ret = moveCursorLeft(false);
break;
case MYKEY_RIGHT:
if (tick(SDL_GetKeyState(NULL)[MYKEY_RIGHT]))
l_ret = moveCursorRight(false);
break;
case MYKEY_OPEN:
// A => Add letter
if (tick(SDL_GetKeyState(NULL)[MYKEY_OPEN]))
l_ret = type();
break;
case MYKEY_SYSTEM:
// Y => Backspace
if (tick(SDL_GetKeyState(NULL)[MYKEY_SYSTEM]))
l_ret = backspace();
break;
case MYKEY_OPERATION:
// X => Space
if (tick(SDL_GetKeyState(NULL)[MYKEY_OPERATION]))
l_ret = type(" ");
break;
default:
break;
}
return l_ret;
}
const bool CKeyboard::moveCursorUp(const bool p_loop)
{
bool l_ret(false);
if (m_selected == 39)
{
m_selected = 29;
l_ret = true;
}
else if (m_selected == 40)
{
m_selected = 35;
l_ret = true;
}
else if (m_selected >= 13)
{
m_selected -= 13;
l_ret = true;
}
else if (m_selected >= 6)
{
if (p_loop)
{
m_selected = 40;
l_ret = true;
}
}
else
{
if (p_loop)
{
m_selected = 39;
l_ret = true;
}
}
return l_ret;
}
const bool CKeyboard::moveCursorDown(const bool p_loop)
{
bool l_ret(false);
if (m_selected == 39)
{
if (p_loop)
{
m_selected = 3;
l_ret = true;
}
}
else if (m_selected == 40)
{
if (p_loop)
{
m_selected = 9;
l_ret = true;
}
}
else if (m_selected >= 32)
{
m_selected = 40;
l_ret = true;
}
else if (m_selected >= 26)
{
m_selected = 39;
l_ret = true;
}
else
{
m_selected += 13;
l_ret = true;
}
return l_ret;
}
const bool CKeyboard::moveCursorLeft(const bool p_loop)
{
bool l_ret(false);
switch (m_selected)
{
case 0:
case 13:
case 26:
if (p_loop)
{
m_selected += 12;
l_ret = true;
}
break;
case 39:
if (p_loop)
{
m_selected = 40;
l_ret = true;
}
break;
default:
--m_selected;
l_ret = true;
break;
}
return l_ret;
}
const bool CKeyboard::moveCursorRight(const bool p_loop)
{
bool l_ret(false);
switch (m_selected)
{
case 12:
case 25:
case 38:
if (p_loop)
{
m_selected -= 12;
l_ret = true;
}
break;
case 40:
if (p_loop)
{
m_selected = 39;
l_ret = true;
}
break;
default:
++m_selected;
l_ret = true;
break;
}
return l_ret;
}
const bool CKeyboard::type(const std::string &p_text)
{
if (p_text.empty())
{
// Append selected character to the input text
if (m_selected < 39)
{
// Get real index
unsigned char l_index(0);
for (unsigned char l_c = 0; l_c < m_selected; ++l_c)
l_index += 1 + utf8Code(m_keySets[m_keySet].at(l_index));
// Get size
size_t l_size = 1 + utf8Code(m_keySets[m_keySet].at(l_index));
// Append text
m_inputText += m_keySets[m_keySet].substr(l_index, l_size);
}
else
std::cerr << "CKeyboard::type : unexpected value: " << m_selected << std::endl;
}
else
// Append given text
m_inputText += p_text;
return true;
}
const std::string &CKeyboard::getInputText(void) const
{
return m_inputText;
}
const bool CKeyboard::backspace(void)
{
bool l_ret(false);
if (!m_inputText.empty())
{
if (m_inputText.size() >= 2 && utf8Code(m_inputText.at(m_inputText.size() - 2)))
m_inputText.resize(m_inputText.size() - 2);
else
m_inputText.resize(m_inputText.size() - 1);
l_ret = true;
}
return l_ret;
}
const bool CKeyboard::utf8Code(const unsigned char p_c) const
{
return (p_c >= 194 && p_c <= 198) || p_c == 208 || p_c == 209;
}