diff --git a/src/sdlutils.cpp b/src/sdlutils.cpp index a0a83aa..9b9e642 100644 --- a/src/sdlutils.cpp +++ b/src/sdlutils.cpp @@ -265,3 +265,15 @@ SDL_Texture *SDLUtils::renderText(const std::string &p_text, TTF_Font *p_font, c } return texture; } + +//------------------------------------------------------------------------------ + +// Width of one character in monospace font +int SDLUtils::getCharWidthMono(void) +{ + int w(0); + SDL_Texture *tex = SDLUtils::renderText("a", g_fontMono, {COLOR_TEXT_NORMAL}, {COLOR_BODY_BG}); + SDL_QueryTexture(tex, NULL, NULL, &w, NULL); + SDL_DestroyTexture(tex); + return w; +} diff --git a/src/sdlutils.h b/src/sdlutils.h index faa14f8..e59554f 100644 --- a/src/sdlutils.h +++ b/src/sdlutils.h @@ -49,6 +49,9 @@ namespace SDLUtils // Render text and return the texture SDL_Texture *renderText(const std::string &p_text, TTF_Font *p_font, const SDL_Color &p_fg, const SDL_Color &p_bg); + // Width of one character in monospace font + int getCharWidthMono(void); + } #endif diff --git a/src/textEditor.cpp b/src/textEditor.cpp index cc63b13..3b6706b 100644 --- a/src/textEditor.cpp +++ b/src/textEditor.cpp @@ -9,17 +9,12 @@ // Constructor TextEditor::TextEditor(const std::string &p_title): IWindow(true, p_title), - m_charW(0), + m_charW(SDLUtils::getCharWidthMono()), m_oldX(0) { // Init cursor m_inputTextCursor.x = 0; m_inputTextCursor.y = 0; - // Width of one character (monospace font) - SDL_Texture *tex = SDLUtils::renderText("a", g_fontMono, {COLOR_TEXT_NORMAL}, {COLOR_BODY_BG}); - SDL_QueryTexture(tex, NULL, NULL, &m_charW, NULL); - SDL_DestroyTexture(tex); - tex = NULL; // Read file std::ifstream ifs(p_title); if (! ifs.is_open()) diff --git a/src/textInput.cpp b/src/textInput.cpp index c9ba94c..4df2d99 100644 --- a/src/textInput.cpp +++ b/src/textInput.cpp @@ -1,3 +1,4 @@ +#include #include "textInput.h" #include "def.h" #include "sdlutils.h" @@ -7,8 +8,24 @@ TextInput::TextInput(const std::string &p_title, SDL_Texture *p_icon, const std::string p_inputText): IWindow(false, p_title), m_icon(p_icon), - m_inputText(p_inputText) + m_inputText(p_inputText), + m_charW(SDLUtils::getCharWidthMono()), + m_nbVisibleChars(0) { + // Cursor at the end of the text + m_cursor = m_inputText.size(); + // Dialog background + m_dialogBackground.w = SCREEN_WIDTH - 2*DIALOG_BORDER; + m_dialogBackground.h = 2*LINE_HEIGHT + DIALOG_BORDER; + m_dialogBackground.x = (SCREEN_WIDTH - m_dialogBackground.w) / 2; + m_dialogBackground.y = SCREEN_HEIGHT - Keyboard::getKeyboardH() - m_dialogBackground.h - DIALOG_BORDER; + // Dialog body + m_dialogBody.x = m_dialogBackground.x + DIALOG_BORDER; + m_dialogBody.y = m_dialogBackground.y + LINE_HEIGHT; + m_dialogBody.w = m_dialogBackground.w - 2*DIALOG_BORDER; + m_dialogBody.h = m_dialogBackground.h - LINE_HEIGHT - DIALOG_BORDER; + // Number of visible characters + m_nbVisibleChars = (m_dialogBody.w - 2*MARGIN_X) / m_charW; } //------------------------------------------------------------------------------ @@ -24,32 +41,27 @@ TextInput::~TextInput(void) void TextInput::render(const bool p_focus) { // Dialog background - SDL_Rect rectBackground; - rectBackground.w = SCREEN_WIDTH - 2*DIALOG_BORDER; - rectBackground.h = 2*LINE_HEIGHT + DIALOG_BORDER; - rectBackground.x = (SCREEN_WIDTH - rectBackground.w) / 2; - rectBackground.y = SCREEN_HEIGHT - Keyboard::getKeyboardH() - rectBackground.h - DIALOG_BORDER; SDL_SetRenderDrawColor(g_renderer, COLOR_TITLE_BG, 255); - SDL_RenderFillRect(g_renderer, &rectBackground); + SDL_RenderFillRect(g_renderer, &m_dialogBackground); // Dialog icon - SDLUtils::renderTexture(m_icon, rectBackground.x + MARGIN_X, rectBackground.y + LINE_HEIGHT/2, SDLUtils::T_ALIGN_LEFT, SDLUtils::T_ALIGN_MIDDLE); + SDLUtils::renderTexture(m_icon, m_dialogBackground.x + MARGIN_X, m_dialogBackground.y + LINE_HEIGHT/2, SDLUtils::T_ALIGN_LEFT, SDLUtils::T_ALIGN_MIDDLE); // Dialog title - SDLUtils::renderText(m_title, g_font, rectBackground.x + MARGIN_X + ICON_SIZE + MARGIN_X, rectBackground.y + LINE_HEIGHT/2, {COLOR_TEXT_NORMAL}, {COLOR_TITLE_BG}, SDLUtils::T_ALIGN_LEFT, SDLUtils::T_ALIGN_MIDDLE); + SDLUtils::renderText(m_title, g_font, m_dialogBackground.x + MARGIN_X + ICON_SIZE + MARGIN_X, m_dialogBackground.y + LINE_HEIGHT/2, {COLOR_TEXT_NORMAL}, {COLOR_TITLE_BG}, SDLUtils::T_ALIGN_LEFT, SDLUtils::T_ALIGN_MIDDLE); // Dialog body - SDL_Rect rectBody; - rectBody.x = rectBackground.x + DIALOG_BORDER; - rectBody.y = rectBackground.y + LINE_HEIGHT; - rectBody.w = rectBackground.w - 2*DIALOG_BORDER; - rectBody.h = rectBackground.h - LINE_HEIGHT - DIALOG_BORDER; SDL_SetRenderDrawColor(g_renderer, COLOR_BODY_BG, 255); - SDL_RenderFillRect(g_renderer, &rectBody); + SDL_RenderFillRect(g_renderer, &m_dialogBody); // Input text if (! m_inputText.empty()) - SDLUtils::renderText(m_inputText, g_fontMono, rectBody.x + MARGIN_X, rectBody.y + LINE_HEIGHT/2, {COLOR_TEXT_NORMAL}, {COLOR_BODY_BG}, SDLUtils::T_ALIGN_LEFT, SDLUtils::T_ALIGN_MIDDLE, rectBody.w - 2*MARGIN_X, SDLUtils::T_ALIGN_RIGHT); + SDLUtils::renderText(m_inputText.substr(m_camera.x, m_nbVisibleChars), g_fontMono, m_dialogBody.x + MARGIN_X, m_dialogBody.y + LINE_HEIGHT/2, {COLOR_TEXT_NORMAL}, {COLOR_BODY_BG}, SDLUtils::T_ALIGN_LEFT, SDLUtils::T_ALIGN_MIDDLE); + + // Cursor + SDL_SetRenderDrawColor(g_renderer, COLOR_TEXT_NORMAL, 255); + SDL_Rect rect = { m_dialogBody.x + MARGIN_X + (m_cursor - m_camera.x) * m_charW, m_dialogBody.y + 3, 1, LINE_HEIGHT - 6 }; + SDL_RenderFillRect(g_renderer, &rect); } //------------------------------------------------------------------------------ @@ -57,25 +69,41 @@ void TextInput::render(const bool p_focus) // Callbacks for virtual keyboard void TextInput::keyboardInputChar(const std::string &p_string) { - m_inputText.append(p_string); + m_inputText.insert(m_cursor, p_string); + m_cursor++; + adjustCamera(); g_hasChanged = true; } void TextInput::keyboardBackspace(void) { - if (! m_inputText.empty()) + if (m_cursor > 0 && ! m_inputText.empty()) { - m_inputText.pop_back(); + m_inputText.erase(m_cursor - 1, 1); + --m_cursor; + adjustCamera(); g_hasChanged = true; } } void TextInput::keyboardMoveLeft(void) { + if (m_cursor > 0) + { + --m_cursor; + adjustCamera(); + g_hasChanged = true; + } } void TextInput::keyboardMoveRight(void) { + if (m_cursor < static_cast(m_inputText.size())) + { + ++m_cursor; + adjustCamera(); + g_hasChanged = true; + } } //------------------------------------------------------------------------------ @@ -94,3 +122,18 @@ const std::string &TextInput::getInputText(void) const { return m_inputText; } + +//------------------------------------------------------------------------------ + +// Adjust camera +void TextInput::adjustCamera(void) +{ + if (static_cast(m_inputText.size()) <= m_nbVisibleChars) + m_camera.x = 0; + else if (m_cursor < m_camera.x) + m_camera.x = m_cursor; + else if (m_cursor > m_camera.x + m_nbVisibleChars) + m_camera.x = m_cursor - m_nbVisibleChars; + else if (m_camera.x > static_cast(m_inputText.size()) - m_nbVisibleChars && m_cursor > static_cast(m_inputText.size()) - m_nbVisibleChars) + m_camera.x = m_inputText.size() - m_nbVisibleChars; +} diff --git a/src/textInput.h b/src/textInput.h index 47f77e6..c1d038e 100644 --- a/src/textInput.h +++ b/src/textInput.h @@ -36,11 +36,24 @@ class TextInput : public IWindow virtual void keyboardMoveLeft(void); virtual void keyboardMoveRight(void); + // Adjust camera + void adjustCamera(void); + // Icon SDL_Texture *m_icon; // Input text std::string m_inputText; + + // Width of one character (monospace font) + int m_charW; + + // Number of visible characters + int m_nbVisibleChars; + + // Dialog background and body + SDL_Rect m_dialogBackground; + SDL_Rect m_dialogBody; }; #endif