diff --git a/src/frontend/gui/controls.cpp b/src/frontend/gui/controls.cpp index 25d9f7499..cdfb7cddd 100644 --- a/src/frontend/gui/controls.cpp +++ b/src/frontend/gui/controls.cpp @@ -36,6 +36,14 @@ std::wstring Label::getText() const { return text; } +void Label::setFontName(std::string name) { + this->fontName = name; +} + +const std::string& Label::getFontName() const { + return fontName; +} + void Label::draw(const GfxContext* pctx, Assets* assets) { if (supplier) { setText(supplier()); @@ -246,6 +254,24 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding) setHoverColor(glm::vec4(0.05f, 0.1f, 0.2f, 0.75f)); } +void TextBox::draw(const GfxContext* pctx, Assets* assets) { + Panel::draw(pctx, assets); + + if (!isFocused()) + return; + + if (int((Window::time() - caretLastMove) * 2) % 2 == 0) { + auto batch = pctx->getBatch2D(); + batch->texture(nullptr); + batch->color = glm::vec4(1.0f); + + glm::vec2 lcoord = label->calcCoord(); + auto font = assets->getFont(label->getFontName()); + int width = font->calcWidth(input.substr(0, caret)); + batch->rect(lcoord.x + width, lcoord.y, 2, font->getLineHeight()); + } +} + void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) { glm::vec2 coord = calcCoord(); @@ -279,11 +305,22 @@ void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) { setScrollable(false); } -void TextBox::typed(unsigned int codepoint) { - input += std::wstring({(wchar_t)codepoint}); +void TextBox::paste(const std::wstring& text) { + if (caret >= input.length()) { + input += text; + } else { + auto left = input.substr(0, caret); + auto right = input.substr(caret); + input = left + text + right; + } + caret += text.length(); validate(); } +void TextBox::typed(unsigned int codepoint) { + paste(std::wstring({(wchar_t)codepoint})); +} + bool TextBox::validate() { if (validator) { valid = validator(getText()); @@ -308,6 +345,7 @@ void TextBox::setOnEditStart(runnable oneditstart) { void TextBox::focus(GUI* gui) { Panel::focus(gui); if (onEditStart){ + caret = input.size(); onEditStart(); } } @@ -319,22 +357,39 @@ void TextBox::refresh() { void TextBox::keyPressed(int key) { if (key == keycode::BACKSPACE) { - if (!input.empty()){ - input = input.substr(0, input.length()-1); + if (caret > 0 && input.length() > 0) { + if (caret > input.length()) { + caret = input.length(); + } + input = input.substr(0, caret-1) + input.substr(caret); + caret--; validate(); } } else if (key == keycode::ENTER) { if (validate() && consumer) { consumer(label->getText()); } - defocus(); + defocus(); + } else if (key == keycode::LEFT) { + if (caret > 0) { + if (caret > input.length()) { + caret = input.length()-1; + } else { + caret--; + } + caretLastMove = Window::time(); + } + } else if (key == keycode::RIGHT) { + if (caret < input.length()) { + caret++; + caretLastMove = Window::time(); + } } // Pasting text from clipboard if (key == keycode::V && Events::pressed(keycode::LEFT_CONTROL)) { const char* text = Window::getClipboardText(); if (text) { - input += util::str2wstr_utf8(text); - validate(); + paste(util::str2wstr_utf8(text)); } } } @@ -389,6 +444,14 @@ void TextBox::setPlaceholder(const std::wstring& placeholder) { this->placeholder = placeholder; } +uint TextBox::getCaret() const { + return caret; +} + +void TextBox::setCaret(uint position) { + this->caret = position; +} + // ============================== InputBindBox ================================ InputBindBox::InputBindBox(Binding& binding, glm::vec4 padding) : Panel(glm::vec2(100,32), padding, 0), diff --git a/src/frontend/gui/controls.h b/src/frontend/gui/controls.h index 60cb43375..ee606d999 100644 --- a/src/frontend/gui/controls.h +++ b/src/frontend/gui/controls.h @@ -29,6 +29,9 @@ namespace gui { virtual void setText(std::wstring text); std::wstring getText() const; + virtual void setFontName(std::string name); + const std::string& getFontName() const; + virtual void draw(const GfxContext* pctx, Assets* assets) override; virtual void textSupplier(wstringsupplier supplier); @@ -105,12 +108,18 @@ namespace gui { wstringchecker validator = nullptr; runnable onEditStart = nullptr; bool valid = true; + /// @brief text input pointer, value may be greather than text length + uint caret = 0; + double caretLastMove = 0.0; + + void paste(const std::wstring& text); public: TextBox(std::wstring placeholder, glm::vec4 padding=glm::vec4(4.0f)); virtual std::shared_ptr getAt(glm::vec2 pos, std::shared_ptr self) override; + virtual void draw(const GfxContext* pctx, Assets* assets) override; virtual void drawBackground(const GfxContext* pctx, Assets* assets) override; virtual void typed(unsigned int codepoint) override; virtual void keyPressed(int key) override; @@ -128,6 +137,8 @@ namespace gui { virtual void setText(std::wstring value); virtual std::wstring getPlaceholder() const; virtual void setPlaceholder(const std::wstring&); + virtual uint getCaret() const; + virtual void setCaret(uint position); virtual bool validate(); virtual void setValid(bool valid); virtual bool isValid() const; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index e46b62ee3..1d97ec3c7 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -385,13 +385,15 @@ void Hud::update(bool visible) { contentAccess->setMinSize(glm::vec2(1, Window::height)); hotbarView->setVisible(visible); - for (int i = keycode::NUM_1; i <= keycode::NUM_9; i++) { - if (Events::jpressed(i)) { - player->setChosenSlot(i - keycode::NUM_1); + if (!gui->isFocusCaught() && !pause) { + for (int i = keycode::NUM_1; i <= keycode::NUM_9; i++) { + if (Events::jpressed(i)) { + player->setChosenSlot(i - keycode::NUM_1); + } + } + if (Events::jpressed(keycode::NUM_0)) { + player->setChosenSlot(9); } - } - if (Events::jpressed(keycode::NUM_0)) { - player->setChosenSlot(9); } if (!pause && !inventoryOpen && Events::scroll) { int slot = player->getChosenSlot();