Visible => Mapped constraint
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Subject: Visible => Mapped constraint
- Date: 18 Oct 2000 20:11:10 -0400
One of the TODO list items for GTK+ has to do with the
following constraint from widget-system.txt:
5) if !GTK_WIDGET_TOPLEVEL (widget):
[...]
widget->parent && GTK_WIDGET_MAPPED (widget->parent) &&
GTK_WIDGET_VISIBLE (widget) => GTK_WIDGET_MAPPED (widget)
There are two problems here
- Maintanence of this constraint is split between container
implementations and the GTK+ core in a confusing way.
- It just isn't valid. A good example of this is the GtkNotebook
widget; pages other than the current page can be visible,
and have the parent visible, but still not be mapped.
The constraint really needs another conditional, something like:
widget->parent && GTK_WIDGET_MAPPED (widget->parent) &&
GTK_WIDGET_VISIBLE (widget) && VISIBLE_IN_PARENT (widget, parent)
=> GTK_WIDGET_MAPPED (widget)
I think the best way to do things is to add another (probably private)
widget flag, and have:
void gtk_widget_set_parent_visibility (GtkWidget *widget,
gboolean visible_in_parent);
gboolean gtk_widget_get_parent_visibility (GtkWidget *widget);
We can then move most the enforcement of this constaint, as well
as some related ones into gtk_widget_set_parent ().
Unparenting a widget would automatically restore the parent_visibility
thing to its default state (visible), so that you don't
get carry-over interactions when a widget is removed from a parent
and added to another.
The one thing a container would still have to take care of for
enforcing this constraint is when the parent is mapped - since
the container needs to handle all its children - e.g.,
gtk_bin_map is currently:
===
static void
gtk_bin_map (GtkWidget *widget)
{
GtkBin *bin;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_BIN (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
bin = GTK_BIN (widget);
if (bin->child &&
GTK_WIDGET_VISIBLE (bin->child) &&
!GTK_WIDGET_MAPPED (bin->child))
gtk_widget_map (bin->child);
if (!GTK_WIDGET_NO_WINDOW (widget))
gdk_window_show (widget->window);
}
===
We could, however, provide a default implementation in GtkContainer
that handled this, and other widgets could chain to that if
they have special handling that they need to do in addition
to the default implementation - so gtk_bin_map would look like:
=========
static void
gtk_bin_map (GtkWidget *widget)
{
GTK_WIDGET_CLASS (parent_class)->map (widget);
if (!GTK_WIDGET_NO_WINDOW (widget))
gdk_window_show (widget->window);
}
=========
Another slight ugliness is that there are cases where a widget wants
to take action as its children are hidden and shown. For instance, for
GtkNotebook, when the main widget for a page is hidden, then it
needs to hide the tab label, and redraw stuff.
This isn't really to do with my suggested approach - when a child
is mapped or unmapped, a resize will be queued, and in the size
request, further actions can be taken, but it does mean that
handling of the hide/show is split in rather odd ways.
(And in the case of the notebook you get two request/allocate passes,
since in the size request, the tab label will be unmapped, triggering
another pass.)
There are a couple of other possible approaches
- Make a child_visible() a virtual_function for GtkContainer -
however, this has the problem that you then need something
like a queue_child_visible_changed() signal, and things gets
complicated.
- Simply remove this constraint, and let containers take care
of mapping their children as they wish. I think this interferes
with keeping container writing as simple as possible.
The first approach is, however, I think the cleanest, though
introducing another flag and more state is something I'm
not entirely happy with.
Regards,
Owen
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]