mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
clutter: Remove examples
Running clutter apps standalone using mutters fork is not something worth supporting.
This commit is contained in:
parent
1e2610e4f4
commit
0d9391e282
@ -2,11 +2,7 @@ NULL =
|
||||
|
||||
SUBDIRS = build clutter tests
|
||||
|
||||
if BUILD_EXAMPLES
|
||||
SUBDIRS += examples
|
||||
endif
|
||||
|
||||
DIST_SUBDIRS = clutter tests examples build
|
||||
DIST_SUBDIRS = clutter tests build
|
||||
|
||||
# XXX - this is a massive hack to make autoreconf honour the ACLOCAL_FLAGS
|
||||
# that jhbuild sets while still retaining build/autotools as the authoritative
|
||||
|
@ -698,8 +698,6 @@ AS_IF([test "x$use_gcov" = "xyes"],
|
||||
AC_MSG_ERROR([Could not find genhtml from the LTP package])
|
||||
fi
|
||||
|
||||
AC_DEFINE(HAVE_GCOV, 1, [Whether you have gcov])
|
||||
|
||||
dnl Remove all optimization flags from CFLAGS
|
||||
changequote({,})
|
||||
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
|
||||
@ -727,12 +725,6 @@ dnl === Conformance test suite ================================================
|
||||
|
||||
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 ===========================================================================
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
@ -752,8 +744,6 @@ AC_CONFIG_FILES([
|
||||
tests/interactive/wrapper.sh
|
||||
tests/micro-bench/Makefile
|
||||
tests/performance/Makefile
|
||||
|
||||
examples/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
@ -789,7 +779,6 @@ if test "x$pixbuf_tests" = "xyes"; then
|
||||
echo " Build tests using GDK-Pixbuf: ${pixbuf_tests}"
|
||||
fi
|
||||
echo " Install test suites: ${enable_installed_tests}"
|
||||
echo " Build examples: ${enable_examples}"
|
||||
|
||||
# Clutter backend related flags
|
||||
echo ""
|
||||
|
@ -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
|
@ -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.
|
@ -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;
|
||||
}
|
||||
/* }}} */
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 |
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user