[StContainer] Add :first-child, :last-child pseudo classes

Add support for the CSS :first-child and :last-child properties to
StContainer, and thus to all containers in St and ShellGenericContainer.

The internal ordering of the container's children is used to determine
the child to which to attach the pseudo class, not the children's
positions. This means that containers where positions can differ from
the ordering (ShellGenericContainer / StGroup) may behave unexpectedly,
so some caution is required.

https://bugzilla.gnome.org/show_bug.cgi?id=625316
This commit is contained in:
Florian Müllner 2010-07-22 23:08:45 +02:00
parent 0573cbfbac
commit 0905940ef8

View File

@ -35,6 +35,8 @@
struct _StContainerPrivate struct _StContainerPrivate
{ {
GList *children; GList *children;
ClutterActor *first_child;
ClutterActor *last_child;
}; };
static void clutter_container_iface_init (ClutterContainerIface *iface); static void clutter_container_iface_init (ClutterContainerIface *iface);
@ -43,6 +45,54 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (StContainer, st_container, ST_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
clutter_container_iface_init)); clutter_container_iface_init));
static void
st_container_update_pseudo_classes (StContainer *container)
{
GList *first_item, *last_item;
ClutterActor *first_child, *last_child;
StContainerPrivate *priv = container->priv;
first_item = priv->children;
first_child = first_item ? first_item->data : NULL;
if (first_child != priv->first_child)
{
if (priv->first_child && ST_IS_WIDGET (priv->first_child))
st_widget_remove_style_pseudo_class (ST_WIDGET (priv->first_child),
"first-child");
if (priv->first_child)
{
g_object_unref (priv->first_child);
priv->first_child = NULL;
}
if (first_child && ST_IS_WIDGET (first_child))
st_widget_add_style_pseudo_class (ST_WIDGET (first_child),
"first-child");
if (first_child)
priv->first_child = g_object_ref (first_child);
}
last_item = g_list_last (priv->children);
last_child = last_item ? last_item->data : NULL;
if (last_child != priv->last_child)
{
if (priv->last_child && ST_IS_WIDGET (priv->last_child))
st_widget_remove_style_pseudo_class (ST_WIDGET (priv->last_child),
"last-child");
if (priv->last_child)
{
g_object_unref (priv->last_child);
priv->last_child = NULL;
}
if (last_child && ST_IS_WIDGET (last_child))
st_widget_add_style_pseudo_class (ST_WIDGET (last_child),
"last-child");
if (last_child)
priv->last_child = g_object_ref (last_child);
}
}
/** /**
* st_container_remove_all: * st_container_remove_all:
* @container: An #StContainer * @container: An #StContainer
@ -62,6 +112,7 @@ st_container_remove_all (StContainer *container)
clutter_container_remove_actor (CLUTTER_CONTAINER (container), child); clutter_container_remove_actor (CLUTTER_CONTAINER (container), child);
} }
st_container_update_pseudo_classes (container);
} }
/** /**
@ -104,6 +155,9 @@ st_container_move_child (StContainer *container,
priv->children = g_list_delete_link (priv->children, item); priv->children = g_list_delete_link (priv->children, item);
priv->children = g_list_insert (priv->children, actor, pos); priv->children = g_list_insert (priv->children, actor, pos);
st_container_update_pseudo_classes (container);
clutter_actor_queue_relayout ((ClutterActor*) container); clutter_actor_queue_relayout ((ClutterActor*) container);
} }
@ -159,6 +213,7 @@ st_container_add (ClutterContainer *container,
g_signal_emit_by_name (container, "actor-added", actor); g_signal_emit_by_name (container, "actor-added", actor);
clutter_container_sort_depth_order (container); clutter_container_sort_depth_order (container);
st_container_update_pseudo_classes (ST_CONTAINER (container));
g_object_unref (actor); g_object_unref (actor);
} }
@ -185,6 +240,8 @@ st_container_remove (ClutterContainer *container,
*/ */
g_signal_emit_by_name (container, "actor-removed", actor); g_signal_emit_by_name (container, "actor-removed", actor);
st_container_update_pseudo_classes (ST_CONTAINER (container));
if (CLUTTER_ACTOR_IS_VISIBLE (container)) if (CLUTTER_ACTOR_IS_VISIBLE (container))
clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
@ -248,6 +305,8 @@ st_container_raise (ClutterContainer *container,
clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling));
} }
st_container_update_pseudo_classes (ST_CONTAINER (container));
if (CLUTTER_ACTOR_IS_VISIBLE (container)) if (CLUTTER_ACTOR_IS_VISIBLE (container))
clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
} }
@ -289,6 +348,8 @@ st_container_lower (ClutterContainer *container,
clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling));
} }
st_container_update_pseudo_classes (ST_CONTAINER (container));
if (CLUTTER_ACTOR_IS_VISIBLE (container)) if (CLUTTER_ACTOR_IS_VISIBLE (container))
clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
} }
@ -317,6 +378,14 @@ st_container_dispose (GObject *object)
priv->children = NULL; priv->children = NULL;
} }
if (priv->first_child)
g_object_unref (priv->first_child);
priv->first_child = NULL;
if (priv->last_child)
g_object_unref (priv->last_child);
priv->last_child = NULL;
G_OBJECT_CLASS (st_container_parent_class)->dispose (object); G_OBJECT_CLASS (st_container_parent_class)->dispose (object);
} }