[clutter] cairo-texture: Add the :auto-resize property



commit 7f8838d7cc9fe42ce694830cd07fa0ad0c1d27db
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Tue Jul 26 14:53:26 2011 +0100

    cairo-texture: Add the :auto-resize property
    
    Keeping the backing Cairo surface of a CairoTexture canvas in sync with
    the actor's allocation is tedious and prone to mistakes. We can
    definitely do better by simply exposing a property that does the surface
    resize and invalidation automagically on ::allocate.

 clutter/clutter-cairo-texture.c            |  120 +++++++++++++++++++++++++++-
 clutter/clutter-cairo-texture.h            |    3 +
 doc/reference/clutter/clutter-sections.txt |    2 +
 tests/interactive/test-cairo-clock.c       |    9 ++-
 4 files changed, 129 insertions(+), 5 deletions(-)
---
diff --git a/clutter/clutter-cairo-texture.c b/clutter/clutter-cairo-texture.c
index f5ec310..a6a5b88 100644
--- a/clutter/clutter-cairo-texture.c
+++ b/clutter/clutter-cairo-texture.c
@@ -67,7 +67,7 @@
 #include "config.h"
 #endif
 
-#include <string.h>
+#include <math.h>
 
 #include <cairo-gobject.h>
 
@@ -88,6 +88,7 @@ enum
 
   PROP_SURFACE_WIDTH,
   PROP_SURFACE_HEIGHT,
+  PROP_AUTO_RESIZE,
 
   PROP_LAST
 };
@@ -125,6 +126,8 @@ struct _ClutterCairoTexturePrivate
   guint surface_height;
 
   cairo_t *cr_context;
+
+  guint auto_resize : 1;
 };
 
 typedef struct {
@@ -173,6 +176,9 @@ clutter_cairo_texture_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_SURFACE_WIDTH:
+      /* we perform the resize on notify to coalesce separate
+       * surface-width/surface-height property set
+       */
       priv->surface_width = g_value_get_uint (value);
       break;
 
@@ -180,6 +186,11 @@ clutter_cairo_texture_set_property (GObject      *object,
       priv->surface_height = g_value_get_uint (value);
       break;
 
+    case PROP_AUTO_RESIZE:
+      clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (object),
+                                             g_value_get_boolean (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -206,6 +217,10 @@ clutter_cairo_texture_get_property (GObject    *object,
       g_value_set_uint (value, priv->surface_height);
       break;
 
+    case PROP_AUTO_RESIZE:
+      g_value_set_boolean (value, priv->auto_resize);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -431,6 +446,32 @@ clutter_cairo_texture_get_preferred_height (ClutterActor *actor,
     *natural_height = (gfloat) priv->surface_height;
 }
 
+static void
+clutter_cairo_texture_allocate (ClutterActor           *self,
+                                const ClutterActorBox  *allocation,
+                                ClutterAllocationFlags  flags)
+{
+  ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (self)->priv;
+  ClutterActorClass *parent_class;
+
+  parent_class = CLUTTER_ACTOR_CLASS (clutter_cairo_texture_parent_class);
+  parent_class->allocate (self, allocation, flags);
+
+  if (priv->auto_resize)
+    {
+      ClutterCairoTexture *texture = CLUTTER_CAIRO_TEXTURE (self);
+      gfloat width, height;
+
+      clutter_actor_box_get_size (allocation, &width, &height);
+
+      priv->surface_width = ceilf (width + 0.5);
+      priv->surface_height = ceilf (height + 0.5);
+
+      clutter_cairo_texture_surface_resize_internal (texture);
+      clutter_cairo_texture_invalidate (texture);
+    }
+}
+
 static gboolean
 clutter_cairo_texture_get_paint_volume (ClutterActor       *self,
                                         ClutterPaintVolume *volume)
@@ -521,6 +562,8 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass)
     clutter_cairo_texture_get_preferred_width;
   actor_class->get_preferred_height =
     clutter_cairo_texture_get_preferred_height;
+  actor_class->allocate =
+    clutter_cairo_texture_allocate;
 
   klass->create_surface = clutter_cairo_texture_create_surface;
 
@@ -557,9 +600,24 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass)
                        0,
                        CLUTTER_PARAM_READWRITE);
 
-  g_object_class_install_properties (gobject_class,
-                                     PROP_LAST,
-                                     obj_props);
+  /**
+   * ClutterCairoTexture:auto-resize:
+   *
+   * Controls whether the #ClutterCairoTexture should automatically
+   * resize the Cairo surface whenever the actor's allocation changes.
+   * If :auto-resize is set to %TRUE the surface contents will also
+   * be invalidated automatically.
+   *
+   * Since: 1.8
+   */
+  obj_props[PROP_AUTO_RESIZE] =
+    g_param_spec_boolean ("auto-resize",
+                          P_("Auto Resize"),
+                          P_("Whether the surface should match the allocation"),
+                          FALSE,
+                          CLUTTER_PARAM_READWRITE);
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
 
   /**
    * ClutterCairoTexture::create-surface:
@@ -1058,3 +1116,57 @@ clutter_cairo_texture_clear (ClutterCairoTexture *self)
   if (priv->cr_context == NULL)
     cairo_destroy (cr);
 }
+
+/**
+ * clutter_cairo_texture_set_auto_resize:
+ * @self: a #ClutterCairoTexture
+ * @value: %TRUE if the #ClutterCairoTexture should bind the surface
+ *   size to the allocation
+ *
+ * Sets whether the #ClutterCairoTexture should ensure that the
+ * backing Cairo surface used matches the allocation assigned to
+ * the actor. If the allocation changes, the contents of the
+ * #ClutterCairoTexture will also be invalidated automatically.
+ *
+ * Since: 1.8
+ */
+void
+clutter_cairo_texture_set_auto_resize (ClutterCairoTexture *self,
+                                       gboolean             value)
+{
+  ClutterCairoTexturePrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self));
+
+  value = !!value;
+
+  priv = self->priv;
+
+  if (priv->auto_resize == value)
+    return;
+
+  priv->auto_resize = value;
+
+  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_AUTO_RESIZE]);
+}
+
+/**
+ * clutter_cairo_texture_get_auto_resize:
+ * @self: a #ClutterCairoTexture
+ *
+ * Retrieves the value set using clutter_cairo_texture_set_auto_resize().
+ *
+ * Return value: %TRUE if the #ClutterCairoTexture should track the
+ *   allocation, and %FALSE otherwise
+ *
+ * Since: 1.8
+ */
+gboolean
+clutter_cairo_texture_get_auto_resize (ClutterCairoTexture *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self), FALSE);
+
+  return self->priv->auto_resize;
+}
diff --git a/clutter/clutter-cairo-texture.h b/clutter/clutter-cairo-texture.h
index 4126a62..4b65f8c 100644
--- a/clutter/clutter-cairo-texture.h
+++ b/clutter/clutter-cairo-texture.h
@@ -131,6 +131,9 @@ void            clutter_cairo_texture_set_surface_size          (ClutterCairoTex
 void            clutter_cairo_texture_get_surface_size          (ClutterCairoTexture   *self,
                                                                  guint                 *width,
                                                                  guint                 *height);
+void            clutter_cairo_texture_set_auto_resize           (ClutterCairoTexture   *self,
+                                                                 gboolean               value);
+gboolean        clutter_cairo_texture_get_auto_resize           (ClutterCairoTexture   *self);
 
 void            clutter_cairo_texture_clear                     (ClutterCairoTexture   *self);
 
diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt
index 6d35cd1..21e4da2 100644
--- a/doc/reference/clutter/clutter-sections.txt
+++ b/doc/reference/clutter/clutter-sections.txt
@@ -1756,6 +1756,8 @@ ClutterCairoTextureClass
 clutter_cairo_texture_new
 clutter_cairo_texture_set_surface_size
 clutter_cairo_texture_get_surface_size
+clutter_cairo_texture_set_auto_resize
+clutter_cairo_texture_get_auto_resize
 
 <SUBSECTION>
 clutter_cairo_texture_create
diff --git a/tests/interactive/test-cairo-clock.c b/tests/interactive/test-cairo-clock.c
index b887723..f847e7a 100644
--- a/tests/interactive/test-cairo-clock.c
+++ b/tests/interactive/test-cairo-clock.c
@@ -78,10 +78,11 @@ test_cairo_clock_main (int argc, char *argv[])
   if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
     return EXIT_FAILURE;
 
-  /* create a fixed size stage */
+  /* create a resizable stage */
   stage = clutter_stage_new ();
   clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock");
   clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_LightSkyBlue);
+  clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
   clutter_actor_set_size (stage, 300, 300);
   clutter_actor_show (stage);
 
@@ -89,6 +90,12 @@ test_cairo_clock_main (int argc, char *argv[])
   canvas = clutter_cairo_texture_new (300, 300);
   clutter_container_add_actor (CLUTTER_CONTAINER (stage), canvas);
 
+  /* bind the size of the canvas to that of the stage */
+  clutter_actor_add_constraint (canvas, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0));
+
+  /* make sure to match allocation to canvas size */
+  clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (canvas), TRUE);
+
   /* quit on destroy */
   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]