efl/src/lib/elementary/efl_ui_view_list_segarray.c

475 lines
14 KiB
C
Raw Normal View History

2017-12-12 16:59:48 -08:00
#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"
2017-12-12 16:59:48 -08:00
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;
2017-12-12 16:59:48 -08:00
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;
2017-12-12 16:59:48 -08:00
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)
2017-12-12 16:59:48 -08:00
{
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)
2017-12-12 16:59:48 -08:00
{
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)
2017-12-12 16:59:48 -08:00
{
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*));
2017-12-12 16:59:48 -08:00
node->first = first;
node->max = pd->step_size;
pd->root = (void*)eina_rbtree_inline_insert(EINA_RBTREE_GET(pd->root), EINA_RBTREE_GET(node),
2017-12-12 16:59:48 -08:00
EINA_RBTREE_CMP_NODE_CB(&_rbtree_compare), NULL);
pd->node_count++;
2017-12-12 16:59:48 -08:00
return node;
}
EOLIAN static void
_efl_ui_view_list_segarray_flush(Eo* obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data *pd)
2017-12-12 16:59:48 -08:00
{
if (pd->root)
eina_rbtree_delete(EINA_RBTREE_GET(pd->root), EINA_RBTREE_FREE_CB(_free_node), NULL);
2017-12-12 16:59:48 -08:00
pd->root = NULL;
pd->node_count = 0;
pd->count = 0;
2017-12-12 16:59:48 -08:00
}
static Efl_Ui_View_List_LayoutItem* _create_item_partial(Efl_Model* model)
2017-12-12 16:59:48 -08:00
{
Efl_Ui_View_List_LayoutItem* item = calloc(1, sizeof(Efl_Ui_View_List_LayoutItem));
item->children = model;
2017-12-12 16:59:48 -08:00
return item;
}
static Efl_Ui_View_List_LayoutItem* _create_item(Efl_Model* model, Efl_Ui_View_List_SegArray_Node* node, unsigned int index)
2017-12-12 16:59:48 -08:00
{
Efl_Ui_View_List_LayoutItem* item = _create_item_partial(model);
item->index_offset = index - node->first;
item->tree_node = node;
2017-12-12 16:59:48 -08:00
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)
2017-12-12 16:59:48 -08:00
{
Efl_Ui_View_List_SegArray_Node *node;
Efl_Ui_View_List_LayoutItem *item, *rt;
2017-12-12 16:59:48 -08:00
Eina_Iterator* iterator;
int offset;
node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(pd->root),
2017-12-12 16:59:48 -08:00
&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--;
2017-12-12 16:59:48 -08:00
node->length--;
while (offset < node->length)
{
node->pointers[offset] = node->pointers[offset+1];
item = node->pointers[offset];
--item->index_offset;
2017-12-12 16:59:48 -08:00
++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)
2017-12-12 16:59:48 -08:00
{
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;
2017-12-12 16:59:48 -08:00
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
2017-12-12 16:59:48 -08:00
{
assert(pos == node->length);
2017-12-12 16:59:48 -08:00
assert(node->length != node->max);
node->pointers[pos] = item;
node->length++;
}
}
else
{
node = _alloc_node(pd, index);
2017-12-12 16:59:48 -08:00
node->pointers[0] = item;
node->length++;
item->index_offset = 0;
item->tree_node = node;
2017-12-12 16:59:48 -08:00
}
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)
2017-12-12 16:59:48 -08:00
{
Efl_Ui_View_List_SegArray_Node* node, *next;
Efl_Ui_View_List_LayoutItem* item;
2017-12-12 16:59:48 -08:00
item = _create_item_partial(model);
node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(pd->root),
2017-12-12 16:59:48 -08:00
&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);
2017-12-12 16:59:48 -08:00
else
_efl_ui_view_list_segarray_insert_at_node(pd, index, item, node);
2017-12-12 16:59:48 -08:00
}
else
_efl_ui_view_list_segarray_insert_at_node(pd, index, item, NULL);
2017-12-12 16:59:48 -08:00
}
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)
2017-12-12 16:59:48 -08:00
{
Efl_Model *children;
unsigned int i, len;
2017-12-12 16:59:48 -08:00
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)
2017-12-12 16:59:48 -08:00
{
EINA_VALUE_ARRAY_FOREACH(&v, len, i, children)
2017-12-12 16:59:48 -08:00
{
unsigned int idx = first + i;
2017-12-12 16:59:48 -08:00
efl_ui_view_list_segarray_insert_object(segarray, idx, children);
}
}
else
{
printf("Unknow type !\n");
2017-12-12 16:59:48 -08:00
}
}
EOLIAN static int
_efl_ui_view_list_segarray_count(Eo *obj EINA_UNUSED, Efl_Ui_View_List_SegArray_Data* pd)
2017-12-12 16:59:48 -08:00
{
return pd->count;
2017-12-12 16:59:48 -08:00
}
typedef struct _Efl_Ui_View_List_Segarray_Eina_Accessor
2017-12-12 16:59:48 -08:00
{
Eina_Accessor vtable;
Efl_Ui_View_List_SegArray_Data* segarray;
} Efl_Ui_View_List_Segarray_Eina_Accessor;
2017-12-12 16:59:48 -08:00
static Eina_Bool
_efl_ui_view_list_segarray_accessor_get_at(Efl_Ui_View_List_Segarray_Eina_Accessor* acc,
2017-12-12 16:59:48 -08:00
int idx, void** data)
{
Efl_Ui_View_List_SegArray_Node* node;
2017-12-12 16:59:48 -08:00
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))
2017-12-12 16:59:48 -08:00
{
int i = idx - node->first;
Efl_Ui_View_List_LayoutItem* item = node->pointers[i];
*data = item;
return EINA_TRUE;
2017-12-12 16:59:48 -08:00
}
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));
}
2017-12-12 16:59:48 -08:00
static void*
_efl_ui_view_list_segarray_accessor_get_container(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
return NULL;
}
static void
_efl_ui_view_list_segarray_accessor_free(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
free(acc);
}
static Eina_Bool
_efl_ui_view_list_segarray_accessor_lock(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
return EINA_FALSE;
2017-12-12 16:59:48 -08:00
}
static Eina_Bool
_efl_ui_view_list_segarray_accessor_unlock(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
return EINA_FALSE;
2017-12-12 16:59:48 -08:00
}
static Eina_Accessor*
_efl_ui_view_list_segarray_accessor_clone(Efl_Ui_View_List_Segarray_Eina_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
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)
2017-12-12 16:59:48 -08:00
{
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);
2017-12-12 16:59:48 -08:00
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)
2017-12-12 16:59:48 -08:00
{
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);
2017-12-12 16:59:48 -08:00
return &acc->vtable;
}
typedef struct _Efl_Ui_View_List_Segarray_Node_Accessor
2017-12-12 16:59:48 -08:00
{
Eina_Accessor vtable;
Efl_Ui_View_List_SegArray_Data* segarray;
2017-12-12 16:59:48 -08:00
Eina_Iterator* pre_iterator;
Efl_Ui_View_List_SegArray_Node* current_node;
2017-12-12 16:59:48 -08:00
int current_index;
} Efl_Ui_View_List_Segarray_Node_Accessor;
2017-12-12 16:59:48 -08:00
static Eina_Bool
_efl_ui_view_list_segarray_node_accessor_get_at(Efl_Ui_View_List_Segarray_Node_Accessor* acc,
2017-12-12 16:59:48 -08:00
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)
2017-12-12 16:59:48 -08:00
{
return NULL;
}
static void
_efl_ui_view_list_segarray_node_accessor_free(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
if (acc->pre_iterator)
eina_iterator_free(acc->pre_iterator);
free(acc);
}
static Eina_Bool
_efl_ui_view_list_segarray_node_accessor_lock(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
return EINA_FALSE;
2017-12-12 16:59:48 -08:00
}
static Eina_Bool
_efl_ui_view_list_segarray_node_accessor_unlock(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
return EINA_FALSE;
2017-12-12 16:59:48 -08:00
}
static Eina_Accessor*
_efl_ui_view_list_segarray_node_accessor_clone(Efl_Ui_View_List_Segarray_Node_Accessor* acc EINA_UNUSED)
2017-12-12 16:59:48 -08:00
{
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)
2017-12-12 16:59:48 -08:00
{
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);
2017-12-12 16:59:48 -08:00
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)
2017-12-12 16:59:48 -08:00
{
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);
2017-12-12 16:59:48 -08:00
return &acc->vtable;
}
int efl_ui_view_list_item_index_get(Efl_Ui_View_List_LayoutItem* item)
2017-12-12 16:59:48 -08:00
{
Efl_Ui_View_List_SegArray_Node* node = item->tree_node;
return item->index_offset + node->first;
2017-12-12 16:59:48 -08:00
}
#include "efl_ui_view_list_segarray.eo.c"