mutter/tests/interactive/test-content.c
Emmanuele Bassi be4746b15f Add ClutterContent
ClutterContent is an interface for creating delegate objects that handle
what an actor is going to paint.

Since they are a newly added type, they only hook into the new PaintNode
based API.

The position and size of the content is controlled in part by the
content's own preferred size, and by the ClutterContentGravity
enumeration.
2012-03-16 12:33:36 +00:00

224 lines
6.2 KiB
C

#include <stdlib.h>
#include <gmodule.h>
#include <clutter/clutter.h>
typedef struct _ColorContent {
GObject parent_instance;
double red;
double green;
double blue;
double alpha;
float padding;
} ColorContent;
typedef struct _ColorContentClass {
GObjectClass parent_class;
} ColorContentClass;
static void clutter_content_iface_init (ClutterContentIface *iface);
G_DEFINE_TYPE_WITH_CODE (ColorContent, color_content, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
clutter_content_iface_init))
static void
color_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *root)
{
ColorContent *self = (ColorContent *) content;
ClutterActorBox box, content_box;
ClutterColor color;
PangoLayout *layout;
PangoRectangle logical;
ClutterPaintNode *node;
#if 0
g_debug ("Painting content [%p] "
"{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } "
"for actor [%p] (context: [%p])",
content,
self->red,
self->green,
self->blue,
self->alpha,
actor, context);
#endif
clutter_actor_get_content_box (actor, &content_box);
box = content_box;
box.x1 += self->padding;
box.y1 += self->padding;
box.x2 -= self->padding;
box.y2 -= self->padding;
color.alpha = self->alpha * 255;
color.red = self->red * 255;
color.green = self->green * 255;
color.blue = self->blue * 255;
node = clutter_color_node_new (&color);
clutter_paint_node_add_rectangle (node, &box);
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
color.red = (1.0 - self->red) * 255;
color.green = (1.0 - self->green) * 255;
color.blue = (1.0 - self->blue) * 255;
layout = clutter_actor_create_pango_layout (actor, "A");
pango_layout_get_pixel_extents (layout, NULL, &logical);
node = clutter_text_node_new (layout, &color);
/* top-left */
box.x1 = clutter_actor_box_get_x (&content_box);
box.y1 = clutter_actor_box_get_y (&content_box);
clutter_paint_node_add_rectangle (node, &box);
/* top-right */
box.x1 = clutter_actor_box_get_x (&content_box)
+ clutter_actor_box_get_width (&content_box)
- logical.width;
box.y1 = clutter_actor_box_get_y (&content_box);
clutter_paint_node_add_rectangle (node, &box);
/* bottom-right */
box.x1 = clutter_actor_box_get_x (&content_box)
+ clutter_actor_box_get_width (&content_box)
- logical.width;
box.y1 = clutter_actor_box_get_y (&content_box)
+ clutter_actor_box_get_height (&content_box)
- logical.height;
clutter_paint_node_add_rectangle (node, &box);
/* bottom-left */
box.x1 = clutter_actor_box_get_x (&content_box);
box.y1 = clutter_actor_box_get_y (&content_box)
+ clutter_actor_box_get_height (&content_box)
- logical.height;
clutter_paint_node_add_rectangle (node, &box);
/* center */
box.x1 = clutter_actor_box_get_x (&content_box)
+ (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0;
box.y1 = clutter_actor_box_get_y (&content_box)
+ (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0;
clutter_paint_node_add_rectangle (node, &box);
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
g_object_unref (layout);
}
static void
clutter_content_iface_init (ClutterContentIface *iface)
{
iface->paint_content = color_content_paint_content;
}
static void
color_content_class_init (ColorContentClass *klass)
{
}
static void
color_content_init (ColorContent *self)
{
}
static ClutterContent *
color_content_new (double red,
double green,
double blue,
double alpha,
float padding)
{
ColorContent *self = g_object_new (color_content_get_type (), NULL);
self->red = red;
self->green = green;
self->blue = blue;
self->alpha = alpha;
self->padding = padding;
return (ClutterContent *) self;
}
G_MODULE_EXPORT int
test_content_main (int argc, char *argv[])
{
ClutterActor *stage, *grid;
ClutterContent *content;
int i, n_rects;
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");
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
clutter_actor_show (stage);
grid = clutter_actor_new ();
clutter_actor_set_name (grid, "Grid");
clutter_actor_set_margin_top (grid, 12);
clutter_actor_set_margin_right (grid, 12);
clutter_actor_set_margin_bottom (grid, 12);
clutter_actor_set_margin_left (grid, 12);
clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL));
clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0));
clutter_actor_add_child (stage, grid);
content = color_content_new (g_random_double_range (0.0, 1.0),
g_random_double_range (0.0, 1.0),
g_random_double_range (0.0, 1.0),
1.0,
2.0);
n_rects = g_random_int_range (12, 24);
for (i = 0; i < n_rects; i++)
{
ClutterActor *box = clutter_actor_new ();
ClutterColor bg_color = {
g_random_int_range (0, 255),
g_random_int_range (0, 255),
g_random_int_range (0, 255),
255
};
char *name, *color;
color = clutter_color_to_string (&bg_color);
name = g_strconcat ("Box <", color, ">", NULL);
clutter_actor_set_name (box, name);
g_free (name);
g_free (color);
clutter_actor_set_background_color (box, &bg_color);
clutter_actor_set_content (box, content);
clutter_actor_set_size (box, 64, 64);
clutter_actor_add_child (grid, box);
}
clutter_main ();
g_object_unref (content);
return EXIT_SUCCESS;
}
G_MODULE_EXPORT const char *
test_content_describe (void)
{
return "A simple test for ClutterContent";
}