diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 5ad9af4fad..f1de498b98 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -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 diff --git a/legacy/elementary/src/lib/elm_index.c b/legacy/elementary/src/lib/elm_index.c index af2c1e27f0..fb601b88ab 100644 --- a/legacy/elementary/src/lib/elm_index.c +++ b/legacy/elementary/src/lib/elm_index.c @@ -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; +} +