Moved textbox input code out of InputManager

This commit is contained in:
Yousef Khadadeh 2026-04-03 23:02:33 +03:00
parent df3a78be1f
commit 262bf23bce
19 changed files with 343 additions and 329 deletions

View file

@ -6,6 +6,8 @@ namespace GUIStuff {
void Element::tick_update() {}
void Element::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { }
void Element::input_text_callback(const std::string& str) { }
void Element::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { }
void Element::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) { }
void Element::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) { }

View file

@ -25,6 +25,8 @@ namespace GUIStuff {
virtual void tick_update();
// Return true when mouse obstructs what's behind it
virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key);
virtual void input_text_callback(const std::string& str);
virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button);
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion);
virtual void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel);

View file

@ -5,6 +5,7 @@
#include <modules/skparagraph/include/TextStyle.h>
#include "../../FontData.hpp"
#include "../../InputManager.hpp"
#include "../../RichTextUserInput.hpp"
namespace GUIStuff {
@ -20,27 +21,39 @@ template <typename T> struct TextBoxData {
std::function<void()> onEnter;
};
struct TextEditData {
TextEditData(unsigned initTextboxInputID, const std::shared_ptr<RichText::TextBox>& initTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& initCursor, const std::function<void()>& onTextEdit):
textboxInputID(initTextboxInputID),
userInput(initTextBox, initCursor, nullptr, onTextEdit)
{}
unsigned textboxInputID;
RichTextUserInput userInput;
};
template <typename T> class TextBox : public Element {
public:
TextBox(GUIManager& gui);
void layout(const Clay_ElementId& id, const TextBoxData<T>& userInfo);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key) override;
virtual void input_text_callback(const std::string& str) override;
virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override;
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
virtual void input_key_callback(const InputManager::KeyCallbackArgs& key) override;
~TextBox();
private:
void init_textbox(UpdateInputData& io);
void reset_textbox_text();
bool update_data();
bool is_selected() const;
std::optional<TextEditData> edit;
std::optional<T> oldData;
bool isSelected = false;
TextBoxData<T> userInfo;
std::shared_ptr<RichText::TextBox> textbox;
std::shared_ptr<RichText::TextBox::Cursor> cur;
std::shared_ptr<SCollision::AABB<float>> rect;
};
}

View file

@ -28,7 +28,7 @@ template <typename T> void TextBox<T>::clay_draw(SkCanvas* canvas, UpdateInputDa
SkRect r = SkRect::MakeXYWH(bb.min.x(), bb.min.y(), bb.width(), bb.height());
canvas->drawRect(r, SkPaint(io.theme->backColor2));
SkPaint outline(isSelected ? io.theme->fillColor1 : io.theme->backColor2);
SkPaint outline(is_selected() ? io.theme->fillColor1 : io.theme->backColor2);
outline.setStroke(true);
outline.setStrokeWidth(2.0f);
outline.setAntiAlias(skiaAA);
@ -40,7 +40,7 @@ template <typename T> void TextBox<T>::clay_draw(SkCanvas* canvas, UpdateInputDa
yOffset -= textbox->get_height() * 0.5f;
RichText::TextBox::PaintOpts paintOpts;
if(isSelected) {
if(is_selected()) {
paintOpts.cursor = *cur;
SkRect cursorRect = textbox->get_cursor_rect(cur->pos);
canvas->translate(bb.min.x() - std::max(cursorRect.fRight - bb.width(), -2.0f), bb.min.y() + yOffset);
@ -61,45 +61,65 @@ template <typename T> void TextBox<T>::clay_draw(SkCanvas* canvas, UpdateInputDa
canvas->restore();
}
template <typename T> bool TextBox<T>::is_selected() const {
return edit.has_value();
}
template <typename T> void TextBox<T>::input_text_key_callback(const InputManager::KeyCallbackArgs& key) {
if(is_selected()) {
if(key.key == InputManager::KEY_GENERIC_ENTER && key.down) {
bool success = update_data();
gui.set_post_callback_func_high_priority([&, success] {
if(success && userInfo.onEdit) userInfo.onEdit();
if(userInfo.onEnter) userInfo.onEnter();
reset_textbox_text();
});
}
else
edit.value().userInput.input_key_callback(*gui.io.input, key);
}
}
template <typename T> void TextBox<T>::input_text_callback(const std::string& str) {
if(is_selected())
edit.value().userInput.add_text_to_textbox(str);
}
template <typename T> void TextBox<T>::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
auto& io = gui.io;
if(button.button == InputManager::MouseButton::LEFT && boundingBox.has_value()) {
if(button.down) {
if(mouseHovering) {
*rect = {(boundingBox.value().min + io.windowPos) * io.guiScaleMultiplier, (boundingBox.value().max + io.windowPos) * io.guiScaleMultiplier};
gui.io.input->set_rich_text_box_input_front(textbox, cur, false, rect, userInfo.textInputProps, nullptr);
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, true, gui.io.input->key(InputManager::KEY_TEXT_SHIFT).held);
isSelected = true;
SCollision::AABB<float> rect = {(boundingBox.value().min + io.windowPos) * io.guiScaleMultiplier, (boundingBox.value().max + io.windowPos) * io.guiScaleMultiplier};
unsigned id = gui.io.input->set_text_box_front(rect, userInfo.textInputProps);
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, true, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
edit = TextEditData(id, textbox, cur, [&] {
if(userInfo.immutable)
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data));
else {
if(update_data() && userInfo.onEdit)
gui.set_post_callback_func_high_priority(userInfo.onEdit);
}
});
}
else if(isSelected) {
gui.io.input->remove_rich_text_box_input(textbox);
else if(is_selected()) {
gui.io.input->remove_text_box(edit.value().textboxInputID);
if(update_data())
gui.set_post_callback_func_high_priority(userInfo.onEdit);
reset_textbox_text();
isSelected = false;
edit = std::nullopt;
}
}
else {
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, 0, false, gui.io.input->key(InputManager::KEY_TEXT_SHIFT).held);
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, 0, false, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
}
}
}
template <typename T> void TextBox<T>::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
if(boundingBox.has_value())
textbox->process_mouse_left_button(*cur, motion.pos - boundingBox.value().min, 0, gui.io.input->mouse.leftDown, gui.io.input->key(InputManager::KEY_TEXT_SHIFT).held);
}
template <typename T> void TextBox<T>::input_key_callback(const InputManager::KeyCallbackArgs& key) {
if(key.key == InputManager::KEY_TEXT_ENTER && key.down && isSelected) {
bool success = update_data();
gui.set_post_callback_func_high_priority([&, success] {
if(success && userInfo.onEdit) userInfo.onEdit();
if(userInfo.onEnter) userInfo.onEnter();
reset_textbox_text();
});
}
textbox->process_mouse_left_button(*cur, motion.pos - boundingBox.value().min, 0, gui.io.input->mouse.leftDown, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held);
}
template <typename T> void TextBox<T>::init_textbox(UpdateInputData& io) {
@ -109,17 +129,7 @@ template <typename T> void TextBox<T>::init_textbox(UpdateInputData& io) {
textbox->set_font_data(io.fonts);
textbox->set_allow_newlines(false);
cur = std::make_shared<RichText::TextBox::Cursor>();
rect = std::make_shared<SCollision::AABB<float>>();
}
textbox->onUserTextEdit = [&] {
if(userInfo.immutable)
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data));
else {
if(update_data() && userInfo.onEdit)
gui.set_post_callback_func_high_priority(userInfo.onEdit);
}
};
}
template <typename T> void TextBox<T>::reset_textbox_text() {
@ -138,7 +148,8 @@ template <typename T> bool TextBox<T>::update_data() {
}
template <typename T> TextBox<T>::~TextBox() {
gui.io.input->remove_rich_text_box_input(textbox);
if(is_selected())
gui.io.input->remove_text_box(edit.value().textboxInputID);
}
}