Hi,
On Tue, 2007-10-23 at 13:55 +0100, Neil Jagdish Patel wrote:
> Hi
> If you have a group that consists of a image and label, setting both the
> image and label unreactive (using clutter_actor_unset_reactive at the
> time of creation) will mean that clutter_stage_get_actor_at_pos will
> return you the group that contains them (if the click is in that area).
> This way, you don't have to do the loop, and can use your earlier code
> (direct pointer comparison).
Please disregard this and put it down to too much caffeine & not enough
sleep :-).
I have attached an example which shows how to use the new event model to
received events on actors.
The way it works is that by setting an actor as reactive, you can
connect to events on the actor itself, rather than the stage (just like
Gtk).
Two bits of useful info:
1) A ClutterGroup won't receive events, think of it like a GtkContainer,
it has no window to receive events. However, you still need to set it
reactive if any of its children are (or the event won't propagate).
2) You can use a transparent ClutterRectangle as an 'GtkEventBox', which
you place behind/above other actors to capture events. This way, if you
had a button group, it can contain bg images, an icon and text, but you
only need to set reactive on the transparent rectangle actor (this is
shown in the example code).
Kind regards,
Neil
/* compile with:
* gcc test.c -o test `pkg-config clutter-glx-0.5 --cflags --libs`
*/
#include <clutter/clutter.h>
#include <stdio.h>
#include <glib.h>
static ClutterActor *active; /* The active button */
static ClutterTimeline *main_timeline;
static ClutterTimeline *active_timeline = NULL;
static ClutterEffectTemplate *effect_temp;
static gboolean focused = FALSE;
static void on_fade_in_complete (ClutterActor *actor, gpointer null);
static void on_fade_out_complete (ClutterActor *actor, gpointer null);
static void
fade_in (void)
{
if (active_timeline)
g_object_unref (active_timeline);
active_timeline = clutter_effect_fade (effect_temp,
active,
clutter_actor_get_opacity (active),
255,
on_fade_in_complete,
NULL);
clutter_timeline_start (active_timeline);
}
static void
fade_out (void)
{
if (active_timeline)
g_object_unref (active_timeline);
active_timeline = clutter_effect_fade (effect_temp,
active,
clutter_actor_get_opacity (active),
0,
on_fade_out_complete,
NULL);
clutter_timeline_start (active_timeline);
}
static void
on_fade_in_complete (ClutterActor *actor, gpointer null)
{
if (!focused)
fade_out ();
}
static void
on_fade_out_complete (ClutterActor *actor, gpointer null)
{
if (focused)
fade_in ();
}
static gboolean
on_focus_in_event (ClutterActor *actor, ClutterCrossingEvent *e, gpointer null)
{
focused = TRUE;
if (clutter_timeline_is_playing (active_timeline))
return TRUE;
fade_in ();
return TRUE;
}
static gboolean
on_focus_out_event (ClutterActor *actor, ClutterCrossingEvent *e, gpointer null)
{
focused = FALSE;
if (clutter_timeline_is_playing (active_timeline))
return TRUE;
fade_out ();
return TRUE;
}
gint
main (gint argc, gchar *argv[])
{
ClutterColor blue = { 0x00, 0xff, 0x00, 0xff };
ClutterColor red = { 0xff, 0x00, 0x00, 0xff };
ClutterColor black = { 0x00, 0x00, 0x00, 0xff };
ClutterColor white = { 0xff, 0xff, 0xff, 0xff };
ClutterActor *label, *stage, *button, *trans, *inactive;
GError *err = NULL;
clutter_init_with_args (&argc, &argv, NULL, NULL, NULL, &err);
if (err)
{
g_warning ("Unanble to init Clutter: %s\n", err->message);
g_error_free (err);
return 1;
}
stage = clutter_stage_get_default ();
clutter_actor_set_size (stage, 400, 200);
clutter_stage_set_color (CLUTTER_STAGE (stage), &blue);
/* Make sure actors receive motion events */
clutter_enable_motion_events (TRUE);
/* The button group */
button = clutter_group_new ();
clutter_container_add_actor (CLUTTER_CONTAINER (stage), button);
clutter_actor_set_size (button, 100, 40);
clutter_actor_set_position (button, 150, 60);
clutter_actor_set_reactive (button);
/* The transparent rectangle that captures the motion event (like a
* GtkEventBox) */
trans = clutter_rectangle_new_with_color (&black);
clutter_container_add_actor (CLUTTER_CONTAINER (button), trans);
clutter_actor_set_size (trans, 125, 80);
clutter_actor_set_position (trans, 0, 0);
clutter_actor_set_reactive (trans);
clutter_actor_set_opacity (trans, 0);
/* The inactive button */
inactive = clutter_rectangle_new_with_color (&red);
clutter_container_add_actor (CLUTTER_CONTAINER (button), inactive);
clutter_actor_set_size (inactive, 125, 80);
clutter_actor_set_position (inactive, 0, 0);
clutter_actor_unset_reactive (inactive);
/* The active button */
active = clutter_rectangle_new_with_color (&black);
clutter_container_add_actor (CLUTTER_CONTAINER (button), active);
clutter_actor_set_size (active, 125, 80);
clutter_actor_set_position (active, 0, 0);
clutter_actor_set_opacity (active, 0);
/* The label */
label = clutter_label_new_full ("Sans 14", "Hover over me", &white);
clutter_label_set_line_wrap (CLUTTER_LABEL (label), FALSE);
clutter_container_add_actor (CLUTTER_CONTAINER (button), label);
clutter_actor_set_size (label, 125, 80);
clutter_actor_set_position (label, 0, 25);
/* Set up the effect stuff */
main_timeline = active_timeline = clutter_timeline_new (40, 60);
effect_temp = clutter_effect_template_new (main_timeline,
clutter_sine_inc_func);
/* Hook up to the relevant events */
g_signal_connect (trans, "enter-event",
G_CALLBACK (on_focus_in_event), NULL);
g_signal_connect (trans, "leave-event",
G_CALLBACK (on_focus_out_event), NULL);
clutter_actor_show_all (button);
clutter_actor_show_all (stage);
clutter_main ();
return 0;
}