diff --git a/src/frontend/UiDocument.cpp b/src/frontend/UiDocument.cpp index 5e8df9f1..7c6f8d13 100644 --- a/src/frontend/UiDocument.cpp +++ b/src/frontend/UiDocument.cpp @@ -67,7 +67,7 @@ std::unique_ptr UiDocument::read( ? scripting::create_doc_environment(scripting::get_root_environment(), name) : scripting::create_doc_environment(penv, name); - gui::UiXmlReader reader(gui, env); + gui::UiXmlReader reader(gui, scriptenv(env)); auto view = reader.readXML(file.string(), *xmldoc->getRoot()); view->setId("root"); uidocscript script {}; diff --git a/src/graphics/ui/elements/Container.cpp b/src/graphics/ui/elements/Container.cpp index 72de920b..eddde7e2 100644 --- a/src/graphics/ui/elements/Container.cpp +++ b/src/graphics/ui/elements/Container.cpp @@ -71,6 +71,10 @@ void Container::mouseRelease(int x, int y) { } void Container::act(float delta) { + if (mustRefresh) { + refresh(); + mustRefresh = false; + } for (const auto& node : nodes) { if (node->isVisible()) { node->act(delta); @@ -162,7 +166,7 @@ void Container::add(const std::shared_ptr& node) { nodes.push_back(node); node->setParent(this); node->reposition(); - refresh(); + mustRefresh = true; } void Container::add(const std::shared_ptr& node, glm::vec2 pos) { @@ -202,7 +206,6 @@ void Container::listenInterval(float interval, ontimeout callback, int repeat) { void Container::setSize(glm::vec2 size) { if (size == getSize()) { - refresh(); return; } UINode::setSize(size); diff --git a/src/graphics/ui/elements/Container.hpp b/src/graphics/ui/elements/Container.hpp index d3dbbfc7..459d5b07 100644 --- a/src/graphics/ui/elements/Container.hpp +++ b/src/graphics/ui/elements/Container.hpp @@ -9,6 +9,7 @@ namespace gui { class Container : public UINode, public ::util::ObjectsKeeper { int prevScrollY = -1; + bool mustRefresh = true; protected: std::vector> nodes; std::vector intervalEvents; diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 49407b8d..1e8f48d6 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -74,6 +74,11 @@ UINode* UINode::listenDoubleClick(const onaction& action) { return this; } +UINode* UINode::listenFocus(const onaction& action) { + focusCallbacks.listen(action); + return this; +} + UINode* UINode::listenDefocus(const onaction& action) { defocusCallbacks.listen(action); return this; @@ -101,6 +106,11 @@ bool UINode::isPressed() const { return pressed; } +void UINode::onFocus() { + focused = true; + focusCallbacks.notify(gui); +} + void UINode::defocus() { focused = false; defocusCallbacks.notify(gui); diff --git a/src/graphics/ui/elements/UINode.hpp b/src/graphics/ui/elements/UINode.hpp index 9fc2edc4..e03eb91e 100644 --- a/src/graphics/ui/elements/UINode.hpp +++ b/src/graphics/ui/elements/UINode.hpp @@ -114,6 +114,8 @@ namespace gui { ActionsSet actions; /// @brief 'ondoubleclick' callbacks ActionsSet doubleClickCallbacks; + /// @brief 'onfocus' callbacks + ActionsSet focusCallbacks; /// @brief 'ondefocus' callbacks ActionsSet defocusCallbacks; /// @brief element tooltip text @@ -173,9 +175,10 @@ namespace gui { virtual UINode* listenAction(const onaction& action); virtual UINode* listenDoubleClick(const onaction& action); + virtual UINode* listenFocus(const onaction& action); virtual UINode* listenDefocus(const onaction& action); - virtual void onFocus() {focused = true;} + virtual void onFocus(); virtual void doubleClick(int x, int y); virtual void click(int x, int y); virtual void clicked(Mousecode button) {} diff --git a/src/graphics/ui/gui_util.cpp b/src/graphics/ui/gui_util.cpp index 76ed43ca..6d28b990 100644 --- a/src/graphics/ui/gui_util.cpp +++ b/src/graphics/ui/gui_util.cpp @@ -21,7 +21,7 @@ std::shared_ptr guiutil::create( if (env == nullptr) { env = scripting::get_root_environment(); } - UiXmlReader reader(gui, env); + UiXmlReader reader(gui, std::move(env)); return reader.readXML("[string]", source); } diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index f17092a7..06262fec 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -63,7 +63,7 @@ static runnable create_runnable( const std::string& name ) { if (element.has(name)) { - std::string text = element.attr(name).getText(); + const std::string& text = element.attr(name).getText(); if (!text.empty()) { return scripting::create_runnable( reader.getEnvironment(), text, reader.getFilename() @@ -180,6 +180,10 @@ static void read_uinode( node.listenAction(onclick); } + if (auto onfocus = create_action(reader, element, "onfocus")) { + node.listenFocus(onfocus); + } + if (auto ondefocus = create_action(reader, element, "ondefocus")) { node.listenDefocus(ondefocus); } @@ -761,7 +765,7 @@ static std::shared_ptr read_iframe( return iframe; } -UiXmlReader::UiXmlReader(gui::GUI& gui, const scriptenv& env) : gui(gui), env(env) { +UiXmlReader::UiXmlReader(gui::GUI& gui, scriptenv&& env) : gui(gui), env(std::move(env)) { contextStack.emplace(""); add("image", read_image); add("canvas", read_canvas); diff --git a/src/graphics/ui/gui_xml.hpp b/src/graphics/ui/gui_xml.hpp index 73350352..4a8a301f 100644 --- a/src/graphics/ui/gui_xml.hpp +++ b/src/graphics/ui/gui_xml.hpp @@ -20,9 +20,9 @@ namespace gui { std::unordered_set ignored; std::stack contextStack; std::string filename; - const scriptenv& env; + scriptenv env; public: - UiXmlReader(gui::GUI& gui, const scriptenv& env); + UiXmlReader(gui::GUI& gui, scriptenv&& env); void add(const std::string& tag, uinode_reader reader); bool hasReader(const std::string& tag) const; diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index e1180e1c..466ea3aa 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -94,8 +94,8 @@ static int l_container_add(lua::State* L) { auto subnode = guiutil::create( engine->getGUI(), xmlsrc, std::move(env) ); - node->add(subnode); UINode::getIndices(subnode, docnode.document->getMapWriteable()); + node->add(std::move(subnode)); } catch (const std::exception& err) { throw std::runtime_error(err.what()); }