diff options
Diffstat (limited to 'src/lib/elementary/efl_ui_view_list_segarray.c')
-rw-r--r-- | src/lib/elementary/efl_ui_view_list_segarray.c | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/src/lib/elementary/efl_ui_view_list_segarray.c b/src/lib/elementary/efl_ui_view_list_segarray.c new file mode 100644 index 0000000000..bb2dd9477a --- /dev/null +++ b/src/lib/elementary/efl_ui_view_list_segarray.c @@ -0,0 +1,470 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include <Efl.h> +#include <assert.h> + +#define MY_CLASS EFL_UI_VIEW_LIST_SEGARRAY_CLASS +#define MY_CLASS_NAME "Efl.Ui.View.List.SegArray" + +#include "efl_ui_view_list_private.h" +#include "efl_ui_view_list_segarray.h" + +static int _search_lookup_cb(Eina_Rbtree const* rbtree, const void* key, int length EINA_UNUSED, void* data EINA_UNUSED) +{ + Efl_Ui_View_List_SegArray_Node const* node = (void const*)rbtree; + int index = *(int*)key; + if(index < node->first) + { + return 1; + } + else if(index < node->first + node->length) + { + return 0; + } + else + { + return -1; + } +} + +static int _insert_lookup_cb(Eina_Rbtree const* rbtree, const void* key, int length EINA_UNUSED, void* data EINA_UNUSED) +{ + Efl_Ui_View_List_SegArray_Node const* node = (void const*)rbtree; + int index = *(int*)key; + if(index < node->first) + { + return 1; + } + else if(index < node->first + node->max) + { + return 0; + } + else + { + return -1; + } +} + +static Eina_Rbtree_Direction _rbtree_compare(Efl_Ui_View_List_SegArray_Node const* left, + Efl_Ui_View_List_SegArray_Node const* right, void* data EINA_UNUSED) +{ + if(left->first < right->first) + return EINA_RBTREE_LEFT; + else + return EINA_RBTREE_RIGHT; +} + + +static void +_free_node(Efl_Ui_View_List_SegArray_Node* node, void* data EINA_UNUSED) +{ + int i = 0; + + while (i < node->length) + { + free(node->pointers[i]); + ++i; + } + + free(node); +} + +static Efl_Ui_View_List_SegArray_Node* +_alloc_node(Efl_Ui_View_List_SegArray_Data* pd, int first) +{ + Efl_Ui_View_List_SegArray_Node* node; + node = calloc(1, sizeof(Efl_Ui_View_List_SegArray_Node) + pd->step_size*sizeof(Efl_Ui_View_List_LayoutItem*)); + node->first = first; + node->max = pd->step_size; + pd->root = (void*)eina_rbtree_inline_insert(EINA_RBTREE_GET(pd->root), EINA_RBTREE_GET(node), + EINA_RBTREE_CMP_NODE_CB(&_rbtree_compare), NULL); + pd->node_count++; + return node; +} + +EOLIAN static void +_efl_ui_view_list_segarray_flush(Eo* obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data *pd) +{ + if (pd->root) + eina_rbtree_delete(EINA_RBTREE_GET(pd->root), EINA_RBTREE_FREE_CB(_free_node), NULL); + + pd->root = NULL; + pd->node_count = 0; + pd->count = 0; +} + +static Efl_Ui_View_List_LayoutItem* _create_item_partial(Efl_Model* model) +{ + Efl_Ui_View_List_LayoutItem* item = calloc(1, sizeof(Efl_Ui_View_List_LayoutItem)); + item->children = model; + return item; +} + +static Efl_Ui_View_List_LayoutItem* _create_item(Efl_Model* model, Efl_Ui_View_List_SegArray_Node* node, unsigned int index) +{ + Efl_Ui_View_List_LayoutItem* item = _create_item_partial(model); + item->index_offset = index - node->first; + item->tree_node = node; + return item; +} + +EOLIAN static Efl_Ui_View_List_LayoutItem* +_efl_ui_view_list_segarray_remove(Eo* obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data *pd, int index) +{ + Efl_Ui_View_List_SegArray_Node *node; + Efl_Ui_View_List_LayoutItem *item, *rt; + Eina_Iterator* iterator; + int offset; + + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(pd->root), + &index, sizeof(index), &_insert_lookup_cb, NULL); + if (!node) return NULL; + + offset = index - node->first; + if (offset >= node->length) return NULL; + + rt = node->pointers[offset]; + pd->count--; + node->length--; + + while (offset < node->length) + { + node->pointers[offset] = node->pointers[offset+1]; + item = node->pointers[offset]; + --item->index_offset; + ++offset; + } + + node = (void*)EINA_RBTREE_GET(node)->son[EINA_RBTREE_LEFT]; + iterator = eina_rbtree_iterator_infix((void*)node); + while(eina_iterator_next(iterator, (void**)&node)) + node->first--; + + return rt; +} + +static void +_efl_ui_view_list_segarray_insert_at_node(Efl_Ui_View_List_SegArray_Data* pd, int index, Efl_Ui_View_List_LayoutItem* item, Efl_Ui_View_List_SegArray_Node* node) +{ + Eina_Iterator* iterator; + int pos; + + if(node && node->length != node->max && (index - node->first) <= node->length) + { + pos = index - node->first; + item->tree_node = node; + item->index_offset = pos; + if(pos < node->length) + { + assert(node->length != node->max); + + memmove(&node->pointers[pos], &node->pointers[pos+1], sizeof(node->pointers[pos])*(node->length - pos)); + node->pointers[pos] = item; + node->length++; + } + else + { + assert(pos == node->length); + + assert(node->length != node->max); + node->pointers[pos] = item; + node->length++; + } + } + else + { + node = _alloc_node(pd, index); + node->pointers[0] = item; + node->length++; + item->index_offset = 0; + item->tree_node = node; + } + + node = (void*)EINA_RBTREE_GET(node)->son[EINA_RBTREE_LEFT]; + iterator = eina_rbtree_iterator_infix((void*)node); + while(eina_iterator_next(iterator, (void**)&node)) + { + node->first++; + } + + eina_iterator_free(iterator); +} + + +EOLIAN static void +_efl_ui_view_list_segarray_insert(Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data* pd, int index, Efl_Model* model) +{ + Efl_Ui_View_List_SegArray_Node* node, *next; + Efl_Ui_View_List_LayoutItem* item; + + item = _create_item_partial(model); + + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(pd->root), + &index, sizeof(index), &_insert_lookup_cb, NULL); + if(node) + { + next = (void*)EINA_RBTREE_GET(node)->son[EINA_RBTREE_LEFT]; + if(next && next->first <= index) + _efl_ui_view_list_segarray_insert_at_node(pd, index, item, next); + else + _efl_ui_view_list_segarray_insert_at_node(pd, index, item, node); + } + else + _efl_ui_view_list_segarray_insert_at_node(pd, index, item, NULL); +} + +static void +efl_ui_view_list_segarray_insert_object(Efl_Ui_View_List_SegArray_Data *segarray, unsigned int index, Efl_Model *children) +{ + Efl_Ui_View_List_SegArray_Node *node; + + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(segarray->root), + &index, sizeof(index), &_insert_lookup_cb, NULL); + if (!node) + { + node = _alloc_node(segarray, index); + } + + assert(node->length < node->max); + node->pointers[node->length] = _create_item(children, node, index); + node->length++; + segarray->count++; +} + +EOLIAN static void +_efl_ui_view_list_segarray_insert_value(Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data *segarray, int first, Eina_Value v) +{ + Efl_Model *children; + unsigned int i, len; + + if (eina_value_type_get(&v) == EINA_VALUE_TYPE_OBJECT) + { + children = eina_value_object_get(&v); + efl_ui_view_list_segarray_insert_object(segarray, first, children); + } + else if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ARRAY) + { + EINA_VALUE_ARRAY_FOREACH(&v, len, i, children) + { + unsigned int idx = first + i; + + efl_ui_view_list_segarray_insert_object(segarray, idx, children); + } + } + else + { + printf("Unknow type !\n"); + } +} + +EOLIAN static int +_efl_ui_view_list_segarray_count(Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data* pd) +{ + return pd->count; +} + +typedef struct _Efl_Ui_View_List_Segarray_Eina_Accessor +{ + Eina_Accessor vtable; + Efl_Ui_View_List_SegArray_Data* segarray; +} Efl_Ui_View_List_Segarray_Eina_Accessor; + +static Eina_Bool +_efl_ui_view_list_segarray_accessor_get_at(Efl_Ui_View_List_Segarray_Eina_Accessor* acc, + int idx, void** data) +{ + Efl_Ui_View_List_SegArray_Node* node; + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(acc->segarray->root), + &idx, sizeof(idx), &_search_lookup_cb, NULL); + if (node && (node->first <= idx && node->first + node->length > idx)) + { + int i = idx - node->first; + Efl_Ui_View_List_LayoutItem* item = node->pointers[i]; + *data = item; + return EINA_TRUE; + } + return EINA_FALSE; +} + +EOLIAN static void +_efl_ui_view_list_segarray_setup(Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data *pd, int size) +{ + pd->step_size = size; +} + +EOLIAN static Eo * +_efl_ui_view_list_segarray_efl_object_constructor(Eo *obj, Efl_Ui_View_List_SegArray_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + return obj; +} + +EOLIAN static void +_efl_ui_view_list_segarray_efl_object_destructor(Eo *obj, Efl_Ui_View_List_SegArray_Data *pd) +{ + if (pd->root) + eina_rbtree_delete(EINA_RBTREE_GET(pd->root), EINA_RBTREE_FREE_CB(_free_node), NULL); + + pd->root = NULL; + efl_destructor(efl_super(obj, MY_CLASS)); +} + +static void* +_efl_ui_view_list_segarray_accessor_get_container(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ + return NULL; +} + +static void +_efl_ui_view_list_segarray_accessor_free(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ + free(acc); +} + +static void +_efl_ui_view_list_segarray_accessor_lock(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ +} + +static void +_efl_ui_view_list_segarray_accessor_unlock(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ +} + +static Eina_Accessor* +_efl_ui_view_list_segarray_accessor_clone(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ + return &acc->vtable; +} + +static void +_efl_ui_view_list_segarray_accessor_setup(Efl_Ui_View_List_Segarray_Eina_Accessor* acc, Efl_Ui_View_List_SegArray_Data* segarray) +{ + EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR); + acc->vtable.version = EINA_ACCESSOR_VERSION; + acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_ui_view_list_segarray_accessor_get_at); + acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_ui_view_list_segarray_accessor_get_container); + acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_ui_view_list_segarray_accessor_free); + acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_ui_view_list_segarray_accessor_lock); + acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_ui_view_list_segarray_accessor_unlock); + acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_ui_view_list_segarray_accessor_clone); + acc->segarray = segarray; +} + +EOLIAN static Eina_Accessor* +_efl_ui_view_list_segarray_accessor_get(const Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data* pd) +{ + Efl_Ui_View_List_Segarray_Eina_Accessor* acc = calloc(1, sizeof(Efl_Ui_View_List_Segarray_Eina_Accessor)); + _efl_ui_view_list_segarray_accessor_setup(acc, pd); + return &acc->vtable; +} + +typedef struct _Efl_Ui_View_List_Segarray_Node_Accessor +{ + Eina_Accessor vtable; + Efl_Ui_View_List_SegArray_Data* segarray; + Eina_Iterator* pre_iterator; + Efl_Ui_View_List_SegArray_Node* current_node; + int current_index; +} Efl_Ui_View_List_Segarray_Node_Accessor; + +static Eina_Bool +_efl_ui_view_list_segarray_node_accessor_get_at(Efl_Ui_View_List_Segarray_Node_Accessor* acc, + int idx, void** data) +{ + if(idx == acc->current_index && acc->current_node) + { + (*data) = acc->current_node; + } + else + { + if(acc->current_index >= idx || !acc->current_node) + { + eina_iterator_free(acc->pre_iterator); + acc->pre_iterator = NULL; + acc->current_node = NULL; + acc->current_index = -1; + } + + if(!acc->pre_iterator) + acc->pre_iterator = eina_rbtree_iterator_infix((void*)acc->segarray->root); + + for(;acc->current_index != idx;++acc->current_index) + { + if(!eina_iterator_next(acc->pre_iterator, (void**)&acc->current_node)) + { + --acc->current_index; + return EINA_FALSE; + } + } + (*data) = acc->current_node; + return EINA_TRUE; + } + return EINA_FALSE; +} + +static void* +_efl_ui_view_list_segarray_node_accessor_get_container(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ + return NULL; +} + +static void +_efl_ui_view_list_segarray_node_accessor_free(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ + if (acc->pre_iterator) + eina_iterator_free(acc->pre_iterator); + free(acc); +} + +static void +_efl_ui_view_list_segarray_node_accessor_lock(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ +} + +static void +_efl_ui_view_list_segarray_node_accessor_unlock(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ +} + +static Eina_Accessor* +_efl_ui_view_list_segarray_node_accessor_clone(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ + return &acc->vtable; +} + +static void +_efl_ui_view_list_segarray_node_accessor_setup(Efl_Ui_View_List_Segarray_Node_Accessor* acc, Efl_Ui_View_List_SegArray_Data* segarray) +{ + EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR); + acc->vtable.version = EINA_ACCESSOR_VERSION; + acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_ui_view_list_segarray_node_accessor_get_at); + acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_ui_view_list_segarray_node_accessor_get_container); + acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_ui_view_list_segarray_node_accessor_free); + acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_ui_view_list_segarray_node_accessor_lock); + acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_ui_view_list_segarray_node_accessor_unlock); + acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_ui_view_list_segarray_node_accessor_clone); + acc->segarray = segarray; + acc->pre_iterator = NULL; + acc->current_index = -1; + acc->current_node = NULL; +} + +EOLIAN static Eina_Accessor* +_efl_ui_view_list_segarray_node_accessor_get(const Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data* pd) +{ + Efl_Ui_View_List_Segarray_Node_Accessor* acc = calloc(1, sizeof(Efl_Ui_View_List_Segarray_Node_Accessor)); + _efl_ui_view_list_segarray_node_accessor_setup(acc, pd); + return &acc->vtable; +} + +int efl_ui_view_list_item_index_get(Efl_Ui_View_List_LayoutItem* item) +{ + Efl_Ui_View_List_SegArray_Node* node = item->tree_node; + return item->index_offset + node->first; +} + +#include "efl_ui_view_list_segarray.eo.c" |