13
0

Gtkmm2ext::Pane: attempt to track child lifetime, since Gtkmm 2.4 doesn't do this correctly

This commit is contained in:
Paul Davis 2016-07-19 23:31:07 -04:00
parent 541e6aaeb1
commit 82d3afb851
2 changed files with 32 additions and 2 deletions

View File

@ -46,10 +46,11 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
public:
struct Child
{
Pane* pane;
Gtk::Widget* w;
int32_t minsize;
Child (Gtk::Widget* widget, uint32_t ms) : w (widget), minsize (ms) {}
Child (Pane* p, Gtk::Widget* widget, uint32_t ms) : pane (p), w (widget), minsize (ms) {}
};
typedef std::list<Child> Children;
@ -108,6 +109,9 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
void add_divider ();
void handle_child_visibility ();
bool fract_is_ok (Dividers::size_type, float fract);
static void* notify_child_destroyed (void*);
void* child_destroyed (Gtk::Widget*);
};
class LIBGTKMM2EXT_API HPane : public Pane

View File

@ -48,6 +48,7 @@ Pane::Pane (bool h)
Pane::~Pane ()
{
for (Children::iterator c = children.begin(); c != children.end(); ++c) {
c->w->remove_destroy_notify_callback (&(*c));
c->w->unparent ();
}
}
@ -140,9 +141,14 @@ Pane::handle_child_visibility ()
void
Pane::on_add (Widget* w)
{
children.push_back (Child (w, 0));
children.push_back (Child (this, w, 0));
w->set_parent (*this);
/* Gtkmm 2.4 does not correctly arrange for ::on_remove() to be called
for custom containers that derive from Gtk::Container. So ... we need
to ensure that we hear about child destruction ourselves.
*/
w->add_destroy_notify_callback (&children.back(), &Pane::notify_child_destroyed);
w->signal_show().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
w->signal_hide().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
@ -152,11 +158,31 @@ Pane::on_add (Widget* w)
}
}
void*
Pane::notify_child_destroyed (void* data)
{
Child* child = reinterpret_cast<Child*> (data);
return child->pane->child_destroyed (child->w);
}
void*
Pane::child_destroyed (Gtk::Widget* w)
{
for (Children::iterator c = children.begin(); c != children.end(); ++c) {
if (c->w == w) {
children.erase (c);
break;
}
}
return 0;
}
void
Pane::on_remove (Widget* w)
{
for (Children::iterator c = children.begin(); c != children.end(); ++c) {
if (c->w == w) {
w->remove_destroy_notify_callback (&(*c));
w->unparent ();
children.erase (c);
break;