diff --git a/data/layout.xml b/data/layout.xml
index da48052..acb00c7 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -693,7 +693,7 @@
-
+
@@ -731,7 +731,7 @@
-
+
@@ -753,10 +753,10 @@
-
+
-
+
@@ -771,7 +771,7 @@
-
+
@@ -789,8 +789,8 @@
-
-
+
+
diff --git a/src/app_layout.cpp b/src/app_layout.cpp
index 48c5a76..7e0152f 100644
--- a/src/app_layout.cpp
+++ b/src/app_layout.cpp
@@ -354,7 +354,10 @@ void App::init_sidebar()
if (grid->m_parent)
{
if (auto fp = dynamic_cast(grid->m_parent->m_parent))
+ {
+ grid->remove_from_parent();
fp->destroy();
+ }
}
layout[main_id]->add_child(grid);
auto tick = layout[main_id]->add_child();
@@ -505,7 +508,7 @@ void App::init_menu_file()
{
menu_file->on_click = [=](Node*) {
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
- auto popup = (NodePopupMenu*)layout[const_hash("file-menu")]->m_children[0]->clone();
+ auto popup = layout[const_hash("file-menu")]->m_children[0]->clone();
popup->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup->m_size.x + menu_file->m_size.x;
@@ -610,7 +613,7 @@ void App::init_menu_file()
if (auto b = popup->find("file-export-tick"))
b->on_click = [this, b, popup](Node*) {
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
- auto subpopup = (NodePopupMenu*)layout[const_hash("file-submenu-export")]->m_children[0]->clone();
+ auto subpopup = layout[const_hash("file-submenu-export")]->m_children[0]->clone();
subpopup->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - subpopup->m_size.x + b->m_size.x;
@@ -685,7 +688,7 @@ void App::init_menu_edit()
{
menu_file->on_click = [=](Node*) {
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
- auto popup = (NodePopupMenu*)layout[const_hash("edit-menu")]->m_children[0]->clone();
+ auto popup = layout[const_hash("edit-menu")]->m_children[0]->clone();
popup->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup->m_size.x + menu_file->m_size.x;
@@ -709,7 +712,7 @@ void App::init_menu_tools()
{
menu_exp->on_click = [this, menu_exp, main](Node*) {
glm::vec2 pos = menu_exp->m_pos + glm::vec2(0, menu_exp->m_size.y);
- auto popup_exp = (NodePopupMenu*)layout[const_hash("tools-menu")]->m_children[0]->clone();
+ auto popup_exp = layout[const_hash("tools-menu")]->m_children[0]->clone();
popup_exp->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup_exp->m_size.x + menu_exp->m_size.x;
@@ -727,7 +730,7 @@ void App::init_menu_tools()
if (auto menu_time = popup_exp->find("tools-timelapse"))
{
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
- auto popup_time = (NodePopupMenu*)layout[const_hash("timelapse-menu")]->m_children[0]->clone();
+ auto popup_time = layout[const_hash("timelapse-menu")]->m_children[0]->clone();
popup_time->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup_time->m_size.x + b->m_size.x;
@@ -773,7 +776,7 @@ void App::init_menu_tools()
if (auto menu_time = popup_exp->find("tools-panels"))
{
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
- auto popup_time = (NodePopupMenu*)layout[const_hash("panels-menu")]->m_children[0]->clone();
+ auto popup_time = layout[const_hash("panels-menu")]->m_children[0]->clone();
popup_time->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup_time->m_size.x + b->m_size.x;
@@ -1039,7 +1042,7 @@ void App::init_menu_about()
{
menu_file->on_click = [=](Node*) {
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
- auto popup = (NodePopupMenu*)layout[const_hash("about-menu")]->m_children[0]->clone();
+ auto popup = layout[const_hash("about-menu")]->m_children[0]->clone();
popup->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup->m_size.x + menu_file->m_size.x;
@@ -1160,7 +1163,7 @@ void App::init_menu_layer()
{
menu_file->on_click = [=](Node*) {
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
- auto popup = (NodePopupMenu*)layout[const_hash("layers-menu")]->m_children[0]->clone();
+ auto popup = layout[const_hash("layers-menu")]->m_children[0]->clone();
popup->update();
if (YGNodeStyleGetDirection(layout[main_id]->y_node) == YGDirectionRTL)
pos.x = pos.x - popup->m_size.x + menu_file->m_size.x;
diff --git a/src/node.cpp b/src/node.cpp
index c14c8d9..09b3523 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -58,13 +58,22 @@ void Node::watch(std::function observer)
void Node::destroy()
{
- App::I->ui_task([&]
- {
- mouse_release();
- key_release();
- remove_all_children();
- remove_from_parent();
- });
+ m_destroyed = true;
+ mouse_release();
+ key_release();
+// for (auto& c : m_children)
+// c->destroy();
+ for (auto p = m_parent; p; p = p->m_parent)
+ if (p->child_mouse_focus.get() == this)
+ p->child_mouse_focus = nullptr;
+ //App::I->ui_task([&]
+ //{
+ // auto cp = m_children;
+ // for (auto& c : cp)
+ // c->destroy();
+ // remove_all_children();
+ // remove_from_parent();
+ //});
}
Node* Node::root()
@@ -78,6 +87,9 @@ Node* Node::root()
kEventResult Node::on_event(Event* e)
{
kEventResult ret = kEventResult::Available;
+
+ if (m_destroyed)
+ return ret;
if (current_mouse_capture && current_mouse_capture.get() != this)
{
@@ -134,7 +146,7 @@ kEventResult Node::on_event(Event* e)
if (e->m_cat == kEventCategory::MouseEvent && child_mouse_focus.get() != it->get())
{
MouseEvent* me = static_cast(e);
- if (child_mouse_focus)
+ if (child_mouse_focus && !child_mouse_focus->m_destroyed)
{
MouseEvent e2 = *me;
e2.m_type = kEventType::MouseUnfocus;
@@ -144,8 +156,15 @@ kEventResult Node::on_event(Event* e)
MouseEvent e2 = *me;
e2.m_type = kEventType::MouseFocus;
(*it)->handle_event(&e2);
- child_mouse_focus = *it;
- child_mouse_focus->m_mouse_focus = true;
+ if (!(*it)->m_destroyed)
+ {
+ child_mouse_focus = *it;
+ child_mouse_focus->m_mouse_focus = true;
+ }
+ //else
+ //{
+ // child_mouse_focus = nullptr;
+ //}
}
ret = kEventResult::Consumed;
break;
@@ -295,7 +314,9 @@ void Node::added(Node* parent)
void Node::removed(Node* parent)
{
-
+ for (auto p = m_parent; p; p = p->m_parent)
+ if (p->child_mouse_focus.get() == this)
+ p->child_mouse_focus = nullptr;
}
const Node* Node::init_template(const char* id)
@@ -329,6 +350,7 @@ void Node::add_child(Node* n)
m_children.emplace_back(n);
n->m_parent = this;
n->m_manager = m_manager;
+ n->m_destroyed = false;
YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
n->added(this);
on_child_added(n);
@@ -344,6 +366,7 @@ void Node::add_child(Node* n, int index)
m_children.emplace_back(n);
n->m_parent = this;
n->m_manager = m_manager;
+ n->m_destroyed = false;
YGNodeInsertChild(y_node, n->y_node, index);
n->added(this);
on_child_added(n);
@@ -359,6 +382,7 @@ void Node::add_child(std::shared_ptr n)
m_children.push_back(n);
n->m_parent = this;
n->m_manager = m_manager;
+ n->m_destroyed = false;
YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
n->added(this);
on_child_added(n.get());
@@ -374,6 +398,7 @@ void Node::add_child(std::shared_ptr n, int index)
m_children.insert(m_children.begin() + index, n);
n->m_parent = this;
n->m_manager = m_manager;
+ n->m_destroyed = false;
YGNodeInsertChild(y_node, n->y_node, index);
n->added(this);
on_child_added(n.get());
@@ -663,6 +688,7 @@ Node::Node(Node&& o)
m_pos_offset_childred = o.m_pos_offset_childred;
m_clip_uncut = o.m_clip_uncut;
+ m_destroyed = o.m_destroyed;
}
Node::~Node()
@@ -1015,6 +1041,9 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj, float
for (auto& c : m_children)
c->update_internal(m_pos, proj, zoom);
+
+ m_children.erase(std::remove_if(m_children.begin(), m_children.end(),
+ [](const auto& n) { return n->m_destroyed; }), m_children.end());
}
void Node::tick(float dt)
@@ -1320,15 +1349,6 @@ void Node::draw()
}
-Node* Node::clone()
-{
- Node* n = clone_instantiate();
- clone_copy(n);
- clone_children(n);
- clone_finalize(n);
- return n;
-}
-
Node* Node::clone_instantiate() const
{
return new Node();
@@ -1363,14 +1383,16 @@ void Node::clone_copy(Node* dest) const
dest->m_pos_offset = m_pos_offset;
dest->m_pos_offset_childred = m_pos_offset_childred;
dest->m_clip_uncut = m_clip_uncut;
+
+ dest->m_destroyed = m_destroyed;
}
void Node::clone_children(Node* dest) const
{
for (auto& c : m_children)
{
- Node* cn = c->clone();
- dest->m_children.emplace_back(cn);
+ std::shared_ptr cn = c->clone();
+ dest->m_children.push_back(cn);
cn->m_parent = dest;
cn->m_manager = dest->m_manager;
cn->loaded();
diff --git a/src/node.h b/src/node.h
index 652a601..a58c2c9 100644
--- a/src/node.h
+++ b/src/node.h
@@ -135,6 +135,8 @@ public:
// it's actually rendering
bool m_on_screen = false;
+ bool m_destroyed = false;
+
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
Node&& operator=(Node&& o);
@@ -194,7 +196,6 @@ public:
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
void load_internal(const tinyxml2::XMLElement* x_node);
virtual void draw();
- Node* clone();
virtual Node* clone_instantiate() const;
virtual void clone_copy(Node* dest) const;
virtual void clone_children(Node* dest) const;
@@ -203,6 +204,16 @@ public:
virtual void destroy();
Node* root();
+
+ template std::shared_ptr clone()
+ {
+ std::shared_ptr n = std::shared_ptr((T*)clone_instantiate());
+ clone_copy(n.get());
+ clone_children(n.get());
+ clone_finalize(n.get());
+ return n;
+ }
+
template T* find(const char* ids)
{
uint16_t id = const_hash(ids);
diff --git a/src/node_about.cpp b/src/node_about.cpp
index 4bd079d..be15857 100644
--- a/src/node_about.cpp
+++ b/src/node_about.cpp
@@ -8,19 +8,29 @@ Node* NodeAbout::clone_instantiate() const
return new NodeAbout();
}
+void NodeAbout::clone_finalize(Node* dest) const
+{
+ NodeAbout* n = static_cast(dest);
+ n->init_controls();
+}
+
void NodeAbout::init()
{
- SetPosition(0, 0);
- SetWidthP(100);
- SetHeightP(100);
- SetPositioning(YGPositionTypeAbsolute);
- m_template = (*m_manager)[const_hash("about")]->m_children[0]->clone();
- add_child(m_template);
- btn_ok = m_template->find("btn-ok");
- btn_ok->on_click = [&](Node*) { destroy(); };
+ init_template("about");
+ init_controls();
}
kEventResult NodeAbout::handle_event(Event* e)
{
return kEventResult::Consumed;
}
+
+void NodeAbout::init_controls()
+{
+ SetPosition(0, 0);
+ SetWidthP(100);
+ SetHeightP(100);
+ SetPositioning(YGPositionTypeAbsolute);
+ btn_ok = find("btn-ok");
+ btn_ok->on_click = [&](Node*) { destroy(); };
+}
diff --git a/src/node_about.h b/src/node_about.h
index efbdba2..e6ed555 100644
--- a/src/node_about.h
+++ b/src/node_about.h
@@ -4,10 +4,11 @@
class NodeAbout : public Node
{
- Node* m_template;
NodeButton* btn_ok;
public:
virtual Node* clone_instantiate() const override;
virtual void init() override;
virtual kEventResult handle_event(Event* e) override;
+ virtual void clone_finalize(Node* dest) const override;
+ void init_controls();
};
diff --git a/src/node_changelog.cpp b/src/node_changelog.cpp
index de8bf14..2d6bd93 100644
--- a/src/node_changelog.cpp
+++ b/src/node_changelog.cpp
@@ -10,13 +10,13 @@ Node* NodeChangelog::clone_instantiate() const
void NodeChangelog::init()
{
+ init_template("changelog");
+
SetPosition(0, 0);
SetWidthP(100);
SetHeightP(100);
SetPositioning(YGPositionTypeAbsolute);
- m_template = (*m_manager)[const_hash("changelog")]->m_children[0]->clone();
- add_child(m_template);
- btn_ok = m_template->find("btn-ok");
+ btn_ok = find("btn-ok");
btn_ok->on_click = [&](Node*) { destroy(); };
}
diff --git a/src/node_dialog_cloud.cpp b/src/node_dialog_cloud.cpp
index 63ba217..93d2d80 100644
--- a/src/node_dialog_cloud.cpp
+++ b/src/node_dialog_cloud.cpp
@@ -45,6 +45,7 @@ void NodeDialogCloud::loaded()
void NodeDialogCloud::removed(Node* parent)
{
+ NodeBorder::removed(parent);
closed = true;
}
diff --git a/src/node_message_box.cpp b/src/node_message_box.cpp
index d387159..5eeb216 100644
--- a/src/node_message_box.cpp
+++ b/src/node_message_box.cpp
@@ -10,17 +10,17 @@ Node* NodeMessageBox::clone_instantiate() const
void NodeMessageBox::init()
{
+ init_template("message-box");
+
SetPosition(0, 0);
SetWidthP(100);
SetHeightP(100);
SetPositioning(YGPositionTypeAbsolute);
- m_template = (*m_manager)[const_hash("message-box")]->m_children[0]->clone();
- add_child(m_template);
- m_title = m_template->find("title");
- m_message = m_template->find("message");
- btn_ok = m_template->find("btn-ok");
+ m_title = find("title");
+ m_message = find("message");
+ btn_ok = find("btn-ok");
btn_ok->on_click = [&](Node*) { destroy(); };
- btn_cancel = m_template->find("btn-cancel");
+ btn_cancel = find("btn-cancel");
on_submit = btn_cancel->on_click = [&](Node*) { destroy(); };
m_capture_children = false; // don't capture children events on mouse_capture
}
diff --git a/src/node_progress_bar.cpp b/src/node_progress_bar.cpp
index f3a5501..d6d5fb7 100644
--- a/src/node_progress_bar.cpp
+++ b/src/node_progress_bar.cpp
@@ -19,6 +19,7 @@ void NodeProgressBar::init()
btn_cancel = find("btn-cancel");
btn_cancel->on_click = [&](Node*) { destroy(); };
m_progress = find("progress");
+ m_body = find("body");
m_progress->SetWidthP(0);
}
@@ -34,3 +35,9 @@ void NodeProgressBar::set_progress(float p) noexcept
{
m_progress->SetWidthP(p * 100.f);
}
+
+void NodeProgressBar::added(Node* parent)
+{
+ NodeBorder::added(parent);
+ m_body->mouse_capture();
+}
diff --git a/src/node_progress_bar.h b/src/node_progress_bar.h
index f8436e1..7fdae6d 100644
--- a/src/node_progress_bar.h
+++ b/src/node_progress_bar.h
@@ -11,6 +11,7 @@ public:
NodeButton* btn_cancel;
NodeText* m_title;
NodeBorder* m_progress;
+ NodeBorder* m_body;
int m_total = 0;
int m_count = 0;
virtual Node* clone_instantiate() const override;
@@ -18,4 +19,5 @@ public:
void increment() noexcept;
// set progress where p [0, 1]
void set_progress(float p) noexcept;
+ virtual void added(Node* parent) override;
};
diff --git a/src/node_settings.cpp b/src/node_settings.cpp
index 28f0599..ecd964b 100644
--- a/src/node_settings.cpp
+++ b/src/node_settings.cpp
@@ -10,13 +10,13 @@ Node* NodeSettings::clone_instantiate() const
void NodeSettings::init()
{
+ init_template("settings");
+
SetPosition(0, 0);
SetWidthP(100);
SetHeightP(100);
SetPositioning(YGPositionTypeAbsolute);
- m_template = (*m_manager)[const_hash("settings")]->m_children[0]->clone();
- add_child(m_template);
- btnOk = m_template->find("btn-ok");
+ btnOk = find("btn-ok");
btnOk->on_click = [&](Node*) { destroy(); };
}
diff --git a/src/node_usermanual.cpp b/src/node_usermanual.cpp
index 18121d8..7eadf5b 100644
--- a/src/node_usermanual.cpp
+++ b/src/node_usermanual.cpp
@@ -10,14 +10,16 @@ Node* NodeUserManual::clone_instantiate() const
void NodeUserManual::init()
{
+ init_template("usermanual");
+
SetPosition(0, 0);
SetWidthP(100);
SetHeightP(100);
SetPositioning(YGPositionTypeAbsolute);
- m_template = (*m_manager)[const_hash("usermanual")]->m_children[0]->clone();
- add_child(m_template);
- btn_ok = m_template->find("btn-ok");
- btn_ok->on_click = [&](Node*) { destroy(); };
+ btn_ok = find("btn-ok");
+ btn_ok->on_click = [&](Node*) {
+ destroy();
+ };
}
kEventResult NodeUserManual::handle_event(Event* e)