Add calculate callback to Evas_Smart_Class.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 7 Sep 2008 01:25:49 +0000 (01:25 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 7 Sep 2008 01:25:49 +0000 (01:25 +0000)
Some people is using it for some time now without problems, so I'm
adding it to SVN to get some broader use. Remember to recompile ALL
libraries that depend on Evas as it will change the
EVAS_SMART_CLASS_VERSION and old classes will fail to load.

This will also change Edje so it will postpone _edje_recalc() to
render time, calculate() callback, however some methods will force
early recalculation.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@35860 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Evas.h
src/lib/canvas/evas_main.c
src/lib/canvas/evas_object_smart.c
src/lib/canvas/evas_render.c
src/lib/include/evas_private.h

index 73156d6..e5c1e44 100644 (file)
@@ -137,7 +137,7 @@ typedef enum _Evas_Aspect_Control
 } Evas_Aspect_Control;
 
 
-#define EVAS_SMART_CLASS_VERSION 1 /** the version you have to put into the version field in the smart class struct */
+#define EVAS_SMART_CLASS_VERSION 2 /** the version you have to put into the version field in the smart class struct */
 struct _Evas_Smart_Class /** a smart object class */
 {
    const char *name; /** the string name of the class */
@@ -153,6 +153,7 @@ struct _Evas_Smart_Class /** a smart object class */
    void  (*color_set)   (Evas_Object *o, int r, int g, int b, int a); // FIXME: DELETE ME
    void  (*clip_set)    (Evas_Object *o, Evas_Object *clip); // FIXME: DELETE ME
    void  (*clip_unset)  (Evas_Object *o); // FIXME: DELETE ME
+   void  (*calculate)   (Evas_Object *o);
 
    const void *data;
 };
@@ -767,6 +768,11 @@ extern "C" {
    EAPI void              evas_object_smart_callback_add    (Evas_Object *obj, const char *event, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data);
    EAPI void             *evas_object_smart_callback_del    (Evas_Object *obj, const char *event, void (*func) (void *data, Evas_Object *obj, void *event_info));
    EAPI void              evas_object_smart_callback_call   (Evas_Object *obj, const char *event, void *event_info);
+   EAPI void              evas_object_smart_changed         (Evas_Object *obj);
+   EAPI void              evas_object_smart_need_recalculate_set(Evas_Object *obj, Evas_Bool value);
+   EAPI Evas_Bool         evas_object_smart_need_recalculate_get(Evas_Object *obj);
+   EAPI void               evas_object_smart_calculate      (Evas_Object *obj);
+
 
 /* events */
    EAPI void              evas_event_freeze                 (Evas *e);
index 27b3ce6..1a9b34c 100644 (file)
@@ -70,6 +70,7 @@ evas_new(void)
    evas_array_setup(&e->pending_objects, 16);
    evas_array_setup(&e->obscuring_objects, 16);
    evas_array_setup(&e->temporary_objects, 16);
+   evas_array_setup(&e->calculate_objects, 16);
 
    return e;
 }
index 811cb81..608a828 100644 (file)
@@ -13,6 +13,7 @@ struct _Evas_Object_Smart
    Evas_Object_List *contained;
    int               walking_list;
    Evas_Bool         deletions_waiting : 1;
+   Evas_Bool         need_recalculate : 1;
 };
 
 struct _Evas_Smart_Callback
@@ -436,6 +437,163 @@ evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event
    evas_object_smart_callbacks_clear(obj);
 }
 
+/**
+ * Set the need_recalculate flag of given smart object.
+ *
+ * If this flag is set then calculate() callback (method) of the given
+ * smart object will be called, if one is provided, during render phase
+ * usually evas_render(). After this step, this flag will be automatically
+ * unset.
+ *
+ * If no calculate() is provided, this flag will be left unchanged.
+ *
+ * @note just setting this flag will not make scene dirty and evas_render()
+ *       will have no effect. To do that, use evas_object_smart_changed(),
+ *       that will automatically call this function with 1 as parameter.
+ *
+ * @param obj the smart object
+ * @param value if one want to set or unset the need_recalculate flag.
+ *
+ * @ingroup Evas_Smart_Object_Group
+ */
+EAPI void
+evas_object_smart_need_recalculate_set(Evas_Object *obj, Evas_Bool value)
+{
+   Evas_Object_Smart *o;
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   o = obj->object_data;
+   MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
+   return;
+   MAGIC_CHECK_END();
+
+   value = !!value;
+   if (o->need_recalculate == value)
+     return;
+   o->need_recalculate = value;
+
+   if (!obj->smart.smart->smart_class->calculate)
+     return;
+
+   /* XXX: objects can be present multiple times in calculate_objects()
+    * XXX: after a set-unset-set cycle, but it's not a problem since
+    * XXX: on _evas_render_call_smart_calculate() will check for the flag
+    * XXX: and it will be unset after the first.
+    */
+   if (o->need_recalculate)
+     {
+       Evas *e;
+       e = obj->layer->evas;
+       _evas_array_append(&e->calculate_objects, obj);
+     }
+   /* TODO: else, remove from array */
+}
+
+/**
+ * Get the current value of need_recalculate flag.
+ *
+ * @note this flag will be unset during the render phase, after calculate()
+ *       is called if one is provided.  If no calculate() is provided, then
+ *       the flag will be left unchanged after render phase.
+ *
+ * @param obj the smart object
+ * @return if flag is set or not.
+ *
+ * @ingroup Evas_Smart_Object_Group
+ */
+EAPI Evas_Bool
+evas_object_smart_need_recalculate_get(Evas_Object *obj)
+{
+   Evas_Object_Smart *o;
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   o = obj->object_data;
+   MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
+   return;
+   MAGIC_CHECK_END();
+
+   return o->need_recalculate;
+}
+
+/**
+ * Call user provided calculate() and unset need_calculate.
+ *
+ * @param obj the smart object
+ * @return if flag is set or not.
+ *
+ * @ingroup Evas_Smart_Object_Group
+ */
+EAPI void
+evas_object_smart_calculate(Evas_Object *obj)
+{
+   Evas_Object_Smart *o;
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   o = obj->object_data;
+   MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
+   return;
+   MAGIC_CHECK_END();
+
+   if (obj->smart.smart->smart_class->calculate)
+     obj->smart.smart->smart_class->calculate(obj);
+   o->need_recalculate = 0;
+}
+
+/**
+ * Call calculate() on all smart objects that need_recalculate.
+ *
+ * @internal
+ */
+void
+evas_call_smarts_calculate(Evas *e)
+{
+   Evas_Array *calculate;
+   unsigned int i;
+
+   calculate = &e->calculate_objects;
+   for (i = 0; i < calculate->count; ++i)
+     {
+       Evas_Object *obj;
+       Evas_Object_Smart *o;
+
+       obj = _evas_array_get(calculate, i);
+       if (obj->delete_me)
+         continue;
+
+       o = obj->object_data;
+       if (o->need_recalculate)
+         {
+            obj->smart.smart->smart_class->calculate(obj);
+            o->need_recalculate = 0;
+         }
+     }
+
+   evas_array_flush(calculate);
+}
+
+/**
+ * Mark smart object as changed, dirty.
+ *
+ * This will inform the scene that it changed and needs to be redraw, also
+ * setting need_recalculate on the given object.
+ *
+ * @see evas_object_smart_need_recalculate_set().
+ *
+ * @ingroup Evas_Smart_Object_Group
+ */
+EAPI void
+evas_object_smart_changed(Evas_Object *obj)
+{
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   evas_object_change(obj);
+   evas_object_smart_need_recalculate_set(obj, 1);
+}
+
 /* internal calls */
 static void
 evas_object_smart_callbacks_clear(Evas_Object *obj)
index 8eb6a96..c36d438 100644 (file)
@@ -341,6 +341,8 @@ evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char
    MAGIC_CHECK_END();
    if (!e->changed) return NULL;
 
+   evas_call_smarts_calculate(e);
+
    /* Check if the modified object mean recalculating every thing */
    if (!e->invalidate)
      _evas_render_check_pending_objects(&e->pending_objects, e);
index d2d5671..2f6a790 100644 (file)
@@ -288,6 +288,7 @@ struct _Evas
    Evas_Array    pending_objects;
    Evas_Array     obscuring_objects;
    Evas_Array     temporary_objects;
+   Evas_Array     calculate_objects;
 
    int            delete_grabs;
    int            walking_grabs;
@@ -713,6 +714,7 @@ void evas_object_smart_member_lower(Evas_Object *member);
 void evas_object_smart_member_stack_above(Evas_Object *member, Evas_Object *other);
 void evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *other);
 const Evas_Object_List *evas_object_smart_members_get_direct(const Evas_Object *obj);
+void evas_call_smarts_calculate(Evas *e);
 void *evas_mem_calloc(int size);
 void evas_object_event_callback_all_del(Evas_Object *obj);
 void evas_object_event_callback_cleanup(Evas_Object *obj);