2006-11-20 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-rectangle.h:
	* clutter/clutter-rectangle.c: Add border to the ClutterRectangle
	actor; add "border-width", "border-color" and "has-border"
	properties, plus their accessors.  The border generation code is
	pretty lame, at the moment.

	* examples/behave.c: Add code to test the new rectangle properties.
This commit is contained in:
Emmanuele Bassi 2006-11-20 22:20:48 +00:00
parent ada4b4e96b
commit af0d04be7c
6 changed files with 369 additions and 34 deletions

View File

@ -1,3 +1,13 @@
2006-11-20 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-rectangle.h:
* clutter/clutter-rectangle.c: Add border to the ClutterRectangle
actor; add "border-width", "border-color" and "has-border"
properties, plus their accessors. The border generation code is
pretty lame, at the moment.
* examples/behave.c: Add code to test the new rectangle properties.
2006-11-20 Matthew Allum <mallum@openedhand.com>
* clutter.doap:

View File

@ -42,7 +42,11 @@ G_DEFINE_TYPE (ClutterRectangle, clutter_rectangle, CLUTTER_TYPE_ACTOR);
enum
{
PROP_0,
PROP_COLOR
PROP_COLOR,
PROP_BORDER_COLOR,
PROP_BORDER_WIDTH,
PROP_HAS_BORDER
/* FIXME: Add gradient, rounded corner props etc */
};
@ -53,6 +57,11 @@ enum
struct _ClutterRectanglePrivate
{
ClutterColor color;
ClutterColor border_color;
guint border_width;
guint has_border : 1;
};
static void
@ -72,15 +81,40 @@ clutter_rectangle_paint (ClutterActor *self)
clutter_actor_get_geometry (self, &geom);
glColor4ub(priv->color.red,
priv->color.green,
priv->color.blue,
clutter_actor_get_opacity (self));
/* parent paint call will have translated us into position so
* paint from 0,0
*/
glRecti (0, 0, geom.width, geom.height);
* paint from 0, 0
*/
if (priv->has_border)
{
glColor4ub (priv->border_color.red,
priv->border_color.green,
priv->border_color.blue,
clutter_actor_get_opacity (self));
/* this sucks, but it's the only way to make a border */
glRecti (0, 0,
geom.width, priv->border_width);
glRecti (geom.width - priv->border_width, priv->border_width,
geom.width, geom.height - priv->border_width);
glRecti (0, geom.height - priv->border_width,
geom.width, geom.height);
glRecti (0, priv->border_width,
priv->border_width, geom.height - priv->border_width);
glColor4ub (priv->color.red,
priv->color.green,
priv->color.blue,
clutter_actor_get_opacity (self));
glRecti (priv->border_width,
priv->border_width,
geom.width - priv->border_width,
geom.height - priv->border_width);
}
else
{
glRecti (0, 0, geom.width, geom.height);
}
glDisable(GL_BLEND);
@ -100,6 +134,17 @@ clutter_rectangle_set_property (GObject *object,
case PROP_COLOR:
clutter_rectangle_set_color (rectangle, g_value_get_boxed (value));
break;
case PROP_BORDER_COLOR:
clutter_rectangle_set_border_color (rectangle,
g_value_get_boxed (value));
break;
case PROP_BORDER_WIDTH:
clutter_rectangle_set_border_width (rectangle,
g_value_get_uint (value));
break;
case PROP_HAS_BORDER:
rectangle->priv->has_border = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -121,6 +166,16 @@ clutter_rectangle_get_property (GObject *object,
clutter_rectangle_get_color (rectangle, &color);
g_value_set_boxed (value, &color);
break;
case PROP_BORDER_COLOR:
clutter_rectangle_get_border_color (rectangle, &color);
g_value_set_boxed (value, &color);
break;
case PROP_BORDER_WIDTH:
g_value_set_uint (value, rectangle->priv->border_width);
break;
case PROP_HAS_BORDER:
g_value_set_boolean (value, rectangle->priv->has_border);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -154,13 +209,61 @@ clutter_rectangle_class_init (ClutterRectangleClass *klass)
gobject_class->set_property = clutter_rectangle_set_property;
gobject_class->get_property = clutter_rectangle_get_property;
g_object_class_install_property
(gobject_class, PROP_COLOR,
g_param_spec_boxed ("color",
"Color",
"The color of the rectangle",
CLUTTER_TYPE_COLOR,
G_PARAM_READWRITE));
/**
* ClutterRectangle:color:
*
* The color of the rectangle.
*/
g_object_class_install_property (gobject_class,
PROP_COLOR,
g_param_spec_boxed ("color",
"Color",
"The color of the rectangle",
CLUTTER_TYPE_COLOR,
G_PARAM_READWRITE));
/**
* ClutterRectangle:border-color:
*
* The color of the border of the rectangle.
*
* Since: 0.2
*/
g_object_class_install_property (gobject_class,
PROP_BORDER_COLOR,
g_param_spec_boxed ("border-color",
"Border Color",
"The color of the border of the rectangle",
CLUTTER_TYPE_COLOR,
G_PARAM_READWRITE));
/**
* ClutterRectangle:border-width:
*
* The width of the border of the rectangle, in pixels.
*
* Since: 0.2
*/
g_object_class_install_property (gobject_class,
PROP_BORDER_WIDTH,
g_param_spec_uint ("border-width",
"Border Width",
"The width of the border of the rectangle",
0, G_MAXUINT,
0,
G_PARAM_READWRITE));
/**
* ClutterRectangle:has-border:
*
* Whether the #ClutterRectangle should be displayed with a border.
*
* Since: 0.2
*/
g_object_class_install_property (gobject_class,
PROP_HAS_BORDER,
g_param_spec_boolean ("has-border",
"Has Border",
"Whether the rectangle should have a border",
FALSE,
G_PARAM_READWRITE));
g_type_class_add_private (gobject_class, sizeof (ClutterRectanglePrivate));
}
@ -168,12 +271,23 @@ clutter_rectangle_class_init (ClutterRectangleClass *klass)
static void
clutter_rectangle_init (ClutterRectangle *self)
{
self->priv = CLUTTER_RECTANGLE_GET_PRIVATE (self);
ClutterRectanglePrivate *priv;
self->priv->color.red = 0xff;
self->priv->color.green = 0xff;
self->priv->color.blue = 0xff;
self->priv->color.alpha = 0xff;
self->priv = priv = CLUTTER_RECTANGLE_GET_PRIVATE (self);
priv->color.red = 0xff;
priv->color.green = 0xff;
priv->color.blue = 0xff;
priv->color.alpha = 0xff;
priv->border_color.red = 0x00;
priv->border_color.green = 0x00;
priv->border_color.blue = 0x00;
priv->border_color.alpha = 0xff;
priv->border_width = 0;
priv->has_border = FALSE;
}
/**
@ -246,6 +360,8 @@ clutter_rectangle_set_color (ClutterRectangle *rectangle,
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
g_object_ref (rectangle);
priv = rectangle->priv;
priv->color.red = color->red;
@ -260,4 +376,127 @@ clutter_rectangle_set_color (ClutterRectangle *rectangle,
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
g_object_notify (G_OBJECT (rectangle), "color");
g_object_unref (rectangle);
}
/**
* clutter_rectangle_get_border_width:
* @rectangle: a #ClutterRectangle
*
* Gets the width (in pixels) of the border used by @rectangle
*
* Return value: the border's width
*
* Since: 0.2
*/
guint
clutter_rectangle_get_border_width (ClutterRectangle *rectangle)
{
g_return_val_if_fail (CLUTTER_IS_RECTANGLE (rectangle), 0);
return rectangle->priv->border_width;
}
/**
* clutter_rectangle_set_border_width:
* @rectangle: a #ClutterRectangle
* @width: the width of the border
*
* Sets the width (in pixel) of the border used by @rectangle.
* A @width of 0 will unset the border.
*
* Since: 0.2
*/
void
clutter_rectangle_set_border_width (ClutterRectangle *rectangle,
guint width)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
priv = rectangle->priv;
if (priv->border_width != width)
{
g_object_ref (rectangle);
priv->border_width = width;
if (priv->border_width != 0)
priv->has_border = TRUE;
else
priv->has_border = FALSE;
if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (rectangle)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
g_object_notify (G_OBJECT (rectangle), "border-width");
g_object_notify (G_OBJECT (rectangle), "has-border");
g_object_unref (rectangle);
}
}
/**
* clutter_rectangle_get_border_color:
* @rectangle: a #ClutterRectangle
* @color: return location for a #ClutterColor
*
* Gets the color of the border used by @rectangle and places
* it into @color.
*
* Since: 0.2
*/
void
clutter_rectangle_get_border_color (ClutterRectangle *rectangle,
ClutterColor *color)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
priv = rectangle->priv;
color->red = priv->border_color.red;
color->green = priv->border_color.green;
color->blue = priv->border_color.blue;
color->alpha = priv->border_color.alpha;
}
/**
* clutter_rectangle_set_border_color:
* @rectangle: a #ClutterRectangle
* @color: the color of the border
*
* Sets the color of the border used by @rectangle using @color
*/
void
clutter_rectangle_set_border_color (ClutterRectangle *rectangle,
const ClutterColor *color)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
priv = rectangle->priv;
if (priv->border_color.red != color->red &&
priv->border_color.green != color->green &&
priv->border_color.blue != color->blue &&
priv->border_color.alpha != color->alpha)
{
g_object_ref (rectangle);
priv->border_color.red = color->red;
priv->border_color.green = color->green;
priv->border_color.blue = color->blue;
priv->border_color.alpha = color->alpha;
if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (rectangle)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
g_object_notify (G_OBJECT (rectangle), "border-color");
g_object_unref (rectangle);
}
}

View File

@ -79,13 +79,20 @@ struct _ClutterRectangleClass
GType clutter_rectangle_get_type (void) G_GNUC_CONST;
ClutterActor *clutter_rectangle_new (void);
ClutterActor *clutter_rectangle_new_with_color (const ClutterColor *color);
ClutterActor *clutter_rectangle_new (void);
ClutterActor *clutter_rectangle_new_with_color (const ClutterColor *color);
void clutter_rectangle_get_color (ClutterRectangle *rectangle,
ClutterColor *color);
void clutter_rectangle_set_color (ClutterRectangle *rectangle,
void clutter_rectangle_get_color (ClutterRectangle *rectangle,
ClutterColor *color);
void clutter_rectangle_set_color (ClutterRectangle *rectangle,
const ClutterColor *color);
guint clutter_rectangle_get_border_width (ClutterRectangle *rectangle);
void clutter_rectangle_set_border_width (ClutterRectangle *rectangle,
guint width);
void clutter_rectangle_get_border_color (ClutterRectangle *rectangle,
ClutterColor *color);
void clutter_rectangle_set_border_color (ClutterRectangle *rectangle,
const ClutterColor *color);
G_END_DECLS

View File

@ -165,6 +165,10 @@ clutter_rectangle_new
clutter_rectangle_new_with_color
clutter_rectangle_get_color
clutter_rectangle_set_color
clutter_rectangle_get_border_color
clutter_rectangle_set_border_color
clutter_rectangle_get_border_width
clutter_rectangle_set_border_width
<SUBSECTION Standard>
CLUTTER_RECTANGLE
CLUTTER_IS_RECTANGLE

View File

@ -23,11 +23,26 @@ ClutterRectangle
</para>
<!-- ##### ARG ClutterRectangle:border-color ##### -->
<para>
</para>
<!-- ##### ARG ClutterRectangle:border-width ##### -->
<para>
</para>
<!-- ##### ARG ClutterRectangle:color ##### -->
<para>
</para>
<!-- ##### ARG ClutterRectangle:has-border ##### -->
<para>
</para>
<!-- ##### STRUCT ClutterRectangleClass ##### -->
<para>
@ -74,3 +89,39 @@ ClutterRectangle
@color:
<!-- ##### FUNCTION clutter_rectangle_get_border_color ##### -->
<para>
</para>
@rectangle:
@color:
<!-- ##### FUNCTION clutter_rectangle_set_border_color ##### -->
<para>
</para>
@rectangle:
@color:
<!-- ##### FUNCTION clutter_rectangle_get_border_width ##### -->
<para>
</para>
@rectangle:
@Returns:
<!-- ##### FUNCTION clutter_rectangle_set_border_width ##### -->
<para>
</para>
@rectangle:
@width:

View File

@ -6,16 +6,22 @@ main (int argc, char *argv[])
ClutterTimeline *timeline;
ClutterAlpha *alpha;
ClutterBehaviour *behave;
ClutterActor *stage, *hand;
ClutterActor *stage;
ClutterActor *group, *rect, *hand;
ClutterColor stage_color = { 0xcc, 0xcc, 0xcc, 0xff };
ClutterColor rect_bg_color = { 0x33, 0x22, 0x22, 0xff };
ClutterColor rect_border_color = { 0xff, 0xcc, 0xcc, 0xff };
GdkPixbuf *pixbuf;
ClutterKnot knots[] = {{ 100, 100 }, { 100, 200 }, { 200, 200 },
{ 200, 100 }, {100, 100 }};
ClutterKnot knots[] = {{ 0, 0 }, { 0, 300 }, { 300, 300 },
{ 300, 0 }, {0, 0 }};
clutter_init (&argc, &argv);
stage = clutter_stage_get_default ();
g_signal_connect (stage, "key-press-event",
G_CALLBACK (clutter_main_quit),
NULL);
pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL);
@ -26,12 +32,30 @@ main (int argc, char *argv[])
&stage_color);
/* Make a hand */
group = clutter_group_new ();
clutter_group_add (CLUTTER_GROUP (stage), group);
clutter_actor_show (group);
rect = clutter_rectangle_new ();
clutter_actor_set_position (rect, 0, 0);
clutter_actor_set_size (rect,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect),
&rect_bg_color);
clutter_rectangle_set_border_width (CLUTTER_RECTANGLE (rect), 10);
clutter_rectangle_set_border_color (CLUTTER_RECTANGLE (rect),
&rect_border_color);
clutter_actor_show (rect);
hand = clutter_texture_new_from_pixbuf (pixbuf);
clutter_actor_set_position (hand, 100, 100);
clutter_group_add (CLUTTER_GROUP (stage), hand);
clutter_actor_set_position (hand, 0, 0);
clutter_actor_show (hand);
clutter_group_add_many (CLUTTER_GROUP (group), rect, hand, NULL);
/* Make a timeline */
timeline = clutter_timeline_new (100, 60); /* num frames, fps */
timeline = clutter_timeline_new (100, 26); /* num frames, fps */
g_object_set (timeline, "loop", TRUE, 0);
/* Set an alpha func to power behaviour - ramp is constant rise/fall */
@ -43,11 +67,11 @@ main (int argc, char *argv[])
behave = clutter_behaviour_opacity_new (alpha, 0X33, 0xff);
/* Apply it to our actor */
clutter_behaviour_apply (behave, hand);
clutter_behaviour_apply (behave, group);
/* Make a path behaviour and apply that too */
behave = clutter_behaviour_path_new (alpha, knots, 5);
clutter_behaviour_apply (behave, hand);
clutter_behaviour_apply (behave, group);
/* start the timeline and thus the animations */
clutter_timeline_start (timeline);