diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2015-07-09 16:53:39 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2015-07-09 16:53:39 +0100 |
commit | bf0ca916629f5034ff322642269c222e62efaf28 (patch) | |
tree | 1ce938c8dfa1a3cb7ce678c98979f67396a4f3ab /examples | |
parent | 365bd482fbce9ae61e810878afe685d21e6a801d (diff) | |
download | clutter-bf0ca916629f5034ff322642269c222e62efaf28.tar.gz |
examples/actor-model: Clean up and comment
This is an example so it ought to be a bit more didactic.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/actor-model.c | 310 |
1 files changed, 169 insertions, 141 deletions
diff --git a/examples/actor-model.c b/examples/actor-model.c index f87fc64d9..b44fa4b03 100644 --- a/examples/actor-model.c +++ b/examples/actor-model.c @@ -2,35 +2,152 @@ #include <gio/gio.h> #include <clutter/clutter.h> +/* {{{ MenuItemModel */ + +/* This is our "model" of a Menu item; it has a "label" property, and + * a "selected" state property. The user is supposed to operate on the + * model instance, and change its state. + */ + +#define EXAMPLE_TYPE_MENU_ITEM_MODEL (example_menu_item_model_get_type ()) + +G_DECLARE_FINAL_TYPE (ExampleMenuItemModel, example_menu_item_model, EXAMPLE, MENU_ITEM_MODEL, GObject) + +struct _ExampleMenuItemModel +{ + GObject parent_instance; + + char *label; + + gboolean selected; +}; + +struct _ExampleMenuItemModelClass +{ + GObjectClass parent_class; +}; + +enum { + MENU_ITEM_MODEL_PROP_LABEL = 1, + MENU_ITEM_MODEL_PROP_SELECTED, + MENU_ITEM_MODEL_N_PROPS +}; + +static GParamSpec *menu_item_model_props[MENU_ITEM_MODEL_N_PROPS] = { NULL, }; + +G_DEFINE_TYPE (ExampleMenuItemModel, example_menu_item_model, G_TYPE_OBJECT) + +static void +example_menu_item_model_finalize (GObject *gobject) +{ + ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; + + g_free (self->label); + + G_OBJECT_CLASS (example_menu_item_model_parent_class)->finalize (gobject); +} + +static void +example_menu_item_model_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; + + switch (prop_id) + { + case MENU_ITEM_MODEL_PROP_LABEL: + g_free (self->label); + self->label = g_value_dup_string (value); + break; + + case MENU_ITEM_MODEL_PROP_SELECTED: + self->selected = g_value_get_boolean (value); + break; + } +} + +static void +example_menu_item_model_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; + + switch (prop_id) + { + case MENU_ITEM_MODEL_PROP_LABEL: + g_value_set_string (value, self->label); + break; + + case MENU_ITEM_MODEL_PROP_SELECTED: + g_value_set_boolean (value, self->selected); + break; + } +} + +static void +example_menu_item_model_class_init (ExampleMenuItemModelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = example_menu_item_model_set_property; + gobject_class->get_property = example_menu_item_model_get_property; + gobject_class->finalize = example_menu_item_model_finalize; + + menu_item_model_props[MENU_ITEM_MODEL_PROP_LABEL] = + g_param_spec_string ("label", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + menu_item_model_props[MENU_ITEM_MODEL_PROP_SELECTED] = + g_param_spec_boolean ("selected", NULL, NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (gobject_class, MENU_ITEM_MODEL_N_PROPS, menu_item_model_props); +} + +static void +example_menu_item_model_init (ExampleMenuItemModel *self) +{ +} +/* }}} */ + /* {{{ MenuItem */ -#define EXAMPLE_TYPE_MENU_ITEM (example_menu_item_get_type ()) -G_DECLARE_FINAL_TYPE (ExampleMenuItem, example_menu_item, EXAMPLE, MENU_ITEM, ClutterText) +/* This is our "view" of a Menu item; it changes state depending on whether + * the "selected" property is set. The "view" reflects the state of the + * "model" instance, though it has no direct connection to it. + */ +#define EXAMPLE_TYPE_MENU_ITEM_VIEW (example_menu_item_view_get_type ()) + +G_DECLARE_FINAL_TYPE (ExampleMenuItemView, example_menu_item_view, EXAMPLE, MENU_ITEM_VIEW, ClutterText) -struct _ExampleMenuItem +struct _ExampleMenuItemView { ClutterText parent_instance; gboolean is_selected; }; -struct _ExampleMenuItemClass +struct _ExampleMenuItemViewClass { ClutterTextClass parent_class; }; -G_DEFINE_TYPE (ExampleMenuItem, example_menu_item, CLUTTER_TYPE_TEXT) +G_DEFINE_TYPE (ExampleMenuItemView, example_menu_item_view, CLUTTER_TYPE_TEXT) enum { - MENU_ITEM_PROP_SELECTED = 1, - MENU_ITEM_N_PROPS + MENU_ITEM_VIEW_PROP_SELECTED = 1, + MENU_ITEM_VIEW_N_PROPS }; -static GParamSpec *menu_item_props[MENU_ITEM_N_PROPS] = { NULL, }; +static GParamSpec *menu_item_view_props[MENU_ITEM_VIEW_N_PROPS] = { NULL, }; static void -example_menu_item_set_selected (ExampleMenuItem *self, - gboolean selected) +example_menu_item_view_set_selected (ExampleMenuItemView *self, + gboolean selected) { selected = !!selected; if (self->is_selected == selected) @@ -43,57 +160,57 @@ example_menu_item_set_selected (ExampleMenuItem *self, else clutter_text_set_color (CLUTTER_TEXT (self), CLUTTER_COLOR_White); - g_object_notify_by_pspec (G_OBJECT (self), menu_item_props[MENU_ITEM_PROP_SELECTED]); + g_object_notify_by_pspec (G_OBJECT (self), menu_item_view_props[MENU_ITEM_VIEW_PROP_SELECTED]); } static void -example_menu_item_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +example_menu_item_view_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { switch (prop_id) { - case MENU_ITEM_PROP_SELECTED: - example_menu_item_set_selected (EXAMPLE_MENU_ITEM (gobject), - g_value_get_boolean (value)); + case MENU_ITEM_VIEW_PROP_SELECTED: + example_menu_item_view_set_selected (EXAMPLE_MENU_ITEM_VIEW (gobject), + g_value_get_boolean (value)); break; } } static void -example_menu_item_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) +example_menu_item_view_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) { switch (prop_id) { - case MENU_ITEM_PROP_SELECTED: - g_value_set_boolean (value, EXAMPLE_MENU_ITEM (gobject)->is_selected); + case MENU_ITEM_VIEW_PROP_SELECTED: + g_value_set_boolean (value, EXAMPLE_MENU_ITEM_VIEW (gobject)->is_selected); break; } } static void -example_menu_item_class_init (ExampleMenuItemClass *klass) +example_menu_item_view_class_init (ExampleMenuItemViewClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->set_property = example_menu_item_set_property; - gobject_class->get_property = example_menu_item_get_property; + gobject_class->set_property = example_menu_item_view_set_property; + gobject_class->get_property = example_menu_item_view_get_property; - menu_item_props[MENU_ITEM_PROP_SELECTED] = + menu_item_view_props[MENU_ITEM_VIEW_PROP_SELECTED] = g_param_spec_boolean ("selected", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (gobject_class, MENU_ITEM_N_PROPS, menu_item_props); + g_object_class_install_properties (gobject_class, MENU_ITEM_VIEW_N_PROPS, menu_item_view_props); } static void -example_menu_item_init (ExampleMenuItem *self) +example_menu_item_view_init (ExampleMenuItemView *self) { ClutterText *text = CLUTTER_TEXT (self); ClutterActor *actor = CLUTTER_ACTOR (self); @@ -108,7 +225,12 @@ example_menu_item_init (ExampleMenuItem *self) /* }}} */ /* {{{ Menu */ -#define EXAMPLE_TYPE_MENU (example_menu_get_type ()) + +/* This is our container actor, which binds the GListStore with the + * ExampleMenuItemModel instances to the ExampleMenuItemView actors + */ + +#define EXAMPLE_TYPE_MENU (example_menu_get_type ()) G_DECLARE_FINAL_TYPE (ExampleMenu, example_menu, EXAMPLE, MENU, ClutterActor) @@ -153,12 +275,14 @@ example_menu_select_item (ExampleMenu *self, { ClutterActor *item; + /* Any change in the view is reflected into the model */ + if (idx == self->current_idx) return clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx); item = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx); if (item != NULL) - example_menu_item_set_selected ((ExampleMenuItem *) item, FALSE); + example_menu_item_view_set_selected ((ExampleMenuItemView *) item, FALSE); if (idx < 0) idx = clutter_actor_get_n_children (CLUTTER_ACTOR (self)) - 1; @@ -169,7 +293,7 @@ example_menu_select_item (ExampleMenu *self, item = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx); if (item != NULL) - example_menu_item_set_selected ((ExampleMenuItem *) item, TRUE); + example_menu_item_view_set_selected ((ExampleMenuItemView *) item, TRUE); return item; } @@ -188,112 +312,6 @@ example_menu_select_prev (ExampleMenu *self) /* }}} */ -/* {{{ MenuItemModel */ -#define EXAMPLE_TYPE_MENU_ITEM_MODEL (example_menu_item_model_get_type ()) - -G_DECLARE_FINAL_TYPE (ExampleMenuItemModel, example_menu_item_model, EXAMPLE, MENU_ITEM_MODEL, GObject) - -struct _ExampleMenuItemModel -{ - GObject parent_instance; - - char *label; - - gboolean selected; -}; - -struct _ExampleMenuItemModelClass -{ - GObjectClass parent_class; -}; - -enum { - MENU_ITEM_MODEL_PROP_LABEL = 1, - MENU_ITEM_MODEL_PROP_SELECTED, - MENU_ITEM_MODEL_N_PROPS -}; - -static GParamSpec *menu_item_model_props[MENU_ITEM_MODEL_N_PROPS] = { NULL, }; - -G_DEFINE_TYPE (ExampleMenuItemModel, example_menu_item_model, G_TYPE_OBJECT) - -static void -example_menu_item_model_finalize (GObject *gobject) -{ - ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; - - g_free (self->label); - - G_OBJECT_CLASS (example_menu_item_model_parent_class)->finalize (gobject); -} - -static void -example_menu_item_model_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; - - switch (prop_id) - { - case MENU_ITEM_MODEL_PROP_LABEL: - g_free (self->label); - self->label = g_value_dup_string (value); - break; - - case MENU_ITEM_MODEL_PROP_SELECTED: - self->selected = g_value_get_boolean (value); - break; - } -} - -static void -example_menu_item_model_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; - - switch (prop_id) - { - case MENU_ITEM_MODEL_PROP_LABEL: - g_value_set_string (value, self->label); - break; - - case MENU_ITEM_MODEL_PROP_SELECTED: - g_value_set_boolean (value, self->selected); - break; - } -} - -static void -example_menu_item_model_class_init (ExampleMenuItemModelClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->set_property = example_menu_item_model_set_property; - gobject_class->get_property = example_menu_item_model_get_property; - gobject_class->finalize = example_menu_item_model_finalize; - - menu_item_model_props[MENU_ITEM_MODEL_PROP_LABEL] = - g_param_spec_string ("label", NULL, NULL, - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - menu_item_model_props[MENU_ITEM_MODEL_PROP_SELECTED] = - g_param_spec_boolean ("selected", NULL, NULL, - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (gobject_class, MENU_ITEM_MODEL_N_PROPS, menu_item_model_props); -} - -static void -example_menu_item_model_init (ExampleMenuItemModel *self) -{ -} -/* }}} */ - /* {{{ main */ static gboolean on_key_press (ClutterActor *stage, @@ -348,7 +366,7 @@ static ClutterActor * create_menu_item (gpointer item, gpointer data G_GNUC_UNUSED) { - ClutterActor *res = g_object_new (EXAMPLE_TYPE_MENU_ITEM, NULL); + ClutterActor *res = g_object_new (EXAMPLE_TYPE_MENU_ITEM_VIEW, NULL); /* The label goes from the model to the view */ g_object_bind_property (item, "label", @@ -368,6 +386,7 @@ create_menu_item (gpointer item, static ClutterActor * create_menu_actor (void) { + /* Our store of menu item models */ GListStore *model = g_list_store_new (EXAMPLE_TYPE_MENU_ITEM_MODEL); ClutterActor *menu = g_object_new (EXAMPLE_TYPE_MENU, NULL); int i; @@ -387,18 +406,27 @@ create_menu_actor (void) g_free (label); } + /* Bind the list of menu item models to the menu actor; this will + * create ClutterActor views of each item in the model, and add them + * to the menu actor + */ clutter_actor_bind_model (menu, G_LIST_MODEL (model), create_menu_item, NULL, NULL); - /* The actor owns the model */ + /* We don't need a pointer to the model any more, so we transfer ownership + * to the menu actor; this means that the model will go away when the menu + * actor is destroyed + */ g_object_unref (model); + /* Select the first item in the menu */ example_menu_select_item ((ExampleMenu *) menu, 0); return menu; } +/* The scrolling container for the menu */ static ClutterActor * create_scroll_actor (void) { |