Container::~Container()
{
+ // Clear children here while members are still valid
while(!children.empty())
- delete children.front()->widget;
+ {
+ if(children.back()->own_widget)
+ /* Avoid destroying the unique_ptr for the widget from within its own
+ reset() function */
+ unique_ptr<Widget> w = move(children.back()->own_widget);
+ else
+ children.pop_back();
+ }
}
-void Container::add(Widget &wdg)
+void Container::add(unique_ptr<Widget> wdg)
{
- wdg.set_parent(this);
- children.push_back(create_child(&wdg));
- if(wdg.get_animation_interval())
- check_animation_interval();
- children_rebuild_needed = true;
- signal_rebuild_needed.emit();
- on_child_added(wdg);
+ add_child(*wdg).own_widget = move(wdg);
}
void Container::remove(Widget &wdg)
{
- auto i = find_if(children, [&wdg](const Child *c){ return c->widget==&wdg; });
+ auto i = find_if(children, [&wdg](const unique_ptr<Child> &c){ return c->widget==&wdg; });
if(i==children.end())
throw hierarchy_error("widget not in container");
- wdg.set_parent(0);
- delete *i;
+ unique_ptr<Widget> owned = move((*i)->own_widget);
+ if(&wdg==saved_input_focus)
+ saved_input_focus = nullptr;
+ wdg.set_parent(nullptr);
children.erase(i);
if(wdg.get_animation_interval())
check_animation_interval();
on_child_removed(wdg);
}
-Container::Child *Container::create_child(Widget *wdg)
+Container::Child &Container::add_child(Widget &wdg)
{
- return new Child(*this, wdg);
+ wdg.set_parent(this);
+ children.push_back(make_unique<Child>(*this, &wdg));
+ if(wdg.get_animation_interval())
+ check_animation_interval();
+ children_rebuild_needed = true;
+ signal_rebuild_needed.emit();
+ on_child_added(wdg);
+ return *children.back();
}
Geometry Container::determine_child_geometry(const Widget &child, const Part &part) const
child.set_geometry(determine_child_geometry(child, part));
}
-list<Widget *> Container::get_children() const
+vector<Widget *> Container::get_children() const
{
- list<Widget *> result;
- for(const Child *c: children)
+ vector<Widget *> result;
+ for(const unique_ptr<Child> &c: children)
result.push_back(c->widget);
return result;
}
-Widget *Container::get_child_at(int x, int y) const
+Widget *Container::find_child_at(int x, int y) const
{
for(auto i=children.end(); i!=children.begin();)
if((*--i)->widget->is_visible() && (*i)->widget->get_geometry().is_inside(x, y))
return (*i)->widget;
- return 0;
+ return nullptr;
}
-Widget *Container::get_descendant_at(int x, int y) const
+Widget *Container::find_descendant_at(int x, int y) const
{
- Widget *wdg = get_child_at(x, y);
+ Widget *wdg = find_child_at(x, y);
if(Container *cont = dynamic_cast<Container *>(wdg))
{
const Geometry &cgeom = wdg->get_geometry();
- Widget *wdg2 = cont->get_descendant_at(x-cgeom.x, y-cgeom.y);
- if(wdg2)
+ if(Widget *wdg2 = cont->find_descendant_at(x-cgeom.x, y-cgeom.y))
return wdg2;
}
return wdg;
void Container::raise(Widget &wdg)
{
- auto i = find_if(children, [&wdg](const Child *c){ return c->widget==&wdg; });
+ auto i = find_if(children, [&wdg](const unique_ptr<Child> &c){ return c->widget==&wdg; });
if(i==children.end())
throw hierarchy_error("widget not in container");
- children.splice(children.end(), children, i);
+ unique_ptr<Child> c = move(*i);
+ children.erase(i);
+ children.push_back(move(c));
}
void Container::set_pointer_focus(Widget *wdg, bool grab)
void Container::check_animation_interval()
{
Time::TimeDelta shortest;
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
const Time::TimeDelta &child_iv = c->widget->get_animation_interval();
if(child_iv && (!shortest || child_iv<shortest))
if(children_rebuild_needed)
{
children_rebuild_needed = false;
- for(Child *c: children)
+ for(const unique_ptr<Child> &c: children)
c->widget->rebuild_hierarchy();
}
}
{
if(child==click_focus && btn==click_button)
{
- click_focus = 0;
+ click_focus = nullptr;
if(!pointer_focus)
- set_pointer_focus(get_child_at(x, y));
+ set_pointer_focus(find_child_at(x, y));
}
const Geometry &cgeom = child->get_geometry();
{
Widget *child = get_pointer_target(x, y, false);
if(!pointer_grabbed)
- set_pointer_focus((child && child->get_geometry().is_inside(x, y)) ? child : 0);
+ set_pointer_focus((child && child->get_geometry().is_inside(x, y)) ? child : nullptr);
if(child)
{
return touch_focus;
else
{
- Widget *child = get_child_at(x, y);
+ Widget *child = find_child_at(x, y);
if(child && child->is_enabled())
return child;
else
- return 0;
+ return nullptr;
}
}
void Container::pointer_leave()
{
Widget::pointer_leave();
- set_pointer_focus(0);
+ set_pointer_focus(nullptr);
}
void Container::touch_press(int x, int y, unsigned finger)
{
// TODO track focus for each finger separately
if(child==touch_focus)
- touch_focus = 0;
+ touch_focus = nullptr;
const Geometry &cgeom = child->get_geometry();
child->touch_release(x-cgeom.x, y-cgeom.y, finger);
void Container::focus_in()
{
- if(saved_input_focus && saved_input_focus->get_parent()==this)
+ if(saved_input_focus)
set_input_focus(saved_input_focus);
Widget::focus_in();
}
void Container::focus_out()
{
saved_input_focus = input_focus;
- set_input_focus(0);
+ set_input_focus(nullptr);
Widget::focus_out();
}
void Container::animate(const Time::TimeDelta &dt)
{
- for(Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
const Time::TimeDelta &child_iv = c->widget->get_animation_interval();
if(!child_iv)
void Container::on_reparent()
{
- for(const Child *c: children)
+ for(const unique_ptr<Child> &c: children)
{
if(Container *o = dynamic_cast<Container *>(c->widget))
o->on_reparent();
widget->signal_rebuild_needed.connect(sigc::mem_fun(this, &Child::rebuild_needed));
}
+Container::Child::Child(Container &c, unique_ptr<Widget> w):
+ Child(c, w.get())
+{
+ own_widget = move(w);
+}
+
Container::Child::~Child()
{
visibility_changed(false);
if(!v)
{
if(widget==container.click_focus)
- container.click_focus = 0;
+ container.click_focus = nullptr;
if(widget==container.pointer_focus)
- container.set_pointer_focus(0);
+ container.set_pointer_focus(nullptr);
if(widget==container.input_focus)
- container.set_input_focus(0);
+ container.set_input_focus(nullptr);
}
}
if(container.pointer_grabbed && container.pointer_focus==widget)
{
// XXX Should set to the widget under pointer
- container.set_pointer_focus(0);
+ container.set_pointer_focus(nullptr);
container.signal_ungrab_pointer.emit();
}
}