ecore,efl: add Efl.Model.property_get helper which will suceed once when a property...
authorCedric BAIL <cedric@osg.samsung.com>
Thu, 22 Nov 2018 00:44:17 +0000 (16:44 -0800)
committerHermet Park <hermetpark@gmail.com>
Wed, 5 Dec 2018 05:37:06 +0000 (14:37 +0900)
Reviewed-by: Vitor Sousa da Silva <vitorsousa@expertisesolutions.com.br>
Differential Revision: https://phab.enlightenment.org/D7323

src/Makefile_Ecore.am
src/lib/ecore/Ecore_Eo.h
src/lib/ecore/efl_model_loop.c [new file with mode: 0644]
src/lib/ecore/efl_model_loop.eo [new file with mode: 0644]
src/lib/ecore/meson.build
src/lib/efl/interfaces/efl_model.eo

index 3f855a5..1a24712 100644 (file)
@@ -41,6 +41,7 @@ ecore_eolian_files_public = \
        lib/ecore/efl_bounce_interpolator.eo \
        lib/ecore/efl_spring_interpolator.eo \
        lib/ecore/efl_cubic_bezier_interpolator.eo \
+       lib/ecore/efl_model_loop.eo \
        lib/ecore/efl_model_item.eo \
        lib/ecore/efl_model_container.eo \
        lib/ecore/efl_model_container_item.eo \
@@ -117,6 +118,7 @@ lib/ecore/efl_io_stderr.c \
 lib/ecore/efl_io_file.c \
 lib/ecore/efl_io_copier.c \
 lib/ecore/efl_io_buffered_stream.c \
+lib/ecore/efl_model_loop.c \
 lib/ecore/efl_model_item.c \
 lib/ecore/efl_model_container.c \
 lib/ecore/efl_model_container_item.c \
index 3310ee7..d835713 100644 (file)
@@ -127,6 +127,7 @@ EAPI Eo *efl_app_get(void);
  * @{
  */
 
+#include "efl_model_loop.eo.h"
 #include "efl_model_item.eo.h"
 #include "efl_model_container.eo.h"
 #include "efl_model_container_item.eo.h"
diff --git a/src/lib/ecore/efl_model_loop.c b/src/lib/ecore/efl_model_loop.c
new file mode 100644 (file)
index 0000000..a64b3f8
--- /dev/null
@@ -0,0 +1,109 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Eina.h"
+#include "Efl.h"
+#include <Ecore.h>
+#include "Eo.h"
+
+#include "efl_model_loop.eo.h"
+
+typedef struct _Efl_Model_Loop_Watcher_Data Efl_Model_Loop_Watcher_Data;
+
+struct _Efl_Model_Loop_Watcher_Data
+{
+   const char *property;
+   Eina_Promise *p;
+   Eo *obj;
+};
+
+static void _propagate_future(void *data, const Efl_Event *event);
+
+static void
+_efl_model_loop_wathcer_free(Efl_Model_Loop_Watcher_Data *wd)
+{
+   efl_event_callback_del(wd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
+                          _propagate_future, wd);
+   eina_stringshare_del(wd->property);
+   free(wd);
+}
+
+static void
+_propagate_future(void *data, const Efl_Event *event)
+{
+   Efl_Model_Property_Event *ev = event->info;
+   const char *property;
+   unsigned int i;
+   Eina_Array_Iterator it;
+   Efl_Model_Loop_Watcher_Data *wd = data;
+
+   EINA_ARRAY_ITER_NEXT(ev->changed_properties, i, property, it)
+     if (property == wd->property || !strcmp(property, wd->property))
+       {
+          Eina_Value *v = efl_model_property_get(wd->obj, wd->property);
+
+          if (eina_value_type_get(v) == EINA_VALUE_TYPE_ERROR)
+            {
+               Eina_Error err = 0;
+
+               eina_value_get(v, &err);
+
+               if (err == EAGAIN)
+                 return ; // Not ready yet
+
+               eina_promise_reject(wd->p, err);
+            }
+          else
+            {
+               eina_promise_resolve(wd->p, eina_value_reference_copy(v));
+            }
+
+          eina_value_free(v);
+          _efl_model_loop_wathcer_free(wd);
+          break ;
+       }
+}
+
+static void
+_event_cancel(void *data, const Eina_Promise *dead_ptr)
+{
+   _efl_model_loop_wathcer_free(data);
+}
+
+static Eina_Future *
+_efl_model_loop_efl_model_property_ready_get(Eo *obj, void *pd EINA_UNUSED, const char *property)
+{
+   Eina_Value *value = efl_model_property_get(obj, property);
+   Eina_Future *f;
+
+   if (eina_value_type_get(value) == EINA_VALUE_TYPE_ERROR)
+     {
+        Eina_Error err = 0;
+
+        eina_value_get(value, &err);
+        eina_value_free(value);
+
+        if (err == EAGAIN)
+          {
+             Efl_Model_Loop_Watcher_Data *wd = calloc(1, sizeof (Efl_Model_Loop_Watcher_Data));
+
+             wd->obj = obj;
+             wd->property = eina_stringshare_add(property);
+             wd->p = eina_promise_new(efl_loop_future_scheduler_get(obj),
+                                      _event_cancel, wd);
+
+             efl_event_callback_add(obj,
+                                    EFL_MODEL_EVENT_PROPERTIES_CHANGED,
+                                    _propagate_future, wd);
+          }
+
+        return eina_future_rejected(efl_loop_future_scheduler_get(obj), err);
+     }
+   f = eina_future_resolved(efl_loop_future_scheduler_get(obj),
+                            eina_value_reference_copy(value));
+   eina_value_free(value);
+   return efl_future_Eina_FutureXXX_then(obj, f);
+}
+
+#include "efl_model_loop.eo.c"
diff --git a/src/lib/ecore/efl_model_loop.eo b/src/lib/ecore/efl_model_loop.eo
new file mode 100644 (file)
index 0000000..be4fe6a
--- /dev/null
@@ -0,0 +1,7 @@
+class Efl.Model_Loop (Efl.Loop_Consumer, Efl.Model)
+{
+   data: null;
+   implements {
+      Efl.Model.property_ready_get;
+   }
+}
\ No newline at end of file
index 60525ee..96ad59b 100644 (file)
@@ -67,6 +67,7 @@ pub_eo_files = [
   'efl_cubic_bezier_interpolator.eo',
   'efl_loop_message_future_handler.eo',
   'efl_loop_message_future.eo',
+  'efl_model_loop.eo',
   'efl_model_item.eo',
   'efl_model_container.eo',
   'efl_model_container_item.eo',
@@ -144,6 +145,7 @@ ecore_src = [
   'efl_io_file.c',
   'efl_io_copier.c',
   'efl_io_buffered_stream.c',
+  'efl_model_loop.c',
   'efl_model_item.c',
   'efl_model_container.c',
   'efl_model_container_item.c',
index ffe8bf4..ff06a32 100644 (file)
@@ -76,6 +76,23 @@ interface Efl.Model ()
               value: any_value_ptr; [[Property value]]
            }
         }
+       property_ready_get {
+           [[Get a future value when it change to something that is not error:EAGAIN
+
+             property_get can return an error with code EAGAIN when it doesn't have any
+             meaningful value. To make life easier, this future will resolve when
+             the error:EAGAIN disapear. Either into a failed future in case the error
+             code change to something else or a success with the value of property whenever
+             the property finally change.
+
+
+             The future can also be canceled if the model itself get destroyed.
+          ]]
+           params {
+              @in property: string;
+           }
+           return: future<any_value_ptr>;
+        }
         children_slice_get {
                [[Get children slice OR full range.