felipealmeida pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=df9f2e07722fa384cba09e934351e90f0d237009

commit df9f2e07722fa384cba09e934351e90f0d237009
Author: Felipe Magno de Almeida <fel...@expertisesolutions.com.br>
Date:   Thu Sep 7 12:06:17 2017 +0900

    ecore: Add efl_model_copmosite_selection model
---
 src/Makefile_Ecore.am                              |   4 +
 src/Makefile_Efl.am                                |   2 +-
 src/lib/ecore/Ecore_Eo.h                           |   2 +
 src/lib/ecore/efl_model_accessor_view.c            | 133 ++++++++++++
 src/lib/ecore/efl_model_accessor_view_private.h    |   5 +
 src/lib/ecore/efl_model_composite_boolean.c        |  81 ++++---
 src/lib/ecore/efl_model_composite_boolean.eo       |  15 +-
 src/lib/ecore/efl_model_composite_selection.c      | 237 +++++++++++++++++++++
 src/lib/ecore/efl_model_composite_selection.eo     |  21 ++
 .../efl_model_composite_selection_children.eo      |   7 +
 src/lib/ecore/efl_model_item.c                     |   2 +-
 ...posite_boolean.c => efl_test_model_composite.c} | 111 +++++++++-
 12 files changed, 577 insertions(+), 43 deletions(-)

diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 4158ae5185..755d4bb0f8 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -30,6 +30,8 @@ ecore_eolian_files = \
        lib/ecore/efl_model_container_item.eo \
        lib/ecore/efl_model_composite_boolean.eo \
        lib/ecore/efl_model_composite_boolean_children.eo \
+       lib/ecore/efl_model_composite_selection.eo \
+       lib/ecore/efl_model_composite_selection_children.eo \
        $(ecore_eolian_files_legacy)
 
 ecore_eolian_c = $(ecore_eolian_files:%.eo=%.eo.c)
@@ -90,6 +92,8 @@ lib/ecore/efl_model_container.c \
 lib/ecore/efl_model_container_item.c \
 lib/ecore/efl_model_container_private.h \
 lib/ecore/efl_model_composite_boolean.c \
+lib/ecore/efl_model_composite_selection.c \
+lib/ecore/efl_model_accessor_view.c \
 lib/ecore/ecore_pipe.c \
 lib/ecore/ecore_poller.c \
 lib/ecore/ecore_time.c \
diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am
index 58601aabdd..25dde93a7c 100644
--- a/src/Makefile_Efl.am
+++ b/src/Makefile_Efl.am
@@ -193,7 +193,7 @@ TESTS += tests/efl/efl_suite
 tests_efl_efl_suite_SOURCES = \
 tests/efl/efl_suite.c \
 tests/efl/efl_test_model_container.c \
-tests/efl/efl_test_model_composite_boolean.c \
+tests/efl/efl_test_model_composite.c \
 tests/efl/efl_suite.h
 
 tests_efl_efl_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h
index 502f6419ec..aadd2ba136 100644
--- a/src/lib/ecore/Ecore_Eo.h
+++ b/src/lib/ecore/Ecore_Eo.h
@@ -115,6 +115,8 @@ EAPI Efl_Future *efl_future_iterator_race(Eina_Iterator 
*it);
 #include "efl_model_container_item.eo.h"
 #include "efl_model_composite_boolean.eo.h"
 #include "efl_model_composite_boolean_children.eo.h"
+#include "efl_model_composite_selection.eo.h"
+#include "efl_model_composite_selection_children.eo.h"
 
 /**
  * @}
diff --git a/src/lib/ecore/efl_model_accessor_view.c 
b/src/lib/ecore/efl_model_accessor_view.c
new file mode 100644
index 0000000000..2afe1dc8f3
--- /dev/null
+++ b/src/lib/ecore/efl_model_accessor_view.c
@@ -0,0 +1,133 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Eina.h"
+#include "Eo.h"
+
+#include "efl_model_accessor_view_private.h"
+
+typedef struct _Efl_Model_Accessor
+{
+   Eina_Accessor                          vtable;
+   Eina_Accessor                          *real_accessor;
+   void                                   *pdata;
+   Efl_Model_Accessor_View_Constructor_Cb cb;
+   Eina_Array                             *children;
+} Efl_Model_Accessor;
+
+static void
+_efl_model_accessor_setup(Efl_Model_Accessor *acc,
+                          Eina_Accessor* real_accessor,
+                          Efl_Model_Accessor_View_Constructor_Cb ctor,
+                          void* pdata);
+
+static Eina_Bool
+_efl_model_acessor_get_at(Efl_Model_Accessor *acc, unsigned int idx, void 
**data)
+{
+  void* eo;
+  Eo *p;
+  Eo *child;
+
+  if(eina_accessor_data_get(acc->real_accessor, idx, &eo))
+    {
+      p = eo;
+      child = acc->cb(acc->pdata, p);
+      if(!acc->children)
+        {
+           acc->children = eina_array_new(32);
+        }
+      eina_array_push(acc->children, child);
+      *data = child;
+      return !!*data;
+    }
+  else
+    return EINA_FALSE;
+}
+
+static void *
+_efl_model_acessor_get_container(Efl_Model_Accessor *acc)
+{
+   return eina_accessor_container_get(acc->real_accessor);
+}
+
+static void
+_efl_model_acessor_free(Efl_Model_Accessor *acc)
+{
+   if (acc->real_accessor)
+     {
+        eina_accessor_free(acc->real_accessor);
+        acc->real_accessor = NULL;
+     }
+
+   if(acc->children)
+     {
+        unsigned i;
+        Eina_Array_Iterator iterator;
+        Eo* item;
+       
+        EINA_ARRAY_ITER_NEXT(acc->children, i, item, iterator)
+          {
+            efl_del(item);
+          }
+        eina_array_free(acc->children);
+        acc->children = NULL;
+     }
+
+   free(acc);
+}
+
+static Eina_Bool
+_efl_model_acessor_lock(Efl_Model_Accessor *acc)
+{
+   return eina_accessor_lock(acc->real_accessor);
+}
+
+static Eina_Bool
+_efl_model_acessor_unlock(Efl_Model_Accessor *acc)
+{
+   return eina_accessor_unlock(acc->real_accessor);
+}
+
+static Efl_Model_Accessor *
+_efl_model_acessor_clone(Efl_Model_Accessor *acc EINA_UNUSED)
+{
+   Efl_Model_Accessor* accessor = calloc(1, sizeof(Efl_Model_Accessor));
+   _efl_model_accessor_setup(accessor, eina_accessor_clone(acc->real_accessor),
+                             acc->cb, acc->pdata);
+   return accessor;
+}
+
+static void
+_efl_model_accessor_setup(Efl_Model_Accessor *acc,
+                                Eina_Accessor* real_accessor,
+                                Efl_Model_Accessor_View_Constructor_Cb ctor,
+                                void* pdata)
+{
+   acc->vtable.version = EINA_ACCESSOR_VERSION;
+   acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_model_acessor_get_at);
+   acc->vtable.get_container = 
FUNC_ACCESSOR_GET_CONTAINER(_efl_model_acessor_get_container);
+   acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_model_acessor_free);
+
+   acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_model_acessor_lock);
+   acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_model_acessor_unlock);
+
+   acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_model_acessor_clone);
+
+   EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR);
+
+   acc->real_accessor = real_accessor;
+   acc->cb = ctor;
+   acc->pdata = pdata;
+}
+
+Eina_Accessor* efl_model_accessor_view_new(Eina_Accessor* accessor,
+                                           
Efl_Model_Accessor_View_Constructor_Cb ctor,
+                                           void* data)
+{
+   Efl_Model_Accessor* acc = calloc(1, sizeof(Efl_Model_Accessor));
+   _efl_model_accessor_setup(acc, accessor, ctor, data);
+   return &acc->vtable;
+}
+
+
diff --git a/src/lib/ecore/efl_model_accessor_view_private.h 
b/src/lib/ecore/efl_model_accessor_view_private.h
new file mode 100644
index 0000000000..c44f2ec3cb
--- /dev/null
+++ b/src/lib/ecore/efl_model_accessor_view_private.h
@@ -0,0 +1,5 @@
+
+typedef Eo*(*Efl_Model_Accessor_View_Constructor_Cb)(void* data, Eo* child);
+
+Eina_Accessor* efl_model_accessor_view_new(Eina_Accessor* accessor,
+                                           
Efl_Model_Accessor_View_Constructor_Cb constructor, void* data);
diff --git a/src/lib/ecore/efl_model_composite_boolean.c 
b/src/lib/ecore/efl_model_composite_boolean.c
index 7ec344d05c..62107bbffc 100644
--- a/src/lib/ecore/efl_model_composite_boolean.c
+++ b/src/lib/ecore/efl_model_composite_boolean.c
@@ -18,7 +18,6 @@ typedef struct _Efl_Model_Hash_Value
 typedef struct _Efl_Model_Composite_Boolean_Data
 {
    Efl_Model  *composite_model;
-   Eina_Array *bool_children_cache;
    Eina_Array *empty_properties;
    Eina_Hash  *values; // [property_name, Efl_Model_Hash_Value*]
 } Efl_Model_Composite_Boolean_Data;
@@ -39,8 +38,14 @@ typedef struct _Efl_Model_Accessor_Slice
    Efl_Model_Composite_Boolean_Data *parent_pd;
    Efl_Promise                      *promise;
    unsigned int                      index;
+   Eina_Array *bool_children_cache;
 } Efl_Model_Accessor_Slice;
 
+static void
+efl_model_accessor_slice_setup(Efl_Model_Accessor_Slice *acc,
+  Efl_Model *parent, Efl_Model_Composite_Boolean_Data *parent_pd, Efl_Promise 
*promise, int start);
+
+
 static Eina_Value *
 _value_clone(const Eina_Value *value)
 {
@@ -66,7 +71,8 @@ _future_error_forward_cb(void *data, Efl_Event const *event)
 static Eina_Bool
 _bit_get(const unsigned char *bitstream, unsigned int idx)
 {
-   return (bitstream[idx / 8] >> (idx % 8)) & 1u;
+   Eina_Bool b = (bitstream[idx / 8] >> (idx % 8)) & 1u;
+   return b;
 }
 
 static void
@@ -160,8 +166,8 @@ 
_efl_model_composite_boolean_children_efl_model_property_get(Eo *obj EINA_UNUSED
         Eina_Value *eina_value = eina_value_new(EINA_VALUE_TYPE_UCHAR);
         if (hv->bits_count <= pd->index)
           {
-            unsigned char f = hv->default_value;
-            eina_value_set(eina_value, f);
+             unsigned char f = hv->default_value;
+             eina_value_set(eina_value, f);
           }
         else
           {
@@ -194,7 +200,7 @@ 
_efl_model_composite_boolean_children_efl_model_property_set(Eo *obj EINA_UNUSED
      {
         Eina_Bool flag = EINA_FALSE;
 
-        if (eina_value_type_get(value) == EINA_VALUE_TYPE_UCHAR)
+        if (eina_value_type_get(value) != EINA_VALUE_TYPE_UCHAR)
           {
              efl_promise_failed_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE);
              return rfuture;
@@ -285,7 +291,7 @@ static Eina_Bool
 efl_model_acessor_slice_get_at(Efl_Model_Accessor_Slice *acc, unsigned int 
idx, void **data)
 {
    Efl_Model *child_bool;
-   Eina_Array *children_cache = acc->parent_pd->bool_children_cache;
+   Eina_Array *children_cache = acc->bool_children_cache;
 
    /* NOTE: Efl.Model.Composite.Boolean must alloc the cache with the correct 
size
       and NULL initialized. */
@@ -295,7 +301,7 @@ efl_model_acessor_slice_get_at(Efl_Model_Accessor_Slice 
*acc, unsigned int idx,
         return EINA_FALSE;
      }
 
-   child_bool = eina_array_data_get(children_cache, idx);
+   child_bool = eina_array_data_get(children_cache, acc->index + idx);
 
    if (!child_bool)
      {
@@ -306,13 +312,13 @@ efl_model_acessor_slice_get_at(Efl_Model_Accessor_Slice 
*acc, unsigned int idx,
 
         if (child)
           {
-             Efl_Model_Composite_Boolean_Children_Data *pd;
+             Efl_Model_Composite_Boolean_Children_Data *cpd;
              child_bool = efl_add(EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS, 
NULL);
-             pd = efl_data_scope_get(child_bool, 
EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS);
+             cpd = efl_data_scope_get(child_bool, 
EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS);
 
-             pd->parent_pd = acc->parent_pd;
-             pd->composite_child = efl_ref(child);
-             pd->index = acc->index++;
+             cpd->parent_pd = acc->parent_pd;
+             cpd->composite_child = efl_ref(child);
+             cpd->index = acc->index + idx;
 
              eina_array_data_set(children_cache, idx, child_bool);
           }
@@ -331,9 +337,15 @@ 
efl_model_acessor_slice_get_container(Efl_Model_Accessor_Slice *acc)
 static void
 efl_model_acessor_slice_free(Efl_Model_Accessor_Slice *acc)
 {
-   if (acc->real_accessor)
+    if (acc->bool_children_cache)
+     {
+        _bool_children_cache_array_free(acc->bool_children_cache);
+        acc->bool_children_cache = NULL;
+     }
+
+    if (acc->real_accessor)
      {
-        eina_accessor_free(acc->real_accessor);
+        /* eina_accessor_free(acc->real_accessor); */
         acc->real_accessor = NULL;
      }
 
@@ -364,12 +376,31 @@ efl_model_acessor_slice_unlock(Efl_Model_Accessor_Slice 
*acc)
 static Efl_Model_Accessor_Slice *
 efl_model_acessor_slice_clone(Efl_Model_Accessor_Slice *acc EINA_UNUSED)
 {
-   return NULL;
+   Efl_Model_Accessor_Slice* new_accessor = calloc(1, 
sizeof(Efl_Model_Accessor_Slice));
+   Eina_Array* children_cache;
+   unsigned i;
+   unsigned children_count = eina_array_count(acc->bool_children_cache);
+   
+   efl_model_accessor_slice_setup(new_accessor, acc->parent, acc->parent_pd, 
NULL
+                                  , acc->index);
+   new_accessor->real_accessor = eina_accessor_clone(acc->real_accessor);
+
+   children_cache = eina_array_new(children_count);
+   for (i = 0 ; i < children_count; ++i)
+     {
+        // NOTE: eina_array_push do not accept NULL
+        eina_array_push(children_cache, (void*)0x01);
+        eina_array_data_set(children_cache, i, NULL);
+     }
+
+   new_accessor->bool_children_cache = children_cache;
+   
+   return new_accessor;
 }
 
 static void
 efl_model_accessor_slice_setup(Efl_Model_Accessor_Slice *acc,
-   Efl_Model *parent, Efl_Model_Composite_Boolean_Data *parent_pd, Efl_Promise 
*promise)
+  Efl_Model *parent, Efl_Model_Composite_Boolean_Data *parent_pd, Efl_Promise 
*promise, int start)
 {
    acc->vtable.version = EINA_ACCESSOR_VERSION;
    acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(efl_model_acessor_slice_get_at);
@@ -386,6 +417,7 @@ efl_model_accessor_slice_setup(Efl_Model_Accessor_Slice 
*acc,
    acc->parent = efl_ref(parent);
    acc->parent_pd = parent_pd;
    acc->promise = promise;
+   acc->index = start;
 }
 
 static void
@@ -413,8 +445,8 @@ _efl_model_composite_boolean_slice_then_cb(void *data, 
Efl_Event const *event)
         Eina_Array *children_cache;
         unsigned int i;
 
-        if (slice_acc->parent_pd->bool_children_cache)
-          
_bool_children_cache_array_free(slice_acc->parent_pd->bool_children_cache);
+        if (slice_acc->bool_children_cache)
+          _bool_children_cache_array_free(slice_acc->bool_children_cache);
 
         children_cache = eina_array_new(*children_count);
         for (i = 0 ; i < *children_count; ++i)
@@ -424,7 +456,7 @@ _efl_model_composite_boolean_slice_then_cb(void *data, 
Efl_Event const *event)
              eina_array_data_set(children_cache, i, NULL);
           }
 
-        slice_acc->parent_pd->bool_children_cache = children_cache;
+        slice_acc->bool_children_cache = children_cache;
 
         efl_promise_value_set(slice_acc->promise, slice_acc, 
(Eina_Free_Cb)&eina_accessor_free);
      }
@@ -460,11 +492,6 @@ efl_model_hash_value_free(void *p)
 static void
 _composite_model_data_reset(Efl_Model_Composite_Boolean_Data *pd)
 {
-   if (pd->bool_children_cache)
-     {
-        _bool_children_cache_array_free(pd->bool_children_cache);
-        pd->bool_children_cache = NULL;
-     }
 
    if (pd->composite_model)
      {
@@ -494,7 +521,7 @@ _efl_model_composite_boolean_efl_object_destructor(Eo *obj, 
Efl_Model_Composite_
 }
 
 static void
-_efl_model_composite_boolean_composite_model_set(Eo *obj EINA_UNUSED,
+_efl_model_composite_boolean_efl_ui_view_model_set(Eo *obj EINA_UNUSED,
   Efl_Model_Composite_Boolean_Data *pd, Efl_Model *model)
 {
    if (pd->composite_model)
@@ -506,7 +533,7 @@ _efl_model_composite_boolean_composite_model_set(Eo *obj 
EINA_UNUSED,
 }
 
 static Efl_Model *
-_efl_model_composite_boolean_composite_model_get(Eo *obj EINA_UNUSED, 
Efl_Model_Composite_Boolean_Data *pd)
+_efl_model_composite_boolean_efl_ui_view_model_get(Eo *obj EINA_UNUSED, 
Efl_Model_Composite_Boolean_Data *pd)
 {
    return pd->composite_model;
 }
@@ -586,7 +613,7 @@ 
_efl_model_composite_boolean_efl_model_children_slice_get(Eo *obj, Efl_Model_Com
         composite_future = efl_future_all(futures[0], futures[1]);
 
         accessor = calloc(1, sizeof(Efl_Model_Accessor_Slice));
-        efl_model_accessor_slice_setup(accessor, obj, pd, promise);
+        efl_model_accessor_slice_setup(accessor, obj, pd, promise, start);
 
         efl_future_then(composite_future, 
&_efl_model_composite_boolean_slice_then_cb,
                           &_efl_model_composite_boolean_slice_error_cb, NULL, 
accessor);
diff --git a/src/lib/ecore/efl_model_composite_boolean.eo 
b/src/lib/ecore/efl_model_composite_boolean.eo
index cdca17e998..bb7eacbb11 100644
--- a/src/lib/ecore/efl_model_composite_boolean.eo
+++ b/src/lib/ecore/efl_model_composite_boolean.eo
@@ -1,17 +1,7 @@
-class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model)
+class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model, Efl.Ui.View)
 {
    [[Efl model composite boolean class]]
    methods {
-      @property composite_model {
-         [[Composite model]]
-         set {
-         }
-         get {
-         }
-         values {
-           model: Efl.Model; [[Efl model]]
-         }
-      }
       property_add {
          [[Adds property]]
          params {
@@ -29,9 +19,10 @@ class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model)
       Efl.Model.children_count_get;
       Efl.Model.child_add;
       Efl.Model.child_del;
+      Efl.Ui.View.model { set; get; }
    }
    constructors {
-      .composite_model;
+      Efl.Ui.View.model;
       .property_add @optional;
    }
 }
diff --git a/src/lib/ecore/efl_model_composite_selection.c 
b/src/lib/ecore/efl_model_composite_selection.c
new file mode 100644
index 0000000000..8311f1c7b5
--- /dev/null
+++ b/src/lib/ecore/efl_model_composite_selection.c
@@ -0,0 +1,237 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Eina.h"
+#include "Efl.h"
+#include <Ecore.h>
+#include "Eo.h"
+
+#include "efl_model_composite_selection.eo.h"
+#include "efl_model_accessor_view_private.h"
+
+typedef struct _Efl_Model_Composite_Selection_Data
+{
+   Efl_Model_Composite_Selection* obj;
+   struct {
+      Efl_Model* selected_child;
+   } exclusive_data;
+   Eina_Bool is_exclusive;
+  
+} Efl_Model_Composite_Selection_Data;
+
+typedef struct _Efl_Model_Composite_Selection_Children_Data
+{
+   Efl_Model_Composite_Selection_Data* pd;
+} Efl_Model_Composite_Selection_Children_Data;
+
+static Eo*
+_efl_model_composite_selection_efl_object_constructor(Eo *obj,
+  Efl_Model_Composite_Selection_Data *pd EINA_UNUSED)
+{
+   efl_constructor(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS));
+   efl_model_composite_boolean_property_add(obj, "selected", EINA_FALSE);
+   pd->obj = obj;
+   return obj;
+}
+
+/***************************/
+static void _select_property_failed(void* data, Efl_Event const* event)
+{
+   Efl_Promise* promise = data;
+   Efl_Future_Event_Failure* fail = event->info;
+   efl_promise_failed_set(promise, fail->error);
+   efl_unref(promise);
+}
+
+static void _select_property_then(void* data, Efl_Event const* event 
EINA_UNUSED)
+{
+   Efl_Promise* promise = data;
+   Eina_Value* v = eina_value_new(EINA_VALUE_TYPE_UCHAR);
+   eina_value_set(v, EINA_TRUE);
+   efl_promise_value_set(promise, v, (Eina_Free_Cb)&eina_value_free);
+   efl_unref(promise);
+}
+
+static void _select_slice_then(void* data EINA_UNUSED, Efl_Event const* event)
+{
+   Efl_Future_Event_Success* success = event->info;
+   Eina_Accessor* accessor = eina_accessor_clone(success->value);
+   Eina_Value value;
+   Efl_Model* child;
+
+   eina_accessor_data_get(accessor, 0, (void**)&child);
+    
+   eina_value_setup(&value, EINA_VALUE_TYPE_UCHAR);
+   eina_value_set(&value, EINA_TRUE);
+  
+   efl_future_then(efl_model_property_set(child, "selected", &value),
+                   _select_property_then, _select_property_failed, NULL, 
efl_ref(success->next));
+}
+
+static void _select_error(void* data EINA_UNUSED, Efl_Event const* event)
+{
+   Efl_Future_Event_Failure* fail = event->info;
+   efl_promise_failed_set(fail->next, fail->error);
+}
+
+/***************************/
+
+static Efl_Future*
+_efl_model_composite_selection_select(Eo *obj,
+                                      Efl_Model_Composite_Selection_Data *pd, 
int idx)
+{
+   return efl_future_then(efl_model_children_slice_get(obj, idx, 1),
+                          &_select_slice_then,
+                          &_select_error,
+                          NULL, pd);
+}
+
+static void
+_efl_model_composite_selection_exclusive_selection_set(Eo *obj EINA_UNUSED,
+  Efl_Model_Composite_Selection_Data *pd, Eina_Bool exclusive)
+{
+   pd->is_exclusive = exclusive;
+}
+
+static Eina_Bool
+_efl_model_composite_selection_exclusive_selection_get(Eo *obj EINA_UNUSED,
+  Efl_Model_Composite_Selection_Data *pd)
+{
+  return pd->is_exclusive;
+}
+
+static void
+_exclusive_future_link_then_cb(void* data, Efl_Event const* event)
+{
+   Efl_Future_Event_Success *success = event->info;
+   efl_promise_value_set(data, success->value, NULL); // We would need to move 
the value
+                                                      // Needs to set 
exclusive_child
+   efl_unref(data);
+}
+
+static void
+_exclusive_future_link_failed(void* data, Efl_Event const* event)
+{
+   Efl_Future_Event_Failure *failed = event->info;
+   efl_promise_failed_set(data, failed->error);
+   efl_unref(data);
+}
+
+static void
+_exclusive_unselected_then_cb(void* data, Efl_Event const* event)
+{
+   Efl_Future_Event_Success *success = event->info;
+   Eina_Value* true_value = eina_value_new(EINA_VALUE_TYPE_UCHAR);
+   eina_value_set(true_value, EINA_TRUE);
+   efl_future_then(efl_model_property_set(data, "selected", true_value),
+                   _exclusive_future_link_then_cb, 
_exclusive_future_link_failed,
+                   NULL, efl_ref(success->next));
+   efl_unref(data);
+}
+
+static void
+_exclusive_unselected_failed(void* data, Efl_Event const* event)
+{
+   Efl_Future_Event_Failure *failed = event->info;
+   efl_promise_failed_set(data, failed->error);
+   efl_unref(data);
+}
+
+static Efl_Future *
+_efl_model_composite_selection_children_efl_model_property_set(Eo *obj 
EINA_UNUSED,
+  Efl_Model_Composite_Selection_Children_Data *pd, const char *property, const 
Eina_Value *value)
+{
+   if(!strcmp("selected", property))
+     {
+        unsigned long v = EINA_FALSE;
+        if(eina_value_type_get(value) != EINA_VALUE_TYPE_ULONG)
+          {
+            Eina_Value to;
+            eina_value_setup(&to, EINA_VALUE_TYPE_ULONG);
+            if(eina_value_convert(value, &to))
+              eina_value_get(&to, &v);
+            eina_value_flush(&to);
+          }
+        else
+          eina_value_get(value, &v);
+
+        if(v && pd->pd->is_exclusive)
+          {
+             if(pd->pd->exclusive_data.selected_child)
+               {
+                  // unset current selected
+                  // set this child as current
+                  // bookkeep this child as current selection
+                  // return with future for this asynchronous task
+                  Eina_Value* false_value = 
eina_value_new(EINA_VALUE_TYPE_UCHAR);
+                  eina_value_set(false_value, EINA_FALSE);
+                  return
+                    efl_future_then(efl_model_property_set
+                                    (pd->pd->exclusive_data.selected_child,
+                                     property, false_value),
+                                    _exclusive_unselected_then_cb,
+                                    _exclusive_unselected_failed, NULL,
+                                    efl_ref(obj));
+               }
+             else
+               {
+                  Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, 
ecore_main_loop_get());
+                  Efl_Future *rfuture = efl_promise_future_get(promise);
+                  Eina_Value* true_value = 
eina_value_new(EINA_VALUE_TYPE_UCHAR);
+                  eina_value_set(true_value, EINA_TRUE);
+                  efl_future_then(efl_model_property_set
+                                  (efl_super(obj, 
EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS),
+                                   "selected", true_value),
+                                  _exclusive_future_link_then_cb, 
_exclusive_future_link_failed,
+                                  NULL, efl_ref(promise));
+                  return rfuture;
+               }             
+          }
+        else
+          {
+            
+          }
+     }
+
+   return efl_model_property_set(efl_super(obj, 
EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS),
+                                 property, value);
+}
+
+static Eo* _construct_children(void* pdata, Eo* child)
+{
+  Efl_Model_Composite_Selection_Data* pd = pdata;
+  Eo* new_child = efl_add(EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS, NULL);
+  Efl_Model_Composite_Selection_Children_Data* data = efl_data_scope_get
+    (new_child, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS);
+  data->pd = pd;
+  efl_composite_attach(new_child, efl_ref(child));
+  return new_child;
+}
+
+static void _composited_children_slice_get_then(void* data, Efl_Event const* 
event)
+{
+  Efl_Future_Event_Success* success = event->info;
+  Eina_Accessor* accessor = success->value;
+  efl_promise_value_set(success->next,
+                        
efl_model_accessor_view_new(eina_accessor_clone(accessor), &_construct_children,
+                                                    data),
+                        (Eina_Free_Cb)&eina_accessor_free);
+}
+static void _composited_children_slice_get_fail(void* data EINA_UNUSED, 
Efl_Event const* event)
+{
+  Efl_Future_Event_Failure* failure = event->info;
+  efl_promise_failed_set(failure->next, failure->error);
+}
+
+static Efl_Future *
+_efl_model_composite_selection_efl_model_children_slice_get(Eo *obj, 
Efl_Model_Composite_Selection_Data *pd, unsigned int start, unsigned int count)
+{
+   Efl_Future* composited_future = efl_model_children_slice_get
+     (efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS),start, count);
+   return efl_future_then(composited_future, 
&_composited_children_slice_get_then,
+                          &_composited_children_slice_get_fail, NULL, pd);
+}
+
+#include "efl_model_composite_selection.eo.c"
+#include "efl_model_composite_selection_children.eo.c"
diff --git a/src/lib/ecore/efl_model_composite_selection.eo 
b/src/lib/ecore/efl_model_composite_selection.eo
new file mode 100644
index 0000000000..bccf0070ad
--- /dev/null
+++ b/src/lib/ecore/efl_model_composite_selection.eo
@@ -0,0 +1,21 @@
+class Efl.Model.Composite.Selection (Efl.Model.Composite.Boolean)
+{
+   [[Efl model composite selection class]]
+   methods {
+      select {
+         params {
+           idx: int;
+         }
+         return: future<eina.value>;
+      }
+      @property exclusive_selection {
+         values {
+           exclusive: bool;
+         }
+      }
+   }
+   implements {
+      Efl.Object.constructor;
+      Efl.Model.children_slice_get;
+   }
+}
diff --git a/src/lib/ecore/efl_model_composite_selection_children.eo 
b/src/lib/ecore/efl_model_composite_selection_children.eo
new file mode 100644
index 0000000000..2ea5c950ef
--- /dev/null
+++ b/src/lib/ecore/efl_model_composite_selection_children.eo
@@ -0,0 +1,7 @@
+class Efl.Model.Composite.Selection.Children (Efl.Object, Efl.Model)
+{
+   [[Efl model composite selection children class]]
+   implements {
+      Efl.Model.property_set;
+   }
+}
diff --git a/src/lib/ecore/efl_model_item.c b/src/lib/ecore/efl_model_item.c
index 5f61ee79e9..8afc0a77a4 100644
--- a/src/lib/ecore/efl_model_item.c
+++ b/src/lib/ecore/efl_model_item.c
@@ -169,9 +169,9 @@ _efl_model_item_efl_model_child_add(Eo *obj, 
Efl_Model_Item_Data *sd)
         eina_error_set(EFL_MODEL_ERROR_UNKNOWN);
         return NULL;
      }
+   cevt.index = eina_list_count(sd->children);
    sd->children = eina_list_append(sd->children, child);
    cevt.child = child;
-   cevt.index = eina_list_count(sd->children);
    efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
    efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, 
&cevt.index);
    return child;
diff --git a/src/tests/efl/efl_test_model_composite_boolean.c 
b/src/tests/efl/efl_test_model_composite.c
similarity index 56%
rename from src/tests/efl/efl_test_model_composite_boolean.c
rename to src/tests/efl/efl_test_model_composite.c
index 2b94fa7aa0..a38e776746 100644
--- a/src/tests/efl/efl_test_model_composite_boolean.c
+++ b/src/tests/efl/efl_test_model_composite.c
@@ -39,6 +39,7 @@ typedef struct _Test_Child_Data
 
 const int child_number = 3;
 const int base_ints[] = { 41, 42, 43 };
+const Eina_Bool base_selections[] = { EINA_FALSE, EINA_FALSE, EINA_TRUE };
 
 static void
 _future_error_then(void *data EINA_UNUSED, Efl_Event const* event EINA_UNUSED)
@@ -79,6 +80,45 @@ _property_get_then(void *data, Efl_Event const *event)
 }
 
 static void
+_selection_property_get_then(void *data, Efl_Event const *event)
+{
+   Test_Child_Data *t = data;
+   Eina_Accessor *value_itt = 
(Eina_Accessor*)((Efl_Future_Event_Success*)event->info)->value;
+   int v_int = 0;
+   Eina_Bool v_bool = EINA_FALSE;
+
+
+#define EFL_TEST_value_get_and_compare(it, i, var, cmp)  \
+   do { \
+      Eina_Value *vvv = NULL; \
+      if (!eina_accessor_data_get(it, i, (void **)&vvv) || !vvv || \
+          !eina_value_get(vvv, &var)) \
+        { \
+           fprintf(stderr, "Could not get value!\n"); fflush(stderr); \
+           ck_abort_msg("Could not get value"); \
+           return; \
+        } \
+      else if(var != cmp)                       \
+        { \
+           fprintf(stderr, "Value did not match!\n"); fflush(stderr); \
+           ck_abort_msg("Value did not match"); \
+           return;                              \
+        }               \
+      else              \
+        fprintf(stderr, "Value matched\n"); fflush(stderr);    \
+   } while(0)
+
+   EFL_TEST_value_get_and_compare(value_itt, 0, v_bool, 
base_selections[t->idx]);
+   EFL_TEST_value_get_and_compare(value_itt, 1, v_int, base_ints[t->idx]);
+
+   t->tdata->child_count++;
+   if (t->tdata->child_count == 3)
+     t->tdata->success_flag = EINA_TRUE;
+
+#undef EFL_TEST_value_get_and_compare
+}
+
+static void
 _children_slice_get_then(void *data, Efl_Event const* event)
 {
    Eina_Accessor *children = (Eina_Accessor 
*)((Efl_Future_Event_Success*)event->info)->value;
@@ -86,7 +126,6 @@ _children_slice_get_then(void *data, Efl_Event const* event)
    Test_Child_Data *t;
    unsigned int i = 0;
 
-   fprintf(stderr, "OPAAAAAAa\n");
    EINA_ACCESSOR_FOREACH(children, i, child)
      {
         Efl_Future *futures[3] = {NULL,};
@@ -105,6 +144,31 @@ _children_slice_get_then(void *data, Efl_Event const* 
event)
      }
 }
 
+static void
+_selection_children_slice_get_then(void *data, Efl_Event const* event)
+{
+   Eina_Accessor *children = (Eina_Accessor 
*)((Efl_Future_Event_Success*)event->info)->value;
+   Efl_Model *child;
+   Test_Child_Data *t;
+   unsigned int i = 0;
+
+   EINA_ACCESSOR_FOREACH(children, i, child)
+     {
+        Efl_Future *futures[2] = {NULL,};
+        Efl_Future *future_all = NULL;
+
+        futures[0] = efl_model_property_get(child, "selected");
+        futures[1] = efl_model_property_get(child, "test_p_int");
+
+        future_all = efl_future_all(futures[0], futures[1]);
+
+        t = calloc(1, sizeof(Test_Child_Data));
+        t->tdata = data;
+        t->idx = i;
+        efl_future_then(future_all, _selection_property_get_then, 
_future_error_then, NULL, t);
+     }
+}
+
 START_TEST(efl_test_model_composite_boolean)
 {
    Efl_Model_Item *base_model, *child;
@@ -131,7 +195,7 @@ START_TEST(efl_test_model_composite_boolean)
      }
 
    model = efl_add(EFL_MODEL_COMPOSITE_BOOLEAN_CLASS, NULL,
-                  efl_model_composite_boolean_composite_model_set(efl_added, 
base_model),
+                  efl_ui_view_model_set(efl_added, base_model),
                   efl_model_composite_boolean_property_add(efl_added, 
"test_p_true", EINA_TRUE),
                   efl_model_composite_boolean_property_add(efl_added, 
"test_p_false", EINA_FALSE));
    ck_assert(!!model);
@@ -148,8 +212,51 @@ START_TEST(efl_test_model_composite_boolean)
 }
 END_TEST
 
+START_TEST(efl_test_model_composite_selection)
+{
+   Efl_Model_Item *base_model, *child;
+   int i;
+   Eina_Value v;
+   Efl_Model_Composite_Selection *model;
+   Test_Data *tdata;
+   Efl_Future *future;
+
+   fail_if(!ecore_init(), "ERROR: Cannot init Ecore!\n");
+   fail_if(!efl_object_init(), "ERROR: Cannot init EO!\n");
+
+   eina_value_setup(&v, EINA_VALUE_TYPE_INT);
+
+   base_model = efl_add(EFL_MODEL_ITEM_CLASS, NULL);
+   ck_assert(!!base_model);
+
+   for (i = 0; i < child_number; ++i)
+     {
+        child = efl_model_child_add(base_model);
+        ck_assert(!!child);
+        ck_assert(eina_value_set(&v, base_ints[i]));
+        efl_model_property_set(child, "test_p_int", &v);
+     }
+
+   model = efl_add(EFL_MODEL_COMPOSITE_SELECTION_CLASS, NULL,
+                   efl_ui_view_model_set(efl_added, base_model));
+   ck_assert(!!model);
+   efl_model_composite_selection_select(model, 2);
+
+   tdata = calloc(1, sizeof(Test_Data));
+   future = efl_model_children_slice_get(model, 0, 0);
+   efl_future_then(future, _selection_children_slice_get_then, 
_future_error_then, NULL, tdata);
+
+   ecore_main_loop_iterate();
+
+   ck_assert(tdata->success_flag);
+
+   ecore_shutdown();
+}
+END_TEST
+
 void
 efl_test_case_model_composite_boolean(TCase *tc)
 {
    tcase_add_test(tc, efl_test_model_composite_boolean);
+   tcase_add_test(tc, efl_test_model_composite_selection);
 }

-- 


Reply via email to