2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-actor.c:
	(clutter_actor_real_request_coords),
	(clutter_actor_request_coords),
	(clutter_actor_class_init): Provide a default ::request_coords()
	implementation in ClutterActor and use it to store the bounding
	box passed to clutter_actor_request_coords(). This makes the code
	more reliable and clean, and avoids a call to the subclass
	request_coords() method if the bounding box did not change. Now,
	every class overriding ClutterActor::request_coords() *must* chain
	up to the parent class method or the bounding box will not be
	saved inside the ClutterActor structure.
	
	* clutter/clutter-entry.c:
	* clutter/clutter-group.c:
	* clutter/clutter-hbox.c:
	* clutter/clutter-label.c:
	* clutter/clutter-texture.c:
	* clutter/clutter-vbox.c: Chain up to the parent class
	request_coords() method.
This commit is contained in:
Emmanuele Bassi 2007-11-23 17:12:27 +00:00
parent b0446d66fe
commit c4f89675e0
10 changed files with 89 additions and 40 deletions

View File

@ -1,3 +1,25 @@
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-actor.c:
(clutter_actor_real_request_coords),
(clutter_actor_request_coords),
(clutter_actor_class_init): Provide a default ::request_coords()
implementation in ClutterActor and use it to store the bounding
box passed to clutter_actor_request_coords(). This makes the code
more reliable and clean, and avoids a call to the subclass
request_coords() method if the bounding box did not change. Now,
every class overriding ClutterActor::request_coords() *must* chain
up to the parent class method or the bounding box will not be
saved inside the ClutterActor structure.
* clutter/clutter-entry.c:
* clutter/clutter-group.c:
* clutter/clutter-hbox.c:
* clutter/clutter-label.c:
* clutter/clutter-texture.c:
* clutter/clutter-vbox.c: Chain up to the parent class
request_coords() method.
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com> 2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-event.h: Add more documentation. * clutter/clutter-event.h: Add more documentation.

View File

@ -42,21 +42,21 @@
* <listitem><para>Events are handled by connecting signal handlers to * <listitem><para>Events are handled by connecting signal handlers to
* the numerous event signal types.</para></listitem> * the numerous event signal types.</para></listitem>
* <listitem><para>Event handlers must return %TRUE if they handled * <listitem><para>Event handlers must return %TRUE if they handled
* the event and wish to block the event emission chain; and %FALSE * the event and wish to block the event emission chain, or %FALSE
* if the emission chain must continue</para></listitem> * if the emission chain must continue</para></listitem>
* <listitem><para>Keyboard events are emitted if actor has focus, see * <listitem><para>Keyboard events are emitted if actor has focus, see
* clutter_stage_set_focus()</para></listitem> * clutter_stage_set_key_focus()</para></listitem>
* <listitem><para>Motion events (motion, enter, leave) are only emitted * <listitem><para>Motion events (motion, enter, leave) are not emitted
* per actor if clutter_enable_motion_events() was called with %TRUE. If * if clutter_set_motion_events_enabled() is called with %FALSE.
* set to %FALSE (the default) then only the stage emits motion * See clutter_set_motion_events_enabled() documentation for more
* events (no enter or leave events).</para></listitem> * information.</para></listitem>
* <listitem><para>Once emitted, an event emmision chain has two * <listitem><para>Once emitted, an event emission chain has two
* phases: capture and bubble. A emitted event starts in the capture * phases: capture and bubble. A emitted event starts in the capture
* phase beginning at the stage and transversing child actors until * phase beginning at the stage and traversing every child actor until
* the event source actor is reached. The emmision then enters the bubble * the event source actor is reached. The emission then enters the bubble
* phase transversing back up via parents to the stage. An event * phase, traversing back up the chain via parents until it reaches the
* handler can abort this chain at point by returning * stage. Any event handler can abort this chain by returning
* %TRUE.</para></listitem> * %TRUE (meaning "event handled").</para></listitem>
* <listitem><para>Pointer events will 'pass through' non reactive actors. * <listitem><para>Pointer events will 'pass through' non reactive actors.
* </para></listitem> * </para></listitem>
* </orderedlist> * </orderedlist>
@ -864,52 +864,59 @@ clutter_actor_paint (ClutterActor *self)
#undef M #undef M
static void
clutter_actor_real_request_coords (ClutterActor *self,
ClutterActorBox *box)
{
self->priv->coords = *box;
}
/** /**
* clutter_actor_request_coords: * clutter_actor_request_coords:
* @self: A #ClutterActor * @self: A #ClutterActor
* @box: A #ClutterActorBox with requested new co-ordinates in ClutterUnits * @box: A #ClutterActorBox with the new coordinates, in ClutterUnits
* *
* Requests new untransformed co-ordinates for the #ClutterActor * Requests new untransformed coordinates for the bounding box of
* ralative to any parent. * a #ClutterActor. The coordinates must be relative to the current
* parent of the actor.
* *
* This function should not be called directly by applications instead * This function should not be called directly by applications;
* the various position/geometry methods should be used. * instead, the various position/geometry methods should be used.
**/ *
* Note: Actors overriding the ClutterActor::request_coords() virtual
* function should always chain up to the parent class request_coords()
* method. Actors should override this function only if they need to
* recompute some internal state or need to reposition their evental
* children.
*/
void void
clutter_actor_request_coords (ClutterActor *self, clutter_actor_request_coords (ClutterActor *self,
ClutterActorBox *box) ClutterActorBox *box)
{ {
ClutterActorClass *klass; ClutterActorPrivate *priv;
gboolean x_change, y_change, width_change, height_change; gboolean x_change, y_change, width_change, height_change;
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (box != NULL); g_return_if_fail (box != NULL);
klass = CLUTTER_ACTOR_GET_CLASS (self); priv = self->priv;
if (klass->request_coords) /* avoid calling request coords if the coordinates did not change */
klass->request_coords (self, box); x_change = (priv->coords.x1 != box->x1);
y_change = (priv->coords.y1 != box->y1);
x_change = (self->priv->coords.x1 != box->x1); width_change = ((priv->coords.x2 - priv->coords.x1) != (box->x2 - box->x1));
y_change = (self->priv->coords.y1 != box->y1); height_change = ((priv->coords.y2 - priv->coords.y1) != (box->y2 - box->y1));
width_change = ((self->priv->coords.x2 - self->priv->coords.x1) !=
(box->x2 - box->x1));
height_change = ((self->priv->coords.y2 - self->priv->coords.y1) !=
(box->y2 - box->y1));
if (x_change || y_change || width_change || height_change) if (x_change || y_change || width_change || height_change)
{ {
self->priv->coords.x1 = box->x1; g_object_ref (self);
self->priv->coords.y1 = box->y1; g_object_freeze_notify (G_OBJECT (self));
self->priv->coords.x2 = box->x2;
self->priv->coords.y2 = box->y2; CLUTTER_ACTOR_GET_CLASS (self)->request_coords (self, box);
if (CLUTTER_ACTOR_IS_VISIBLE (self)) if (CLUTTER_ACTOR_IS_VISIBLE (self))
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
g_object_ref (self);
g_object_freeze_notify (G_OBJECT (self));
if (x_change) if (x_change)
g_object_notify (G_OBJECT (self), "x"); g_object_notify (G_OBJECT (self), "x");
@ -1646,6 +1653,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
klass->hide = clutter_actor_real_hide; klass->hide = clutter_actor_real_hide;
klass->hide_all = clutter_actor_hide; klass->hide_all = clutter_actor_hide;
klass->pick = clutter_actor_real_pick; klass->pick = clutter_actor_real_pick;
klass->request_coords = clutter_actor_real_request_coords;
} }
static void static void

View File

@ -491,6 +491,8 @@ clutter_entry_request_coords (ClutterActor *self,
priv->width = width; priv->width = width;
} }
CLUTTER_ACTOR_CLASS (clutter_entry_parent_class)->request_coords (self, box);
} }
static void static void

View File

@ -124,8 +124,8 @@ clutter_group_pick (ClutterActor *actor,
static void static void
clutter_group_request_coords (ClutterActor *self, clutter_group_request_coords (ClutterActor *self,
ClutterActorBox *box) ClutterActorBox *box)
{ {
ClutterActorBox cbox; ClutterActorBox cbox;
@ -136,6 +136,8 @@ clutter_group_request_coords (ClutterActor *self,
*/ */
box->x2 = box->x1 + (cbox.x2 - cbox.x1); box->x2 = box->x1 + (cbox.x2 - cbox.x1);
box->y2 = box->y1 + (cbox.y2 - cbox.y1); box->y2 = box->y1 + (cbox.y2 - cbox.y1);
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->request_coords (self, box);
} }
static void static void

View File

@ -102,6 +102,8 @@ clutter_hbox_request_coords (ClutterActor *actor,
box->allocation.y1 = coords->y1; box->allocation.y1 = coords->y1;
box->allocation.x2 = -1; box->allocation.x2 = -1;
box->allocation.y2 = -1; box->allocation.y2 = -1;
CLUTTER_ACTOR_CLASS (clutter_hbox_parent_class)->request_coords (actor, coords);
} }
static void static void

View File

@ -362,6 +362,8 @@ clutter_label_request_coords (ClutterActor *self,
clutter_label_clear_layout (label); clutter_label_clear_layout (label);
priv->allocation = *box; priv->allocation = *box;
CLUTTER_ACTOR_CLASS (clutter_label_parent_class)->request_coords (self, box);
} }
static void static void

View File

@ -786,6 +786,8 @@ clutter_texture_request_coords (ClutterActor *self,
if (((box->x2 - box->x1) != (old_request.x2 - old_request.x1)) || if (((box->x2 - box->x1) != (old_request.x2 - old_request.x1)) ||
((box->y2 - box->y1) != (old_request.y2 - old_request.y1))) ((box->y2 - box->y1) != (old_request.y2 - old_request.y1)))
texture->priv->sync_actor_size = FALSE; texture->priv->sync_actor_size = FALSE;
CLUTTER_ACTOR_CLASS (clutter_texture_parent_class)->request_coords (self, box);
} }
static void static void

View File

@ -102,6 +102,8 @@ clutter_vbox_request_coords (ClutterActor *actor,
box->allocation.y1 = coords->y1; box->allocation.y1 = coords->y1;
box->allocation.x2 = -1; box->allocation.x2 = -1;
box->allocation.y2 = -1; box->allocation.y2 = -1;
CLUTTER_ACTOR_CLASS (clutter_vbox_parent_class)->request_coords (actor, coords);
} }
static void static void

View File

@ -1,3 +1,8 @@
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* subclassing-ClutterActor.sgml: Mention the chain-up needed when
overriding the request_coords() vfunc of ClutterActor.
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com> 2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* clutter-sections.txt: Add unused API. * clutter-sections.txt: Add unused API.

View File

@ -77,8 +77,10 @@ foo_actor_query_coords (ClutterActor *actor,
is invoked when clutter_actor_request_coords() is called on an instance is invoked when clutter_actor_request_coords() is called on an instance
of that actor class. It is used to set the coordinates of the bounding of that actor class. It is used to set the coordinates of the bounding
box for the actor. Container actors, or composite actors with internal box for the actor. Container actors, or composite actors with internal
children, should call clutter_actor_request_coords() on each visible children, should override the request_coords() virtual function and call
child.</para> clutter_actor_request_coords() on each visible child. Every actor class
overriding the request_coords() virtual function must chain up to the
parent class request_coords() method.</para>
<para>The ClutterActor::paint() method should be overridden if the <para>The ClutterActor::paint() method should be overridden if the
actor needs to control its drawing process, by using the GL API actor needs to control its drawing process, by using the GL API