textbox: 'editable' property

This commit is contained in:
MihailRis 2024-03-04 20:16:22 +03:00
parent d41973583c
commit 9fbf46169f
4 changed files with 92 additions and 14 deletions

View File

@ -388,7 +388,7 @@ void TextBox::draw(const GfxContext* pctx, Assets* assets) {
lcoord.y -= 2;
auto batch = pctx->getBatch2D();
batch->texture(nullptr);
if (int((Window::time() - caretLastMove) * 2) % 2 == 0) {
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
uint line = label->getLineByTextIndex(caret);
uint lcaret = caret - label->getTextLineOffset(line);
batch->setColor(glm::vec4(1.0f));
@ -426,7 +426,7 @@ void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) {
batch->texture(nullptr);
if (valid) {
if (isFocused()) {
if (isFocused() && !multiline) {
batch->setColor(focusedColor);
} else if (hover && !multiline) {
batch->setColor(hoverColor);
@ -442,6 +442,17 @@ void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) {
input = supplier();
}
if (isFocused() && multiline) {
batch->setColor(glm::vec4(1, 1, 1, 0.1f));
glm::vec2 lcoord = label->calcCoord();
lcoord.y -= 4;
uint line = label->getLineByTextIndex(caret);
int lineY = label->getLineYOffset(line);
int lineHeight = font->getLineHeight() * label->getLineInterval();
batch->rect(lcoord.x, lcoord.y+lineY, label->getSize().x, 1);
batch->rect(lcoord.x, lcoord.y+lineY+lineHeight, label->getSize().x, 1);
}
label->setColor(glm::vec4(input.empty() ? 0.5f : 1.0f));
label->setText(getText());
if (multiline && font) {
@ -465,8 +476,8 @@ void TextBox::paste(const std::wstring& text) {
auto left = input.substr(0, caret);
auto right = input.substr(caret);
input = left + text + right;
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
}
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
// refresh label lines configuration for correct setCaret work
label->setText(input);
@ -560,6 +571,14 @@ bool TextBox::isMultiline() const {
return multiline;
}
void TextBox::setEditable(bool editable) {
this->editable = editable;
}
bool TextBox::isEditable() const {
return editable;
}
void TextBox::setOnEditStart(runnable oneditstart) {
onEditStart = oneditstart;
}
@ -621,9 +640,7 @@ void TextBox::resetMaxLocalCaret() {
maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
}
// TODO: refactor
void TextBox::keyPressed(keycode key) {
void TextBox::performEditingKeyboardEvents(keycode key) {
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
uint previousCaret = caret;
@ -726,6 +743,12 @@ void TextBox::keyPressed(keycode key) {
resetSelection();
}
}
}
void TextBox::keyPressed(keycode key) {
if (editable) {
performEditingKeyboardEvents(key);
}
if (Events::pressed(keycode::LEFT_CONTROL)) {
// Copy selected text to clipboard
if (key == keycode::C || key == keycode::X) {
@ -733,12 +756,12 @@ void TextBox::keyPressed(keycode key) {
if (!text.empty()) {
Window::setClipboardText(text.c_str());
}
if (key == keycode::X) {
if (editable && key == keycode::X) {
eraseSelected();
}
}
// Paste text from clipboard
if (key == keycode::V) {
if (key == keycode::V && editable) {
const char* text = Window::getClipboardText();
if (text) {
paste(util::str2wstr_utf8(text));

View File

@ -175,6 +175,7 @@ namespace gui {
size_t selectionOrigin = 0;
bool multiline = false;
bool editable = true;
size_t normalizeIndex(int index);
@ -192,34 +193,83 @@ namespace gui {
/// @brief Set maxLocalCaret to local (line) caret position
void resetMaxLocalCaret();
void performEditingKeyboardEvents(keycode key);
public:
TextBox(std::wstring placeholder,
glm::vec4 padding=glm::vec4(4.0f));
TextBox(
std::wstring placeholder,
glm::vec4 padding=glm::vec4(4.0f)
);
virtual void setTextSupplier(wstringsupplier supplier);
/// @brief Consumer called on stop editing text (textbox defocus)
/// @param consumer std::wstring consumer function
virtual void setTextConsumer(wstringconsumer consumer);
/// @brief Text validator called while text editing and returns true if
/// text is valid
/// @param validator std::wstring consumer returning boolean
virtual void setTextValidator(wstringchecker validator);
virtual void setFocusedColor(glm::vec4 color);
virtual glm::vec4 getFocusedColor() const;
/// @brief Set color of textbox marked by validator as invalid
virtual void setErrorColor(glm::vec4 color);
/// @brief Get color of textbox marked by validator as invalid
virtual glm::vec4 getErrorColor() const;
/// @brief Get TextBox content text or placeholder if empty
virtual std::wstring getText() const;
/// @brief Set TextBox content text
virtual void setText(std::wstring value);
/// @brief Get text placeholder
virtual std::wstring getPlaceholder() const;
virtual void setPlaceholder(const std::wstring&);
/// @brief Set text placeholder
/// @param text will be used instead of empty
virtual void setPlaceholder(const std::wstring& text);
/// @brief Get selected text
virtual std::wstring getSelection() const;
/// @brief Get current caret position in text
/// @return integer in range [0, text.length()]
virtual uint getCaret() const;
/// @brief Set caret position in the text
/// @param position integer in range [0, text.length()]
virtual void setCaret(uint position);
/// @brief Select part of the text
/// @param start index of the first selected character
/// @param end index of the last selected character + 1
virtual void select(int start, int end);
/// @brief Check text with validator set with setTextValidator
/// @return true if text is valid
virtual bool validate();
virtual void setValid(bool valid);
virtual bool isValid() const;
// multiline mode is in development
/// @brief Enable/disable multiline mode
virtual void setMultiline(bool multiline);
/// @brief Check if multiline mode is enabled
virtual bool isMultiline() const;
/// @brief Enable/disable text editing feature
virtual void setEditable(bool editable);
/// @brief Check if text editing feature is enabled
virtual bool isEditable() const;
/// @brief Set runnable called on textbox focus
virtual void setOnEditStart(runnable oneditstart);
virtual void focus(GUI*) override;

View File

@ -221,6 +221,10 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
if (element->has("multiline")) {
textbox->setMultiline(element->attr("multiline").asBool());
}
if (element->has("editable")) {
textbox->setEditable(element->attr("editable").asBool());
}
if (element->has("consumer")) {
auto consumer = scripting::create_wstring_consumer(

View File

@ -353,8 +353,9 @@ void Hud::update(bool visible) {
setPause(true);
}
}
if (visible && !gui->isFocusCaught() && Events::jactive(BIND_HUD_INVENTORY)) {
if (!pause) {
if (visible && !gui->isFocusCaught() && !pause) {
if (Events::jactive(BIND_HUD_INVENTORY)) {
if (inventoryOpen) {
closeInventory();
} else {