/* * Experiment with permutations of layout properties for a ClutterBoxLayout * * See the text (in brackets) at the bottom of the application * window for available key presses */ #include #include #define STAGE_SIDE 510 #define BOX_SIDE STAGE_SIDE * 0.75 #define RED_SIDE STAGE_SIDE / 4 #define GREEN_SIDE STAGE_SIDE / 8 #define BLUE_SIDE STAGE_SIDE / 16 typedef struct { ClutterLayoutManager *box_layout; ClutterActor *box; ClutterActor *status_display; gboolean x_fill; gboolean y_fill; gboolean expand; ClutterBoxAlignment x_align; ClutterBoxAlignment y_align; } State; static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff }; static const ClutterColor box_color = { 0x66, 0x66, 0x00, 0xff }; static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff }; static const ClutterColor green_color = { 0x00, 0xff, 0x00, 0xff }; static const ClutterColor blue_color = { 0x00, 0x00, 0xff, 0xff }; static const ClutterColor white_color = { 0xff, 0xff, 0xff, 0xff }; static GValue gboolean_to_gvalue (gboolean value) { GValue gval = {0}; g_value_init (&gval, G_TYPE_BOOLEAN); g_value_set_boolean (&gval, value); return gval; } static GValue alignment_to_gvalue (ClutterBoxAlignment value) { GValue gval = {0}; g_value_init (&gval, G_TYPE_INT); g_value_set_int (&gval, value); return gval; } static gchar* alignment_as_string (ClutterBoxAlignment value) { gchar *align_string = "start "; switch (value) { case CLUTTER_BOX_ALIGNMENT_CENTER: align_string = "center"; break; case CLUTTER_BOX_ALIGNMENT_END: align_string = "end "; break; case CLUTTER_BOX_ALIGNMENT_START: align_string = "start "; break; } return align_string; } static ClutterBoxAlignment get_next_alignment (ClutterBoxAlignment alignment) { alignment++; if (alignment > CLUTTER_BOX_ALIGNMENT_CENTER) alignment = CLUTTER_BOX_ALIGNMENT_START; return alignment; } static void show_status (State *state) { ClutterText *text = CLUTTER_TEXT (state->status_display); ClutterBoxLayout *box_layout = CLUTTER_BOX_LAYOUT (state->box_layout); gboolean homogeneous = clutter_box_layout_get_homogeneous (box_layout); gboolean vertical = clutter_box_layout_get_vertical (box_layout); gchar *message = g_strdup_printf ("x_fill (x): %s\t\t\t" "y_fill (y): %s\n" "expand (e): %s\t\t" "homogeneous (h): %s\n" "spacing (+/-): %dpx\t\t" "vertical (v): %s\n" "x_align (right): %s\t" "y_align (up): %s", (state->x_fill ? "true" : "false"), (state->y_fill ? "true" : "false"), (state->expand ? "true" : "false"), (homogeneous ? "true" : "false"), clutter_box_layout_get_spacing (box_layout), (vertical ? "true" : "false"), alignment_as_string (state->x_align), alignment_as_string (state->y_align)); clutter_text_set_text (text, message); g_free (message); } static void set_property_on_layout_children (State *state, const gchar *property, GValue value) { ClutterActor *actor; ClutterContainer *container = CLUTTER_CONTAINER (state->box); ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (state->box_layout); GList *actors = clutter_container_get_children (container); for (; actors; actors = actors->next) { actor = CLUTTER_ACTOR (actors->data); clutter_layout_manager_child_set_property (manager, container, actor, property, &value); } g_list_free (actors); } static void toggle_x_fill (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; state->x_fill = !state->x_fill; set_property_on_layout_children (state, "x-fill", gboolean_to_gvalue (state->x_fill)); } static void toggle_y_fill (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; state->y_fill = !state->y_fill; set_property_on_layout_children (state, "y-fill", gboolean_to_gvalue (state->y_fill)); } static void toggle_expand (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; state->expand = !state->expand; set_property_on_layout_children (state, "expand", gboolean_to_gvalue (state->expand)); } static void rotate_x_alignment (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; state->x_align = get_next_alignment (state->x_align); set_property_on_layout_children (state, "x-align", alignment_to_gvalue (state->x_align)); } static void rotate_y_alignment (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; state->y_align = get_next_alignment (state->y_align); set_property_on_layout_children (state, "y-align", alignment_to_gvalue (state->y_align)); } static void toggle_vertical (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; ClutterBoxLayout *box_layout = CLUTTER_BOX_LAYOUT (state->box_layout); gboolean vertical = clutter_box_layout_get_vertical (box_layout); clutter_box_layout_set_vertical (box_layout, !vertical); } static void toggle_homogeneous (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; ClutterBoxLayout *box_layout = CLUTTER_BOX_LAYOUT (state->box_layout); gboolean homogeneous = clutter_box_layout_get_homogeneous (box_layout); clutter_box_layout_set_homogeneous (box_layout, !homogeneous); } static void increase_spacing (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; ClutterBoxLayout *box_layout = CLUTTER_BOX_LAYOUT (state->box_layout); guint spacing = clutter_box_layout_get_spacing (box_layout) + 5; clutter_box_layout_set_spacing (box_layout, spacing); } static void decrease_spacing (GObject *instance, const gchar *action_name, guint key_val, ClutterModifierType modifiers, gpointer user_data) { State *state = (State *) user_data; ClutterBoxLayout *box_layout = CLUTTER_BOX_LAYOUT (state->box_layout); guint spacing = clutter_box_layout_get_spacing (box_layout); if (spacing >= 5) clutter_box_layout_set_spacing (box_layout, spacing - 5); } static gboolean key_pressed_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) { State *state = (State *) user_data; ClutterBindingPool *pool; gboolean return_value; pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor)); return_value = clutter_binding_pool_activate (pool, clutter_event_get_key_symbol (event), clutter_event_get_state (event), G_OBJECT (actor)); show_status (state); return return_value; } int main (int argc, char *argv[]) { ClutterActor *stage; GObjectClass *stage_class; ClutterBindingPool *binding_pool; ClutterActor *red; ClutterActor *green; ClutterActor *blue; State *state = g_new0 (State, 1); clutter_init (&argc, &argv); state->x_fill = FALSE; state->y_fill = FALSE; state->expand = FALSE; state->x_align = CLUTTER_BOX_ALIGNMENT_START; stage = clutter_stage_get_default (); clutter_actor_set_size (stage, STAGE_SIDE, STAGE_SIDE); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); /* for key bindings */ stage_class = G_OBJECT_GET_CLASS (stage); binding_pool = clutter_binding_pool_get_for_class (stage_class); clutter_binding_pool_install_action (binding_pool, "toggle-expand", CLUTTER_KEY_e, 0, G_CALLBACK (toggle_expand), state, NULL); clutter_binding_pool_install_action (binding_pool, "toggle-x-fill", CLUTTER_KEY_x, 0, G_CALLBACK (toggle_x_fill), state, NULL); clutter_binding_pool_install_action (binding_pool, "toggle-y-fill", CLUTTER_KEY_y, 0, G_CALLBACK (toggle_y_fill), state, NULL); clutter_binding_pool_install_action (binding_pool, "toggle-vertical", CLUTTER_KEY_v, 0, G_CALLBACK (toggle_vertical), state, NULL); clutter_binding_pool_install_action (binding_pool, "toggle-homogeneous", CLUTTER_KEY_h, 0, G_CALLBACK (toggle_homogeneous), state, NULL); clutter_binding_pool_install_action (binding_pool, "rotate-x-alignment", CLUTTER_KEY_Right, 0, G_CALLBACK (rotate_x_alignment), state, NULL); clutter_binding_pool_install_action (binding_pool, "rotate-y-alignment", CLUTTER_KEY_Up, 0, G_CALLBACK (rotate_y_alignment), state, NULL); clutter_binding_pool_install_action (binding_pool, "increase-spacing", CLUTTER_KEY_plus, CLUTTER_SHIFT_MASK, G_CALLBACK (increase_spacing), state, NULL); clutter_binding_pool_install_action (binding_pool, "decrease-spacing", CLUTTER_KEY_minus, 0, G_CALLBACK (decrease_spacing), state, NULL); /* rectangles inside the layout */ red = clutter_rectangle_new_with_color (&red_color); clutter_actor_set_size (red, RED_SIDE, RED_SIDE); green = clutter_rectangle_new_with_color (&green_color); clutter_actor_set_size (green, GREEN_SIDE, GREEN_SIDE); blue = clutter_rectangle_new_with_color (&blue_color); clutter_actor_set_size (blue, BLUE_SIDE, BLUE_SIDE); /* the layout */ state->box_layout = clutter_box_layout_new (); clutter_box_layout_set_use_animations (CLUTTER_BOX_LAYOUT (state->box_layout), TRUE); state->box = clutter_box_new (state->box_layout); clutter_box_set_color (CLUTTER_BOX (state->box), &box_color); clutter_actor_set_size (state->box, BOX_SIDE, BOX_SIDE); clutter_actor_add_constraint (state->box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5)); clutter_actor_add_constraint (state->box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.1)); /* text to show status */ state->status_display = clutter_text_new (); clutter_text_set_color (CLUTTER_TEXT (state->status_display), &white_color); clutter_actor_set_size (state->status_display, STAGE_SIDE, STAGE_SIDE * 0.2); clutter_actor_set_position (state->status_display, (STAGE_SIDE - BOX_SIDE) / 2, STAGE_SIDE * 0.8); /* set text for initial state */ show_status (state); /* connect key presses to a callback on the binding pool */ g_signal_connect (stage, "key-press-event", G_CALLBACK (key_pressed_cb), state); /* pack UI */ clutter_container_add (CLUTTER_CONTAINER (state->box), red, green, blue, NULL); clutter_container_add (CLUTTER_CONTAINER (stage), state->box, state->status_display, NULL); /* show stage */ clutter_actor_show (stage); clutter_main (); /* clean up */ g_object_unref (binding_pool); g_free (state); return EXIT_SUCCESS; }