combine uinode actions callbacks sets & cleanup

This commit is contained in:
MihailRis 2025-11-14 19:50:09 +03:00
parent f9bab5a5cf
commit 95721a6864
5 changed files with 53 additions and 31 deletions

View File

@ -42,7 +42,7 @@ Button::Button(
} }
if (action) { if (action) {
listenAction(action); listenClick(action);
} }
setScrollable(false); setScrollable(false);

View File

@ -19,7 +19,7 @@ SelectBox::SelectBox(
: Button(gui, selected.text, padding, nullptr, glm::vec2(contentWidth, -1)), : Button(gui, selected.text, padding, nullptr, glm::vec2(contentWidth, -1)),
options(std::move(options)) { options(std::move(options)) {
listenAction([this](GUI& gui) { listenClick([this](GUI& gui) {
auto panel = std::make_shared<Panel>(gui, getSize()); auto panel = std::make_shared<Panel>(gui, getSize());
panel->setPos(calcPos() + glm::vec2(0, size.y)); panel->setPos(calcPos() + glm::vec2(0, size.y));
for (const auto& option : this->options) { for (const auto& option : this->options) {

View File

@ -64,24 +64,20 @@ UINode* UINode::getParent() const {
return parent; return parent;
} }
UINode* UINode::listenAction(const OnAction& action) { void UINode::listenClick(OnAction action) {
actions.listen(action); actions.listen(UIAction::CLICK, std::move(action));
return this;
} }
UINode* UINode::listenDoubleClick(const OnAction& action) { void UINode::listenDoubleClick(OnAction action) {
doubleClickCallbacks.listen(action); actions.listen(UIAction::DOUBLE_CLICK, std::move(action));
return this;
} }
UINode* UINode::listenFocus(const OnAction& action) { void UINode::listenFocus(OnAction action) {
focusCallbacks.listen(action); actions.listen(UIAction::FOCUS, std::move(action));
return this;
} }
UINode* UINode::listenDefocus(const OnAction& action) { void UINode::listenDefocus(OnAction action) {
defocusCallbacks.listen(action); actions.listen(UIAction::DEFOCUS, std::move(action));
return this;
} }
void UINode::click(int, int) { void UINode::click(int, int) {
@ -91,14 +87,14 @@ void UINode::click(int, int) {
void UINode::doubleClick(int x, int y) { void UINode::doubleClick(int x, int y) {
pressed = true; pressed = true;
if (isInside(glm::vec2(x, y))) { if (isInside(glm::vec2(x, y))) {
doubleClickCallbacks.notify(gui); actions.notify(UIAction::DOUBLE_CLICK, gui);
} }
} }
void UINode::mouseRelease(int x, int y) { void UINode::mouseRelease(int x, int y) {
pressed = false; pressed = false;
if (isInside(glm::vec2(x, y))) { if (isInside(glm::vec2(x, y))) {
actions.notify(gui); actions.notify(UIAction::CLICK, gui);
} }
} }
@ -108,12 +104,12 @@ bool UINode::isPressed() const {
void UINode::onFocus() { void UINode::onFocus() {
focused = true; focused = true;
focusCallbacks.notify(gui); actions.notify(UIAction::FOCUS, gui);
} }
void UINode::defocus() { void UINode::defocus() {
focused = false; focused = false;
defocusCallbacks.notify(gui); actions.notify(UIAction::DEFOCUS, gui);
} }
bool UINode::isFocused() const { bool UINode::isFocused() const {

View File

@ -46,7 +46,39 @@ namespace gui {
} }
}; };
using ActionsSet = CallbacksSet<GUI&>; template<class TagT, typename... Args>
class TaggedCallbacksSet {
public:
using Func = std::function<void(Args...)>;
private:
std::unique_ptr<std::vector<std::pair<TagT, Func>>> callbacks;
public:
void listen(TagT tag, Func&& callback) {
if (callbacks == nullptr) {
callbacks =
std::make_unique<std::vector<std::pair<TagT, Func>>>();
}
callbacks->push_back({tag, std::move(callback)});
}
void notify(TagT notifyTag, Args&&... args) {
if (callbacks == nullptr) {
return;
}
for (const auto& [tag, callback] : * callbacks) {
if (tag != notifyTag) {
continue;
}
callback(args...);
}
}
};
enum class UIAction {
CLICK, DOUBLE_CLICK, FOCUS, DEFOCUS
};
using ActionsSet = TaggedCallbacksSet<UIAction, GUI&>;
using StringCallbacksSet = CallbacksSet<GUI&, const std::string&>; using StringCallbacksSet = CallbacksSet<GUI&, const std::string&>;
enum class Align { enum class Align {
@ -119,14 +151,8 @@ namespace gui {
vec2supplier positionfunc = nullptr; vec2supplier positionfunc = nullptr;
/// @brief size supplier for the element (called on parent element size update) /// @brief size supplier for the element (called on parent element size update)
vec2supplier sizefunc = nullptr; vec2supplier sizefunc = nullptr;
/// @brief 'onclick' callbacks /// @brief parameterless callbacks
ActionsSet actions; ActionsSet actions;
/// @brief 'ondoubleclick' callbacks
ActionsSet doubleClickCallbacks;
/// @brief 'onfocus' callbacks
ActionsSet focusCallbacks;
/// @brief 'ondefocus' callbacks
ActionsSet defocusCallbacks;
/// @brief element tooltip text /// @brief element tooltip text
std::wstring tooltip; std::wstring tooltip;
/// @brief element tooltip delay /// @brief element tooltip delay
@ -187,10 +213,10 @@ namespace gui {
/// @brief Get element z-index /// @brief Get element z-index
int getZIndex() const; int getZIndex() const;
virtual UINode* listenAction(const OnAction& action); virtual void listenClick(OnAction action);
virtual UINode* listenDoubleClick(const OnAction& action); virtual void listenDoubleClick(OnAction action);
virtual UINode* listenFocus(const OnAction& action); virtual void listenFocus(OnAction action);
virtual UINode* listenDefocus(const OnAction& action); virtual void listenDefocus(OnAction action);
virtual void onFocus(); virtual void onFocus();
virtual void doubleClick(int x, int y); virtual void doubleClick(int x, int y);

View File

@ -178,7 +178,7 @@ static void read_uinode(
} }
if (auto onclick = create_action(reader, element, "onclick")) { if (auto onclick = create_action(reader, element, "onclick")) {
node.listenAction(onclick); node.listenClick(onclick);
} }
if (auto onfocus = create_action(reader, element, "onfocus")) { if (auto onfocus = create_action(reader, element, "onfocus")) {