On Mon, May 24, 2010 at 10:48 PM, Bruno Dilly <bdi...@profusion.mobi> wrote: > On Mon, May 24, 2010 at 12:06 AM, Iván Briano (Sachiel) > <sachi...@gmail.com> wrote: >> On Mon, May 24, 2010 at 8:41 AM, Enlightenment SVN >> <no-re...@enlightenment.org> wrote: >>> Log: >>> 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. >>> >>> Author: bdilly >>> Date: 2010-05-23 16:41:32 -0700 (Sun, 23 May 2010) >>> New Revision: 49171 >>> >>> Modified: >>> trunk/TMP/st/elementary/src/lib/Elementary.h.in >>> trunk/TMP/st/elementary/src/lib/elm_index.c >>> >>> Modified: trunk/TMP/st/elementary/src/lib/Elementary.h.in >>> =================================================================== >>> --- trunk/TMP/st/elementary/src/lib/Elementary.h.in 2010-05-23 23:23:51 >>> UTC (rev 49170) >>> +++ trunk/TMP/st/elementary/src/lib/Elementary.h.in 2010-05-23 23:41:32 >>> UTC (rev 49171) >>> @@ -1266,6 +1266,7 @@ >>> * 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 @@ >>> 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 >>> >>> Modified: trunk/TMP/st/elementary/src/lib/elm_index.c >>> =================================================================== >>> --- trunk/TMP/st/elementary/src/lib/elm_index.c 2010-05-23 23:23:51 UTC >>> (rev 49170) >>> +++ trunk/TMP/st/elementary/src/lib/elm_index.c 2010-05-23 23:41:32 UTC >>> (rev 49171) >>> @@ -9,7 +9,6 @@ >>> */ >>> >>> typedef struct _Widget_Data Widget_Data; >>> -typedef struct _Item Item; >>> >>> struct _Widget_Data >>> { >>> @@ -26,7 +25,7 @@ >>> Eina_Bool down : 1; >>> }; >>> >>> -struct _Item >>> +struct _Elm_Index_Item >>> { >>> Evas_Object *obj; >>> const char *letter; >>> @@ -42,13 +41,13 @@ >>> 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 @@ >>> 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 @@ >>> 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 @@ >>> } >>> >>> 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 @@ >>> { >>> 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 @@ >>> { >>> 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 @@ >>> _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_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_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_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_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_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) >>> { >>> @@ -735,6 +734,62 @@ >>> } >>> >>> /** >>> + * 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); >> >> What happens to the old data from p_it here? > > Leaving this responsibility to cmp_data_func is a bad approach? > In this function you know that if you return >= 0 this data will be > replaced in index item, and > if it need to be free or whatever you want, it's the time to do that. > It won't happen in the cases I was working with (that is the index > pointing to list items), but it surely can be a problem. > > I don't know, if you have a better solution in mind, I'm listening =) >
Two options, document that cmp_data_func should take care of freeing the old stuff if needed, or pass a free_func as yet another parameter. >> Also, what about the case where the cmp_data_func is used to sort >> two different items with the same label? Shouldn't a 0 return be used > > This case should be solved by cmp_func. You can have a cmp_func like this: > > cmp_func (it1, it2) > { > label1 = elm_index_item_letter_get(it1); > label2 = elm_index_item_letter_get(it2); > ret = strcasecmp(label1, label2); > if (!ret) { > data1 = elm_index_item_data_get(it1); > data2 = elm_index_item_data_get(it2); > ret = function_to_sort_different_items_with_the_same_label(data1, data2); > } > return ret; > } > >> for replace and the other two just for order of insertion? > > For sort, you should use cmp_func. The idea is to use cmp_data_func to decide > which data should be pointed by an item index already there. Sometimes > we will want that things just stay the way it already is, sometimes you will > want a replacement. > Fine then. >> >>> + } >>> + } >>> + >>> + _index_box_clear(obj, wd->bx[wd->level], wd->level); >>> +} >>> + >>> +/** >>> * Remove an item from the index. >>> * >>> * @param obj The index object >>> @@ -747,7 +802,7 @@ >>> { >>> 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; >>> @@ -756,6 +811,24 @@ >>> } >>> >>> /** >>> + * 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. >>> * >>> * @param obj The index object. >>> @@ -767,7 +840,7 @@ >>> { >>> 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 @@ >>> _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; >>> +} >>> + >>> >>> >>> ------------------------------------------------------------------------------ >>> >>> _______________________________________________ >>> enlightenment-svn mailing list >>> enlightenment-...@lists.sourceforge.net >>> https://lists.sourceforge.net/lists/listinfo/enlightenment-svn >>> >> >> ------------------------------------------------------------------------------ >> >> _______________________________________________ >> enlightenment-devel mailing list >> enlightenment-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel >> > ------------------------------------------------------------------------------ _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel