Re: help on array of widgets



On Thu, 28 Jul 2011 10:37:26 +0800 (SGT)
Mj Mendoza IV <mjmendoza konsolscript org> wrote:
> > Probably the original poster needs to explain what purpose he is
> > trying to achieve in storing widgets in a vector. There is probably
> > a fundamental design error present.
> 
> Hi Chris,
> 
> What I had in mind is like GIMP's Layer Dock where, a layer can be
> added, removed and rearranged. To keep my learning simple, I
> experimented with Buttons first. What I opted to do is a vector of
> Buttons, which failed obviously. So with Yann's suggestion, I'm
> currently using vector of Button pointers instead.
> 
> Do you have any better design in mind?

I am afraid I don't know anything about GIMP's layer dock, nor what a
"Layer" is, nor whether it is cognate with a GTK+ widget.  It sounds as
if you want a widget stack.  Qt has one of those, but GTK+ doesn't as
far as I am aware.

With such ignorance about GIMP, all I can do is give you some pointers.
The main thing you need to realise, if you want to transfer GTK+
widgets between parents, is that only one parent can own a child widget
at a time.

Since you can only have one parent owning a child, placing widgets in a
C++ aggregate container is in most cases a waste of time (see below
about dormant widgets as an exception to this).

In terms of GTK+'s C interface, all you need to do to reparent a widget
is to (i) increment its reference count so removal from its parent
doesn't destroy it, (ii) remove it from its parent, (iii) add it to its
new parent, and (iv) decrement the reference count again so that the new
parent controls its lifetime.  There is a convenience function call
which will do this for you in one go (gtk_widget_reparent()).

Of course you can have a GTK+ widget which at any one time does not
have a parent, provided that it is in a dormant (hidden) condition,
simply by stopping after stage (ii) above.  It could make sense to keep
dormant widgets of this kind in a C++ container until they are reused.
Under this scheme, if that is what your program UI requires, you would
"pop" it from the C++ container/widget stack when you place it into a
new GTK+ container.

You can more or less map this approach into gtkmm.  In fact you can map
it directly with non-widgets such as tree models, which are held by
Glib::RefPtr.

The problem that arises relates to objects deriving from Gtk::Widget.
Gtk::Widget::reparent() exists, but that wouldn't help you with
obtaining and keeping dormant widgets.  The nearest approach to this
would be to create a gtkmm widget with the new expression, put it into
a gtkmm container with the manage flag set and then, when you need to
make it dormant, take it out of the container, unset the manage flag,
and store it in a C++ aggregate container ready for re-use.

However, I don't know of any way of unsetting the managed flag on
Gtk::Widgets. gtkmm widgets inherit a set_managed() method from
Gtk::Object, but not an unset_managed() flag.

Therefore, if you do want to store dormant widgets, one approach is to
take over lifetime management by hand.  That is, don't set the managed
flag at all, and keep track by hand of what gtkmm container if any
happens to "own" a widget at any one time.  You would be responsible for
deleting the widgets when no longer needed - for example, when last
removing a redundant widget from a container or when the container of a
redundant widget is destroyed.

Another possible approach is to store all widgets, dormant or
otherwise, in the C++ container and transfer widget lifetime
"ownership" to the C++ container by managing the gtkmm widget by
std::shared_ptr.  This would mean that any widget would be destroyed
as soon as the C++ container is destroyed. This would in turn have the
effect of removing the widget from its gtkmm container automatically
when the C++ container is destroyed, I think safely: you would need to
check what the effect is of calling the delete expression on a gtkmm
widget owned by gtkmm container - I think it should safely remove it
because invoking the widget's destructor will cause the destroy signal
to be emitted (by calling gtk_widget_destroy() on the contained C
object), so causing the GTK+ container's reference on the widget to be
released.

Chris




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]