[gtk+/wip/baedert/progressbar: 1/18] widget: Add gtk_widget_insert_before/after
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/baedert/progressbar: 1/18] widget: Add gtk_widget_insert_before/after
- Date: Sun, 23 Apr 2017 15:53:35 +0000 (UTC)
commit 5c36dec843f1caaed4163db137fce16dc8408bed
Author: Timm Bäder <mail baedert org>
Date: Wed Apr 5 19:57:11 2017 +0200
widget: Add gtk_widget_insert_before/after
To insert a widget into the widget tree before or after a child widget
of the soon-to-be parent.
docs/reference/gtk/gtk4-sections.txt | 2 +
gtk/gtkcssnode.c | 2 -
gtk/gtkwidget.c | 190 ++++++++++++++++++++++++++++------
gtk/gtkwidget.h | 8 ++
4 files changed, 167 insertions(+), 35 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index df8b221..84229d0 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4647,6 +4647,8 @@ gtk_widget_get_next_sibling
gtk_widget_get_prev_sibling
gtk_widget_get_first_child
gtk_widget_get_last_child
+gtk_widget_insert_before
+gtk_widget_insert_after
<SUBSECTION>
gtk_widget_get_path
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index 46ed213..d94c09d 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -842,8 +842,6 @@ gtk_css_node_insert_after (GtkCssNode *parent,
GtkCssNode *cssnode,
GtkCssNode *previous_sibling)
{
- g_return_if_fail (previous_sibling == NULL || previous_sibling->parent == parent);
- g_return_if_fail (cssnode != previous_sibling);
if (cssnode->previous_sibling == previous_sibling &&
cssnode->parent == parent)
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index eb3761a..8267798 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -8374,37 +8374,27 @@ gtk_widget_is_sensitive (GtkWidget *widget)
return !(widget->priv->state_flags & GTK_STATE_FLAG_INSENSITIVE);
}
-/**
- * gtk_widget_set_parent:
- * @widget: a #GtkWidget
- * @parent: parent container
- *
- * This function is useful only when implementing subclasses of
- * #GtkContainer.
- * Sets the container as the parent of @widget, and takes care of
- * some details such as updating the state and style of the child
- * to reflect its new location. The opposite function is
- * gtk_widget_unparent().
- **/
-void
-gtk_widget_set_parent (GtkWidget *widget,
- GtkWidget *parent)
+
+/* Insert @widget into the children list of @parent,
+ * after @previous_child */
+static void
+gtk_widget_reposition_after (GtkWidget *widget,
+ GtkWidget *parent,
+ GtkWidget *previous_child)
{
GtkStateFlags parent_flags;
- GtkWidgetPrivate *priv;
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+ GtkWidget *prev_parent;
GtkStateData data;
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (GTK_IS_WIDGET (parent));
- g_return_if_fail (widget != parent);
+ prev_parent = priv->parent;
- priv = widget->priv;
-
- if (priv->parent != NULL)
+ if (priv->parent != NULL && priv->parent != parent)
{
g_warning ("Can't set a parent on widget which has a parent");
return;
}
+
if (_gtk_widget_is_toplevel (widget))
{
g_warning ("Can't set a parent on a toplevel widget");
@@ -8421,14 +8411,53 @@ gtk_widget_set_parent (GtkWidget *widget,
gtk_widget_push_verify_invariants (widget);
priv->parent = parent;
- if (parent)
+
+ if (previous_child)
{
- priv->prev_sibling = parent->priv->last_child;
- if (parent->priv->last_child)
- parent->priv->last_child->priv->next_sibling = widget;
- parent->priv->last_child = widget;
- if (!parent->priv->first_child)
- parent->priv->first_child = widget;
+ if (previous_child->priv->next_sibling)
+ previous_child->priv->next_sibling->priv->prev_sibling = widget;
+
+ if (priv->prev_sibling)
+ priv->prev_sibling->priv->next_sibling = priv->next_sibling;
+
+ if (priv->next_sibling)
+ priv->next_sibling->priv->prev_sibling = priv->prev_sibling;
+
+
+ if (parent->priv->first_child == widget)
+ parent->priv->first_child = priv->next_sibling;
+
+ if (parent->priv->last_child == widget)
+ parent->priv->last_child = priv->prev_sibling;
+
+ priv->prev_sibling = previous_child;
+ priv->next_sibling = previous_child->priv->next_sibling;
+ previous_child->priv->next_sibling = widget;
+
+ if (parent->priv->last_child == previous_child)
+ parent->priv->last_child = widget;
+ else if (parent->priv->last_child == widget)
+ parent->priv->last_child = priv->next_sibling;
+ }
+ else
+ {
+ /* Beginning */
+ if (parent->priv->last_child == widget)
+ {
+ parent->priv->last_child = priv->prev_sibling;
+ if (priv->prev_sibling)
+ priv->prev_sibling->priv->next_sibling = NULL;
+ }
+
+ priv->prev_sibling = NULL;
+ priv->next_sibling = parent->priv->first_child;
+ if (parent->priv->first_child)
+ parent->priv->first_child->priv->prev_sibling = widget;
+
+ parent->priv->first_child = widget;
+
+ if (parent->priv->last_child == NULL)
+ parent->priv->last_child = widget;
}
parent_flags = _gtk_widget_get_state_flags (parent);
@@ -8440,7 +8469,12 @@ gtk_widget_set_parent (GtkWidget *widget,
gtk_widget_propagate_state (widget, &data);
if (gtk_css_node_get_parent (widget->priv->cssnode) == NULL)
- gtk_css_node_set_parent (widget->priv->cssnode, parent->priv->cssnode);
+ {
+ gtk_css_node_insert_after (parent->priv->cssnode,
+ priv->cssnode,
+ previous_child ? previous_child->priv->cssnode : NULL);
+ }
+
if (priv->context)
gtk_style_context_set_parent (priv->context,
_gtk_widget_get_style_context (parent));
@@ -8448,7 +8482,7 @@ gtk_widget_set_parent (GtkWidget *widget,
_gtk_widget_update_parent_muxer (widget);
g_signal_emit (widget, widget_signals[PARENT_SET], 0, NULL);
- if (priv->parent->priv->anchored)
+ if (priv->parent->priv->anchored && prev_parent == NULL)
_gtk_widget_propagate_hierarchy_changed (widget, NULL);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
@@ -8461,8 +8495,8 @@ gtk_widget_set_parent (GtkWidget *widget,
_gtk_widget_get_visible (widget))
{
if (_gtk_widget_get_child_visible (widget) &&
- _gtk_widget_get_mapped (priv->parent))
- gtk_widget_map (widget);
+ _gtk_widget_get_mapped (priv->parent))
+ gtk_widget_map (widget);
gtk_widget_queue_resize (priv->parent);
}
@@ -8489,6 +8523,31 @@ gtk_widget_set_parent (GtkWidget *widget,
}
/**
+ * gtk_widget_set_parent:
+ * @widget: a #GtkWidget
+ * @parent: parent container
+ *
+ * This function is useful only when implementing subclasses of
+ * #GtkContainer.
+ * Sets the container as the parent of @widget, and takes care of
+ * some details such as updating the state and style of the child
+ * to reflect its new location. The opposite function is
+ * gtk_widget_unparent().
+ **/
+void
+gtk_widget_set_parent (GtkWidget *widget,
+ GtkWidget *parent)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+ g_return_if_fail (_gtk_widget_get_parent (widget) == NULL);
+
+ gtk_widget_reposition_after (widget,
+ parent,
+ _gtk_widget_get_last_child (parent));
+}
+
+/**
* gtk_widget_get_parent:
* @widget: a #GtkWidget
*
@@ -15634,6 +15693,71 @@ gtk_widget_get_prev_sibling (GtkWidget *widget)
return widget->priv->prev_sibling;
}
+/*
+ * @widget: a #GtkWidget
+ * @parent: the parent #GtkWidget to insert @widget into
+ * @previous_child: (nullable): the new previous sibling of @widget
+ *
+ * Inserts @widget into the child widget list of @parent.
+ * It will be placed after @previous_child, or at the beginning if @previous_child is %NULL.
+ *
+ * After calling this function, gtk_widget_get_prev_sibling(widget) will return @previous_child.
+ */
+void
+gtk_widget_insert_after (GtkWidget *widget,
+ GtkWidget *parent,
+ GtkWidget *previous_child)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+ g_return_if_fail (previous_child == NULL || GTK_IS_WIDGET (previous_child));
+ g_return_if_fail (previous_child == NULL || _gtk_widget_get_parent (previous_child) == parent);
+
+ if (widget == previous_child ||
+ (previous_child && _gtk_widget_get_prev_sibling (widget) == previous_child))
+ return;
+
+ if (!previous_child && _gtk_widget_get_first_child (parent) == widget)
+ return;
+
+ gtk_widget_reposition_after (widget,
+ parent,
+ previous_child);
+}
+
+/*
+ * @widget: a #GtkWidget
+ * @parent: the parent #GtkWidget to insert @widget into
+ * @next_child: (nullable): the new next sibling of @widget or %NULL
+ *
+ * Inserts @widget into the child widget list of @parent.
+ * It will be placed before @next_child, or at the end if @next_child is %NULL.
+ *
+ * After calling this function, gtk_widget_get_next_sibling(widget) will return @next_child
+ * if @next_child was not %NULL.
+ */
+void
+gtk_widget_insert_before (GtkWidget *widget,
+ GtkWidget *parent,
+ GtkWidget *next_child)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+ g_return_if_fail (next_child == NULL || GTK_IS_WIDGET (next_child));
+ g_return_if_fail (next_child == NULL || _gtk_widget_get_parent (next_child) == parent);
+
+ if (widget == next_child ||
+ (next_child && _gtk_widget_get_next_sibling (widget) == next_child))
+ return;
+
+ if (!next_child && _gtk_widget_get_last_child (parent) == widget)
+ return;
+
+ gtk_widget_reposition_after (widget, parent,
+ next_child ? _gtk_widget_get_prev_sibling (next_child) :
+ _gtk_widget_get_last_child (parent));
+}
+
void
gtk_widget_forall (GtkWidget *widget,
GtkCallback callback,
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index c1cbe20..837fbd0 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -1243,6 +1243,14 @@ GDK_AVAILABLE_IN_3_90
GtkWidget * gtk_widget_get_next_sibling (GtkWidget *widget);
GDK_AVAILABLE_IN_3_90
GtkWidget * gtk_widget_get_prev_sibling (GtkWidget *widget);
+GDK_AVAILABLE_IN_3_92
+void gtk_widget_insert_after (GtkWidget *widget,
+ GtkWidget *parent,
+ GtkWidget *previous_child);
+GDK_AVAILABLE_IN_3_92
+void gtk_widget_insert_before (GtkWidget *widget,
+ GtkWidget *parent,
+ GtkWidget *next_child);
GDK_AVAILABLE_IN_3_90
void gtk_widget_set_focus_child (GtkWidget *widget,
GtkWidget *child);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]