add history to TextBox
This commit is contained in:
parent
223a846784
commit
4c493aff25
@ -108,7 +108,7 @@ void GUI::actMouse(float delta) {
|
|||||||
doubleClicked = false;
|
doubleClicked = false;
|
||||||
doubleClickTimer += delta + mouseDelta * 0.1f;
|
doubleClickTimer += delta + mouseDelta * 0.1f;
|
||||||
|
|
||||||
auto hover = container->getAt(Events::cursor, nullptr);
|
auto hover = container->getAt(Events::cursor);
|
||||||
if (this->hover && this->hover != hover) {
|
if (this->hover && this->hover != hover) {
|
||||||
this->hover->setHover(false);
|
this->hover->setHover(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,9 +17,7 @@ Container::~Container() {
|
|||||||
Container::clear();
|
Container::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UINode> Container::getAt(
|
std::shared_ptr<UINode> Container::getAt(const glm::vec2& pos) {
|
||||||
const glm::vec2& pos, const std::shared_ptr<UINode>& self
|
|
||||||
) {
|
|
||||||
if (!isInteractive() || !isEnabled()) {
|
if (!isInteractive() || !isEnabled()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -28,19 +26,19 @@ std::shared_ptr<UINode> Container::getAt(
|
|||||||
}
|
}
|
||||||
int diff = (actualLength-size.y);
|
int diff = (actualLength-size.y);
|
||||||
if (scrollable && diff > 0 && pos.x > calcPos().x + getSize().x - scrollBarWidth) {
|
if (scrollable && diff > 0 && pos.x > calcPos().x + getSize().x - scrollBarWidth) {
|
||||||
return UINode::getAt(pos, self);
|
return UINode::getAt(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = nodes.size()-1; i >= 0; i--) {
|
for (int i = nodes.size()-1; i >= 0; i--) {
|
||||||
auto& node = nodes[i];
|
auto& node = nodes[i];
|
||||||
if (!node->isVisible())
|
if (!node->isVisible())
|
||||||
continue;
|
continue;
|
||||||
auto hover = node->getAt(pos, node);
|
auto hover = node->getAt(pos);
|
||||||
if (hover != nullptr) {
|
if (hover != nullptr) {
|
||||||
return hover;
|
return hover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UINode::getAt(pos, self);
|
return UINode::getAt(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::mouseMove(GUI* gui, int x, int y) {
|
void Container::mouseMove(GUI* gui, int x, int y) {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ namespace gui {
|
|||||||
virtual void act(float delta) override;
|
virtual void act(float delta) override;
|
||||||
virtual void drawBackground(const DrawContext& pctx, const Assets& assets);
|
virtual void drawBackground(const DrawContext& pctx, const Assets& assets);
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||||
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos, const std::shared_ptr<UINode>& self) override;
|
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos) override;
|
||||||
virtual void add(const std::shared_ptr<UINode>& node);
|
virtual void add(const std::shared_ptr<UINode>& node);
|
||||||
virtual void add(const std::shared_ptr<UINode>& node, glm::vec2 pos);
|
virtual void add(const std::shared_ptr<UINode>& node, glm::vec2 pos);
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
@ -13,18 +13,177 @@
|
|||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include "window/Events.hpp"
|
#include "window/Events.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
|
#include "devtools/actions.hpp"
|
||||||
#include "../markdown.hpp"
|
#include "../markdown.hpp"
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
inline constexpr int LINE_NUMBERS_PANE_WIDTH = 40;
|
inline constexpr int LINE_NUMBERS_PANE_WIDTH = 40;
|
||||||
|
|
||||||
|
class InputAction : public Action {
|
||||||
|
std::weak_ptr<TextBox> textbox;
|
||||||
|
size_t position;
|
||||||
|
std::wstring string;
|
||||||
|
public:
|
||||||
|
InputAction(
|
||||||
|
std::weak_ptr<TextBox> textbox, size_t position, std::wstring string
|
||||||
|
)
|
||||||
|
: textbox(std::move(textbox)),
|
||||||
|
position(position),
|
||||||
|
string(std::move(string)) {
|
||||||
|
}
|
||||||
|
void apply() override {
|
||||||
|
if (auto box = textbox.lock()) {
|
||||||
|
box->select(position, position);
|
||||||
|
box->paste(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void revert() override {
|
||||||
|
if (auto box = textbox.lock()) {
|
||||||
|
box->select(position, position);
|
||||||
|
box->erase(position, string.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectionAction : public Action {
|
||||||
|
std::weak_ptr<TextBox> textbox;
|
||||||
|
size_t start;
|
||||||
|
size_t end;
|
||||||
|
public:
|
||||||
|
SelectionAction(std::weak_ptr<TextBox> textbox, size_t start, size_t end)
|
||||||
|
: textbox(std::move(textbox)), start(start), end(end) {}
|
||||||
|
|
||||||
|
void apply() override {
|
||||||
|
if (auto box = textbox.lock()) {
|
||||||
|
box->select(start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void revert() override {
|
||||||
|
if (auto box = textbox.lock()) {
|
||||||
|
box->select(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
/// @brief Accumulates small changes into words for InputAction creation
|
||||||
|
class TextBoxHistorian {
|
||||||
|
public:
|
||||||
|
TextBoxHistorian(TextBox& textBox, ActionsHistory& history)
|
||||||
|
: textBox(textBox), history(history) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPaste(size_t pos, std::wstring_view text) {
|
||||||
|
if (locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (erasing) {
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
if (this->pos == static_cast<size_t>(-1)) {
|
||||||
|
this->pos = pos;
|
||||||
|
}
|
||||||
|
if (this->pos + length != pos || text == L" " || text == L"\n") {
|
||||||
|
sync();
|
||||||
|
this->pos = pos;
|
||||||
|
}
|
||||||
|
ss << text;
|
||||||
|
length += text.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onErase(size_t pos, std::wstring_view text, bool selection=false) {
|
||||||
|
if (locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!erasing) {
|
||||||
|
sync();
|
||||||
|
erasing = true;
|
||||||
|
}
|
||||||
|
if (selection) {
|
||||||
|
history.store(
|
||||||
|
std::make_unique<SelectionAction>(
|
||||||
|
getTextBoxWeakptr(),
|
||||||
|
textBox.getSelectionStart(),
|
||||||
|
textBox.getSelectionEnd()
|
||||||
|
),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this->pos == static_cast<size_t>(-1)) {
|
||||||
|
this->pos = pos;
|
||||||
|
} else if (this->pos - text.length() != pos) {
|
||||||
|
sync();
|
||||||
|
erasing = true;
|
||||||
|
this->pos = pos;
|
||||||
|
}
|
||||||
|
if (text == L" " || text == L"\n") {
|
||||||
|
sync();
|
||||||
|
erasing = true;
|
||||||
|
this->pos = pos;
|
||||||
|
}
|
||||||
|
auto str = ss.str();
|
||||||
|
ss.seekp(0);
|
||||||
|
ss << text << str;
|
||||||
|
|
||||||
|
this->pos = pos;
|
||||||
|
length += text.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Flush buffer and push all changes to the ActionsHistory
|
||||||
|
void sync() {
|
||||||
|
auto string = ss.str();
|
||||||
|
if (string.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto action =
|
||||||
|
std::make_unique<InputAction>(getTextBoxWeakptr(), pos, string);
|
||||||
|
history.store(std::move(action), erasing);
|
||||||
|
pos = -1;
|
||||||
|
length = 0;
|
||||||
|
ss = {};
|
||||||
|
erasing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() {
|
||||||
|
sync();
|
||||||
|
locked = true;
|
||||||
|
history.undo();
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void redo() {
|
||||||
|
sync();
|
||||||
|
locked = true;
|
||||||
|
history.redo();
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
TextBox& textBox;
|
||||||
|
ActionsHistory& history;
|
||||||
|
std::wstringstream ss;
|
||||||
|
size_t pos = -1;
|
||||||
|
size_t length = 0;
|
||||||
|
bool erasing = false;
|
||||||
|
bool locked = false;
|
||||||
|
|
||||||
|
std::weak_ptr<TextBox> getTextBoxWeakptr() {
|
||||||
|
return std::weak_ptr<TextBox>(std::dynamic_pointer_cast<TextBox>(
|
||||||
|
textBox.shared_from_this()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
||||||
: Container(glm::vec2(200,32)),
|
: Container(glm::vec2(200, 32)),
|
||||||
|
history(std::make_shared<ActionsHistory>()),
|
||||||
|
historian(std::make_unique<TextBoxHistorian>(*this, *history)),
|
||||||
padding(padding),
|
padding(padding),
|
||||||
input(L""),
|
input(L""),
|
||||||
placeholder(std::move(placeholder))
|
placeholder(std::move(placeholder)) {
|
||||||
{
|
|
||||||
setCursor(CursorShape::TEXT);
|
setCursor(CursorShape::TEXT);
|
||||||
setOnUpPressed(nullptr);
|
setOnUpPressed(nullptr);
|
||||||
setOnDownPressed(nullptr);
|
setOnDownPressed(nullptr);
|
||||||
@ -49,6 +208,8 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
|||||||
scrollStep = 0;
|
scrollStep = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextBox::~TextBox() = default;
|
||||||
|
|
||||||
void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
|
void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
|
||||||
Container::draw(pctx, assets);
|
Container::draw(pctx, assets);
|
||||||
|
|
||||||
@ -71,6 +232,7 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
auto batch = pctx.getBatch2D();
|
auto batch = pctx.getBatch2D();
|
||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
batch->setColor(glm::vec4(1.0f));
|
batch->setColor(glm::vec4(1.0f));
|
||||||
|
|
||||||
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
|
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
|
||||||
uint line = rawTextCache.getLineByTextIndex(caret);
|
uint line = rawTextCache.getLineByTextIndex(caret);
|
||||||
uint lcaret = caret - rawTextCache.getTextLineOffset(line);
|
uint lcaret = caret - rawTextCache.getTextLineOffset(line);
|
||||||
@ -260,18 +422,22 @@ void TextBox::refreshLabel() {
|
|||||||
|
|
||||||
/// @brief Insert text at the caret. Also selected text will be erased
|
/// @brief Insert text at the caret. Also selected text will be erased
|
||||||
/// @param text Inserting text
|
/// @param text Inserting text
|
||||||
void TextBox::paste(const std::wstring& text) {
|
void TextBox::paste(const std::wstring& text, bool history) {
|
||||||
eraseSelected();
|
eraseSelected();
|
||||||
|
auto inputText = text;
|
||||||
|
inputText.erase(
|
||||||
|
std::remove(inputText.begin(), inputText.end(), '\r'), inputText.end()
|
||||||
|
);
|
||||||
|
historian->onPaste(caret, inputText);
|
||||||
if (caret >= input.length()) {
|
if (caret >= input.length()) {
|
||||||
input += text;
|
input += inputText;
|
||||||
} else {
|
} else {
|
||||||
auto left = input.substr(0, caret);
|
auto left = input.substr(0, caret);
|
||||||
auto right = input.substr(caret);
|
auto right = input.substr(caret);
|
||||||
input = left + text + right;
|
input = left + inputText + right;
|
||||||
}
|
}
|
||||||
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
|
|
||||||
refreshLabel();
|
refreshLabel();
|
||||||
setCaret(caret + text.length());
|
setCaret(caret + inputText.length());
|
||||||
if (validate()) {
|
if (validate()) {
|
||||||
onInput();
|
onInput();
|
||||||
}
|
}
|
||||||
@ -296,6 +462,11 @@ bool TextBox::eraseSelected() {
|
|||||||
if (selectionStart == selectionEnd) {
|
if (selectionStart == selectionEnd) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
historian->onErase(
|
||||||
|
selectionStart,
|
||||||
|
input.substr(selectionStart, selectionEnd - selectionStart),
|
||||||
|
true
|
||||||
|
);
|
||||||
erase(selectionStart, selectionEnd-selectionStart);
|
erase(selectionStart, selectionEnd-selectionStart);
|
||||||
resetSelection();
|
resetSelection();
|
||||||
onInput();
|
onInput();
|
||||||
@ -336,7 +507,9 @@ void TextBox::setTextOffset(uint x) {
|
|||||||
|
|
||||||
void TextBox::typed(unsigned int codepoint) {
|
void TextBox::typed(unsigned int codepoint) {
|
||||||
if (editable) {
|
if (editable) {
|
||||||
paste(std::wstring({(wchar_t)codepoint}));
|
// Combine deleting selected text and inserting a symbol
|
||||||
|
auto combination = history->beginCombination();
|
||||||
|
paste(std::wstring({static_cast<wchar_t>(codepoint)}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,6 +556,15 @@ bool TextBox::isEditable() const {
|
|||||||
return editable;
|
return editable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t TextBox::getSelectionStart() const {
|
||||||
|
return selectionStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TextBox::getSelectionEnd() const {
|
||||||
|
return selectionEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TextBox::setOnEditStart(runnable oneditstart) {
|
void TextBox::setOnEditStart(runnable oneditstart) {
|
||||||
onEditStart = oneditstart;
|
onEditStart = oneditstart;
|
||||||
}
|
}
|
||||||
@ -615,6 +797,7 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
|||||||
if (caret > input.length()) {
|
if (caret > input.length()) {
|
||||||
caret = input.length();
|
caret = input.length();
|
||||||
}
|
}
|
||||||
|
historian->onErase(caret - 1, input.substr(caret - 1, caret));
|
||||||
input = input.substr(0, caret-1) + input.substr(caret);
|
input = input.substr(0, caret-1) + input.substr(caret);
|
||||||
setCaret(caret-1);
|
setCaret(caret-1);
|
||||||
if (validate()) {
|
if (validate()) {
|
||||||
@ -623,6 +806,7 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
|||||||
}
|
}
|
||||||
} else if (key == keycode::DELETE) {
|
} else if (key == keycode::DELETE) {
|
||||||
if (!eraseSelected() && caret < input.length()) {
|
if (!eraseSelected() && caret < input.length()) {
|
||||||
|
historian->onErase(caret, input.substr(caret, caret + 1));
|
||||||
input = input.substr(0, caret) + input.substr(caret + 1);
|
input = input.substr(0, caret) + input.substr(caret + 1);
|
||||||
if (validate()) {
|
if (validate()) {
|
||||||
onInput();
|
onInput();
|
||||||
@ -669,7 +853,11 @@ void TextBox::keyPressed(keycode key) {
|
|||||||
if (key == keycode::V && editable) {
|
if (key == keycode::V && editable) {
|
||||||
const char* text = Window::getClipboardText();
|
const char* text = Window::getClipboardText();
|
||||||
if (text) {
|
if (text) {
|
||||||
|
historian->sync(); // flush buffer before combination
|
||||||
|
// Combine deleting selected text and pasing a clipboard content
|
||||||
|
auto combination = history->beginCombination();
|
||||||
paste(util::str2wstr_utf8(text));
|
paste(util::str2wstr_utf8(text));
|
||||||
|
historian->sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Select/deselect all
|
// Select/deselect all
|
||||||
@ -680,6 +868,12 @@ void TextBox::keyPressed(keycode key) {
|
|||||||
resetSelection();
|
resetSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (key == keycode::Z) {
|
||||||
|
historian->undo();
|
||||||
|
}
|
||||||
|
if (key == keycode::Y) {
|
||||||
|
historian->redo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,10 +898,8 @@ size_t TextBox::getLinePos(uint line) const {
|
|||||||
return label->getTextLineOffset(line);
|
return label->getTextLineOffset(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UINode> TextBox::getAt(
|
std::shared_ptr<UINode> TextBox::getAt(const glm::vec2& pos) {
|
||||||
const glm::vec2& pos, const std::shared_ptr<UINode>& self
|
return UINode::getAt(pos);
|
||||||
) {
|
|
||||||
return UINode::getAt(pos, self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::setOnUpPressed(const runnable &callback) {
|
void TextBox::setOnUpPressed(const runnable &callback) {
|
||||||
|
|||||||
@ -4,10 +4,14 @@
|
|||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
|
|
||||||
class Font;
|
class Font;
|
||||||
|
class ActionsHistory;
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
|
class TextBoxHistorian;
|
||||||
class TextBox : public Container {
|
class TextBox : public Container {
|
||||||
LabelCache rawTextCache;
|
LabelCache rawTextCache;
|
||||||
|
std::shared_ptr<ActionsHistory> history;
|
||||||
|
std::unique_ptr<TextBoxHistorian> historian;
|
||||||
protected:
|
protected:
|
||||||
glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f};
|
glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
glm::vec4 invalidColor {0.1f, 0.05f, 0.03f, 1.0f};
|
glm::vec4 invalidColor {0.1f, 0.05f, 0.03f, 1.0f};
|
||||||
@ -68,7 +72,6 @@ namespace gui {
|
|||||||
|
|
||||||
int calcIndexAt(int x, int y) const;
|
int calcIndexAt(int x, int y) const;
|
||||||
void setTextOffset(uint x);
|
void setTextOffset(uint x);
|
||||||
void erase(size_t start, size_t length);
|
|
||||||
bool eraseSelected();
|
bool eraseSelected();
|
||||||
void resetSelection();
|
void resetSelection();
|
||||||
void extendSelection(int index);
|
void extendSelection(int index);
|
||||||
@ -94,7 +97,10 @@ namespace gui {
|
|||||||
glm::vec4 padding=glm::vec4(4.0f)
|
glm::vec4 padding=glm::vec4(4.0f)
|
||||||
);
|
);
|
||||||
|
|
||||||
void paste(const std::wstring& text);
|
virtual ~TextBox();
|
||||||
|
|
||||||
|
void paste(const std::wstring& text, bool history=true);
|
||||||
|
void erase(size_t start, size_t length);
|
||||||
|
|
||||||
virtual void setTextSupplier(wstringsupplier supplier);
|
virtual void setTextSupplier(wstringsupplier supplier);
|
||||||
|
|
||||||
@ -201,6 +207,9 @@ namespace gui {
|
|||||||
virtual void setPadding(glm::vec4 padding);
|
virtual void setPadding(glm::vec4 padding);
|
||||||
glm::vec4 getPadding() const;
|
glm::vec4 getPadding() const;
|
||||||
|
|
||||||
|
size_t getSelectionStart() const;
|
||||||
|
size_t getSelectionEnd() const;
|
||||||
|
|
||||||
/// @brief Set runnable called on textbox focus
|
/// @brief Set runnable called on textbox focus
|
||||||
virtual void setOnEditStart(runnable oneditstart);
|
virtual void setOnEditStart(runnable oneditstart);
|
||||||
|
|
||||||
@ -221,9 +230,7 @@ namespace gui {
|
|||||||
virtual void drawBackground(const DrawContext& pctx, const Assets& assets) override;
|
virtual void drawBackground(const DrawContext& pctx, const Assets& assets) override;
|
||||||
virtual void typed(unsigned int codepoint) override;
|
virtual void typed(unsigned int codepoint) override;
|
||||||
virtual void keyPressed(keycode key) override;
|
virtual void keyPressed(keycode key) override;
|
||||||
virtual std::shared_ptr<UINode> getAt(
|
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos) override;
|
||||||
const glm::vec2& pos, const std::shared_ptr<UINode>& self
|
|
||||||
) override;
|
|
||||||
virtual void setOnUpPressed(const runnable &callback);
|
virtual void setOnUpPressed(const runnable &callback);
|
||||||
virtual void setOnDownPressed(const runnable &callback);
|
virtual void setOnDownPressed(const runnable &callback);
|
||||||
|
|
||||||
|
|||||||
@ -111,11 +111,11 @@ bool UINode::isInside(glm::vec2 point) {
|
|||||||
point.x < pos.x + size.x && point.y < pos.y + size.y);
|
point.x < pos.x + size.x && point.y < pos.y + size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UINode> UINode::getAt(const glm::vec2& point, const std::shared_ptr<UINode>& self) {
|
std::shared_ptr<UINode> UINode::getAt(const glm::vec2& point) {
|
||||||
if (!isInteractive() || !enabled) {
|
if (!isInteractive() || !enabled) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return isInside(point) ? self : nullptr;
|
return isInside(point) ? shared_from_this() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UINode::isInteractive() const {
|
bool UINode::isInteractive() const {
|
||||||
|
|||||||
@ -63,7 +63,7 @@ namespace gui {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Base abstract class for all UI elements
|
/// @brief Base abstract class for all UI elements
|
||||||
class UINode {
|
class UINode : public std::enable_shared_from_this<UINode> {
|
||||||
/// @brief element identifier used for direct access in UiDocument
|
/// @brief element identifier used for direct access in UiDocument
|
||||||
std::string id = "";
|
std::string id = "";
|
||||||
/// @brief element enabled state
|
/// @brief element enabled state
|
||||||
@ -195,7 +195,7 @@ namespace gui {
|
|||||||
/// @param pos cursor screen position
|
/// @param pos cursor screen position
|
||||||
/// @param self shared pointer to element
|
/// @param self shared pointer to element
|
||||||
/// @return self, sub-element or nullptr if element is not interractive
|
/// @return self, sub-element or nullptr if element is not interractive
|
||||||
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos, const std::shared_ptr<UINode>& self);
|
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos);
|
||||||
|
|
||||||
/// @brief Check if element is opaque for cursor
|
/// @brief Check if element is opaque for cursor
|
||||||
virtual bool isInteractive() const;
|
virtual bool isInteractive() const;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user