Implement elm index sorted insert

- Name index item as Elm_Index_Item
 - Add some other index functions:
   + Item find
   + Data get/set
   + Letter get

I think this stuff will make easier to create index for
dynamically created lists.


SVN revision: 49171
This commit is contained in:
Bruno Dilly 2010-05-23 23:41:32 +00:00
parent de41ec04e3
commit 0fa431bcc0
2 changed files with 147 additions and 20 deletions

View File

@ -1266,6 +1266,7 @@ extern "C" {
* vertical (two up/down buttons at the right side and text left aligned)
*/
typedef struct _Elm_Index_Item Elm_Index_Item;
EAPI Evas_Object *elm_index_add(Evas_Object *parent);
EAPI void elm_index_active_set(Evas_Object *obj, Eina_Bool active);
EAPI void elm_index_item_level_set(Evas_Object *obj, int level);
@ -1275,9 +1276,14 @@ extern "C" {
EAPI void elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item);
EAPI void elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative);
EAPI void elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative);
EAPI void elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, const void *item, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func);
EAPI void elm_index_item_del(Evas_Object *obj, const void *item);
EAPI Elm_Index_Item *elm_index_item_find(Evas_Object *obj, const void *item);
EAPI void elm_index_item_clear(Evas_Object *obj);
EAPI void elm_index_item_go(Evas_Object *obj, int level);
EAPI void *elm_index_item_data_get(const Elm_Index_Item *item);
EAPI void elm_index_item_data_set(Elm_Index_Item *it, const void *data);
EAPI const char *elm_index_item_letter_get(const Elm_Index_Item *item);
/* smart callbacks called:
* "changed" - when the selected index item changes
* "delay,changed" - when the selected index item changes, but after some small idle period

View File

@ -9,7 +9,6 @@
*/
typedef struct _Widget_Data Widget_Data;
typedef struct _Item Item;
struct _Widget_Data
{
@ -26,7 +25,7 @@ struct _Widget_Data
Eina_Bool down : 1;
};
struct _Item
struct _Elm_Index_Item
{
Evas_Object *obj;
const char *letter;
@ -42,13 +41,13 @@ static void _theme_hook(Evas_Object *obj);
static void _sizing_eval(Evas_Object *obj);
static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
static void _item_free(Item *it);
static void _item_free(Elm_Index_Item *it);
static void
_del_hook(Evas_Object *obj)
{
Widget_Data *wd = elm_widget_data_get(obj);
Item *it;
Elm_Index_Item *it;
Eina_List *l, *clear = NULL;
if (!wd) return;
_index_box_clear(obj, wd->bx[wd->level], wd->level);
@ -138,13 +137,13 @@ _sizing_eval(Evas_Object *obj)
evas_object_size_hint_max_set(obj, maxw, maxh);
}
static Item *
static Elm_Index_Item *
_item_new(Evas_Object *obj, const char *letter, const void *item)
{
Widget_Data *wd = elm_widget_data_get(obj);
Item *it;
Elm_Index_Item *it;
if (!wd) return NULL;
it = calloc(1, sizeof(Item));
it = calloc(1, sizeof(Elm_Index_Item));
if (!it) return NULL;
it->obj = obj;
it->letter = eina_stringshare_add(letter);
@ -153,12 +152,12 @@ _item_new(Evas_Object *obj, const char *letter, const void *item)
return it;
}
static Item *
static Elm_Index_Item *
_item_find(Evas_Object *obj, const void *item)
{
Widget_Data *wd = elm_widget_data_get(obj);
Eina_List *l;
Item *it;
Elm_Index_Item *it;
if (!wd) return NULL;
EINA_LIST_FOREACH(wd->items, l, it)
if (it->data == item) return it;
@ -166,7 +165,7 @@ _item_find(Evas_Object *obj, const void *item)
}
static void
_item_free(Item *it)
_item_free(Elm_Index_Item *it)
{
Widget_Data *wd = elm_widget_data_get(it->obj);
if (!wd) return;
@ -182,7 +181,7 @@ _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
{
Widget_Data *wd = elm_widget_data_get(obj);
Eina_List *l;
Item *it;
Elm_Index_Item *it;
Evas_Coord mw, mh, w, h;
int i = 0;
if (!wd) return;
@ -235,7 +234,7 @@ _index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
{
Widget_Data *wd = elm_widget_data_get(obj);
Eina_List *l;
Item *it;
Elm_Index_Item *it;
if (!wd) return;
if (!wd->level_active[level]) return;
EINA_LIST_FOREACH(wd->items, l, it)
@ -264,7 +263,7 @@ static void
_sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
{
Widget_Data *wd = elm_widget_data_get(obj);
Item *it, *it_closest, *it_last;
Elm_Index_Item *it, *it_closest, *it_last;
Eina_List *l;
Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
double cdv = 0.5;
@ -614,7 +613,7 @@ elm_index_item_selected_get(const Evas_Object *obj, int level)
ELM_CHECK_WIDTYPE(obj, widtype) NULL;
Widget_Data *wd = elm_widget_data_get(obj);
Eina_List *l;
Item *it;
Elm_Index_Item *it;
if (!wd) return NULL;
EINA_LIST_FOREACH(wd->items, l, it)
if ((it->selected) && (it->level == level)) return it->data;
@ -635,7 +634,7 @@ elm_index_item_append(Evas_Object *obj, const char *letter, const void *item)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Item *it;
Elm_Index_Item *it;
if (!wd) return;
it = _item_new(obj, letter, item);
if (!it) return;
@ -657,7 +656,7 @@ elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Item *it;
Elm_Index_Item *it;
if (!wd) return;
it = _item_new(obj, letter, item);
@ -681,7 +680,7 @@ elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Item *it, *it_rel;
Elm_Index_Item *it, *it_rel;
if (!wd) return;
if (!relative)
{
@ -715,7 +714,7 @@ elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Item *it, *it_rel;
Elm_Index_Item *it, *it_rel;
if (!wd) return;
if (!relative)
{
@ -734,6 +733,62 @@ elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void
_index_box_clear(obj, wd->bx[wd->level], wd->level);
}
/**
* Insert a new @p item into the sorted index @p obj in @p letter.
*
* @param obj The index object
* @param letter Letter under which the item should be indexed
* @param item The item to put in the index
* @param cmp_func The function called for the sort of index items.
* @param cmp_data_func The function called for the sort of the data. It will
* be used when cmp_func return 0. It means the index item already exists.
* So, to decide which data item should be pointed by the index item, a function
* to compare them is needed. If this function is not provided, index items
* will be duplicated.
*
* @ingroup Index
*/
EAPI void
elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, const void *item, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Eina_List *lnear;
Elm_Index_Item *it;
int cmp;
if (!wd) return;
if (!(wd->items))
{
elm_index_item_append(obj, letter, item);
return;
}
it = _item_new(obj, letter, item);
if (!it) return;
lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
if (cmp < 0)
wd->items = eina_list_append_relative_list(wd->items, it, lnear);
else if (cmp > 0)
wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
else
{
/* If cmp_data_func is not provided, append a duplicated item */
if (!cmp_data_func)
wd->items = eina_list_append_relative_list(wd->items, it, lnear);
else
{
Elm_Index_Item *p_it = eina_list_data_get(lnear);
if (cmp_data_func(p_it->data, it->data) >= 0)
p_it->data = it->data;
_item_free(it);
}
}
_index_box_clear(obj, wd->bx[wd->level], wd->level);
}
/**
* Remove an item from the index.
*
@ -747,7 +802,7 @@ elm_index_item_del(Evas_Object *obj, const void *item)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Item *it;
Elm_Index_Item *it;
if (!wd) return;
it = _item_find(obj, item);
if (!it) return;
@ -755,6 +810,24 @@ elm_index_item_del(Evas_Object *obj, const void *item)
_index_box_clear(obj, wd->bx[wd->level], wd->level);
}
/**
* Find an index item using item data.
*
* @param obj The index object
* @param item The item pointed by index item
* @return The index item pointing to @p item
*
* @ingroup Index
*/
EAPI Elm_Index_Item *
elm_index_item_find(Evas_Object *obj, const void *item)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return NULL;
return _item_find(obj, item);
}
/**
* Clears an index of its items.
*
@ -767,7 +840,7 @@ elm_index_item_clear(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Item *it;
Elm_Index_Item *it;
Eina_List *l, *clear = NULL;
if (!wd) return;
_index_box_clear(obj, wd->bx[wd->level], wd->level);
@ -796,3 +869,51 @@ elm_index_item_go(Evas_Object *obj, int level __UNUSED__)
_index_box_auto_fill(obj, wd->bx[0], 0);
if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
}
/**
* Returns the data associated with the item.
*
* @param it The list item
* @return The data associated with @p it
*
* @ingroup Index
*/
EAPI void *
elm_index_item_data_get(const Elm_Index_Item *it)
{
if (!it) return NULL;
return (void *)it->data;
}
/**
* Set the data item from the index item
*
* This set a new data value.
*
* @param it The item
* @param data The new data pointer to set
*
* @ingroup Index
*/
EAPI void
elm_index_item_data_set(Elm_Index_Item *it, const void *data)
{
if (!it) return;
it->data = data;
}
/**
* Gets the letter of the item.
*
* @param it The list item
* @return The letter of @p it
*
* @ingroup Index
*/
EAPI const char *
elm_index_item_letter_get(const Elm_Index_Item *it)
{
if (!it) return NULL;
return it->letter;
}