mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 05:12:15 +00:00
466 lines
15 KiB
C
466 lines
15 KiB
C
|
/*
|
||
|
* 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 <stdlib.h>
|
||
|
#include <clutter/clutter.h>
|
||
|
|
||
|
#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;
|
||
|
}
|