From 1e3bf0ea7e5c266a445bdf341b0f3bbabd4eb516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 22 Mar 2010 01:26:19 +0100 Subject: [PATCH] Add StGroup container Currently if we want a stylable fixed-layout container, we use either a Clutter.Group inside an St.Bin, or we abuse St.BoxLayout. https://bugzilla.gnome.org/show_bug.cgi?id=613907 --- src/Makefile-st.am | 2 + src/st/st-group.c | 232 +++++++++++++++++++++++++++++++++++++++++++++ src/st/st-group.h | 71 ++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 src/st/st-group.c create mode 100644 src/st/st-group.h diff --git a/src/Makefile-st.am b/src/Makefile-st.am index d3597fdcd..b3cc7aa82 100644 --- a/src/Makefile-st.am +++ b/src/Makefile-st.am @@ -77,6 +77,7 @@ st_source_h = \ st/st-container.h \ st/st-drawing-area.h \ st/st-entry.h \ + st/st-group.h \ st/st-im-text.h \ st/st-label.h \ st/st-overflow-box.h \ @@ -124,6 +125,7 @@ st_source_c = \ st/st-container.c \ st/st-drawing-area.c \ st/st-entry.c \ + st/st-group.c \ st/st-im-text.c \ st/st-label.c \ st/st-overflow-box.c \ diff --git a/src/st/st-group.c b/src/st/st-group.c new file mode 100644 index 000000000..690f7a7ef --- /dev/null +++ b/src/st/st-group.c @@ -0,0 +1,232 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * st-group.h: A fixed layout container based on ClutterGroup + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/** + * SECTION:st-group + * SECTION:clutter-group + * @short_description: A fixed layout container + * + * A #StGroup is an Actor which contains multiple child actors positioned + * relative to the #StGroup position. Other operations such as scaling, + * rotating and clipping of the group will apply to the child actors. + * + * A #StGroup's size is defined by the size and position of its children; + * it will be the smallest non-negative size that covers the right and bottom + * edges of all of its children. + * + * Setting the size on a Group using #ClutterActor methods like + * clutter_actor_set_size() will override the natural size of the Group, + * however this will not affect the size of the children and they may still + * be painted outside of the allocation of the group. One way to constrain + * the visible area of a #StGroup to a specified allocation is to + * explicitly set the size of the #StGroup and then use the + * #ClutterActor:clip-to-allocation property. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "st-group.h" +#include "st-enum-types.h" +#include "st-private.h" + +G_DEFINE_TYPE (StGroup, st_group, ST_TYPE_CONTAINER); + +static void +st_group_paint (ClutterActor *actor) +{ + CLUTTER_ACTOR_CLASS (st_group_parent_class)->paint (actor); + + clutter_container_foreach (CLUTTER_CONTAINER (actor), + CLUTTER_CALLBACK (clutter_actor_paint), + NULL); +} + +static void +st_group_pick (ClutterActor *actor, + const ClutterColor *pick) +{ + /* Chain up so we get a bounding box painted (if we are reactive) */ + CLUTTER_ACTOR_CLASS (st_group_parent_class)->pick (actor, pick); + + clutter_container_foreach (CLUTTER_CONTAINER (actor), + CLUTTER_CALLBACK (clutter_actor_paint), + NULL); +} + +static void +st_group_get_preferred_width (ClutterActor *actor, + gfloat for_height, + gfloat *min_width, + gfloat *natural_width) +{ + GList *l, *children; + gdouble min_right, natural_right; + + /* We will always be at least 0 sized (ie, if all of the actors are + to the left of the origin we won't return a negative size) */ + min_right = 0; + natural_right = 0; + + children = st_container_get_children_list (ST_CONTAINER (actor)); + + for (l = children; l != NULL; l = l->next) + { + ClutterActor *child = l->data; + gfloat child_x, child_min, child_nat; + + child_x = clutter_actor_get_x (child); + + /* for_height is irrelevant to the fixed layout, so it's not used */ + _st_actor_get_preferred_width (child, -1, FALSE, + &child_min, &child_nat); + + /* Track the rightmost edge */ + if (child_x + child_min > min_right) + min_right = child_x + child_min; + + if (child_x + child_nat > natural_right) + natural_right = child_x + child_nat; + } + + /* The size is defined as the distance from the origin to the right-hand + edge of the rightmost actor */ + if (min_width) + *min_width = min_right; + + if (natural_width) + *natural_width = natural_right; +} + +static void +st_group_get_preferred_height (ClutterActor *actor, + gfloat for_width, + gfloat *min_height, + gfloat *natural_height) +{ + GList *l, *children; + gdouble min_bottom, natural_bottom; + + /* We will always be at least 0 sized (ie, if all of the actors are + above of the origin we won't return a negative size) */ + min_bottom = 0; + natural_bottom = 0; + + children = st_container_get_children_list (ST_CONTAINER (actor)); + + for (l = children; l != NULL; l = l->next) + { + ClutterActor *child = l->data; + gfloat child_y, child_min, child_nat; + + child_y = clutter_actor_get_y (child); + + /* for_width is irrelevant to the fixed layout, so it's not used */ + _st_actor_get_preferred_height (child, -1, FALSE, + &child_min, &child_nat); + + /* Track the bottommost edge */ + if (child_y + child_min > min_bottom) + min_bottom = child_y + child_min; + + if (child_y + child_nat > natural_bottom) + natural_bottom = child_y + child_nat; + } + + /* The size is defined as the distance from the origin to the right-hand + edge of the rightmost actor */ + if (min_height) + *min_height = min_bottom; + + if (natural_height) + *natural_height = natural_bottom; +} + +static void +st_group_allocate (ClutterActor *actor, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + GList *l, *children; + + CLUTTER_ACTOR_CLASS (st_group_parent_class)->allocate (actor, box, flags); + + children = st_container_get_children_list (ST_CONTAINER (actor)); + for (l = children; l != NULL; l = l->next) + { + ClutterActor *child = l->data; + clutter_actor_allocate_preferred_size (child, flags); + } +} + +static void +st_group_show_all (ClutterActor *actor) +{ + clutter_container_foreach (CLUTTER_CONTAINER (actor), + CLUTTER_CALLBACK (clutter_actor_show), + NULL); + clutter_actor_show (actor); +} + +static void +st_group_hide_all (ClutterActor *actor) +{ + clutter_actor_hide (actor); + clutter_container_foreach (CLUTTER_CONTAINER (actor), + CLUTTER_CALLBACK (clutter_actor_hide), + NULL); +} + + + + +static void +st_group_class_init (StGroupClass *klass) +{ + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + actor_class->get_preferred_width = st_group_get_preferred_width; + actor_class->get_preferred_height = st_group_get_preferred_height; + actor_class->allocate = st_group_allocate; + actor_class->paint = st_group_paint; + actor_class->pick = st_group_pick; + actor_class->show_all = st_group_show_all; + actor_class->hide_all = st_group_hide_all; +} + +static void +st_group_init (StGroup *self) +{ +} + +/** + * st_group_new: + * + * Create a new #StGroup. + * + * Return value: the newly created #StGroup actor + */ +StWidget * +st_group_new (void) +{ + return g_object_new (ST_TYPE_GROUP, NULL); +} diff --git a/src/st/st-group.h b/src/st/st-group.h new file mode 100644 index 000000000..bf7e34b6f --- /dev/null +++ b/src/st/st-group.h @@ -0,0 +1,71 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * st-group.h: A fixed layout container based on ClutterGroup + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * Boston, MA 02111-1307, USA. + * + */ + +#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) +#error "Only can be included directly.h" +#endif + +#ifndef __ST_GROUP_H__ +#define __ST_GROUP_H__ + +#include +#include + +G_BEGIN_DECLS + +#define ST_TYPE_GROUP (st_group_get_type ()) +#define ST_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_GROUP, StGroup)) +#define ST_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_GROUP)) +#define ST_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_GROUP, StGroupClass)) +#define ST_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_GROUP)) +#define ST_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_GROUP, StGroupClass)) + +typedef struct _StGroup StGroup; +typedef struct _StGroupPrivate StGroupPrivate; +typedef struct _StGroupClass StGroupClass; + +/** + * StGroup: + * + * The #StGroup struct contains only private data + */ +struct _StGroup +{ + /*< private >*/ + StContainer parent_instance; +}; + +/** + * StGroupClass: + * + * The #StGroupClass struct contains only private data + */ +struct _StGroupClass +{ + /*< private >*/ + StContainerClass parent_class; +}; + +GType st_group_get_type (void) G_GNUC_CONST; +StWidget *st_group_new (void); + +G_END_DECLS + +#endif /* __ST_GROUP_H__ */