#include #include #include #include #define MAX_NWIDGETS 4 #define WINWIDTH 400 #define WINHEIGHT 400 #define RADIUS 80 static ClutterActor *group = NULL; static ClutterActor *widgets[MAX_NWIDGETS]; static gboolean do_rotate = TRUE; static int nwidgets; /* Timeline handler */ void frame_cb (ClutterTimeline *timeline, gint msecs, gpointer data) { double rotation = clutter_timeline_get_progress (timeline) * 360.0; gint i; if (!do_rotate) return; /* Rotate everything clockwise about stage center */ clutter_actor_set_rotation_angle (group, CLUTTER_Z_AXIS, rotation); for (i = 0; i < nwidgets; i++) { clutter_actor_set_rotation_angle (widgets[i], CLUTTER_Z_AXIS, - 2 * rotation); clutter_actor_set_opacity (widgets[i], 50 * sin (2 * M_PI * rotation / 360) + (255 - 50)); } } static void button_clicked (GtkWidget *button, GtkWidget *vbox) { GtkWidget *label; g_print ("button clicked\n"); label = gtk_label_new ("A new label"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); } static ClutterActor * create_gtk_actor (int i) { GtkWidget *button, *vbox, *entry, *bin; ClutterActor *gtk_actor; gtk_actor = gtk_clutter_actor_new (); bin = gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (gtk_actor)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (bin), vbox); button = gtk_button_new_with_label ("A Button"); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); g_signal_connect (button, "clicked", G_CALLBACK (button_clicked), vbox); button = gtk_check_button_new_with_label ("Another button"); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0); gtk_widget_show_all (bin); return gtk_actor; } static void add_clutter_actor (ClutterActor *actor, ClutterActor *container, int i) { float x, y, w, h; /* Add to our group group */ clutter_actor_add_child (container, actor); /* Place around a circle */ w = clutter_actor_get_width (widgets[0]); h = clutter_actor_get_height (widgets[0]); x = WINWIDTH / 2 + RADIUS * cosf (i * 2 * M_PI / (MAX_NWIDGETS)) - w / 2; y = WINHEIGHT / 2 + RADIUS * sinf (i * 2 * M_PI / (MAX_NWIDGETS)) - h / 2; clutter_actor_set_position (actor, x, y); clutter_actor_set_pivot_point (actor, 0.5, 0.5); } static gboolean add_or_remove_timeout (gpointer user_data) { if (nwidgets == MAX_NWIDGETS) { /* Removing an item */ clutter_actor_remove_child (group, widgets[MAX_NWIDGETS - 1]); widgets[MAX_NWIDGETS - 1] = NULL; nwidgets--; } else { /* Adding an item */ widgets[MAX_NWIDGETS - 1] = create_gtk_actor (MAX_NWIDGETS - 1); nwidgets++; add_clutter_actor (widgets[MAX_NWIDGETS - 1], group, MAX_NWIDGETS - 1); } return G_SOURCE_CONTINUE; } int main (int argc, char *argv[]) { ClutterTimeline *timeline; ClutterActor *stage; ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; GtkWidget *window, *clutter; GtkWidget *button, *vbox; gint i; if (gtk_clutter_init_with_args (&argc, &argv, NULL, NULL, NULL, NULL) != CLUTTER_INIT_SUCCESS) g_error ("Unable to initialize GtkClutter"); if (argc != 1) do_rotate = FALSE; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (window), vbox); clutter = gtk_clutter_embed_new (); gtk_widget_set_size_request (clutter, WINWIDTH, WINHEIGHT); gtk_box_pack_start (GTK_BOX (vbox), clutter, TRUE, TRUE, 0); stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutter)); button = gtk_button_new_with_mnemonic ("_Quit"); g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window); gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0); clutter_actor_set_background_color (stage, &stage_color); nwidgets = 0; /* create a new group to hold multiple actors in a group */ group = clutter_actor_new (); clutter_actor_set_pivot_point (group, 0.5, 0.5); for (i = 0; i < MAX_NWIDGETS; i++) { widgets[i] = create_gtk_actor (i); nwidgets++; add_clutter_actor (widgets[i], group, i); } /* Add the group to the stage and center it*/ clutter_actor_add_child (stage, group); clutter_actor_add_constraint (group, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); gtk_widget_show_all (window); /* Create a timeline to manage animation */ timeline = clutter_timeline_new (6000); clutter_timeline_set_repeat_count (timeline, -1); /* fire a callback for frame change */ g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), stage); /* and start it */ clutter_timeline_start (timeline); g_timeout_add_seconds (3, add_or_remove_timeout, NULL); gtk_main(); return 0; }