forked from enlightenment/efl
ecore: add Efl.Filter_Model
This model provide facility to filter the content of composited model. Reviewed-by: SangHyeon Jade Lee <sh10233.lee@samsung.com> Differential Revision: https://phab.enlightenment.org/D8797
This commit is contained in:
parent
7b44b02e10
commit
fd35f6c193
|
@ -119,6 +119,7 @@ EAPI Eo *efl_main_loop_get(void);
|
|||
#include "efl_composite_model.eo.h"
|
||||
#include "efl_boolean_model.eo.h"
|
||||
#include "efl_select_model.eo.h"
|
||||
#include "efl_filter_model.eo.h"
|
||||
#include "efl_view_model.eo.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,569 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <Efl_Core.h>
|
||||
|
||||
#include "efl_composite_model_private.h"
|
||||
|
||||
typedef struct _Efl_Filter_Model_Mapping Efl_Filter_Model_Mapping;
|
||||
struct _Efl_Filter_Model_Mapping
|
||||
{
|
||||
EINA_RBTREE;
|
||||
|
||||
uint64_t original;
|
||||
uint64_t mapped;
|
||||
|
||||
EINA_REFCOUNT;
|
||||
};
|
||||
|
||||
typedef struct _Efl_Filter_Model_Data Efl_Filter_Model_Data;
|
||||
struct _Efl_Filter_Model_Data
|
||||
{
|
||||
Efl_Filter_Model_Mapping *self;
|
||||
|
||||
Eina_Rbtree *mapping;
|
||||
|
||||
struct {
|
||||
void *data;
|
||||
EflFilterModel cb;
|
||||
Eina_Free_Cb free_cb;
|
||||
uint64_t count;
|
||||
} filter;
|
||||
|
||||
uint64_t counted;
|
||||
Eina_Bool counting_started : 1;
|
||||
Eina_Bool processed : 1;
|
||||
};
|
||||
|
||||
static Eina_Rbtree_Direction
|
||||
_filter_mapping_cmp_cb(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data EINA_UNUSED)
|
||||
{
|
||||
const Efl_Filter_Model_Mapping *l, *r;
|
||||
|
||||
l = (const Efl_Filter_Model_Mapping *) left;
|
||||
r = (const Efl_Filter_Model_Mapping *) right;
|
||||
|
||||
if (l->mapped < r->mapped)
|
||||
return EINA_RBTREE_LEFT;
|
||||
return EINA_RBTREE_RIGHT;
|
||||
}
|
||||
|
||||
static int
|
||||
_filter_mapping_looking_cb(const Eina_Rbtree *node, const void *key,
|
||||
int length EINA_UNUSED, void *data EINA_UNUSED)
|
||||
{
|
||||
const Efl_Filter_Model_Mapping *n = (const Efl_Filter_Model_Mapping *) node;
|
||||
const uint64_t *k = key;
|
||||
|
||||
return n->mapped - *k;
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_filter_model_filter_set(Eo *obj EINA_UNUSED, Efl_Filter_Model_Data *pd,
|
||||
void *filter_data, EflFilterModel filter, Eina_Free_Cb filter_free_cb)
|
||||
{
|
||||
if (pd->filter.cb)
|
||||
pd->filter.free_cb(pd->filter.data);
|
||||
pd->filter.data = filter_data;
|
||||
pd->filter.cb = filter;
|
||||
pd->filter.free_cb = filter_free_cb;
|
||||
}
|
||||
|
||||
static void
|
||||
_rbtree_free_cb(Eina_Rbtree *node, void *data EINA_UNUSED)
|
||||
{
|
||||
Efl_Filter_Model_Mapping *m = (Efl_Filter_Model_Mapping*) node;
|
||||
|
||||
EINA_REFCOUNT_UNREF(m)
|
||||
free(m);
|
||||
}
|
||||
|
||||
typedef struct _Efl_Filter_Request Efl_Filter_Request;
|
||||
struct _Efl_Filter_Request
|
||||
{
|
||||
Efl_Filter_Model_Data *pd;
|
||||
Efl_Model *parent;
|
||||
Efl_Model *child;
|
||||
uint64_t index;
|
||||
};
|
||||
|
||||
static Efl_Filter_Model *
|
||||
_efl_filter_lookup(const Efl_Class *klass,
|
||||
Efl_Model *parent, Efl_Model *view,
|
||||
Efl_Filter_Model_Mapping *mapping)
|
||||
{
|
||||
Efl_Filter_Model *child;
|
||||
Efl_Filter_Model_Data *cpd;
|
||||
|
||||
child = _efl_composite_lookup(klass, parent, view, mapping->mapped);
|
||||
if (!child) return NULL;
|
||||
|
||||
cpd = efl_data_scope_get(child, EFL_FILTER_MODEL_CLASS);
|
||||
cpd->processed = EINA_TRUE;
|
||||
cpd->self = mapping;
|
||||
EINA_REFCOUNT_REF(mapping);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_efl_filter_model_filter(Eo *o EINA_UNUSED, void *data, const Eina_Value v)
|
||||
{
|
||||
Efl_Filter_Model_Mapping *mapping;
|
||||
Efl_Filter_Model *child;
|
||||
Efl_Model_Children_Event cevt = { 0 };
|
||||
Efl_Filter_Request *r = data;
|
||||
Eina_Value ret = v;
|
||||
Eina_Bool result = EINA_FALSE;
|
||||
|
||||
if (!eina_value_bool_get(&v, &result)) goto end;
|
||||
if (!result) goto end;
|
||||
|
||||
mapping = calloc(1, sizeof (Efl_Filter_Model_Mapping));
|
||||
if (!mapping)
|
||||
{
|
||||
ret = eina_value_bool_init(EINA_FALSE);
|
||||
goto end;
|
||||
}
|
||||
EINA_REFCOUNT_INIT(mapping);
|
||||
|
||||
mapping->original = r->index;
|
||||
mapping->mapped = r->pd->filter.count++;
|
||||
|
||||
r->pd->mapping = eina_rbtree_inline_insert(r->pd->mapping, EINA_RBTREE_GET(mapping),
|
||||
_filter_mapping_cmp_cb, NULL);
|
||||
|
||||
child = _efl_filter_lookup(efl_class_get(r->parent), r->parent, r->child, mapping);
|
||||
if (!child) goto end;
|
||||
|
||||
cevt.index = mapping->mapped;
|
||||
cevt.child = child;
|
||||
|
||||
efl_event_callback_call(r->parent, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
|
||||
efl_event_callback_call(r->parent, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, NULL);
|
||||
|
||||
efl_unref(cevt.child);
|
||||
|
||||
ret = eina_value_bool_init(EINA_TRUE);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_filter_model_filter_clean(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
|
||||
{
|
||||
Efl_Filter_Request *r = data;
|
||||
|
||||
efl_unref(r->parent);
|
||||
efl_unref(r->child);
|
||||
free(r);
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_efl_filter_model_child_fetch(Eo *o EINA_UNUSED, void *data, const Eina_Value v)
|
||||
{
|
||||
Efl_Filter_Request *r = data;
|
||||
unsigned int i, len;
|
||||
Eina_Future *f;
|
||||
Eo *target = NULL;
|
||||
|
||||
// Get the first and only child in the array
|
||||
EINA_VALUE_ARRAY_FOREACH(&v, len, i, target)
|
||||
break;
|
||||
|
||||
r->child = efl_ref(target);
|
||||
|
||||
f = r->pd->filter.cb(r->pd->filter.data, r->parent, r->child);
|
||||
f = efl_future_then(r->parent, f,
|
||||
.success = _efl_filter_model_filter,
|
||||
.success_type = EINA_VALUE_TYPE_BOOL,
|
||||
.free = _efl_filter_model_filter_clean,
|
||||
.data = r);
|
||||
return eina_future_as_value(f);
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_efl_filter_model_child_error(Eo *o, void *data, Eina_Error err)
|
||||
{
|
||||
_efl_filter_model_filter_clean(o, data, NULL);
|
||||
return eina_value_error_init(err);
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_filter_model_child_added(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Filter_Model_Data *pd = data;
|
||||
Efl_Model_Children_Event *ev = event->info;
|
||||
Efl_Model *child = ev->child;
|
||||
Efl_Filter_Request *r;
|
||||
Eina_Future *f;
|
||||
|
||||
if (child)
|
||||
{
|
||||
Efl_Filter_Model_Data *cpd = efl_data_scope_get(child, EFL_FILTER_MODEL_CLASS);
|
||||
|
||||
if (cpd->processed) return ;
|
||||
}
|
||||
|
||||
r = calloc(1, sizeof (Efl_Filter_Request));
|
||||
if (!r) return ;
|
||||
|
||||
r->pd = pd;
|
||||
r->index = ev->index;
|
||||
r->parent = efl_ref(event->object);
|
||||
|
||||
if (!child)
|
||||
{
|
||||
f = efl_model_children_slice_get(efl_ui_view_model_get(r->parent), r->index, 1);
|
||||
f = efl_future_then(event->object, f,
|
||||
.success = _efl_filter_model_child_fetch,
|
||||
.success_type = EINA_VALUE_TYPE_ARRAY,
|
||||
.error = _efl_filter_model_child_error,
|
||||
.data = r);
|
||||
return ;
|
||||
}
|
||||
|
||||
r->child = efl_ref(child);
|
||||
|
||||
f = pd->filter.cb(pd->filter.data, r->parent, r->child);
|
||||
f = efl_future_then(event->object, f,
|
||||
.success = _efl_filter_model_filter,
|
||||
.success_type = EINA_VALUE_TYPE_BOOL,
|
||||
.free = _efl_filter_model_filter_clean,
|
||||
.data = r);
|
||||
|
||||
efl_event_callback_stop(event->object);
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_filter_model_child_removed(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Filter_Model_Mapping *mapping;
|
||||
Efl_Filter_Model_Data *pd = data;
|
||||
Efl_Model_Children_Event *ev = event->info;
|
||||
uint64_t removed = ev->index;
|
||||
|
||||
mapping = (void *)eina_rbtree_inline_lookup(pd->mapping,
|
||||
&removed, sizeof (uint64_t),
|
||||
_filter_mapping_looking_cb, NULL);
|
||||
if (!mapping) return;
|
||||
|
||||
pd->mapping = eina_rbtree_inline_remove(pd->mapping, EINA_RBTREE_GET(mapping),
|
||||
_filter_mapping_cmp_cb, NULL);
|
||||
|
||||
EINA_REFCOUNT_UNREF(mapping)
|
||||
free(mapping);
|
||||
|
||||
// Update the tree for the index to reflect the removed child
|
||||
for (removed++; removed < pd->filter.count; removed++)
|
||||
{
|
||||
mapping = (void *)eina_rbtree_inline_lookup(pd->mapping,
|
||||
&removed, sizeof (uint64_t),
|
||||
_filter_mapping_looking_cb, NULL);
|
||||
if (!mapping) continue;
|
||||
|
||||
pd->mapping = eina_rbtree_inline_remove(pd->mapping, EINA_RBTREE_GET(mapping),
|
||||
_filter_mapping_cmp_cb, NULL);
|
||||
mapping->mapped--;
|
||||
pd->mapping = eina_rbtree_inline_insert(pd->mapping, EINA_RBTREE_GET(mapping),
|
||||
_filter_mapping_cmp_cb, NULL);
|
||||
}
|
||||
pd->filter.count--;
|
||||
pd->counted--;
|
||||
}
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(filters_callbacks,
|
||||
{ EFL_MODEL_EVENT_CHILD_ADDED, _efl_filter_model_child_added },
|
||||
{ EFL_MODEL_EVENT_CHILD_REMOVED, _efl_filter_model_child_removed });
|
||||
|
||||
static void
|
||||
_efl_filter_model_efl_object_destructor(Eo *obj, Efl_Filter_Model_Data *pd)
|
||||
{
|
||||
eina_rbtree_delete(pd->mapping, _rbtree_free_cb, NULL);
|
||||
|
||||
if (pd->self)
|
||||
{
|
||||
EINA_REFCOUNT_UNREF(pd->self)
|
||||
free(pd->self);
|
||||
}
|
||||
pd->self = NULL;
|
||||
|
||||
efl_destructor(efl_super(obj, EFL_FILTER_MODEL_CLASS));
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_filter_remove_array(Eo *o EINA_UNUSED, void *data, const Eina_Value v)
|
||||
{
|
||||
Efl_Filter_Model_Mapping *mapping = data;
|
||||
unsigned int i, len;
|
||||
Eo *target = NULL;
|
||||
|
||||
EINA_VALUE_ARRAY_FOREACH(&v, len, i, target)
|
||||
break;
|
||||
|
||||
if (efl_isa(target, EFL_FILTER_MODEL_CLASS))
|
||||
{
|
||||
Efl_Filter_Model_Data *pd = efl_data_scope_get(target, EFL_FILTER_MODEL_CLASS);
|
||||
|
||||
pd->self = mapping;
|
||||
EINA_REFCOUNT_REF(pd->self);
|
||||
}
|
||||
|
||||
return eina_value_object_init(target);
|
||||
}
|
||||
|
||||
/* Result from eina_future_all_array is an EINA_VALUE_TYPE_ARRAY that contain Eina_Value of
|
||||
Eo Model. It is expected that children slice get return an EINA_VALUE_TYPE_ARRAY that
|
||||
contain Eo Model directly.
|
||||
*/
|
||||
static Eina_Value
|
||||
_filter_cleanup_array(Eo *o EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v)
|
||||
{
|
||||
unsigned int i, len;
|
||||
Eina_Value created = EINA_VALUE_EMPTY;
|
||||
Eina_Value r = EINA_VALUE_EMPTY;
|
||||
|
||||
eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4);
|
||||
|
||||
EINA_VALUE_ARRAY_FOREACH(&v, len, i, created)
|
||||
{
|
||||
Eo *target = NULL;
|
||||
|
||||
if (eina_value_type_get(&created) != EINA_VALUE_TYPE_OBJECT)
|
||||
goto on_error;
|
||||
|
||||
target = eina_value_object_get(&created);
|
||||
if (!target) goto on_error;
|
||||
|
||||
eina_value_array_append(&r, target);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
on_error:
|
||||
eina_value_flush(&r);
|
||||
return eina_value_error_init(EFL_MODEL_ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
static Eina_Future *
|
||||
_efl_filter_model_efl_model_children_slice_get(Eo *obj, Efl_Filter_Model_Data *pd,
|
||||
unsigned int start, unsigned int count)
|
||||
{
|
||||
Efl_Filter_Model_Mapping **mapping = NULL;
|
||||
Eina_Future **r = NULL;
|
||||
Eina_Future *f;
|
||||
unsigned int i;
|
||||
Eina_Error err = ENOMEM;
|
||||
|
||||
if ((uint64_t) start + (uint64_t) count > pd->filter.count)
|
||||
return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE);
|
||||
if (count == 0)
|
||||
return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE);
|
||||
|
||||
r = malloc((count + 1) * sizeof (Eina_Future *));
|
||||
if (!r) return efl_loop_future_rejected(obj, ENOMEM);
|
||||
|
||||
mapping = calloc(count, sizeof (Efl_Filter_Model_Mapping *));
|
||||
if (!mapping) goto on_error;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
uint64_t lookup = start + i;
|
||||
|
||||
mapping[i] = (void *)eina_rbtree_inline_lookup(pd->mapping,
|
||||
&lookup, sizeof (uint64_t),
|
||||
_filter_mapping_looking_cb, NULL);
|
||||
if (!mapping[i]) goto on_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
r[i] = efl_model_children_slice_get(efl_super(obj, EFL_FILTER_MODEL_CLASS),
|
||||
mapping[i]->original, 1);
|
||||
r[i] = efl_future_then(obj, r[i], .success_type = EINA_VALUE_TYPE_ARRAY,
|
||||
.success = _filter_remove_array,
|
||||
.data = mapping[i]);
|
||||
if (!r) goto on_error;
|
||||
}
|
||||
r[i] = EINA_FUTURE_SENTINEL;
|
||||
|
||||
f = efl_future_then(obj, eina_future_all_array(r), .success = _filter_cleanup_array);
|
||||
free(r);
|
||||
free(mapping);
|
||||
|
||||
return f;
|
||||
|
||||
on_error:
|
||||
free(mapping);
|
||||
|
||||
if (r)
|
||||
for (i = 0; i < count; i ++)
|
||||
if (r[i]) eina_future_cancel(r[i]);
|
||||
free(r);
|
||||
|
||||
return efl_loop_future_rejected(obj, err);
|
||||
}
|
||||
|
||||
typedef struct _Efl_Filter_Model_Result Efl_Filter_Model_Result;
|
||||
struct _Efl_Filter_Model_Result
|
||||
{
|
||||
Efl_Filter_Model_Data *pd;
|
||||
uint64_t count;
|
||||
Efl_Model *targets[1];
|
||||
};
|
||||
|
||||
// This future receive an array of boolean that indicate if a fetched object is to be kept
|
||||
static Eina_Value
|
||||
_efl_filter_model_array_result_request(Eo *o EINA_UNUSED, void *data, const Eina_Value v)
|
||||
{
|
||||
Efl_Filter_Model_Result *req = data;
|
||||
Efl_Filter_Model_Data *pd = req->pd;
|
||||
unsigned int i, len;
|
||||
Eina_Value request = EINA_VALUE_EMPTY;
|
||||
uint64_t pcount = pd->filter.count;
|
||||
|
||||
EINA_VALUE_ARRAY_FOREACH(&v, len, i, request)
|
||||
{
|
||||
Efl_Filter_Model_Mapping *mapping;
|
||||
Efl_Model_Children_Event cevt = { 0 };
|
||||
Eina_Bool b;
|
||||
|
||||
if (eina_value_type_get(&request) != EINA_VALUE_TYPE_BOOL)
|
||||
continue ;
|
||||
|
||||
if (!eina_value_bool_get(&request, &b)) continue;
|
||||
if (!b) continue;
|
||||
|
||||
mapping = calloc(1, sizeof (Efl_Filter_Model_Mapping));
|
||||
if (!mapping) continue;
|
||||
|
||||
EINA_REFCOUNT_INIT(mapping);
|
||||
mapping->original = i;
|
||||
mapping->mapped = pd->filter.count++;
|
||||
|
||||
// Insert in tree here
|
||||
pd->mapping = eina_rbtree_inline_insert(pd->mapping, EINA_RBTREE_GET(mapping),
|
||||
_filter_mapping_cmp_cb, NULL);
|
||||
|
||||
cevt.index = mapping->mapped;
|
||||
cevt.child = _efl_filter_lookup(efl_class_get(o), o, req->targets[i], mapping);
|
||||
if (!cevt.child) continue;
|
||||
|
||||
efl_event_callback_call(o, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
|
||||
efl_unref(cevt.child);
|
||||
}
|
||||
|
||||
if (pcount != pd->filter.count)
|
||||
efl_event_callback_call(o, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, NULL);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_filter_model_array_result_free(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
|
||||
{
|
||||
Efl_Filter_Model_Result *req = data;
|
||||
uint64_t i;
|
||||
|
||||
for (i = 0; i < req->count; i++)
|
||||
efl_unref(req->targets[i]);
|
||||
free(req);
|
||||
}
|
||||
|
||||
// This future receive an array of children object
|
||||
static Eina_Value
|
||||
_efl_filter_model_array_fetch(Eo *o, void *data, const Eina_Value v)
|
||||
{
|
||||
Efl_Filter_Model_Result *req;
|
||||
Efl_Filter_Model_Data *pd = data;
|
||||
unsigned int i, len;
|
||||
Eo *target = NULL;
|
||||
Eina_Future **array = NULL;
|
||||
Eina_Future *r;
|
||||
Eina_Value res = v;
|
||||
|
||||
if (!eina_value_array_count(&v)) return v;
|
||||
|
||||
array = malloc((eina_value_array_count(&v) + 1) * sizeof (Eina_Future*));
|
||||
if (!array) return eina_value_error_init(ENOMEM);
|
||||
|
||||
req = malloc(sizeof (Efl_Filter_Model_Result) +
|
||||
sizeof (Eo*) * (eina_value_array_count(&v) - 1));
|
||||
if (!req)
|
||||
{
|
||||
res = eina_value_error_init(ENOMEM);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
req->pd = pd;
|
||||
req->count = eina_value_array_count(&v);
|
||||
|
||||
EINA_VALUE_ARRAY_FOREACH(&v, len, i, target)
|
||||
{
|
||||
array[i] = pd->filter.cb(pd->filter.data, o, target);
|
||||
req->targets[i] = efl_ref(target);
|
||||
}
|
||||
|
||||
array[i] = EINA_FUTURE_SENTINEL;
|
||||
|
||||
r = eina_future_all_array(array);
|
||||
r = efl_future_then(o, r, .success_type = EINA_VALUE_TYPE_ARRAY,
|
||||
.success = _efl_filter_model_array_result_request,
|
||||
.free = _efl_filter_model_array_result_free,
|
||||
.data = req);
|
||||
res = eina_future_as_value(r);
|
||||
|
||||
on_error:
|
||||
free(array);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
_efl_filter_model_efl_model_children_count_get(const Eo *obj, Efl_Filter_Model_Data *pd)
|
||||
{
|
||||
if (!pd->counting_started && pd->filter.cb)
|
||||
{
|
||||
pd->counting_started = EINA_TRUE;
|
||||
|
||||
// Start watching for children now
|
||||
efl_event_callback_array_add((Eo *)obj, filters_callbacks(), pd);
|
||||
|
||||
// Start counting (which may trigger filter being added asynchronously)
|
||||
pd->counted = efl_model_children_count_get(efl_super(obj, EFL_FILTER_MODEL_CLASS));
|
||||
if (pd->counted > 0)
|
||||
{
|
||||
Eina_Future *f;
|
||||
|
||||
f = efl_model_children_slice_get(efl_ui_view_model_get(obj), 0, pd->counted);
|
||||
efl_future_then(obj, f, .success_type = EINA_VALUE_TYPE_ARRAY,
|
||||
.success = _efl_filter_model_array_fetch,
|
||||
.data = pd);
|
||||
}
|
||||
}
|
||||
|
||||
return pd->filter.count;
|
||||
}
|
||||
|
||||
static Eina_Value *
|
||||
_efl_filter_model_efl_model_property_get(const Eo *obj, Efl_Filter_Model_Data *pd,
|
||||
const char *property)
|
||||
{
|
||||
if (pd->self && !strcmp(property, EFL_COMPOSITE_MODEL_CHILD_INDEX))
|
||||
{
|
||||
return eina_value_uint64_new(pd->self->mapped);
|
||||
}
|
||||
|
||||
return efl_model_property_get(efl_super(obj, EFL_FILTER_MODEL_CLASS), property);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
_efl_filter_model_efl_composite_model_index_get(const Eo *obj, Efl_Filter_Model_Data *pd)
|
||||
{
|
||||
if (pd->self) return pd->self->mapped;
|
||||
return efl_composite_model_index_get(efl_super(obj, EFL_FILTER_MODEL_CLASS));
|
||||
}
|
||||
|
||||
#include "efl_filter_model.eo.c"
|
|
@ -0,0 +1,31 @@
|
|||
function @beta EflFilterModel {
|
||||
[[EflFilterModel function]]
|
||||
params {
|
||||
parent: Efl.Filter_Model; [[This object can be used to know when to cancel the future.]]
|
||||
child: Efl.Model; [[You must reference this object for the duration of your use of it as the caller will not do that for you.]]
|
||||
}
|
||||
return: future<bool>; [[$true if the model should be kept.]]
|
||||
};
|
||||
|
||||
class @beta Efl.Filter_Model extends Efl.Composite_Model
|
||||
{
|
||||
[[Efl model designed to filter its children.]]
|
||||
methods {
|
||||
filter_set {
|
||||
[[Set a filter function that will catch children from the composited model.]]
|
||||
params {
|
||||
filter: EflFilterModel; [[Filter callback]]
|
||||
}
|
||||
}
|
||||
}
|
||||
implements {
|
||||
Efl.Object.destructor;
|
||||
Efl.Model.children_slice_get;
|
||||
Efl.Model.children_count { get; }
|
||||
Efl.Model.property { get; }
|
||||
Efl.Composite_Model.index { get; }
|
||||
}
|
||||
constructors {
|
||||
.filter_set;
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@ pub_eo_files = [
|
|||
'efl_core_proc_env.eo',
|
||||
'efl_core_command_line.eo',
|
||||
'efl_loop_timer.eo',
|
||||
'efl_filter_model.eo',
|
||||
]
|
||||
|
||||
foreach eo_file : pub_eo_files
|
||||
|
@ -145,6 +146,7 @@ ecore_src = [
|
|||
'efl_model_accessor_view.c',
|
||||
'efl_model_accessor_view_private.h',
|
||||
'efl_view_model.c',
|
||||
'efl_filter_model.c',
|
||||
'efl_linear_interpolator.c',
|
||||
'efl_accelerate_interpolator.c',
|
||||
'efl_decelerate_interpolator.c',
|
||||
|
|
Loading…
Reference in New Issue