clutter: Remove examples

Running clutter apps standalone using mutters fork is not something
worth supporting.
This commit is contained in:
Jonas Ådahl 2018-05-23 11:33:21 +02:00
parent 1e2610e4f4
commit 0d9391e282
22 changed files with 1 additions and 4273 deletions

View File

@ -2,11 +2,7 @@ NULL =
SUBDIRS = build clutter tests SUBDIRS = build clutter tests
if BUILD_EXAMPLES DIST_SUBDIRS = clutter tests build
SUBDIRS += examples
endif
DIST_SUBDIRS = clutter tests examples build
# XXX - this is a massive hack to make autoreconf honour the ACLOCAL_FLAGS # XXX - this is a massive hack to make autoreconf honour the ACLOCAL_FLAGS
# that jhbuild sets while still retaining build/autotools as the authoritative # that jhbuild sets while still retaining build/autotools as the authoritative

View File

@ -698,8 +698,6 @@ AS_IF([test "x$use_gcov" = "xyes"],
AC_MSG_ERROR([Could not find genhtml from the LTP package]) AC_MSG_ERROR([Could not find genhtml from the LTP package])
fi fi
AC_DEFINE(HAVE_GCOV, 1, [Whether you have gcov])
dnl Remove all optimization flags from CFLAGS dnl Remove all optimization flags from CFLAGS
changequote({,}) changequote({,})
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
@ -727,12 +725,6 @@ dnl === Conformance test suite ================================================
GLIB_TESTS GLIB_TESTS
AC_ARG_ENABLE([examples],
[AS_HELP_STRING([--enable-examples], [Whether examples should be built])],
[],
[enable_examples=no])
AM_CONDITIONAL(BUILD_EXAMPLES, [test "x$enable_examples" = "xyes"])
dnl =========================================================================== dnl ===========================================================================
AC_CONFIG_FILES([ AC_CONFIG_FILES([
@ -752,8 +744,6 @@ AC_CONFIG_FILES([
tests/interactive/wrapper.sh tests/interactive/wrapper.sh
tests/micro-bench/Makefile tests/micro-bench/Makefile
tests/performance/Makefile tests/performance/Makefile
examples/Makefile
]) ])
AC_OUTPUT AC_OUTPUT
@ -789,7 +779,6 @@ if test "x$pixbuf_tests" = "xyes"; then
echo " Build tests using GDK-Pixbuf: ${pixbuf_tests}" echo " Build tests using GDK-Pixbuf: ${pixbuf_tests}"
fi fi
echo " Install test suites: ${enable_installed_tests}" echo " Install test suites: ${enable_installed_tests}"
echo " Build examples: ${enable_examples}"
# Clutter backend related flags # Clutter backend related flags
echo "" echo ""

View File

@ -1,36 +0,0 @@
all_examples = \
actor-model \
basic-actor \
box-layout \
canvas \
constraints \
drag-action \
drop-action \
easing-modes \
flow-layout \
grid-layout \
layout-manager \
pan-action \
rounded-rectangle \
scroll-actor \
threads
if PIXBUF_TESTS
all_examples += \
bin-layout \
image-content
endif
LDADD = $(top_builddir)/clutter/libmutter-clutter-@LIBMUTTER_API_VERSION@.la $(CLUTTER_LIBS) $(GDK_PIXBUF_LIBS) $(LIBM)
AM_CFLAGS = $(CLUTTER_CFLAGS) $(GDK_PIXBUF_CFLAGS) $(MAINTAINER_CFLAGS)
AM_CPPFLAGS = \
-DG_DISABLE_SINGLE_INCLUDES \
-DGLIB_DISABLE_DEPRECATION_WARNINGS \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(top_srcdir)/clutter \
-I$(top_builddir)/clutter
noinst_PROGRAMS = $(all_examples)
EXTRA_DIST = redhand.png

View File

@ -1,10 +0,0 @@
The code in this directory is meant to be XIncluded into the Clutter API
reference, and thus is to be considered part of the Clutter documentation.
As such, the code MUST be:
- correct;
- idiomatic, i.e. show how a task is meant to be achieved using the
best possible practices given the current API;
- well documented;
- ready for copy and paste.

View File

@ -1,522 +0,0 @@
#include <glib-object.h>
#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)
{
}
/* }}} */
/* {{{ MenuItemView */
/* 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 _ExampleMenuItemView
{
ClutterText parent_instance;
gboolean is_selected;
};
struct _ExampleMenuItemViewClass
{
ClutterTextClass parent_class;
};
G_DEFINE_TYPE (ExampleMenuItemView, example_menu_item_view, CLUTTER_TYPE_TEXT)
enum {
MENU_ITEM_VIEW_PROP_SELECTED = 1,
MENU_ITEM_VIEW_N_PROPS
};
static GParamSpec *menu_item_view_props[MENU_ITEM_VIEW_N_PROPS] = { NULL, };
static void
example_menu_item_view_set_selected (ExampleMenuItemView *self,
gboolean selected)
{
selected = !!selected;
if (self->is_selected == selected)
return;
self->is_selected = selected;
if (self->is_selected)
clutter_text_set_color (CLUTTER_TEXT (self), CLUTTER_COLOR_LightSkyBlue);
else
clutter_text_set_color (CLUTTER_TEXT (self), CLUTTER_COLOR_White);
g_object_notify_by_pspec (G_OBJECT (self), menu_item_view_props[MENU_ITEM_VIEW_PROP_SELECTED]);
}
static void
example_menu_item_view_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
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_view_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
case MENU_ITEM_VIEW_PROP_SELECTED:
g_value_set_boolean (value, EXAMPLE_MENU_ITEM_VIEW (gobject)->is_selected);
break;
}
}
static void
example_menu_item_view_class_init (ExampleMenuItemViewClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = example_menu_item_view_set_property;
gobject_class->get_property = example_menu_item_view_get_property;
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_VIEW_N_PROPS, menu_item_view_props);
}
static void
example_menu_item_view__transition_stopped (ClutterActor *actor,
const char *transition,
gboolean is_finished)
{
clutter_actor_set_scale (actor, 1.0, 1.0);
clutter_actor_set_opacity (actor, 255);
}
static void
example_menu_item_view_init (ExampleMenuItemView *self)
{
ClutterText *text = CLUTTER_TEXT (self);
ClutterActor *actor = CLUTTER_ACTOR (self);
ClutterTransition *scalex_trans, *scaley_trans, *fade_trans;
ClutterTransition *group;
clutter_text_set_font_name (text, "Sans Bold 24px");
clutter_text_set_color (text, CLUTTER_COLOR_White);
clutter_actor_set_margin_left (actor, 12);
clutter_actor_set_margin_right (actor, 12);
clutter_actor_set_pivot_point (actor, 0.5, 0.5);
scalex_trans = clutter_property_transition_new ("scale-x");
clutter_transition_set_from (scalex_trans, G_TYPE_FLOAT, 1.0);
clutter_transition_set_to (scalex_trans, G_TYPE_FLOAT, 3.0);
scaley_trans = clutter_property_transition_new ("scale-y");
clutter_transition_set_from (scaley_trans, G_TYPE_FLOAT, 1.0);
clutter_transition_set_to (scaley_trans, G_TYPE_FLOAT, 3.0);
fade_trans = clutter_property_transition_new ("opacity");
clutter_transition_set_to (fade_trans, G_TYPE_UINT, 0);
group = clutter_transition_group_new ();
clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), scalex_trans);
clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), scaley_trans);
clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), fade_trans);
clutter_timeline_set_duration (CLUTTER_TIMELINE (group), 250);
clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (group), CLUTTER_EASE_OUT);
clutter_actor_add_transition (actor, "activateTransition", group);
g_object_unref (group);
clutter_timeline_stop (CLUTTER_TIMELINE (group));
g_signal_connect (actor, "transition-stopped",
G_CALLBACK (example_menu_item_view__transition_stopped),
group);
}
static void
example_menu_item_view_activate (ExampleMenuItemView *self)
{
ClutterTransition *t;
t = clutter_actor_get_transition (CLUTTER_ACTOR (self), "activateTransition");
clutter_timeline_start (CLUTTER_TIMELINE (t));
}
/* }}} */
/* {{{ Menu */
/* 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)
struct _ExampleMenu
{
ClutterActor parent_instance;
int current_idx;
};
struct _ExampleMenuClass
{
ClutterActorClass parent_class;
};
G_DEFINE_TYPE (ExampleMenu, example_menu, CLUTTER_TYPE_ACTOR)
static void
example_menu_class_init (ExampleMenuClass *klass)
{
}
static void
example_menu_init (ExampleMenu *self)
{
ClutterActor *actor = CLUTTER_ACTOR (self);
ClutterLayoutManager *layout;
layout = clutter_box_layout_new ();
clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout), CLUTTER_ORIENTATION_VERTICAL);
clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12);
clutter_actor_set_layout_manager (actor, layout);
clutter_actor_set_background_color (actor, CLUTTER_COLOR_Black);
self->current_idx = -1;
}
static ClutterActor *
example_menu_select_item (ExampleMenu *self,
int idx)
{
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_view_set_selected ((ExampleMenuItemView *) item, FALSE);
if (idx < 0)
idx = clutter_actor_get_n_children (CLUTTER_ACTOR (self)) - 1;
else if (idx >= clutter_actor_get_n_children (CLUTTER_ACTOR (self)))
idx = 0;
self->current_idx = idx;
item = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx);
if (item != NULL)
example_menu_item_view_set_selected ((ExampleMenuItemView *) item, TRUE);
return item;
}
static ClutterActor *
example_menu_select_next (ExampleMenu *self)
{
return example_menu_select_item (self, self->current_idx + 1);
}
static ClutterActor *
example_menu_select_prev (ExampleMenu *self)
{
return example_menu_select_item (self, self->current_idx - 1);
}
static void
example_menu_activate_item (ExampleMenu *self)
{
ClutterActor *child;
child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self),
self->current_idx);
if (child == NULL)
return;
example_menu_item_view_activate ((ExampleMenuItemView *) child);
}
/* }}} */
/* {{{ main */
static gboolean
on_key_press (ClutterActor *stage,
ClutterEvent *event)
{
ClutterActor *scroll = clutter_actor_get_first_child (stage);
ClutterActor *menu = clutter_actor_get_first_child (scroll);
ClutterActor *item = NULL;
guint key = clutter_event_get_key_symbol (event);
ClutterPoint p;
switch (key)
{
case CLUTTER_KEY_q:
clutter_main_quit ();
break;
case CLUTTER_KEY_Up:
item = example_menu_select_prev ((ExampleMenu *) menu);
clutter_actor_get_position (item, &p.x, &p.y);
break;
case CLUTTER_KEY_Down:
item = example_menu_select_next ((ExampleMenu *) menu);
clutter_actor_get_position (item, &p.x, &p.y);
break;
case CLUTTER_KEY_Return:
case CLUTTER_KEY_KP_Enter:
example_menu_activate_item ((ExampleMenu *) menu);
break;
}
if (item != NULL)
clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (scroll), &p);
return CLUTTER_EVENT_PROPAGATE;
}
static void
on_model_item_selection (GObject *model_item,
GParamSpec *pspec,
gpointer data)
{
char *label = NULL;
gboolean is_selected = FALSE;
g_object_get (model_item, "label", &label, "selected", &is_selected, NULL);
if (is_selected)
g_print ("Item '%s' selected!\n", label);
g_free (label);
}
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;
/* Populate the model */
for (i = 0; i < 12; i++)
{
char *label = g_strdup_printf ("Option %02d", i + 1);
ExampleMenuItemModel *item = g_object_new (EXAMPLE_TYPE_MENU_ITEM_MODEL,
"label", label,
NULL);
g_list_store_append (model, item);
g_signal_connect (item, "notify::selected",
G_CALLBACK (on_model_item_selection),
NULL);
g_object_unref (item);
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_with_properties (menu, G_LIST_MODEL (model),
EXAMPLE_TYPE_MENU_ITEM_VIEW,
"label", "text", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE,
"selected", "selected", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
NULL);
/* 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)
{
ClutterActor *menu = clutter_scroll_actor_new ();
clutter_actor_set_name (menu, "scroll");
clutter_scroll_actor_set_scroll_mode (CLUTTER_SCROLL_ACTOR (menu),
CLUTTER_SCROLL_VERTICALLY);
clutter_actor_set_easing_duration (menu, 250);
clutter_actor_add_child (menu, create_menu_actor ());
return menu;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *menu;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Actor Model");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), NULL);
clutter_actor_show (stage);
#define PADDING 18.f
menu = create_scroll_actor ();
clutter_actor_set_position (menu, 0, PADDING);
clutter_actor_add_constraint (menu, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
clutter_actor_add_constraint (menu, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -PADDING * 2));
clutter_actor_add_child (stage, menu);
clutter_main ();
return 0;
}
/* }}} */

View File

@ -1,153 +0,0 @@
#include <stdlib.h>
#include <clutter/clutter.h>
#define SIZE 128
static gboolean
animate_color (ClutterActor *actor,
ClutterEvent *event)
{
static gboolean toggled = TRUE;
const ClutterColor *end_color;
if (toggled)
end_color = CLUTTER_COLOR_Blue;
else
end_color = CLUTTER_COLOR_Red;
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_duration (actor, 500);
clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR);
clutter_actor_set_background_color (actor, end_color);
clutter_actor_restore_easing_state (actor);
toggled = !toggled;
return CLUTTER_EVENT_STOP;
}
static gboolean
on_crossing (ClutterActor *actor,
ClutterEvent *event)
{
gboolean is_enter = clutter_event_type (event) == CLUTTER_ENTER;
float zpos;
if (is_enter)
zpos = -250.0;
else
zpos = 0.0;
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_duration (actor, 500);
clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_BOUNCE);
clutter_actor_set_z_position (actor, zpos);
clutter_actor_restore_easing_state (actor);
return CLUTTER_EVENT_STOP;
}
static void
on_transition_stopped (ClutterActor *actor,
const gchar *transition_name,
gboolean is_finished)
{
clutter_actor_save_easing_state (actor);
clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, 0.0f);
clutter_actor_restore_easing_state (actor);
/* disconnect so we don't get multiple notifications */
g_signal_handlers_disconnect_by_func (actor,
on_transition_stopped,
NULL);
}
static gboolean
animate_rotation (ClutterActor *actor,
ClutterEvent *event)
{
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_duration (actor, 1000);
clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, 360.0);
clutter_actor_restore_easing_state (actor);
/* get a notification when the rotation-angle-y transition ends */
g_signal_connect (actor,
"transition-stopped::rotation-angle-y",
G_CALLBACK (on_transition_stopped),
NULL);
return CLUTTER_EVENT_STOP;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *vase;
ClutterActor *flowers[3];
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
stage = clutter_stage_new ();
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
clutter_stage_set_title (CLUTTER_STAGE (stage), "Three Flowers in a Vase");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
/* there are three flowers in a vase */
vase = clutter_actor_new ();
clutter_actor_set_name (vase, "vase");
clutter_actor_set_layout_manager (vase, clutter_box_layout_new ());
clutter_actor_set_background_color (vase, CLUTTER_COLOR_LightSkyBlue);
clutter_actor_add_constraint (vase, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
clutter_actor_add_child (stage, vase);
flowers[0] = clutter_actor_new ();
clutter_actor_set_name (flowers[0], "flower.1");
clutter_actor_set_size (flowers[0], SIZE, SIZE);
clutter_actor_set_margin_left (flowers[0], 12);
clutter_actor_set_background_color (flowers[0], CLUTTER_COLOR_Red);
clutter_actor_set_reactive (flowers[0], TRUE);
clutter_actor_add_child (vase, flowers[0]);
g_signal_connect (flowers[0], "button-press-event",
G_CALLBACK (animate_color),
NULL);
flowers[1] = clutter_actor_new ();
clutter_actor_set_name (flowers[1], "flower.2");
clutter_actor_set_size (flowers[1], SIZE, SIZE);
clutter_actor_set_margin_top (flowers[1], 12);
clutter_actor_set_margin_left (flowers[1], 6);
clutter_actor_set_margin_right (flowers[1], 6);
clutter_actor_set_margin_bottom (flowers[1], 12);
clutter_actor_set_background_color (flowers[1], CLUTTER_COLOR_Yellow);
clutter_actor_set_reactive (flowers[1], TRUE);
clutter_actor_add_child (vase, flowers[1]);
g_signal_connect (flowers[1], "enter-event",
G_CALLBACK (on_crossing),
NULL);
g_signal_connect (flowers[1], "leave-event",
G_CALLBACK (on_crossing),
NULL);
/* the third one is green */
flowers[2] = clutter_actor_new ();
clutter_actor_set_name (flowers[2], "flower.3");
clutter_actor_set_size (flowers[2], SIZE, SIZE);
clutter_actor_set_margin_right (flowers[2], 12);
clutter_actor_set_background_color (flowers[2], CLUTTER_COLOR_Green);
clutter_actor_set_pivot_point (flowers[2], 0.5f, 0.0f);
clutter_actor_set_reactive (flowers[2], TRUE);
clutter_actor_add_child (vase, flowers[2]);
g_signal_connect (flowers[2], "button-press-event",
G_CALLBACK (animate_rotation),
NULL);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,307 +0,0 @@
#include <stdlib.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
static const ClutterColor bg_color = { 0xcc, 0xcc, 0xcc, 0x99 };
static gboolean is_expanded = FALSE;
static gboolean
on_canvas_draw (ClutterCanvas *canvas,
cairo_t *cr,
gint width,
gint height)
{
cairo_pattern_t *pat;
gfloat x, y;
g_print (G_STRLOC ": Painting at %d x %d\n", width, height);
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_restore (cr);
#define BG_ROUND_RADIUS 12
x = y = 0;
cairo_move_to (cr, BG_ROUND_RADIUS, y);
cairo_line_to (cr, width - BG_ROUND_RADIUS, y);
cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS);
cairo_line_to (cr, width, height - BG_ROUND_RADIUS);
cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height);
cairo_line_to (cr, BG_ROUND_RADIUS, height);
cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS);
cairo_line_to (cr, x, BG_ROUND_RADIUS);
cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y);
cairo_close_path (cr);
clutter_cairo_set_source_color (cr, &bg_color);
cairo_stroke (cr);
x += 4;
y += 4;
width -= 4;
height -= 4;
cairo_move_to (cr, BG_ROUND_RADIUS, y);
cairo_line_to (cr, width - BG_ROUND_RADIUS, y);
cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS);
cairo_line_to (cr, width, height - BG_ROUND_RADIUS);
cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height);
cairo_line_to (cr, BG_ROUND_RADIUS, height);
cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS);
cairo_line_to (cr, x, BG_ROUND_RADIUS);
cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y);
cairo_close_path (cr);
pat = cairo_pattern_create_linear (0, 0, 0, height);
cairo_pattern_add_color_stop_rgba (pat, 1, .85, .85, .85, 1);
cairo_pattern_add_color_stop_rgba (pat, .95, 1, 1, 1, 1);
cairo_pattern_add_color_stop_rgba (pat, .05, 1, 1, 1, 1);
cairo_pattern_add_color_stop_rgba (pat, 0, .85, .85, .85, 1);
cairo_set_source (cr, pat);
cairo_fill (cr);
cairo_pattern_destroy (pat);
#undef BG_ROUND_RADIUS
return TRUE;
}
static gboolean
on_box_enter (ClutterActor *box,
ClutterEvent *event,
ClutterActor *emblem)
{
/* we ease the opacity linearly */
clutter_actor_save_easing_state (emblem);
clutter_actor_set_easing_mode (emblem, CLUTTER_LINEAR);
clutter_actor_set_opacity (emblem, 255);
clutter_actor_restore_easing_state (emblem);
return CLUTTER_EVENT_STOP;
}
static gboolean
on_box_leave (ClutterActor *box,
ClutterEvent *event,
ClutterActor *emblem)
{
clutter_actor_save_easing_state (emblem);
clutter_actor_set_easing_mode (emblem, CLUTTER_LINEAR);
clutter_actor_set_opacity (emblem, 0);
clutter_actor_restore_easing_state (emblem);
return CLUTTER_EVENT_STOP;
}
static void
on_emblem_clicked (ClutterClickAction *action,
ClutterActor *emblem,
ClutterActor *box)
{
/* we add a little bounce to the resizing of the box */
clutter_actor_save_easing_state (box);
clutter_actor_set_easing_mode (box, CLUTTER_EASE_OUT_BOUNCE);
clutter_actor_set_easing_duration (box, 500);
if (!is_expanded)
clutter_actor_set_size (box, 400, 400);
else
clutter_actor_set_size (box, 200, 200);
clutter_actor_restore_easing_state (box);
is_expanded = !is_expanded;
}
static gboolean
on_emblem_long_press (ClutterClickAction *action,
ClutterActor *emblem,
ClutterLongPressState state,
ClutterActor *box)
{
switch (state)
{
case CLUTTER_LONG_PRESS_QUERY:
g_print ("*** long press: query ***\n");
return is_expanded;
case CLUTTER_LONG_PRESS_CANCEL:
g_print ("*** long press: cancel ***\n");
break;
case CLUTTER_LONG_PRESS_ACTIVATE:
g_print ("*** long press: activate ***\n");
break;
}
return TRUE;
}
static void
redraw_canvas (ClutterActor *actor,
ClutterCanvas *canvas)
{
/* we want to invalidate the canvas and redraw its contents
* only when the size changes at the end of the animation,
* to avoid drawing all the states inbetween
*/
clutter_canvas_set_size (canvas,
clutter_actor_get_width (actor),
clutter_actor_get_height (actor));
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *box, *bg, *icon, *emblem, *label;
ClutterLayoutManager *layout;
ClutterContent *canvas, *image;
ClutterColor *color;
ClutterAction *action;
GdkPixbuf *pixbuf;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
/* prepare the stage */
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "BinLayout");
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium2);
clutter_actor_set_size (stage, 640, 480);
clutter_actor_show (stage);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* this is our BinLayout, with its default alignments */
layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
CLUTTER_BIN_ALIGNMENT_CENTER);
/* the main container; this actor will use the BinLayout to lay
* out its children; we use the anchor point to keep it centered
* on the same position even when we change its size
*/
box = clutter_actor_new ();
clutter_actor_set_layout_manager (box, layout);
clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
clutter_actor_set_position (box, 320, 240);
clutter_actor_set_reactive (box, TRUE);
clutter_actor_set_name (box, "box");
clutter_actor_add_child (stage, box);
/* the background is drawn using a canvas content */
canvas = clutter_canvas_new ();
g_signal_connect (canvas, "draw", G_CALLBACK (on_canvas_draw), NULL);
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 200, 200);
/* this is the background actor; we want it to fill the whole
* of the allocation given to it by its parent
*/
bg = clutter_actor_new ();
clutter_actor_set_name (bg, "background");
clutter_actor_set_size (bg, 200, 200);
clutter_actor_set_content (bg, canvas);
clutter_actor_set_x_expand (bg, TRUE);
clutter_actor_set_y_expand (bg, TRUE);
clutter_actor_set_x_align (bg, CLUTTER_ACTOR_ALIGN_FILL);
clutter_actor_set_y_align (bg, CLUTTER_ACTOR_ALIGN_FILL);
clutter_actor_add_child (box, bg);
/* we use the ::transitions-completed signal to get notification
* of the end of the sizing animation; this allows us to redraw
* the canvas only once the animation has stopped
*/
g_signal_connect (box, "transitions-completed",
G_CALLBACK (redraw_canvas),
canvas);
/* we use GdkPixbuf to load an image from our data directory */
pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL);
image = clutter_image_new ();
clutter_image_set_data (CLUTTER_IMAGE (image),
gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf)
? COGL_PIXEL_FORMAT_RGBA_8888
: COGL_PIXEL_FORMAT_RGB_888,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_rowstride (pixbuf),
NULL);
g_object_unref (pixbuf);
/* this is the icon; it's going to be centered inside the box actor.
* we use the content gravity to keep the aspect ratio of the image,
* and the scaling filters to get a better result when scaling the
* image down.
*/
icon = clutter_actor_new ();
clutter_actor_set_name (icon, "icon");
clutter_actor_set_size (icon, 196, 196);
clutter_actor_set_x_expand (icon, TRUE);
clutter_actor_set_y_expand (icon, TRUE);
clutter_actor_set_x_align (icon, CLUTTER_ACTOR_ALIGN_CENTER);
clutter_actor_set_y_align (icon, CLUTTER_ACTOR_ALIGN_CENTER);
clutter_actor_set_content_gravity (icon, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
clutter_actor_set_content_scaling_filters (icon,
CLUTTER_SCALING_FILTER_TRILINEAR,
CLUTTER_SCALING_FILTER_LINEAR);
clutter_actor_set_content (icon, image);
clutter_actor_add_child (box, icon);
color = clutter_color_new (g_random_int_range (0, 255),
g_random_int_range (0, 255),
g_random_int_range (0, 255),
224);
/* this is the emblem: a small rectangle with a random color, that we
* want to put in the bottom right corner
*/
emblem = clutter_actor_new ();
clutter_actor_set_name (emblem, "emblem");
clutter_actor_set_size (emblem, 48, 48);
clutter_actor_set_background_color (emblem, color);
clutter_actor_set_x_expand (emblem, TRUE);
clutter_actor_set_y_expand (emblem, TRUE);
clutter_actor_set_x_align (emblem, CLUTTER_ACTOR_ALIGN_END);
clutter_actor_set_y_align (emblem, CLUTTER_ACTOR_ALIGN_END);
clutter_actor_set_reactive (emblem, TRUE);
clutter_actor_set_opacity (emblem, 0);
clutter_actor_add_child (box, emblem);
clutter_color_free (color);
/* when clicking on the emblem, we want to perform an action */
action = clutter_click_action_new ();
clutter_actor_add_action (emblem, action);
g_signal_connect (action, "clicked", G_CALLBACK (on_emblem_clicked), box);
g_signal_connect (action, "long-press", G_CALLBACK (on_emblem_long_press), box);
/* whenever the pointer enters the box, we show the emblem; we hide
* the emblem when the pointer leaves the box
*/
g_signal_connect (box,
"enter-event", G_CALLBACK (on_box_enter),
emblem);
g_signal_connect (box,
"leave-event", G_CALLBACK (on_box_leave),
emblem);
/* a label, that we want to position at the top and center of the box */
label = clutter_text_new ();
clutter_actor_set_name (label, "text");
clutter_text_set_text (CLUTTER_TEXT (label), "A simple test");
clutter_actor_set_x_expand (label, TRUE);
clutter_actor_set_x_align (label, CLUTTER_ACTOR_ALIGN_CENTER);
clutter_actor_set_y_expand (label, TRUE);
clutter_actor_set_y_align (label, CLUTTER_ACTOR_ALIGN_START);
clutter_actor_add_child (box, label);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,314 +0,0 @@
/*
* Copyright 2009 Intel Corporation.
*
* 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.
*
*/
#include <stdlib.h>
#include <clutter/clutter.h>
#define INSTRUCTIONS \
"Press v\t\342\236\236\tSwitch horizontal/vertical\n" \
"Press h\t\342\236\236\tToggle homogeneous\n" \
"Press p\t\342\236\236\tToggle pack start/end\n" \
"Press s\t\342\236\236\tIncrement spacing (up to 12px)\n" \
"Press +\t\342\236\236\tAdd a new actor\n" \
"Press a\t\342\236\236\tToggle animations\n" \
"Press q\t\342\236\236\tQuit"
static const gchar *
get_align_name (ClutterActorAlign align)
{
switch (align)
{
case CLUTTER_ACTOR_ALIGN_FILL:
return "fill";
case CLUTTER_ACTOR_ALIGN_START:
return "start";
case CLUTTER_ACTOR_ALIGN_CENTER:
return "center";
case CLUTTER_ACTOR_ALIGN_END:
return "end";
default:
g_assert_not_reached ();
}
}
static gboolean
button_release_cb (ClutterActor *rect,
ClutterEvent *event,
gpointer user_data)
{
ClutterActorAlign x_align, y_align;
gboolean x_expand, y_expand;
g_object_get (rect,
"x-align", &x_align,
"y-align", &y_align,
"x-expand", &x_expand,
"y-expand", &y_expand,
NULL);
switch (clutter_event_get_button (event))
{
case CLUTTER_BUTTON_PRIMARY:
if (clutter_event_has_shift_modifier (event))
{
if (y_align < 3)
y_align += 1;
else
y_align = 0;
break;
}
else
{
if (x_align < 3)
x_align += 1;
else
x_align = 0;
}
break;
case CLUTTER_BUTTON_SECONDARY:
if (clutter_event_has_shift_modifier (event))
y_expand = !y_expand;
else
x_expand = !x_expand;
break;
default:
break;
}
g_object_set (rect,
"x-align", x_align,
"y-align", y_align,
"x-expand", x_expand,
"y-expand", y_expand,
NULL);
return TRUE;
}
static void
changed_cb (ClutterActor *actor,
GParamSpec *pspec,
ClutterActor *text)
{
ClutterActorAlign x_align, y_align;
gboolean x_expand, y_expand;
gchar *label;
g_object_get (actor,
"x-align", &x_align,
"y-align", &y_align,
"x-expand", &x_expand,
"y-expand", &y_expand,
NULL);
label = g_strdup_printf ("%d,%d\n"
"%s\n%s",
x_expand, y_expand,
get_align_name (x_align),
get_align_name (y_align));
clutter_text_set_text (CLUTTER_TEXT (text), label);
g_free (label);
}
static void
add_actor (ClutterActor *box,
gint position)
{
ClutterActor *rect, *text;
ClutterColor color;
ClutterLayoutManager *layout;
clutter_color_from_hls (&color,
g_random_double_range (0.0, 360.0),
0.5,
0.5);
color.alpha = 255;
layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
CLUTTER_BIN_ALIGNMENT_CENTER);
rect = clutter_actor_new ();
clutter_actor_set_layout_manager (rect, layout);
clutter_actor_set_background_color (rect, &color);
clutter_actor_set_reactive (rect, TRUE);
clutter_actor_set_size (rect, 32, 64);
clutter_actor_set_x_expand (rect, TRUE);
clutter_actor_set_y_expand (rect, TRUE);
clutter_actor_set_x_align (rect, CLUTTER_ACTOR_ALIGN_CENTER);
clutter_actor_set_y_align (rect, CLUTTER_ACTOR_ALIGN_CENTER);
text = clutter_text_new_with_text ("Sans 8px", NULL);
clutter_text_set_line_alignment (CLUTTER_TEXT (text),
PANGO_ALIGN_CENTER);
clutter_actor_add_child (rect, text);
g_signal_connect (rect, "button-release-event",
G_CALLBACK (button_release_cb), NULL);
g_signal_connect (rect, "notify::x-expand",
G_CALLBACK (changed_cb), text);
g_signal_connect (rect, "notify::y-expand",
G_CALLBACK (changed_cb), text);
g_signal_connect (rect, "notify::x-align",
G_CALLBACK (changed_cb), text);
g_signal_connect (rect, "notify::y-align",
G_CALLBACK (changed_cb), text);
changed_cb (rect, NULL, text);
clutter_actor_insert_child_at_index (box, rect, position);
}
static gboolean
key_release_cb (ClutterActor *stage,
ClutterEvent *event,
ClutterActor *box)
{
ClutterBoxLayout *layout;
gboolean toggle;
guint spacing;
layout = CLUTTER_BOX_LAYOUT (clutter_actor_get_layout_manager (box));
switch (clutter_event_get_key_symbol (event))
{
case CLUTTER_KEY_a:
{
ClutterActorIter iter;
ClutterActor *child;
clutter_actor_iter_init (&iter, box);
while (clutter_actor_iter_next (&iter, &child))
{
guint duration;
duration = clutter_actor_get_easing_duration (child);
if (duration != 0)
duration = 0;
else
duration = 250;
clutter_actor_set_easing_duration (child, duration);
}
}
break;
case CLUTTER_KEY_v:
{
ClutterOrientation orientation;
orientation = clutter_box_layout_get_orientation (layout);
if (orientation == CLUTTER_ORIENTATION_HORIZONTAL)
orientation = CLUTTER_ORIENTATION_VERTICAL;
else
orientation = CLUTTER_ORIENTATION_HORIZONTAL;
clutter_box_layout_set_orientation (layout, orientation);
}
break;
case CLUTTER_KEY_h:
toggle = clutter_box_layout_get_homogeneous (layout);
clutter_box_layout_set_homogeneous (layout, !toggle);
break;
case CLUTTER_KEY_p:
toggle = clutter_box_layout_get_pack_start (layout);
clutter_box_layout_set_pack_start (layout, !toggle);
break;
case CLUTTER_KEY_s:
spacing = clutter_box_layout_get_spacing (layout);
if (spacing > 12)
spacing = 0;
else
spacing++;
clutter_box_layout_set_spacing (layout, spacing);
break;
case CLUTTER_KEY_plus:
add_actor (box, g_random_int_range (0, clutter_actor_get_n_children (box)));
break;
case CLUTTER_KEY_q:
clutter_main_quit ();
break;
default:
return FALSE;
}
return TRUE;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *box, *instructions;
ClutterLayoutManager *layout;
gint i;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Box Layout");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
/* make the stage a vbox */
layout = clutter_box_layout_new ();
clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout),
CLUTTER_ORIENTATION_VERTICAL);
clutter_actor_set_layout_manager (stage, layout);
box = clutter_actor_new ();
clutter_actor_set_background_color (box, CLUTTER_COLOR_LightGray);
clutter_actor_set_x_expand (box, TRUE);
clutter_actor_set_y_expand (box, TRUE);
layout = clutter_box_layout_new ();
clutter_actor_set_layout_manager (box, layout);
clutter_actor_add_child (stage, box);
instructions = clutter_text_new_with_text ("Sans 12px", INSTRUCTIONS);
clutter_actor_set_x_expand (instructions, TRUE);
clutter_actor_set_y_expand (instructions, FALSE);
clutter_actor_set_x_align (instructions, CLUTTER_ACTOR_ALIGN_START);
clutter_actor_set_margin_top (instructions, 4);
clutter_actor_set_margin_left (instructions, 4);
clutter_actor_set_margin_bottom (instructions, 4);
clutter_actor_add_child (stage, instructions);
for (i = 0; i < 5; i++)
add_actor (box, i);
g_signal_connect (stage, "destroy",
G_CALLBACK (clutter_main_quit), NULL);
g_signal_connect (stage, "key-release-event",
G_CALLBACK (key_release_cb), box);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,170 +0,0 @@
#include <stdlib.h>
#include <math.h>
#include <cairo.h>
#include <clutter/clutter.h>
static gboolean
draw_clock (ClutterCanvas *canvas,
cairo_t *cr,
int width,
int height)
{
GDateTime *now;
float hours, minutes, seconds;
ClutterColor color;
/* get the current time and compute the angles */
now = g_date_time_new_now_local ();
seconds = g_date_time_get_second (now) * G_PI / 30;
minutes = g_date_time_get_minute (now) * G_PI / 30;
hours = g_date_time_get_hour (now) * G_PI / 6;
cairo_save (cr);
/* clear the contents of the canvas, to avoid painting
* over the previous frame
*/
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_restore (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
/* scale the modelview to the size of the surface */
cairo_scale (cr, width, height);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width (cr, 0.1);
/* the black rail that holds the seconds indicator */
clutter_cairo_set_source_color (cr, CLUTTER_COLOR_Black);
cairo_translate (cr, 0.5, 0.5);
cairo_arc (cr, 0, 0, 0.4, 0, G_PI * 2);
cairo_stroke (cr);
/* the seconds indicator */
color = *CLUTTER_COLOR_White;
color.alpha = 128;
clutter_cairo_set_source_color (cr, &color);
cairo_move_to (cr, 0, 0);
cairo_arc (cr, sinf (seconds) * 0.4, - cosf (seconds) * 0.4, 0.05, 0, G_PI * 2);
cairo_fill (cr);
/* the minutes hand */
color = *CLUTTER_COLOR_DarkChameleon;
color.alpha = 196;
clutter_cairo_set_source_color (cr, &color);
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, sinf (minutes) * 0.4, -cosf (minutes) * 0.4);
cairo_stroke (cr);
/* the hours hand */
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, sinf (hours) * 0.2, -cosf (hours) * 0.2);
cairo_stroke (cr);
g_date_time_unref (now);
/* we're done drawing */
return TRUE;
}
static gboolean
invalidate_clock (gpointer data_)
{
/* invalidate the contents of the canvas */
clutter_content_invalidate (data_);
/* keep the timeout source */
return G_SOURCE_CONTINUE;
}
static guint idle_resize_id;
static gboolean
idle_resize (gpointer data)
{
ClutterActor *actor = data;
float width, height;
/* match the canvas size to the actor's */
clutter_actor_get_size (actor, &width, &height);
clutter_canvas_set_size (CLUTTER_CANVAS (clutter_actor_get_content (actor)),
ceilf (width),
ceilf (height));
/* unset the guard */
idle_resize_id = 0;
/* remove the timeout */
return G_SOURCE_REMOVE;
}
static void
on_actor_resize (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
gpointer user_data)
{
/* throttle multiple actor allocations to one canvas resize; we use a guard
* variable to avoid queueing multiple resize operations
*/
if (idle_resize_id == 0)
idle_resize_id = clutter_threads_add_timeout (1000, idle_resize, actor);
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *actor;
ClutterContent *canvas;
/* initialize Clutter */
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
/* create a resizable stage */
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
clutter_actor_set_size (stage, 300, 300);
clutter_actor_show (stage);
/* our 2D canvas, courtesy of Cairo */
canvas = clutter_canvas_new ();
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300);
actor = clutter_actor_new ();
clutter_actor_set_content (actor, canvas);
clutter_actor_set_content_scaling_filters (actor,
CLUTTER_SCALING_FILTER_TRILINEAR,
CLUTTER_SCALING_FILTER_LINEAR);
clutter_actor_add_child (stage, actor);
/* the actor now owns the canvas */
g_object_unref (canvas);
/* bind the size of the actor to that of the stage */
clutter_actor_add_constraint (actor, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0));
/* resize the canvas whenever the actor changes size */
g_signal_connect (actor, "allocation-changed", G_CALLBACK (on_actor_resize), NULL);
/* quit on destroy */
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* connect our drawing code */
g_signal_connect (canvas, "draw", G_CALLBACK (draw_clock), NULL);
/* invalidate the canvas, so that we can draw before the main loop starts */
clutter_content_invalidate (canvas);
/* set up a timer that invalidates the canvas every second */
clutter_threads_add_timeout (1000, invalidate_clock, canvas);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,90 +0,0 @@
#include <stdlib.h>
#include <clutter/clutter.h>
int
main (int argc, char *argv[])
{
ClutterActor *stage, *layer_a, *layer_b, *layer_c;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
/* the main container */
stage = clutter_stage_new ();
clutter_actor_set_name (stage, "stage");
clutter_stage_set_title (CLUTTER_STAGE (stage), "Snap Constraint");
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium1);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* first layer, with a fixed (100, 25) size */
layer_a = clutter_actor_new ();
clutter_actor_set_background_color (layer_a, CLUTTER_COLOR_ScarletRed);
clutter_actor_set_name (layer_a, "layerA");
clutter_actor_set_size (layer_a, 100.0, 25.0);
clutter_actor_add_child (stage, layer_a);
/* the first layer is anchored to the middle of the stage */
clutter_actor_add_constraint (layer_a, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
/* second layer, with no implicit size */
layer_b = clutter_actor_new ();
clutter_actor_set_background_color (layer_b, CLUTTER_COLOR_DarkButter);
clutter_actor_set_name (layer_b, "layerB");
clutter_actor_add_child (stage, layer_b);
/* the second layer tracks the X coordinate and the width of
* the first layer
*/
clutter_actor_add_constraint (layer_b, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_X, 0.0));
clutter_actor_add_constraint (layer_b, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_WIDTH, 0.0));
/* the second layer is snapped between the bottom edge of
* the first layer, and the bottom edge of the stage; a
* spacing of 10 pixels in each direction is added for padding
*/
clutter_actor_add_constraint (layer_b,
clutter_snap_constraint_new (layer_a,
CLUTTER_SNAP_EDGE_TOP,
CLUTTER_SNAP_EDGE_BOTTOM,
10.0));
clutter_actor_add_constraint (layer_b,
clutter_snap_constraint_new (stage,
CLUTTER_SNAP_EDGE_BOTTOM,
CLUTTER_SNAP_EDGE_BOTTOM,
-10.0));
/* the third layer, with no implicit size */
layer_c = clutter_actor_new ();
clutter_actor_set_background_color (layer_c, CLUTTER_COLOR_LightChameleon);
clutter_actor_set_name (layer_c, "layerC");
clutter_actor_add_child (stage, layer_c);
/* as for the second layer, the third layer tracks the X
* coordinate and width of the first layer
*/
clutter_actor_add_constraint (layer_c, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_X, 0.0));
clutter_actor_add_constraint (layer_c, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_WIDTH, 0.0));
/* the third layer is snapped between the top edge of the stage
* and the top edge of the first layer; again, a spacing of
* 10 pixels in each direction is added for padding
*/
clutter_actor_add_constraint (layer_c,
clutter_snap_constraint_new (layer_a,
CLUTTER_SNAP_EDGE_BOTTOM,
CLUTTER_SNAP_EDGE_TOP,
-10.0));
clutter_actor_add_constraint (layer_c,
clutter_snap_constraint_new (stage,
CLUTTER_SNAP_EDGE_TOP,
CLUTTER_SNAP_EDGE_TOP,
10.0));
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,249 +0,0 @@
#include <stdlib.h>
#include <clutter/clutter.h>
static gboolean
on_enter (ClutterActor *actor,
ClutterEvent *event)
{
ClutterTransition *t;
t = clutter_actor_get_transition (actor, "curl");
if (t == NULL)
{
t = clutter_property_transition_new ("@effects.curl.period");
clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250);
clutter_actor_add_transition (actor, "curl", t);
g_object_unref (t);
}
clutter_transition_set_from (t, G_TYPE_DOUBLE, 0.0);
clutter_transition_set_to (t, G_TYPE_DOUBLE, 0.25);
clutter_timeline_rewind (CLUTTER_TIMELINE (t));
clutter_timeline_start (CLUTTER_TIMELINE (t));
return CLUTTER_EVENT_STOP;
}
static gboolean
on_leave (ClutterActor *actor,
ClutterEvent *event)
{
ClutterTransition *t;
t = clutter_actor_get_transition (actor, "curl");
if (t == NULL)
{
t = clutter_property_transition_new ("@effects.curl.period");
clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250);
clutter_actor_add_transition (actor, "curl", t);
g_object_unref (t);
}
clutter_transition_set_from (t, G_TYPE_DOUBLE, 0.25);
clutter_transition_set_to (t, G_TYPE_DOUBLE, 0.0);
clutter_timeline_rewind (CLUTTER_TIMELINE (t));
clutter_timeline_start (CLUTTER_TIMELINE (t));
return CLUTTER_EVENT_STOP;
}
static void
on_drag_begin (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers)
{
gboolean is_copy = (modifiers & CLUTTER_SHIFT_MASK) ? TRUE : FALSE;
ClutterActor *drag_handle = NULL;
ClutterTransition *t;
if (is_copy)
{
ClutterActor *stage = clutter_actor_get_stage (actor);
drag_handle = clutter_actor_new ();
clutter_actor_set_size (drag_handle, 48, 48);
clutter_actor_set_background_color (drag_handle, CLUTTER_COLOR_DarkSkyBlue);
clutter_actor_add_child (stage, drag_handle);
clutter_actor_set_position (drag_handle, event_x, event_y);
}
else
drag_handle = actor;
clutter_drag_action_set_drag_handle (action, drag_handle);
/* fully desaturate the actor */
t = clutter_actor_get_transition (actor, "disable");
if (t == NULL)
{
t = clutter_property_transition_new ("@effects.disable.factor");
clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250);
clutter_actor_add_transition (actor, "disable", t);
g_object_unref (t);
}
clutter_transition_set_from (t, G_TYPE_DOUBLE, 0.0);
clutter_transition_set_to (t, G_TYPE_DOUBLE, 1.0);
clutter_timeline_rewind (CLUTTER_TIMELINE (t));
clutter_timeline_start (CLUTTER_TIMELINE (t));
}
static void
on_drag_end (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers)
{
ClutterActor *drag_handle;
ClutterTransition *t;
drag_handle = clutter_drag_action_get_drag_handle (action);
if (actor != drag_handle)
{
gfloat real_x, real_y;
ClutterActor *parent;
/* if we are dragging a copy we can destroy the copy now
* and animate the real actor to the drop coordinates,
* transformed in the parent's coordinate space
*/
clutter_actor_save_easing_state (drag_handle);
clutter_actor_set_easing_mode (drag_handle, CLUTTER_LINEAR);
clutter_actor_set_opacity (drag_handle, 0);
clutter_actor_restore_easing_state (drag_handle);
g_signal_connect (drag_handle, "transitions-completed",
G_CALLBACK (clutter_actor_destroy),
NULL);
parent = clutter_actor_get_parent (actor);
clutter_actor_transform_stage_point (parent, event_x, event_y,
&real_x,
&real_y);
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC);
clutter_actor_set_position (actor, real_x, real_y);
clutter_actor_restore_easing_state (actor);
}
t = clutter_actor_get_transition (actor, "disable");
if (t == NULL)
{
t = clutter_property_transition_new ("@effects.disable.factor");
clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250);
clutter_actor_add_transition (actor, "disable", t);
g_object_unref (t);
}
clutter_transition_set_from (t, G_TYPE_DOUBLE, 1.0);
clutter_transition_set_to (t, G_TYPE_DOUBLE, 0.0);
clutter_timeline_rewind (CLUTTER_TIMELINE (t));
clutter_timeline_start (CLUTTER_TIMELINE (t));
}
static ClutterDragAxis
get_drag_axis (const gchar *str)
{
if (str == NULL || *str == '\0')
return CLUTTER_DRAG_AXIS_NONE;
if (*str == 'x' || *str == 'X')
return CLUTTER_DRAG_X_AXIS;
if (*str == 'y' || *str == 'Y')
return CLUTTER_DRAG_Y_AXIS;
g_warn_if_reached ();
return CLUTTER_DRAG_AXIS_NONE;
}
static gchar *drag_axis = NULL;
static gint x_drag_threshold = 0;
static gint y_drag_threshold = 0;
static GOptionEntry entries[] = {
{
"x-threshold", 'x',
0,
G_OPTION_ARG_INT,
&x_drag_threshold,
"Set the horizontal drag threshold", "PIXELS"
},
{
"y-threshold", 'y',
0,
G_OPTION_ARG_INT,
&y_drag_threshold,
"Set the vertical drag threshold", "PIXELS"
},
{
"axis", 'a',
0,
G_OPTION_ARG_STRING,
&drag_axis,
"Set the drag axis", "AXIS"
},
{ NULL }
};
int
main (int argc, char *argv[])
{
ClutterActor *stage, *handle;
ClutterAction *action;
GError *error;
error = NULL;
if (clutter_init_with_args (&argc, &argv,
"test-drag",
entries,
NULL,
&error) != CLUTTER_INIT_SUCCESS)
{
g_print ("Unable to run drag-action: %s\n", error->message);
g_error_free (error);
return EXIT_FAILURE;
}
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Drag Test");
clutter_actor_set_size (stage, 800, 600);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
handle = clutter_actor_new ();
clutter_actor_set_background_color (handle, CLUTTER_COLOR_SkyBlue);
clutter_actor_set_size (handle, 128, 128);
clutter_actor_set_position (handle, (800 - 128) / 2, (600 - 128) / 2);
clutter_actor_set_reactive (handle, TRUE);
clutter_actor_add_child (stage, handle);
g_signal_connect (handle, "enter-event", G_CALLBACK (on_enter), NULL);
g_signal_connect (handle, "leave-event", G_CALLBACK (on_leave), NULL);
action = clutter_drag_action_new ();
clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action),
x_drag_threshold,
y_drag_threshold);
clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action),
get_drag_axis (drag_axis));
g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL);
g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL);
clutter_actor_add_action (handle, action);
clutter_actor_add_effect_with_name (handle, "disable", clutter_desaturate_effect_new (0.0));
clutter_actor_add_effect_with_name (handle, "curl", clutter_page_turn_effect_new (0.0, 45.0, 12.0));
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,263 +0,0 @@
#include <stdlib.h>
#include <clutter/clutter.h>
#define TARGET_SIZE 200
#define HANDLE_SIZE 128
static ClutterActor *stage = NULL;
static ClutterActor *target1 = NULL;
static ClutterActor *target2 = NULL;
static ClutterActor *drag = NULL;
static gboolean drop_successful = FALSE;
static void add_drag_object (ClutterActor *target);
static void
on_drag_end (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers)
{
ClutterActor *handle = clutter_drag_action_get_drag_handle (action);
g_print ("Drag ended at: %.0f, %.0f\n",
event_x, event_y);
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR);
clutter_actor_set_opacity (actor, 255);
clutter_actor_restore_easing_state (actor);
clutter_actor_save_easing_state (handle);
if (!drop_successful)
{
ClutterActor *parent = clutter_actor_get_parent (actor);
gfloat x_pos, y_pos;
clutter_actor_save_easing_state (parent);
clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR);
clutter_actor_set_opacity (parent, 255);
clutter_actor_restore_easing_state (parent);
clutter_actor_get_transformed_position (actor, &x_pos, &y_pos);
clutter_actor_set_easing_mode (handle, CLUTTER_EASE_OUT_BOUNCE);
clutter_actor_set_position (handle, x_pos, y_pos);
clutter_actor_set_opacity (handle, 0);
}
else
{
clutter_actor_set_easing_mode (handle, CLUTTER_LINEAR);
clutter_actor_set_opacity (handle, 0);
}
clutter_actor_restore_easing_state (handle);
g_signal_connect (handle, "transitions-completed",
G_CALLBACK (clutter_actor_destroy),
NULL);
}
static void
on_drag_begin (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers)
{
ClutterActor *handle;
gfloat x_pos, y_pos;
clutter_actor_get_position (actor, &x_pos, &y_pos);
handle = clutter_actor_new ();
clutter_actor_set_background_color (handle, CLUTTER_COLOR_DarkSkyBlue);
clutter_actor_set_size (handle, 128, 128);
clutter_actor_set_position (handle, event_x - x_pos, event_y - y_pos);
clutter_actor_add_child (stage, handle);
clutter_drag_action_set_drag_handle (action, handle);
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR);
clutter_actor_set_opacity (actor, 128);
clutter_actor_restore_easing_state (actor);
drop_successful = FALSE;
}
static void
add_drag_object (ClutterActor *target)
{
ClutterActor *parent;
if (drag == NULL)
{
ClutterAction *action;
drag = clutter_actor_new ();
clutter_actor_set_background_color (drag, CLUTTER_COLOR_LightSkyBlue);
clutter_actor_set_size (drag, HANDLE_SIZE, HANDLE_SIZE);
clutter_actor_set_position (drag,
(TARGET_SIZE - HANDLE_SIZE) / 2.0,
(TARGET_SIZE - HANDLE_SIZE) / 2.0);
clutter_actor_set_reactive (drag, TRUE);
action = clutter_drag_action_new ();
g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL);
g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL);
clutter_actor_add_action (drag, action);
}
parent = clutter_actor_get_parent (drag);
if (parent == target)
{
clutter_actor_save_easing_state (target);
clutter_actor_set_easing_mode (target, CLUTTER_LINEAR);
clutter_actor_set_opacity (target, 255);
clutter_actor_restore_easing_state (target);
return;
}
g_object_ref (drag);
if (parent != NULL && parent != stage)
{
clutter_actor_remove_child (parent, drag);
clutter_actor_save_easing_state (parent);
clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR);
clutter_actor_set_opacity (parent, 64);
clutter_actor_restore_easing_state (parent);
}
clutter_actor_add_child (target, drag);
clutter_actor_save_easing_state (target);
clutter_actor_set_easing_mode (target, CLUTTER_LINEAR);
clutter_actor_set_opacity (target, 255);
clutter_actor_restore_easing_state (target);
g_object_unref (drag);
}
static void
on_target_over (ClutterDropAction *action,
ClutterActor *actor,
gpointer _data)
{
gboolean is_over = GPOINTER_TO_UINT (_data);
guint8 final_opacity = is_over ? 128 : 64;
ClutterActor *target;
target = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
clutter_actor_save_easing_state (target);
clutter_actor_set_easing_mode (target, CLUTTER_LINEAR);
clutter_actor_set_opacity (target, final_opacity);
clutter_actor_restore_easing_state (target);
}
static void
on_target_drop (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y)
{
gfloat actor_x, actor_y;
actor_x = actor_y = 0.0f;
clutter_actor_transform_stage_point (actor, event_x, event_y,
&actor_x,
&actor_y);
g_print ("Dropped at %.0f, %.0f (screen: %.0f, %.0f)\n",
actor_x, actor_y,
event_x, event_y);
drop_successful = TRUE;
add_drag_object (actor);
}
int
main (int argc, char *argv[])
{
ClutterActor *dummy;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Drop Action");
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
target1 = clutter_actor_new ();
clutter_actor_set_background_color (target1, CLUTTER_COLOR_LightScarletRed);
clutter_actor_set_size (target1, TARGET_SIZE, TARGET_SIZE);
clutter_actor_set_opacity (target1, 64);
clutter_actor_add_constraint (target1, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
clutter_actor_set_x (target1, 10);
clutter_actor_set_reactive (target1, TRUE);
clutter_actor_add_action_with_name (target1, "drop", clutter_drop_action_new ());
g_signal_connect (clutter_actor_get_action (target1, "drop"),
"over-in",
G_CALLBACK (on_target_over),
GUINT_TO_POINTER (TRUE));
g_signal_connect (clutter_actor_get_action (target1, "drop"),
"over-out",
G_CALLBACK (on_target_over),
GUINT_TO_POINTER (FALSE));
g_signal_connect (clutter_actor_get_action (target1, "drop"),
"drop",
G_CALLBACK (on_target_drop),
NULL);
dummy = clutter_actor_new ();
clutter_actor_set_background_color (dummy, CLUTTER_COLOR_DarkOrange);
clutter_actor_set_size (dummy,
640 - (2 * 10) - (2 * (TARGET_SIZE + 10)),
TARGET_SIZE);
clutter_actor_add_constraint (dummy, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
clutter_actor_add_constraint (dummy, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
clutter_actor_set_reactive (dummy, TRUE);
target2 = clutter_actor_new ();
clutter_actor_set_background_color (target2, CLUTTER_COLOR_LightChameleon);
clutter_actor_set_size (target2, TARGET_SIZE, TARGET_SIZE);
clutter_actor_set_opacity (target2, 64);
clutter_actor_add_constraint (target2, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
clutter_actor_set_x (target2, 640 - TARGET_SIZE - 10);
clutter_actor_set_reactive (target2, TRUE);
clutter_actor_add_action_with_name (target2, "drop", clutter_drop_action_new ());
g_signal_connect (clutter_actor_get_action (target2, "drop"),
"over-in",
G_CALLBACK (on_target_over),
GUINT_TO_POINTER (TRUE));
g_signal_connect (clutter_actor_get_action (target2, "drop"),
"over-out",
G_CALLBACK (on_target_over),
GUINT_TO_POINTER (FALSE));
g_signal_connect (clutter_actor_get_action (target2, "drop"),
"drop",
G_CALLBACK (on_target_drop),
NULL);
clutter_actor_add_child (stage, target1);
clutter_actor_add_child (stage, dummy);
clutter_actor_add_child (stage, target2);
add_drag_object (target1);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,241 +0,0 @@
#include <stdlib.h>
#include <clutter/clutter.h>
/* all the easing modes provided by Clutter */
static const struct {
const gchar *name;
ClutterAnimationMode mode;
} easing_modes[] = {
{ "linear", CLUTTER_LINEAR },
{ "easeInQuad", CLUTTER_EASE_IN_QUAD },
{ "easeOutQuad", CLUTTER_EASE_OUT_QUAD },
{ "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD },
{ "easeInCubic", CLUTTER_EASE_IN_CUBIC },
{ "easeOutCubic", CLUTTER_EASE_OUT_CUBIC },
{ "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC },
{ "easeInQuart", CLUTTER_EASE_IN_QUART },
{ "easeOutQuart", CLUTTER_EASE_OUT_QUART },
{ "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART },
{ "easeInQuint", CLUTTER_EASE_IN_QUINT },
{ "easeOutQuint", CLUTTER_EASE_OUT_QUINT },
{ "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT },
{ "easeInSine", CLUTTER_EASE_IN_SINE },
{ "easeOutSine", CLUTTER_EASE_OUT_SINE },
{ "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE },
{ "easeInExpo", CLUTTER_EASE_IN_EXPO },
{ "easeOutExpo", CLUTTER_EASE_OUT_EXPO },
{ "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO },
{ "easeInCirc", CLUTTER_EASE_IN_CIRC },
{ "easeOutCirc", CLUTTER_EASE_OUT_CIRC },
{ "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC },
{ "easeInElastic", CLUTTER_EASE_IN_ELASTIC },
{ "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC },
{ "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC },
{ "easeInBack", CLUTTER_EASE_IN_BACK },
{ "easeOutBack", CLUTTER_EASE_OUT_BACK },
{ "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK },
{ "easeInBounce", CLUTTER_EASE_IN_BOUNCE },
{ "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE },
{ "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE },
{ "stepStart", CLUTTER_STEP_START },
{ "stepEnd", CLUTTER_STEP_END },
{ "ease", CLUTTER_EASE },
{ "easeIn", CLUTTER_EASE_IN },
{ "easeOut", CLUTTER_EASE_OUT },
{ "easeInOut", CLUTTER_EASE_IN_OUT },
};
#define HELP_TEXT "<b>Easing mode: %s (%d of %d)</b>\n" \
"Left click to tween\n" \
"Middle click to jump\n" \
"Right click to change the easing mode"
static const gint n_easing_modes = G_N_ELEMENTS (easing_modes);
static gint current_mode = 0;
static gint duration = 1;
static ClutterActor *main_stage = NULL;
static ClutterActor *easing_mode_label = NULL;
static gboolean
on_button_press (ClutterActor *actor,
ClutterButtonEvent *event,
ClutterActor *rectangle)
{
if (event->button == CLUTTER_BUTTON_SECONDARY)
{
gchar *text;
/* cycle through the various easing modes */
current_mode = (current_mode + 1 < n_easing_modes)
? current_mode + 1
: 0;
/* update the text of the label */
text = g_strdup_printf (HELP_TEXT,
easing_modes[current_mode].name,
current_mode + 1,
n_easing_modes);
clutter_text_set_markup (CLUTTER_TEXT (easing_mode_label), text);
g_free (text);
}
else if (event->button == CLUTTER_BUTTON_MIDDLE)
{
clutter_actor_set_position (rectangle, event->x, event->y);
}
else if (event->button == CLUTTER_BUTTON_PRIMARY)
{
ClutterAnimationMode cur_mode;
cur_mode = easing_modes[current_mode].mode;
clutter_actor_save_easing_state (rectangle);
/* tween the actor using the current easing mode */
clutter_actor_set_easing_mode (rectangle, cur_mode);
clutter_actor_set_easing_duration (rectangle, duration * 1000);
clutter_actor_set_position (rectangle, event->x, event->y);
clutter_actor_restore_easing_state (rectangle);
}
return CLUTTER_EVENT_STOP;
}
static gboolean
draw_bouncer (ClutterCanvas *canvas,
cairo_t *cr,
int width,
int height)
{
const ClutterColor *bouncer_color;
cairo_pattern_t *pattern;
float radius;
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
radius = MAX (width, height);
cairo_arc (cr, radius / 2, radius / 2, radius / 2, 0.0, 2.0 * G_PI);
bouncer_color = CLUTTER_COLOR_DarkScarletRed;
pattern = cairo_pattern_create_radial (radius / 2, radius / 2, 0,
radius, radius, radius);
cairo_pattern_add_color_stop_rgba (pattern,
0,
bouncer_color->red / 255.0,
bouncer_color->green / 255.0,
bouncer_color->blue / 255.0,
bouncer_color->alpha / 255.0);
cairo_pattern_add_color_stop_rgba (pattern,
0.85,
bouncer_color->red / 255.0,
bouncer_color->green / 255.0,
bouncer_color->blue / 255.0,
0.25);
cairo_set_source (cr, pattern);
cairo_fill_preserve (cr);
cairo_pattern_destroy (pattern);
return TRUE;
}
static ClutterActor *
make_bouncer (gfloat width,
gfloat height)
{
ClutterActor *retval;
ClutterContent *canvas;
retval = clutter_actor_new ();
canvas = clutter_canvas_new ();
g_signal_connect (canvas, "draw", G_CALLBACK (draw_bouncer), NULL);
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), width, height);
clutter_actor_set_name (retval, "bouncer");
clutter_actor_set_size (retval, width, height);
clutter_actor_set_pivot_point (retval, 0.5f, 0.5f);
clutter_actor_set_translation (retval, width / -2.f, height / -2.f, 0.f);
clutter_actor_set_reactive (retval, TRUE);
clutter_actor_set_content (retval, canvas);
g_object_unref (canvas);
return retval;
}
static GOptionEntry test_easing_entries[] = {
{
"duration", 'd',
0,
G_OPTION_ARG_INT, &duration,
"Duration of the animation",
"SECONDS"
},
{ NULL }
};
int
main (int argc, char *argv[])
{
ClutterActor *stage, *rect, *label;
gchar *text;
gfloat stage_width, stage_height;
GError *error = NULL;
if (clutter_init_with_args (&argc, &argv,
NULL,
test_easing_entries,
NULL,
&error) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Easing Modes");
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
main_stage = stage;
clutter_actor_get_size (stage, &stage_width, &stage_height);
/* create the actor that we want to tween */
rect = make_bouncer (50, 50);
clutter_actor_add_child (stage, rect);
clutter_actor_set_position (rect, stage_width / 2, stage_height / 2);
text = g_strdup_printf (HELP_TEXT,
easing_modes[current_mode].name,
current_mode + 1,
n_easing_modes);
label = clutter_text_new ();
clutter_actor_add_child (stage, label);
clutter_text_set_markup (CLUTTER_TEXT (label), text);
clutter_text_set_line_alignment (CLUTTER_TEXT (label), PANGO_ALIGN_RIGHT);
clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.95));
clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95));
easing_mode_label = label;
g_free (text);
g_signal_connect (stage,
"button-press-event", G_CALLBACK (on_button_press),
rect);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,164 +0,0 @@
#include <stdlib.h>
#include <gmodule.h>
#include <cairo.h>
#include <clutter/clutter.h>
#define N_RECTS 20
static gboolean is_homogeneous = FALSE;
static gboolean vertical = FALSE;
static gboolean random_size = FALSE;
static gboolean fixed_size = FALSE;
static gboolean snap_to_grid = TRUE;
static gint n_rects = N_RECTS;
static gint x_spacing = 0;
static gint y_spacing = 0;
static GOptionEntry entries[] = {
{
"random-size", 'r',
0,
G_OPTION_ARG_NONE,
&random_size,
"Randomly size the rectangles", NULL
},
{
"num-rects", 'n',
0,
G_OPTION_ARG_INT,
&n_rects,
"Number of rectangles", "RECTS"
},
{
"vertical", 'v',
0,
G_OPTION_ARG_NONE,
&vertical,
"Set vertical orientation", NULL
},
{
"homogeneous", 'h',
0,
G_OPTION_ARG_NONE,
&is_homogeneous,
"Whether the layout should be homogeneous", NULL
},
{
"x-spacing", 0,
0,
G_OPTION_ARG_INT,
&x_spacing,
"Horizontal spacing between elements", "PX"
},
{
"y-spacing", 0,
0,
G_OPTION_ARG_INT,
&y_spacing,
"Vertical spacing between elements", "PX"
},
{
"fixed-size", 'f',
0,
G_OPTION_ARG_NONE,
&fixed_size,
"Fix the layout size", NULL
},
{
"no-snap-to-grid", 's',
G_OPTION_FLAG_REVERSE,
G_OPTION_ARG_NONE,
&snap_to_grid,
"Don't snap elements to grid", NULL
},
{ NULL }
};
int
main (int argc, char *argv[])
{
ClutterActor *stage, *box;
ClutterLayoutManager *layout;
GError *error;
gint i;
error = NULL;
if (clutter_init_with_args (&argc, &argv,
NULL,
entries,
NULL,
&error) != CLUTTER_INIT_SUCCESS)
{
g_print ("Unable to run flow-layout: %s", error->message);
g_error_free (error);
return EXIT_FAILURE;
}
stage = clutter_stage_new ();
clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue);
clutter_stage_set_title (CLUTTER_STAGE (stage), "Flow Layout");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
layout = clutter_flow_layout_new (vertical ? CLUTTER_FLOW_VERTICAL
: CLUTTER_FLOW_HORIZONTAL);
clutter_flow_layout_set_homogeneous (CLUTTER_FLOW_LAYOUT (layout),
is_homogeneous);
clutter_flow_layout_set_column_spacing (CLUTTER_FLOW_LAYOUT (layout),
x_spacing);
clutter_flow_layout_set_row_spacing (CLUTTER_FLOW_LAYOUT (layout),
y_spacing);
clutter_flow_layout_set_snap_to_grid (CLUTTER_FLOW_LAYOUT (layout),
snap_to_grid);
box = clutter_actor_new ();
clutter_actor_set_layout_manager (box, layout);
clutter_actor_set_background_color (box, CLUTTER_COLOR_Aluminium2);
clutter_actor_add_child (stage, box);
if (!fixed_size)
clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0));
clutter_actor_set_position (box, 0, 0);
clutter_actor_set_name (box, "box");
for (i = 0; i < n_rects; i++)
{
ClutterColor color = CLUTTER_COLOR_INIT (255, 255, 255, 255);
gfloat width, height;
ClutterActor *rect;
gchar *name;
name = g_strdup_printf ("rect%02d", i);
clutter_color_from_hls (&color,
360.0 / n_rects * i,
0.5,
0.8);
rect = clutter_actor_new ();
clutter_actor_set_background_color (rect, &color);
if (random_size)
{
width = g_random_int_range (50, 100);
height = g_random_int_range (50, 100);
}
else
width = height = 50.f;
clutter_actor_set_size (rect, width, height);
clutter_actor_set_name (rect, name);
clutter_actor_add_child (box, rect);
g_free (name);
}
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,378 +0,0 @@
/*
* Copyright 2012 Bastian Winkler <buz@netbuz.org>
*
* 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.
*
*/
#include <stdlib.h>
#include <clutter/clutter.h>
#define INSTRUCTIONS \
"Press r\t\342\236\236\tSwitch row homogeneous\n" \
"Press c\t\342\236\236\tSwitch column homogeneous\n" \
"Press s\t\342\236\236\tIncrement spacing (up to 12px)\n" \
"Press q\t\342\236\236\tQuit\n\n" \
"Left/right click\t\t\342\236\236\tChange actor align\n" \
"Shift left/right click\t\342\236\236\tChange actor expand"
static gboolean random_size = FALSE;
static gboolean random_align = FALSE;
static gboolean default_expand = TRUE;
static gboolean use_box = FALSE;
static gboolean is_vertical = FALSE;
static GOptionEntry entries[] = {
{
"random-size", 'r',
0,
G_OPTION_ARG_NONE,
&random_size,
"Randomly size the rectangles", NULL
},
{
"random-align", 'f',
0,
G_OPTION_ARG_NONE,
&random_align,
"Randomly set the align values", NULL
},
{
"no-expand", 'e',
G_OPTION_FLAG_REVERSE,
G_OPTION_ARG_NONE,
&default_expand,
"Don't expand all actors by default", NULL,
},
{
"box", 'b',
0,
G_OPTION_ARG_NONE,
&use_box,
"Use the layout in a ClutterBoxLayout style", NULL
},
{
"vertical", 'v',
0,
G_OPTION_ARG_NONE,
&is_vertical,
"Use a vertical orientation when used with --box", NULL
},
{ NULL }
};
static gboolean
button_release_cb (ClutterActor *actor,
ClutterEvent *event,
gpointer data)
{
ClutterActorAlign x_align, y_align;
gboolean x_expand, y_expand;
g_object_get (actor,
"x-align", &x_align,
"y-align", &y_align,
"x-expand", &x_expand,
"y-expand", &y_expand,
NULL);
switch (clutter_event_get_button (event))
{
case CLUTTER_BUTTON_PRIMARY:
if (clutter_event_has_shift_modifier (event))
x_expand = !x_expand;
else
{
if (x_align < 3)
x_align += 1;
else
x_align = 0;
}
break;
case CLUTTER_BUTTON_SECONDARY:
if (clutter_event_has_shift_modifier (event))
y_expand = !y_expand;
else
{
if (y_align < 3)
y_align += 1;
else
y_align = 0;
}
break;
default:
return FALSE;
}
g_object_set (actor,
"x-align", x_align,
"y-align", y_align,
"x-expand", x_expand,
"y-expand", y_expand,
NULL);
return TRUE;
}
static const gchar *
get_align_name (ClutterActorAlign align)
{
switch (align)
{
case CLUTTER_ACTOR_ALIGN_FILL:
return "fill";
case CLUTTER_ACTOR_ALIGN_START:
return "start";
case CLUTTER_ACTOR_ALIGN_CENTER:
return "center";
case CLUTTER_ACTOR_ALIGN_END:
return "end";
default:
g_assert_not_reached ();
}
}
static void
changed_cb (ClutterActor *actor,
GParamSpec *pspec,
ClutterActor *text)
{
ClutterActorAlign x_align, y_align;
ClutterActor *box;
ClutterLayoutManager *layout;
ClutterLayoutMeta *meta;
gboolean x_expand, y_expand;
gchar *label;
gint left, top, width, height;
box = clutter_actor_get_parent (actor);
layout = clutter_actor_get_layout_manager (box);
meta = clutter_layout_manager_get_child_meta (layout,
CLUTTER_CONTAINER (box),
actor);
g_object_get (actor,
"x-align", &x_align,
"y-align", &y_align,
"x-expand", &x_expand,
"y-expand", &y_expand,
NULL);
g_object_get (meta,
"left-attach", &left,
"top-attach", &top,
"width", &width,
"height", &height,
NULL);
label = g_strdup_printf ("attach: %d,%d\n"
"span: %d,%d\n"
"expand: %d,%d\n"
"align: %s,%s",
left, top, width, height,
x_expand, y_expand,
get_align_name (x_align),
get_align_name (y_align));
clutter_text_set_text (CLUTTER_TEXT (text), label);
g_free (label);
}
static void
add_actor (ClutterActor *box,
gint left,
gint top,
gint width,
gint height)
{
ClutterActor *rect, *text;
ClutterColor color;
ClutterLayoutManager *layout;
clutter_color_from_hls (&color,
g_random_double_range (0.0, 360.0),
0.5,
0.5);
color.alpha = 255;
layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
CLUTTER_BIN_ALIGNMENT_CENTER);
rect = clutter_actor_new ();
clutter_actor_set_layout_manager (rect, layout);
clutter_actor_set_background_color (rect, &color);
clutter_actor_set_reactive (rect, TRUE);
if (random_size)
clutter_actor_set_size (rect,
g_random_int_range (40, 80),
g_random_int_range (40, 80));
else
clutter_actor_set_size (rect, 60, 60);
clutter_actor_set_x_expand (rect, default_expand);
clutter_actor_set_y_expand (rect, default_expand);
if (!default_expand)
{
clutter_actor_set_x_align (rect, CLUTTER_ACTOR_ALIGN_CENTER);
clutter_actor_set_y_align (rect, CLUTTER_ACTOR_ALIGN_CENTER);
}
if (random_align)
{
clutter_actor_set_x_align (rect, g_random_int_range (0, 3));
clutter_actor_set_y_align (rect, g_random_int_range (0, 3));
}
text = clutter_text_new_with_text ("Sans 8px", NULL);
clutter_text_set_line_alignment (CLUTTER_TEXT (text),
PANGO_ALIGN_CENTER);
clutter_actor_add_child (rect, text);
g_signal_connect (rect, "button-release-event",
G_CALLBACK (button_release_cb), NULL);
g_signal_connect (rect, "notify::x-expand",
G_CALLBACK (changed_cb), text);
g_signal_connect (rect, "notify::y-expand",
G_CALLBACK (changed_cb), text);
g_signal_connect (rect, "notify::x-align",
G_CALLBACK (changed_cb), text);
g_signal_connect (rect, "notify::y-align",
G_CALLBACK (changed_cb), text);
layout = clutter_actor_get_layout_manager (box);
if (use_box)
clutter_actor_add_child (box, rect);
else
clutter_grid_layout_attach (CLUTTER_GRID_LAYOUT (layout), rect,
left, top, width, height);
changed_cb (rect, NULL, text);
}
static gboolean
key_release_cb (ClutterActor *stage,
ClutterEvent *event,
ClutterActor *box)
{
ClutterGridLayout *layout;
gboolean toggle;
guint spacing;
layout = CLUTTER_GRID_LAYOUT (clutter_actor_get_layout_manager (box));
switch (clutter_event_get_key_symbol (event))
{
case CLUTTER_KEY_c:
toggle = clutter_grid_layout_get_column_homogeneous (layout);
clutter_grid_layout_set_column_homogeneous (layout, !toggle);
break;
case CLUTTER_KEY_r:
toggle = clutter_grid_layout_get_row_homogeneous (layout);
clutter_grid_layout_set_row_homogeneous (layout, !toggle);
break;
case CLUTTER_KEY_s:
spacing = clutter_grid_layout_get_column_spacing (layout);
if (spacing < 12)
spacing += 1;
else
spacing = 0;
clutter_grid_layout_set_column_spacing (layout, spacing);
clutter_grid_layout_set_row_spacing (layout, spacing);
break;
case CLUTTER_KEY_q:
clutter_main_quit ();
break;
default:
return FALSE;
}
return TRUE;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *box, *instructions;
ClutterLayoutManager *stage_layout, *grid_layout;
GError *error = NULL;
if (clutter_init_with_args (&argc, &argv,
NULL,
entries,
NULL,
&error) != CLUTTER_INIT_SUCCESS)
{
g_print ("Unable to run grid-layout: %s", error->message);
g_error_free (error);
return EXIT_FAILURE;
}
stage = clutter_stage_new ();
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
stage_layout = clutter_box_layout_new ();
clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (stage_layout),
CLUTTER_ORIENTATION_VERTICAL);
clutter_actor_set_layout_manager (stage, stage_layout);
grid_layout = clutter_grid_layout_new ();
if (is_vertical)
clutter_grid_layout_set_orientation (CLUTTER_GRID_LAYOUT (grid_layout),
CLUTTER_ORIENTATION_VERTICAL);
box = clutter_actor_new ();
clutter_actor_set_background_color (box, CLUTTER_COLOR_LightGray);
clutter_actor_set_x_expand (box, TRUE);
clutter_actor_set_y_expand (box, TRUE);
clutter_actor_set_layout_manager (box, grid_layout);
clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (stage_layout), box,
TRUE, TRUE, TRUE,
CLUTTER_BOX_ALIGNMENT_CENTER,
CLUTTER_BOX_ALIGNMENT_CENTER);
add_actor (box, 0, 0, 1, 1);
add_actor (box, 1, 0, 1, 1);
add_actor (box, 2, 0, 1, 1);
add_actor (box, 0, 1, 1, 1);
add_actor (box, 1, 1, 2, 1);
add_actor (box, 0, 2, 3, 1);
add_actor (box, 0, 3, 2, 2);
add_actor (box, 2, 3, 1, 1);
add_actor (box, 2, 4, 1, 1);
instructions = clutter_text_new_with_text ("Sans 12px", INSTRUCTIONS);
clutter_actor_set_margin_top (instructions, 4);
clutter_actor_set_margin_left (instructions, 4);
clutter_actor_set_margin_bottom (instructions, 4);
clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (stage_layout), instructions,
FALSE, TRUE, FALSE,
CLUTTER_BOX_ALIGNMENT_START,
CLUTTER_BOX_ALIGNMENT_CENTER);
g_signal_connect (stage, "destroy",
G_CALLBACK (clutter_main_quit), NULL);
g_signal_connect (stage, "key-release-event",
G_CALLBACK (key_release_cb), box);
clutter_actor_show (stage);
clutter_main ();
return 0;
}

View File

@ -1,110 +0,0 @@
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
static const struct {
ClutterContentGravity gravity;
const char *name;
} gravities[] = {
{ CLUTTER_CONTENT_GRAVITY_TOP_LEFT, "Top Left" },
{ CLUTTER_CONTENT_GRAVITY_TOP, "Top" },
{ CLUTTER_CONTENT_GRAVITY_TOP_RIGHT, "Top Right" },
{ CLUTTER_CONTENT_GRAVITY_LEFT, "Left" },
{ CLUTTER_CONTENT_GRAVITY_CENTER, "Center" },
{ CLUTTER_CONTENT_GRAVITY_RIGHT, "Right" },
{ CLUTTER_CONTENT_GRAVITY_BOTTOM_LEFT, "Bottom Left" },
{ CLUTTER_CONTENT_GRAVITY_BOTTOM, "Bottom" },
{ CLUTTER_CONTENT_GRAVITY_BOTTOM_RIGHT, "Bottom Right" },
{ CLUTTER_CONTENT_GRAVITY_RESIZE_FILL, "Resize Fill" },
{ CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT, "Resize Aspect" },
};
static int n_gravities = G_N_ELEMENTS (gravities);
static int cur_gravity = 0;
static void
on_tap (ClutterTapAction *action,
ClutterActor *actor,
ClutterText *label)
{
gchar *str;
clutter_actor_save_easing_state (actor);
clutter_actor_set_content_gravity (actor, gravities[cur_gravity].gravity);
clutter_actor_restore_easing_state (actor);
str = g_strconcat ("Content gravity: ", gravities[cur_gravity].name, NULL);
clutter_text_set_text (label, str);
g_free (str);
cur_gravity += 1;
if (cur_gravity >= n_gravities)
cur_gravity = 0;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *text;
ClutterContent *image;
ClutterAction *action;
GdkPixbuf *pixbuf;
gchar *str;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
stage = clutter_stage_new ();
clutter_actor_set_name (stage, "Stage");
clutter_stage_set_title (CLUTTER_STAGE (stage), "Content Box");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
clutter_actor_set_margin_top (stage, 12);
clutter_actor_set_margin_right (stage, 12);
clutter_actor_set_margin_bottom (stage, 12);
clutter_actor_set_margin_left (stage, 12);
clutter_actor_show (stage);
pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL);
image = clutter_image_new ();
clutter_image_set_data (CLUTTER_IMAGE (image),
gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf)
? COGL_PIXEL_FORMAT_RGBA_8888
: COGL_PIXEL_FORMAT_RGB_888,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_rowstride (pixbuf),
NULL);
g_object_unref (pixbuf);
clutter_actor_set_content_scaling_filters (stage,
CLUTTER_SCALING_FILTER_TRILINEAR,
CLUTTER_SCALING_FILTER_LINEAR);
clutter_actor_set_content_gravity (stage, gravities[n_gravities - 1].gravity);
clutter_actor_set_content (stage, image);
g_object_unref (image);
str = g_strconcat ("Content gravity: ",
gravities[n_gravities - 1].name,
NULL);
text = clutter_text_new ();
clutter_text_set_text (CLUTTER_TEXT (text), str);
clutter_actor_add_constraint (text, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
clutter_actor_add_child (stage, text);
g_free (str);
action = clutter_tap_action_new ();
g_signal_connect (action, "tap", G_CALLBACK (on_tap), text);
clutter_actor_add_action (stage, action);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,461 +0,0 @@
#include <math.h>
#include <stdlib.h>
#include <clutter/clutter.h>
typedef struct _MultiLayout MultiLayout;
typedef struct _MultiLayoutClass MultiLayoutClass;
typedef enum {
MULTI_LAYOUT_GRID,
MULTI_LAYOUT_CIRCLE
} MultiLayoutState;
struct _MultiLayout
{
ClutterLayoutManager parent_instance;
/* the state of the layout */
MultiLayoutState state;
/* spacing between children */
float spacing;
/* cell size */
float cell_width;
float cell_height;
};
struct _MultiLayoutClass
{
ClutterLayoutManagerClass parent_class;
};
GType multi_layout_get_type (void);
ClutterLayoutManager * multi_layout_new (void);
void multi_layout_set_state (MultiLayout *layout,
MultiLayoutState state);
MultiLayoutState multi_layout_get_state (MultiLayout *layout);
void multi_layout_set_spacing (MultiLayout *layout,
float spacing);
G_DEFINE_TYPE (MultiLayout, multi_layout, CLUTTER_TYPE_LAYOUT_MANAGER)
static void
multi_layout_get_preferred_width (ClutterLayoutManager *manager,
ClutterContainer *container,
float for_height,
float *min_width_p,
float *nat_width_p)
{
MultiLayout *self = (MultiLayout *) manager;
float minimum, natural;
float max_natural_width;
ClutterActorIter iter;
ClutterActor *child;
int n_children;
minimum = natural = 0.f;
max_natural_width = 0.f;
n_children = 0;
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container));
while (clutter_actor_iter_next (&iter, &child))
{
float child_minimum, child_natural;
if (!clutter_actor_is_visible (child))
continue;
clutter_actor_get_preferred_width (child, -1.f,
&child_minimum,
&child_natural);
max_natural_width = MAX (max_natural_width, child_natural);
if (self->state == MULTI_LAYOUT_GRID)
{
minimum += child_minimum;
natural += child_natural;
}
else if (self->state == MULTI_LAYOUT_CIRCLE)
{
minimum = MAX (minimum, child_minimum);
natural = MAX (natural, child_natural);
}
n_children += 1;
}
self->cell_width = max_natural_width;
minimum += (self->spacing * (n_children - 1));
natural += (self->spacing * (n_children - 1));
if (min_width_p != NULL)
*min_width_p = minimum;
if (nat_width_p != NULL)
*nat_width_p = natural;
}
static void
multi_layout_get_preferred_height (ClutterLayoutManager *manager,
ClutterContainer *container,
float for_width,
float *min_height_p,
float *nat_height_p)
{
MultiLayout *self = (MultiLayout *) manager;
float minimum, natural;
ClutterActorIter iter;
ClutterActor *child;
int n_children;
minimum = natural = self->spacing * 2.f;
n_children = 0;
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container));
while (clutter_actor_iter_next (&iter, &child))
{
float child_minimum, child_natural;
if (!clutter_actor_is_visible (child))
continue;
clutter_actor_get_preferred_height (child, -1.f,
&child_minimum,
&child_natural);
minimum = MAX (minimum, child_minimum);
natural = MAX (natural, child_natural);
n_children += 1;
}
self->cell_height = natural;
minimum += (self->spacing * (n_children - 1));
natural += (self->spacing * (n_children - 1));
if (min_height_p != NULL)
*min_height_p = minimum;
if (nat_height_p != NULL)
*nat_height_p = natural;
}
static int
get_items_per_row (MultiLayout *self,
float for_width)
{
int n_columns;
if (for_width < 0)
return 1;
if (self->cell_width <= 0)
return 1;
n_columns = (int) ((for_width + self->spacing) / (self->cell_width + self->spacing));
return MAX (n_columns, 1);
}
static int
get_visible_children (ClutterActor *actor)
{
ClutterActorIter iter;
ClutterActor *child;
int n_visible_children = 0;
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (clutter_actor_is_visible (child))
n_visible_children += 1;
}
return n_visible_children;
}
static void
multi_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
MultiLayout *self = (MultiLayout *) manager;
float avail_width, avail_height;
float x_offset, y_offset;
ClutterActorIter iter;
ClutterActor *child;
float item_x = 0.f, item_y = 0.f;
int n_items, n_items_per_row = 0, item_index;
ClutterPoint center = CLUTTER_POINT_INIT_ZERO;
double radius = 0, theta = 0;
n_items = get_visible_children (CLUTTER_ACTOR (container));
if (n_items == 0)
return;
clutter_actor_box_get_origin (allocation, &x_offset, &y_offset);
clutter_actor_box_get_size (allocation, &avail_width, &avail_height);
/* ensure we have an updated value of cell_width and cell_height */
multi_layout_get_preferred_width (manager, container, avail_width, NULL, NULL);
multi_layout_get_preferred_height (manager, container, avail_height, NULL, NULL);
item_index = 0;
if (self->state == MULTI_LAYOUT_GRID)
{
n_items_per_row = get_items_per_row (self, avail_width);
item_x = x_offset;
item_y = y_offset;
}
else if (self->state == MULTI_LAYOUT_CIRCLE)
{
center.x = allocation->x2 / 2.f;
center.y = allocation->y2 / 2.f;
radius = MIN ((avail_width - self->cell_width) / 2.0,
(avail_height - self->cell_height) / 2.0);
}
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container));
while (clutter_actor_iter_next (&iter, &child))
{
ClutterActorBox child_allocation = CLUTTER_ACTOR_BOX_INIT_ZERO;
if (!clutter_actor_is_visible (child))
continue;
if (self->state == MULTI_LAYOUT_GRID)
{
if (item_index == n_items_per_row)
{
item_index = 0;
item_x = x_offset;
item_y += self->cell_height + self->spacing;
}
child_allocation.x1 = item_x;
child_allocation.y1 = item_y;
child_allocation.x2 = child_allocation.x1 + self->cell_width;
child_allocation.y2 = child_allocation.y1 + self->cell_height;
item_x += self->cell_width + self->spacing;
}
else if (self->state == MULTI_LAYOUT_CIRCLE)
{
theta = 2.0 * G_PI / n_items * item_index;
child_allocation.x1 = center.x + radius * sinf (theta) - (self->cell_width / 2.f);
child_allocation.y1 = center.y + radius * -cosf (theta) - (self->cell_height / 2.f);
child_allocation.x2 = child_allocation.x1 + self->cell_width;
child_allocation.y2 = child_allocation.y1 + self->cell_height;
}
clutter_actor_allocate (child, &child_allocation, flags);
item_index += 1;
}
}
static void
multi_layout_class_init (MultiLayoutClass *klass)
{
ClutterLayoutManagerClass *manager_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass);
manager_class->get_preferred_width = multi_layout_get_preferred_width;
manager_class->get_preferred_height = multi_layout_get_preferred_height;
manager_class->allocate = multi_layout_allocate;
}
static void
multi_layout_init (MultiLayout *self)
{
self->state = MULTI_LAYOUT_GRID;
self->cell_width = -1.f;
self->cell_height = -1.f;
self->spacing = 0.f;
}
ClutterLayoutManager *
multi_layout_new (void)
{
return g_object_new (multi_layout_get_type (), NULL);
}
void
multi_layout_set_state (MultiLayout *self,
MultiLayoutState state)
{
if (self->state == state)
return;
self->state = state;
clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (self));
}
MultiLayoutState
multi_layout_get_state (MultiLayout *self)
{
return self->state;
}
void
multi_layout_set_spacing (MultiLayout *self,
float spacing)
{
self->spacing = spacing;
clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (self));
}
#define N_RECTS 16
#define RECT_SIZE 64.0
#define N_ROWS 4
#define PADDING 12.0
#define BOX_SIZE (RECT_SIZE * (N_RECTS / N_ROWS) + PADDING * (N_RECTS / N_ROWS - 1))
static gboolean
on_enter (ClutterActor *rect,
ClutterEvent *event)
{
clutter_actor_set_scale (rect, 1.2, 1.2);
return CLUTTER_EVENT_STOP;
}
static gboolean
on_leave (ClutterActor *rect,
ClutterEvent *event)
{
clutter_actor_set_scale (rect, 1.0, 1.0);
return CLUTTER_EVENT_STOP;
}
static gboolean
on_key_press (ClutterActor *stage,
ClutterEvent *event,
ClutterActor *box)
{
guint keysym = clutter_event_get_key_symbol (event);
MultiLayout *layout = (MultiLayout *) clutter_actor_get_layout_manager (box);
switch (keysym)
{
case CLUTTER_KEY_q:
clutter_main_quit ();
break;
case CLUTTER_KEY_t:
{
MultiLayoutState state = multi_layout_get_state (layout);
if (state == MULTI_LAYOUT_GRID)
multi_layout_set_state (layout, MULTI_LAYOUT_CIRCLE);
if (state == MULTI_LAYOUT_CIRCLE)
multi_layout_set_state (layout, MULTI_LAYOUT_GRID);
}
break;
default:
break;
}
return CLUTTER_EVENT_STOP;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *box, *label;
ClutterLayoutManager *manager;
ClutterMargin margin;
ClutterTransition *transition;
int i;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Multi-layout");
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
clutter_actor_show (stage);
/* the layout manager for the main container */
manager = multi_layout_new ();
multi_layout_set_spacing ((MultiLayout *) manager, PADDING);
margin.top = margin.bottom = margin.left = margin.right = PADDING;
/* our main container, centered on the stage */
box = clutter_actor_new ();
clutter_actor_set_margin (box, &margin);
clutter_actor_set_layout_manager (box, manager);
clutter_actor_set_size (box, BOX_SIZE, BOX_SIZE);
clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
clutter_actor_add_child (stage, box);
for (i = 0; i < N_RECTS; i++)
{
ClutterActor *rect = clutter_actor_new ();
ClutterColor color;
clutter_color_from_hls (&color,
360.0 / N_RECTS * i,
0.5,
0.8);
color.alpha = 128 + 128 / N_RECTS * i;
/* elements on the layout */
clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE);
clutter_actor_set_pivot_point (rect, .5f, .5f);
clutter_actor_set_background_color (rect, &color);
clutter_actor_set_opacity (rect, 0);
clutter_actor_set_reactive (rect, TRUE);
/* explicit transition that fades in the element; the delay on
* the transition staggers the fade depending on the index
*/
transition = clutter_property_transition_new ("opacity");
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 250);
clutter_timeline_set_delay (CLUTTER_TIMELINE (transition), i * 50);
clutter_transition_set_from (transition, G_TYPE_UINT, 0);
clutter_transition_set_to (transition, G_TYPE_UINT, 255);
clutter_actor_add_transition (rect, "fadeIn", transition);
g_object_unref (transition);
/* we want all state transitions to be animated */
clutter_actor_set_easing_duration (rect, 250);
clutter_actor_set_easing_mode (rect, CLUTTER_EASE_OUT_CUBIC);
clutter_actor_add_child (box, rect);
/* simple hover effect */
g_signal_connect (rect, "enter-event", G_CALLBACK (on_enter), NULL);
g_signal_connect (rect, "leave-event", G_CALLBACK (on_leave), NULL);
}
label = clutter_text_new ();
clutter_text_set_text (CLUTTER_TEXT (label),
"Press t\t\342\236\236\tToggle layout\n"
"Press q\t\342\236\236\tQuit");
clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95));
clutter_actor_add_child (stage, label);
g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), box);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,194 +0,0 @@
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#ifdef CLUTTER_WINDOWING_X11
#include <clutter/x11/clutter-x11.h>
#endif
static ClutterActor *
create_content_actor (void)
{
ClutterActor *content;
ClutterContent *image;
GdkPixbuf *pixbuf;
content = clutter_actor_new ();
clutter_actor_set_size (content, 720, 720);
pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL);
image = clutter_image_new ();
clutter_image_set_data (CLUTTER_IMAGE (image),
gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf)
? COGL_PIXEL_FORMAT_RGBA_8888
: COGL_PIXEL_FORMAT_RGB_888,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_rowstride (pixbuf),
NULL);
g_object_unref (pixbuf);
clutter_actor_set_content_scaling_filters (content,
CLUTTER_SCALING_FILTER_TRILINEAR,
CLUTTER_SCALING_FILTER_LINEAR);
clutter_actor_set_content_gravity (content, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
clutter_actor_set_content (content, image);
g_object_unref (image);
return content;
}
static gboolean
on_pan (ClutterPanAction *action,
ClutterActor *scroll,
gboolean is_interpolated,
gpointer *user_data)
{
gfloat delta_x, delta_y;
const ClutterEvent *event = NULL;
if (is_interpolated)
clutter_pan_action_get_interpolated_delta (action, &delta_x, &delta_y);
else
{
clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (action), 0, &delta_x, &delta_y);
event = clutter_gesture_action_get_last_event (CLUTTER_GESTURE_ACTION (action), 0);
}
g_print ("[%s] panning dx:%.2f dy:%.2f\n",
event == NULL ? "INTERPOLATED" :
event->type == CLUTTER_MOTION ? "MOTION" :
event->type == CLUTTER_TOUCH_UPDATE ? "TOUCH UPDATE" :
"?",
delta_x, delta_y);
return TRUE;
}
static ClutterActor *
create_scroll_actor (ClutterActor *stage)
{
ClutterActor *scroll;
ClutterAction *pan_action;
/* our scrollable viewport */
scroll = clutter_actor_new ();
clutter_actor_set_name (scroll, "scroll");
clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0));
clutter_actor_add_constraint (scroll, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0));
clutter_actor_add_child (scroll, create_content_actor ());
pan_action = clutter_pan_action_new ();
clutter_pan_action_set_interpolate (CLUTTER_PAN_ACTION (pan_action), TRUE);
g_signal_connect (pan_action, "pan", G_CALLBACK (on_pan), NULL);
clutter_actor_add_action_with_name (scroll, "pan", pan_action);
clutter_actor_set_reactive (scroll, TRUE);
return scroll;
}
static gboolean
on_key_press (ClutterActor *stage,
ClutterEvent *event,
gpointer unused)
{
ClutterActor *scroll;
guint key_symbol;
scroll = clutter_actor_get_first_child (stage);
key_symbol = clutter_event_get_key_symbol (event);
if (key_symbol == CLUTTER_KEY_space)
{
clutter_actor_save_easing_state (scroll);
clutter_actor_set_easing_duration (scroll, 1000);
clutter_actor_set_child_transform (scroll, NULL);
clutter_actor_restore_easing_state (scroll);
}
return CLUTTER_EVENT_STOP;
}
static gboolean
label_clicked_cb (ClutterText *label, ClutterEvent *event, ClutterActor *scroll)
{
ClutterPanAction *action = CLUTTER_PAN_ACTION (clutter_actor_get_action (scroll, "pan"));
const gchar *label_text = clutter_text_get_text (label);
if (g_str_equal (label_text, "X AXIS"))
clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_X_AXIS);
else if (g_str_equal (label_text, "Y AXIS"))
clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_Y_AXIS);
else if (g_str_equal (label_text, "AUTO"))
clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_AXIS_AUTO);
else
clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_AXIS_NONE);
return TRUE;
}
static void
add_label (const gchar *text, ClutterActor *box, ClutterActor *scroll)
{
ClutterActor *label;
label = clutter_text_new_with_text (NULL, text);
clutter_actor_set_reactive (label, TRUE);
clutter_actor_set_x_align (label, CLUTTER_ACTOR_ALIGN_START);
clutter_actor_set_x_expand (label, TRUE);
clutter_actor_add_child (box, label);
g_signal_connect (label, "button-release-event",
G_CALLBACK (label_clicked_cb), scroll);
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *scroll, *box, *info;
ClutterLayoutManager *layout;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
/* create a new stage */
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Pan Action");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
scroll = create_scroll_actor (stage);
clutter_actor_add_child (stage, scroll);
box = clutter_actor_new ();
clutter_actor_add_child (stage, box);
clutter_actor_set_position (box, 12, 12);
layout = clutter_box_layout_new ();
clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout), CLUTTER_ORIENTATION_VERTICAL);
clutter_actor_set_layout_manager (box, layout);
info = clutter_text_new_with_text (NULL, "Press <space> to reset the image position.");
clutter_actor_add_child (box, info);
info = clutter_text_new_with_text (NULL, "Click labels below to change AXIS pinning.");
clutter_actor_add_child (box, info);
add_label ("NONE", box, scroll);
add_label ("X AXIS", box, scroll);
add_label ("Y AXIS", box, scroll);
add_label ("AUTO", box, scroll);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), scroll);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -1,110 +0,0 @@
#include <stdlib.h>
#include <math.h>
#include <cairo.h>
#include <clutter/clutter.h>
static gboolean
draw_content (ClutterCanvas *canvas,
cairo_t *cr,
int surface_width,
int surface_height)
{
/* rounded rectangle taken from:
*
* http://cairographics.org/samples/rounded_rectangle/
*
* we leave 1 pixel around the edges to avoid jagged edges
* when rotating the actor
*/
double x = 1.0, /* parameters like cairo_rectangle */
y = 1.0,
width = surface_width - 2.0,
height = surface_height - 2.0,
aspect = 1.0, /* aspect ratio */
corner_radius = height / 20.0; /* and corner curvature radius */
double radius = corner_radius / aspect;
double degrees = M_PI / 180.0;
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_restore (cr);
cairo_new_sub_path (cr);
cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
cairo_close_path (cr);
cairo_set_source_rgba (cr, 0.5, 0.5, 1, 0.95);
cairo_fill (cr);
/* we're done drawing */
return TRUE;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *actor;
ClutterContent *canvas;
ClutterTransition *transition;
/* initialize Clutter */
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
/* create a stage */
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Rectangle with rounded corners");
clutter_stage_set_use_alpha (CLUTTER_STAGE (stage), TRUE);
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
clutter_actor_set_size (stage, 500, 500);
clutter_actor_set_opacity (stage, 64);
clutter_actor_show (stage);
/* our 2D canvas, courtesy of Cairo */
canvas = clutter_canvas_new ();
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300);
/* the actor that will display the contents of the canvas */
actor = clutter_actor_new ();
clutter_actor_set_content (actor, canvas);
clutter_actor_set_content_gravity (actor, CLUTTER_CONTENT_GRAVITY_CENTER);
clutter_actor_set_content_scaling_filters (actor,
CLUTTER_SCALING_FILTER_TRILINEAR,
CLUTTER_SCALING_FILTER_LINEAR);
clutter_actor_set_pivot_point (actor, 0.5f, 0.5f);
clutter_actor_add_constraint (actor, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
clutter_actor_set_request_mode (actor, CLUTTER_REQUEST_CONTENT_SIZE);
clutter_actor_add_child (stage, actor);
/* the actor now owns the canvas */
g_object_unref (canvas);
/* create the continuous animation of the actor spinning around its center */
transition = clutter_property_transition_new ("rotation-angle-y");
clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0);
clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 2000);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_actor_add_transition (actor, "rotateActor", transition);
/* the actor now owns the transition */
g_object_unref (transition);
/* quit on destroy */
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* connect our drawing code */
g_signal_connect (canvas, "draw", G_CALLBACK (draw_content), NULL);
/* invalidate the canvas, so that we can draw before the main loop starts */
clutter_content_invalidate (canvas);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,193 +0,0 @@
#include <stdlib.h>
#include <glib.h>
#include <clutter/clutter.h>
static const char *menu_items_name[] = {
"Option 1",
"Option 2",
"Option 3",
"Option 4",
"Option 5",
"Option 6",
"Option 7",
"Option 8",
"Option 9",
"Option 10",
"Option 11",
};
static const guint menu_items_len = G_N_ELEMENTS (menu_items_name);
static void
select_item_at_index (ClutterActor *scroll,
int index_)
{
ClutterPoint point;
ClutterActor *menu, *item;
gpointer old_selected;
menu = clutter_actor_get_first_child (scroll);
old_selected = g_object_get_data (G_OBJECT (scroll), "selected-item");
if (old_selected != NULL)
{
item = clutter_actor_get_child_at_index (menu, GPOINTER_TO_INT (old_selected));
clutter_text_set_color (CLUTTER_TEXT (item), CLUTTER_COLOR_White);
}
/* wrap around the index */
if (index_ < 0)
index_ = clutter_actor_get_n_children (menu) - 1;
else if (index_ >= clutter_actor_get_n_children (menu))
index_ = 0;
item = clutter_actor_get_child_at_index (menu, index_);
clutter_actor_get_position (item, &point.x, &point.y);
/* scroll to the actor's position; the menu actor is always set at (0, 0),
* so it does not contribute any further offset, and we can use the position
* of its children to ask the ScrollActor to scroll the visible region; if
* the menu actor had an offset, or was transformed, we would have needed to
* get their relative transformed position instead.
*/
clutter_actor_save_easing_state (scroll);
clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (scroll), &point);
clutter_actor_restore_easing_state (scroll);
clutter_text_set_color (CLUTTER_TEXT (item), CLUTTER_COLOR_LightSkyBlue);
/* store the index of the currently selected item, so that we can
* implement select_next_item() and select_prev_item()
*/
g_object_set_data (G_OBJECT (scroll), "selected-item",
GINT_TO_POINTER (index_));
}
static void
select_next_item (ClutterActor *scroll)
{
gpointer selected_ = g_object_get_data (G_OBJECT (scroll), "selected-item");
select_item_at_index (scroll, GPOINTER_TO_INT (selected_) + 1);
}
static void
select_prev_item (ClutterActor *scroll)
{
gpointer selected_ = g_object_get_data (G_OBJECT (scroll), "selected-item");
select_item_at_index (scroll, GPOINTER_TO_INT (selected_) - 1);
}
static ClutterActor *
create_menu_item (const char *name)
{
ClutterActor *text;
text = clutter_text_new ();
clutter_text_set_font_name (CLUTTER_TEXT (text), "Sans Bold 24");
clutter_text_set_text (CLUTTER_TEXT (text), name);
clutter_text_set_color (CLUTTER_TEXT (text), CLUTTER_COLOR_White);
clutter_actor_set_margin_left (text, 12.f);
clutter_actor_set_margin_right (text, 12.f);
return text;
}
static ClutterActor *
create_menu_actor (ClutterActor *scroll)
{
ClutterActor *menu;
ClutterLayoutManager *layout_manager;
guint i;
/* this is our menu; it contains items in a vertical layout */
layout_manager = clutter_box_layout_new ();
clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout_manager),
CLUTTER_ORIENTATION_VERTICAL);
clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout_manager), 12.f);
menu = clutter_actor_new ();
clutter_actor_set_layout_manager (menu, layout_manager);
clutter_actor_set_background_color (menu, CLUTTER_COLOR_Black);
/* these are the items */
for (i = 0; i < menu_items_len; i++)
clutter_actor_add_child (menu, create_menu_item (menu_items_name[i]));
return menu;
}
static ClutterActor *
create_scroll_actor (ClutterActor *stage)
{
ClutterActor *scroll;
/* our scrollable viewport */
scroll = clutter_scroll_actor_new ();
clutter_actor_set_name (scroll, "scroll");
/* give a vertical offset, and constrain the viewport so that its size
* is bound to the stage size
*/
clutter_actor_set_position (scroll, 0.f, 18.f);
clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
clutter_actor_add_constraint (scroll, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -36.f));
/* we only want to scroll the contents vertically, and
* ignore any horizontal component
*/
clutter_scroll_actor_set_scroll_mode (CLUTTER_SCROLL_ACTOR (scroll),
CLUTTER_SCROLL_VERTICALLY);
clutter_actor_add_child (scroll, create_menu_actor (scroll));
/* select the first item */
select_item_at_index (scroll, 0);
return scroll;
}
static gboolean
on_key_press (ClutterActor *stage,
ClutterEvent *event,
gpointer unused)
{
ClutterActor *scroll;
guint key_symbol;
scroll = clutter_actor_get_first_child (stage);
key_symbol = clutter_event_get_key_symbol (event);
if (key_symbol == CLUTTER_KEY_Up)
select_prev_item (scroll);
else if (key_symbol == CLUTTER_KEY_Down)
select_next_item (scroll);
return CLUTTER_EVENT_STOP;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return EXIT_FAILURE;
/* create a new stage */
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Scroll Actor");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), NULL);
clutter_actor_add_child (stage, create_scroll_actor (stage));
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}

View File

@ -1,292 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <clutter/clutter.h>
/* our thread-specific data */
typedef struct
{
ClutterActor *stage;
ClutterActor *label;
ClutterActor *progress;
ClutterActor *rect;
ClutterTransition *flip;
ClutterTransition *bounce;
} TestThreadData;
static TestThreadData *
test_thread_data_new (void)
{
TestThreadData *data;
data = g_new0 (TestThreadData, 1);
return data;
}
static void
test_thread_data_free (gpointer _data)
{
TestThreadData *data = _data;
if (data == NULL)
return;
g_print ("Removing thread data [%p]\n", _data);
g_clear_object (&data->progress);
g_clear_object (&data->label);
g_clear_object (&data->stage);
g_clear_object (&data->rect);
g_clear_object (&data->flip);
g_clear_object (&data->bounce);
g_free (data);
}
static gboolean
test_thread_done_idle (gpointer user_data)
{
TestThreadData *data = user_data;
g_print ("Last update [%p]\n", data);
clutter_text_set_text (CLUTTER_TEXT (data->label), "Completed");
clutter_actor_remove_transition (data->rect, "bounce");
clutter_actor_remove_transition (data->rect, "flip");
return G_SOURCE_REMOVE;
}
static void
test_thread_data_done (gpointer _data)
{
if (_data == NULL)
return;
g_print ("Thread completed\n");
/* since the TestThreadData structure references Clutter data structures
* we need to free it from within the same thread that called clutter_main()
* which means using an idle handler in the main loop.
*
* clutter_threads_add_idle() is guaranteed to run the callback passed to
* to it under the Big Clutter Lock.
*/
clutter_threads_add_idle_full (G_PRIORITY_DEFAULT,
test_thread_done_idle,
_data,
test_thread_data_free);
}
/* thread local storage */
static GPrivate test_thread_data = G_PRIVATE_INIT (test_thread_data_done);
typedef struct {
gint count;
TestThreadData *thread_data;
} TestUpdate;
static gboolean
update_label_idle (gpointer data)
{
TestUpdate *update = data;
guint width;
gchar *text;
if (update->thread_data->label == NULL)
return G_SOURCE_REMOVE;
text = g_strdup_printf ("Count to %d", update->count);
clutter_text_set_text (CLUTTER_TEXT (update->thread_data->label), text);
clutter_actor_set_width (update->thread_data->label, -1);
if (update->count == 0)
width = 0;
else if (update->count == 100)
width = 350;
else
width = (guint) (update->count / 100.0 * 350.0);
clutter_actor_save_easing_state (update->thread_data->progress);
clutter_actor_set_width (update->thread_data->progress, width);
clutter_actor_restore_easing_state (update->thread_data->progress);
g_free (text);
g_free (update);
return G_SOURCE_REMOVE;
}
static void
do_something_very_slow (void)
{
TestThreadData *data;
gint i;
data = g_private_get (&test_thread_data);
for (i = 0; i <= 100; i++)
{
gint msecs;
msecs = 1 + (int) (100.0 * rand () / ((RAND_MAX + 1.0) / 3));
/* sleep for a while, to emulate some work being done */
g_usleep (msecs * 1000);
if ((i % 10) == 0)
{
TestUpdate *update;
/* update the UI from within the main loop, making sure that the
* Big Clutter Lock is held; only one thread at a time can call
* Clutter API, and it's mandatory to do this from the same thread
* that called clutter_init()/clutter_main().
*/
update = g_new (TestUpdate, 1);
update->count = i;
update->thread_data = data;
clutter_threads_add_idle_full (G_PRIORITY_HIGH,
update_label_idle,
update, NULL);
}
}
}
static gpointer
test_thread_func (gpointer user_data)
{
TestThreadData *data = user_data;
g_private_set (&test_thread_data, data);
/* this function will block */
do_something_very_slow ();
return NULL;
}
static ClutterActor *count_label = NULL;
static ClutterActor *help_label = NULL;
static ClutterActor *progress_rect = NULL;
static ClutterActor *rect = NULL;
static ClutterTransition *flip = NULL;
static ClutterTransition *bounce = NULL;
static gboolean
on_key_press_event (ClutterStage *stage,
ClutterEvent *event,
gpointer user_data)
{
TestThreadData *data;
switch (clutter_event_get_key_symbol (event))
{
case CLUTTER_KEY_s:
clutter_text_set_text (CLUTTER_TEXT (help_label), "Press 'q' to quit");
/* start the animations */
clutter_actor_add_transition (rect, "flip", flip);
clutter_actor_add_transition (rect, "bounce", bounce);
/* the data structure holding all our objects */
data = test_thread_data_new ();
data->stage = g_object_ref (stage);
data->label = g_object_ref (count_label);
data->progress = g_object_ref (progress_rect);
data->rect = g_object_ref (rect);
data->flip = g_object_ref (flip);
data->bounce = g_object_ref (bounce);
/* start the thread that updates the counter and the progress bar */
g_thread_new ("counter", test_thread_func, data);
return CLUTTER_EVENT_STOP;
case CLUTTER_KEY_q:
clutter_main_quit ();
return CLUTTER_EVENT_STOP;
default:
break;
}
return CLUTTER_EVENT_PROPAGATE;
}
int
main (int argc, char *argv[])
{
ClutterTransition *transition;
ClutterActor *stage;
ClutterPoint start = CLUTTER_POINT_INIT (75.f, 150.f);
ClutterPoint end = CLUTTER_POINT_INIT (400.f, 150.f);
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Threading");
clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium3);
clutter_actor_set_size (stage, 600, 300);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
count_label = clutter_text_new_with_text ("Mono 12", "Counter");
clutter_actor_set_position (count_label, 350, 50);
clutter_actor_add_child (stage, count_label);
help_label = clutter_text_new_with_text ("Mono 12", "Press 's' to start");
clutter_actor_set_position (help_label, 50, 50);
clutter_actor_add_child (stage, help_label);
/* a progress bar */
progress_rect = clutter_actor_new ();
clutter_actor_set_background_color (progress_rect, CLUTTER_COLOR_DarkChameleon);
clutter_actor_set_position (progress_rect, 50, 225);
clutter_actor_set_size (progress_rect, 350, 50);
clutter_actor_add_child (stage, progress_rect);
/* an actor we bounce around */
rect = clutter_actor_new ();
clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightScarletRed);
clutter_actor_set_position (rect, 75, 150);
clutter_actor_set_size (rect, 50, 50);
clutter_actor_set_pivot_point (rect, .5f, .5f);
clutter_actor_set_opacity (rect, 224);
clutter_actor_add_child (stage, rect);
/* two transitions we use to bounce rect around */
transition = clutter_property_transition_new ("rotation-angle-z");
clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0);
clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 3000);
flip = transition;
transition = clutter_property_transition_new ("position");
clutter_transition_set_from (transition, CLUTTER_TYPE_POINT, &start);
clutter_transition_set_to (transition, CLUTTER_TYPE_POINT, &end);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 3000);
bounce = transition;
g_signal_connect (stage,
"button-press-event", G_CALLBACK (clutter_main_quit),
NULL);
g_signal_connect (stage,
"key-press-event", G_CALLBACK (on_key_press_event),
NULL);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}