📄 gtkcontainer.c
字号:
widget = GTK_WIDGET (container); gtk_widget_size_request (widget, &requisition); if (requisition.width > widget->allocation.width || requisition.height > widget->allocation.height) { if (GTK_IS_RESIZE_CONTAINER (container)) gtk_widget_size_allocate (GTK_WIDGET (container), >K_WIDGET (container)->allocation); else gtk_widget_queue_resize (widget); } else { gtk_container_resize_children (container); }}/* The container hasn't changed size but one of its children * queued a resize request. Which means that the allocation * is not sufficient for the requisition of some child. * We've already performed a size request at this point, * so we simply need to run through the list of resize * widgets and reallocate their sizes appropriately. We * make the optimization of not performing reallocation * for a widget who also has a parent in the resize widgets * list. GTK_RESIZE_NEEDED is used for flagging those * parents inside this function. */voidgtk_container_resize_children (GtkContainer *container){ GtkWidget *widget; GtkWidget *resize_container; GSList *resize_widgets; GSList *resize_containers; GSList *node; /* resizing invariants: * toplevels have *always* resize_mode != GTK_RESIZE_PARENT set. * containers with resize_mode==GTK_RESIZE_PARENT have to have resize_widgets * set to NULL. * containers that are flagged RESIZE_NEEDED must have resize_widgets set to * NULL, or are toplevels (thus have ->parent set to NULL). * widgets that are in some container->resize_widgets list must be flagged with * RESIZE_NEEDED. * widgets that have RESIZE_NEEDED set must be referenced in some * GTK_IS_RESIZE_CONTAINER (container)->resize_widgets list. * containers that have an idle sizer pending must be flagged with * RESIZE_PENDING. */ g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); /* we first check out if we actually need to perform a resize, * which is not the case if we got another container queued for * a resize in our anchestry. also we can skip the whole * resize_widgets checks if we are a toplevel and NEED_RESIZE. * this code assumes that our allocation is sufficient for our * requisition, since otherwise we would NEED_RESIZE. */ resize_container = GTK_WIDGET (container); while (resize_container) { if (GTK_WIDGET_RESIZE_NEEDED (resize_container)) break; resize_container = resize_container->parent; } if (resize_container) { /* queue_resize and size_allocate both clear our * resize_widgets list. */ if (resize_container->parent) gtk_container_queue_resize (container); else gtk_widget_size_allocate (GTK_WIDGET (container), >K_WIDGET (container)->allocation); return; } resize_container = GTK_WIDGET (container); /* we now walk the anchestry for all resize widgets as long * as they are our children and as long as their allocation * is insufficient, since we don't need to reallocate below that. */ resize_widgets = container->resize_widgets; container->resize_widgets = NULL; for (node = resize_widgets; node; node = node->next) { widget = node->data; GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); while (widget->parent != resize_container && ((widget->allocation.width < widget->requisition.width) || (widget->allocation.height < widget->requisition.height))) widget = widget->parent; GTK_PRIVATE_SET_FLAG (widget, GTK_RESIZE_NEEDED); node->data = widget; } /* for the newly setup resize_widgets list, we now walk each widget's * anchestry to sort those widgets out that have RESIZE_NEEDED parents. * we can safely stop the walk if we are the parent, since we checked * our own anchestry already. */ resize_containers = NULL; for (node = resize_widgets; node; node = node->next) { GtkWidget *parent; widget = node->data; if (!GTK_WIDGET_RESIZE_NEEDED (widget)) continue; parent = widget->parent; while (parent != resize_container) { if (GTK_WIDGET_RESIZE_NEEDED (parent)) { GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); widget = parent; } parent = parent->parent; } if (!g_slist_find (resize_containers, widget)) { resize_containers = g_slist_prepend (resize_containers, widget); gtk_widget_ref (widget); } } g_slist_free (resize_widgets); for (node = resize_containers; node; node = node->next) { widget = node->data; GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); gtk_widget_size_allocate (widget, &widget->allocation); gtk_widget_unref (widget); } g_slist_free (resize_containers);}voidgtk_container_forall (GtkContainer *container, GtkCallback callback, gpointer callback_data){ GtkContainerClass *class; g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (callback != NULL); class = GTK_CONTAINER_CLASS (GTK_OBJECT (container)->klass); if (class->forall) class->forall (container, TRUE, callback, callback_data);}voidgtk_container_foreach (GtkContainer *container, GtkCallback callback, gpointer callback_data){ GtkContainerClass *class; g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (callback != NULL); class = GTK_CONTAINER_CLASS (GTK_OBJECT (container)->klass); if (class->forall) class->forall (container, FALSE, callback, callback_data);}typedef struct _GtkForeachData GtkForeachData;struct _GtkForeachData{ GtkObject *container; GtkCallbackMarshal callback; gpointer callback_data;};static voidgtk_container_foreach_unmarshal (GtkWidget *child, gpointer data){ GtkForeachData *fdata = (GtkForeachData*) data; GtkArg args[2]; /* first argument */ args[0].name = NULL; args[0].type = GTK_OBJECT(child)->klass->type; GTK_VALUE_OBJECT(args[0]) = GTK_OBJECT (child); /* location for return value */ args[1].name = NULL; args[1].type = GTK_TYPE_NONE; fdata->callback (fdata->container, fdata->callback_data, 1, args);}voidgtk_container_foreach_full (GtkContainer *container, GtkCallback callback, GtkCallbackMarshal marshal, gpointer callback_data, GtkDestroyNotify notify){ g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (marshal) { GtkForeachData fdata; fdata.container = GTK_OBJECT (container); fdata.callback = marshal; fdata.callback_data = callback_data; gtk_container_foreach (container, gtk_container_foreach_unmarshal, &fdata); } else { g_return_if_fail (callback != NULL); gtk_container_foreach (container, callback, &callback_data); } if (notify) notify (callback_data);}gintgtk_container_focus (GtkContainer *container, GtkDirectionType direction){ gint return_val; g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE); gtk_signal_emit (GTK_OBJECT (container), container_signals[FOCUS], direction, &return_val); return return_val;}voidgtk_container_set_focus_child (GtkContainer *container, GtkWidget *widget){ g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (widget) g_return_if_fail (GTK_IS_WIDGET (widget)); gtk_signal_emit (GTK_OBJECT (container), container_signals[SET_FOCUS_CHILD], widget);}GList*gtk_container_children (GtkContainer *container){ GList *children; children = NULL; gtk_container_foreach (container, gtk_container_children_callback, &children); return g_list_reverse (children);}voidgtk_container_register_toplevel (GtkContainer *container){ g_return_if_fail (container != NULL); toplevel_list = g_list_prepend (toplevel_list, container); gtk_widget_ref (GTK_WIDGET (container)); gtk_object_sink (GTK_OBJECT (container));}voidgtk_container_unregister_toplevel (GtkContainer *container){ GList *node; g_return_if_fail (container != NULL); node = g_list_find (toplevel_list, container); g_return_if_fail (node != NULL); toplevel_list = g_list_remove_link (toplevel_list, node); g_list_free_1 (node); gtk_widget_unref (GTK_WIDGET (container));}GList*gtk_container_get_toplevels (void){ /* XXX: fixme we should ref all these widgets and duplicate * the list. */ return toplevel_list;}static voidgtk_container_child_position_callback (GtkWidget *widget, gpointer client_data){ struct { GtkWidget *child; guint i; guint index; } *data = client_data; data->i++; if (data->child == widget) data->index = data->i;}static gchar*gtk_container_child_default_composite_name (GtkContainer *container, GtkWidget *child){ struct { GtkWidget *child; guint i; guint index; } data; gchar *name; /* fallback implementation */ data.child = child; data.i = 0; data.index = 0; gtk_container_forall (container, gtk_container_child_position_callback, &data); name = g_strdup_printf ("%s-%u", gtk_type_name (GTK_OBJECT_TYPE (child)), data.index); return name;}gchar*gtk_container_child_composite_name (GtkContainer *container, GtkWidget *child){ g_return_val_if_fail (container != NULL, NULL); g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); g_return_val_if_fail (child != NULL, NULL); g_return_val_if_fail (GTK_IS_WIDGET (child), NULL); g_return_val_if_fail (child->parent == GTK_WIDGET (container), NULL); if (GTK_WIDGET_COMPOSITE_CHILD (child)) { static GQuark quark_composite_name = 0; gchar *name; if (!quark_composite_name) quark_composite_name = g_quark_from_static_string ("gtk-composite-name"); name = gtk_object_get_data_by_id (GTK_OBJECT (child), quark_composite_name); if (!name) { GtkContainerClass *class; class = GTK_CONTAINER_CLASS (GTK_OBJECT (container)->klass); if (class->composite_name) name = class->composite_name (container, child); } else name = g_strdup (name); return name; } return NULL;}voidgtk_container_real_set_focus_child (GtkContainer *container, GtkWidget *child){ g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (child) g_return_if_fail (GTK_IS_WIDGET (child)); if (child != container->focus_child) { if (container->focus_child) gtk_widget_unref (container->focus_child); container->focus_child = child; if (container->focus_child) gtk_widget_ref (container->focus_child); } /* check for h/v adjustments */ if (container->focus_child) { GtkAdjustment *adjustment; adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), vadjustment_key_id); if (adjustment) gtk_adjustment_clamp_page (adjustment, container->focus_child->allocation.y, (container->focus_child->allocation.y + container->focus_child->allocation.height)); adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), hadjustment_key_id); if (adjustment) gtk_adjustment_clamp_page (adjustment, container->focus_child->allocation.x, (container->focus_child->allocation.x + container->focus_child->allocation.width)); }}static gintgtk_container_real_focus (GtkContainer *container, GtkDirectionType direction){ GList *children; GList *tmp_list; GList *tmp_list2; gint return_val; g_return_val_if_fail (container != NULL, FALSE); g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE); /* Fail if the container is inappropriate for focus movement */ if (!GTK_WIDGET_DRAWABLE (container) || !GTK_WIDGET_IS_SENSITIVE (container)) return FALSE; return_val = FALSE; if (GTK_WIDGET_CAN_FOCUS (container)) { gtk_widget_grab_focus (GTK_WIDGET (container)); return_val = TRUE; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -