2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
4 #include <Elementary.h>
8 * @defgroup Index Index
11 * An index object is a type of list that categorizes items in it
15 #define MIN_GRP_SIZE 2 //for symmetry it is 2, otherwise it can be 1 and zero have no meaning.
16 #define MIN_PIXEL_VALUE 1 //Min pixel value is highly dependent on touch sensitivity support.
17 #define MIN_OBJ_HEIGHT 24 //should be taken from .edc file.
18 typedef struct _Widget_Data Widget_Data;
20 typedef struct _PlacementPart PlacementPart;
25 Evas_Object *event[2];
26 Evas_Object *bx[2]; // 2 - for now all that's supported
27 Eina_List *items; // 1 list. yes N levels, but only 2 for now and # of items will be small
29 int max_supp_items_count;
30 int tot_items_count[2];
31 int min_obj_height, max_grp_size;
32 int min_1st_level_obj_height;
35 Evas_Coord pwidth, pheight;
37 const char *special_char;
38 Eina_Bool level_active[2];
39 Eina_Bool horizontal : 1;
42 Eina_Bool hide_button : 1;
47 struct _Elm_Index_Item
51 const char *letter, *vis_letter;
54 Eina_Bool selected : 1;
63 static const char *widtype = NULL;
65 static void _del_hook(Evas_Object *obj);
66 static void _theme_hook(Evas_Object *obj);
67 static void _sizing_eval(Evas_Object *obj);
68 static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
69 static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
70 static void _item_free(Elm_Index_Item *it);
71 static void _index_process(Evas_Object *obj);
73 /* Free a block allocated by `malloc', `realloc' or `calloc' one by one*/
75 _del_hook(Evas_Object *obj)
77 Widget_Data *wd = elm_widget_data_get(obj);
79 Eina_List *l, *clear = NULL;
81 _index_box_clear(obj, wd->bx[wd->level], wd->level);
82 _index_box_clear(obj, wd->bx[0], 0);
83 EINA_LIST_FOREACH(wd->items, l, it) clear = eina_list_append(clear, it);
84 EINA_LIST_FREE(clear, it) _item_free(it);
85 if (wd->delay) ecore_timer_del(wd->delay);
90 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
92 Widget_Data *wd = data;
94 _els_box_layout(o, priv, wd->horizontal, 0); /* making box layout non homogenous */
98 _theme_hook(Evas_Object *obj)
100 Widget_Data *wd = elm_widget_data_get(obj);
102 _index_box_clear(obj, wd->bx[0], 0);
103 _index_box_clear(obj, wd->bx[1], 1);
105 _elm_theme_object_set(obj, wd->base, "index", "base/horizontal", elm_widget_style_get(obj));
107 _elm_theme_object_set(obj, wd->base, "index", "base/vertical", elm_widget_style_get(obj));
108 edje_object_part_swallow(wd->base, "elm.swallow.event.0", wd->event[0]);
109 edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
110 if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
114 wd->bx[1] = evas_object_box_add(evas_object_evas_get(wd->base));
115 evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
116 elm_widget_sub_object_add(obj, wd->bx[1]);
118 edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
119 evas_object_show(wd->bx[1]);
123 evas_object_del(wd->bx[1]);
126 if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
130 Evas_Coord minw = 0, minh = 0;
132 wd->event[1] = evas_object_rectangle_add(evas_object_evas_get(wd->base));
133 evas_object_color_set(wd->event[1], 0, 0, 0, 0);
134 evas_object_size_hint_min_set(wd->event[1], minw, minh);
136 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
137 elm_widget_sub_object_add(obj, wd->event[1]);
139 edje_object_part_swallow(wd->base, "elm.swallow.event.1", wd->event[1]);
141 else if (wd->event[1])
143 evas_object_del(wd->event[1]);
146 edje_object_message_signal_process(wd->base);
147 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
149 _index_box_auto_fill(obj, wd->bx[0], 0);
152 _index_box_auto_fill(obj, wd->bx[1], 1);
156 _sizing_eval(Evas_Object *obj)
158 Widget_Data *wd = elm_widget_data_get(obj);
159 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
161 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
162 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
163 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
164 evas_object_size_hint_min_set(obj, minw, minh);
165 evas_object_size_hint_max_set(obj, maxw, maxh);
168 static Elm_Index_Item *
169 _item_new(Evas_Object *obj, const char *letter, const void *item)
171 Widget_Data *wd = elm_widget_data_get(obj);
173 if (!wd) return NULL;
174 it = calloc(1, sizeof(Elm_Index_Item));
175 if (!it) return NULL;
178 it->level = wd->level;
180 it->size = wd->min_obj_height;
182 it->size = wd->min_1st_level_obj_height;
185 it->letter = eina_stringshare_add(letter);
186 it->vis_letter = eina_stringshare_add(letter);
193 static Elm_Index_Item *
194 _item_find(Evas_Object *obj, const void *item)
196 Widget_Data *wd = elm_widget_data_get(obj);
199 if (!wd) return NULL;
200 EINA_LIST_FOREACH(wd->items, l, it)
201 if (it->data == item) return it;
206 _item_free(Elm_Index_Item *it)
208 Widget_Data *wd = elm_widget_data_get(it->obj);
210 wd->items = eina_list_remove(wd->items, it);
211 if (it->base) evas_object_del(it->base);
212 eina_stringshare_del(it->letter);
213 eina_stringshare_del(it->vis_letter);
217 /* Automatically filling the box with index item*/
219 _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
221 Widget_Data *wd = elm_widget_data_get(obj);
224 Evas_Coord mw, mh, w, h;
227 if (wd->level_active[level]) return;
228 evas_object_geometry_get(box, NULL, NULL, &w, &h);
229 EINA_LIST_FOREACH(wd->items, l, it)
232 const char *stacking;
234 if (it->level != level) continue;
235 if(i > wd->max_supp_items_count) break;
237 o = edje_object_add(evas_object_evas_get(obj));
240 _elm_theme_object_set(obj, o, "index", "item_odd/vertical", elm_widget_style_get(obj));
242 //_elm_theme_object_set(obj, o, "index", "item/vertical", "default");
243 _elm_theme_object_set(obj, o, "index", "item/vertical", elm_widget_style_get(obj));
244 edje_object_part_text_set(o, "elm.text", it->letter);
245 edje_object_size_min_restricted_calc(o, &mw, &mh, 0, 0);
246 evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
247 evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
248 edje_object_part_text_set(o, "elm.text", it->vis_letter);
249 evas_object_resize(o, mw, it->size);
250 evas_object_size_hint_min_set(o, mw, it->size);
251 evas_object_size_hint_max_set(o, mw, it->size);
252 elm_widget_sub_object_add(obj, o);
253 evas_object_box_append(box, o);
254 stacking = edje_object_data_get(o, "stacking");
257 if (!strcmp(stacking, "below")) evas_object_lower(o);
258 else if (!strcmp(stacking, "above")) evas_object_raise(o);
263 wd->tot_items_count[1] = i;
264 evas_object_smart_calculate(box); // force a calc so we know the size
265 evas_object_size_hint_min_get(box, &mw, &mh);
268 _index_box_clear(obj, box, level);
271 // FIXME: only i objects fit! try again. overflows right now
275 evas_object_smart_calculate(box);
276 wd->level_active[level] = 1;
280 _index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
282 Widget_Data *wd = elm_widget_data_get(obj);
286 if (!wd->level_active[level]) return;
287 EINA_LIST_FOREACH(wd->items, l, it)
289 if (!it->base) continue;
290 if (it->level != level) continue;
291 evas_object_del(it->base);
294 wd->level_active[level] = 0;
298 _delay_change(void *data)
300 Widget_Data *wd = elm_widget_data_get(data);
302 if (!wd) return ECORE_CALLBACK_CANCEL;
304 d = (void *)elm_index_item_selected_get(data, wd->level);
305 if (d) evas_object_smart_callback_call(data, "delay,changed", d);
306 return ECORE_CALLBACK_CANCEL;
310 _sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
312 Widget_Data *wd = elm_widget_data_get(obj);
313 Elm_Index_Item *it, *it_closest, *it_last;
315 Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
321 Eina_Bool change = EINA_FALSE;
322 char *label = NULL, *last = NULL;
325 for (i = 0; i <= wd->level; i++)
330 evas_object_geometry_get(wd->bx[i], &bx, &by, &bw, &bh);
331 dmin = (double)(wd->min_1st_level_obj_height*wd->tot_items_count[1])/(2*(double)bh);
332 dmax = 1.0-dmin-0.08;
333 EINA_LIST_FOREACH(wd->items, l, it)
335 if (!((it->level == i) && (it->base))) continue;
341 evas_object_geometry_get(it->base, &x, &y, &w, &h);
346 x = (x * x) + (y * y);
347 if ((x < dist) || (!it_closest))
350 cdv = (double)(xx - bx) / (double)bw;
352 cdv = (double)(yy - by) / (double)bh;
357 if ((i == 0) && (wd->level == 0))
359 if(cdv > dmax || cdv < dmin)
369 edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1", cdv, cdvv);
373 edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1", cdv, cdv);
376 if (it_closest) it_closest->selected = 1;
377 if (it_closest != it_last)
382 const char *stacking, *selectraise;
385 if(wd->level == it->level)
386 edje_object_signal_emit(it->base, "elm,state,inactive", "elm");
387 stacking = edje_object_data_get(it->base, "stacking");
388 selectraise = edje_object_data_get(it->base, "selectraise");
389 if ((selectraise) && (!strcmp(selectraise, "on")))
391 if ((stacking) && (!strcmp(stacking, "below")))
392 evas_object_lower(it->base);
397 const char *selectraise;
400 if(wd->level == it->level)
401 edje_object_signal_emit(it->base, "elm,state,active", "elm");
402 selectraise = edje_object_data_get(it->base, "selectraise");
403 if ((selectraise) && (!strcmp(selectraise, "on")))
404 evas_object_raise(it->base);
405 evas_object_smart_callback_call((void *)obj, "changed", (void *)it->data);
406 if (wd->delay) ecore_timer_del(wd->delay);
407 wd->delay = ecore_timer_add(0.2, _delay_change, obj);
414 last = strdup(it->letter);
417 if (!label) label = strdup(last);
420 label = realloc(label, strlen(label) + strlen(last) + 1);
424 last = strdup(it->letter);
428 if (!label) label = strdup("");
429 if (!last) last = strdup("");
436 edje_object_part_text_set(wd->base, "elm.text.body", last);
437 edje_object_signal_emit(wd->base, "hide_2nd_level", "");
440 if( wd->level == 1 && wd->level_active[1])
442 edje_object_part_text_set(wd->base, "elm.text", last);
443 edje_object_signal_emit(wd->base, "hide_first_level", "");
454 _wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
456 Widget_Data *wd = elm_widget_data_get(data);
461 _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
463 Widget_Data *wd = elm_widget_data_get(data);
464 Evas_Event_Mouse_Down *ev = event_info;
467 if (ev->button != 1) return;
469 evas_object_geometry_get(wd->base, &x, &y, NULL, NULL);
470 wd->dx = ev->canvas.x - x;
471 wd->dy = ev->canvas.y - y;
472 elm_index_active_set(data, 1);
473 _sel_eval(data, ev->canvas.x, ev->canvas.y);
474 edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer", wd->dx, wd->dy);
478 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
480 Widget_Data *wd = elm_widget_data_get(data);
481 Evas_Event_Mouse_Up *ev = event_info;
486 if (ev->button != 1) return;
487 if (wd->level == 1 && wd->delay) ecore_timer_del(wd->delay);
490 d = (void *)elm_index_item_selected_get(data, wd->level);
491 EINA_LIST_FOREACH(wd->items, l, it)
493 edje_object_signal_emit(it->base, "elm,state,inactive", "elm");
495 if (d) evas_object_smart_callback_call(data, "selected", d);
496 elm_index_active_set(data, 0);
497 edje_object_signal_emit(wd->base, "elm,state,level,0", "elm");
501 _mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
503 Widget_Data *wd = elm_widget_data_get(data);
504 Evas_Event_Mouse_Move *ev = event_info;
505 Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
509 if (!wd->down) return;
510 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
511 evas_object_geometry_get(wd->base, &x, &y, NULL, NULL);
512 x = ev->cur.canvas.x - x;
513 y = ev->cur.canvas.y - y;
516 if (adx < 0) adx = -dx;
519 if (ady < 0) ady = -dy;
520 edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer", x, y);
531 snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
532 edje_object_signal_emit(wd->base, buf, "elm");
533 evas_object_smart_callback_call(data, "level,up", NULL);
541 snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
542 edje_object_signal_emit(wd->base, buf, "elm");
543 d = (void *)elm_index_item_selected_get(data, wd->level);
544 evas_object_smart_callback_call(data, "changed", d);
545 if (wd->delay) ecore_timer_del(wd->delay);
546 wd->delay = ecore_timer_add(0.2, _delay_change, data);
547 evas_object_smart_callback_call(data, "level,down", NULL);
551 _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
554 _index_box_refill_job(void *data)
556 Widget_Data *wd = elm_widget_data_get((Evas_Object *)data);
562 evas_object_geometry_get(wd->base, NULL, NULL, &pw, &ph);
563 wd->scale_factor = elm_scale_get();
564 if ( wd->scale_factor == 0.0 ) {
565 wd->scale_factor = 1.0;
567 string = edje_object_data_get(wd->base, "min_obj_height");
569 wd->min_obj_height = (int) (atoi(string))*wd->scale_factor;
571 wd->min_obj_height = MIN_OBJ_HEIGHT*wd->scale_factor;
572 if(!wd->min_obj_height) return;
574 wd->max_grp_size = wd->min_obj_height - 2*MIN_GRP_SIZE;
575 wd->items_count = ph/wd->min_obj_height;
576 wd->max_supp_items_count = wd->max_grp_size*(int)((wd->items_count-1)*0.5)+wd->items_count;
578 if(pw != wd->pwidth && ph != wd->pheight)
583 elm_index_active_set(data, 1);
585 _index_box_clear((Evas_Object *)data, wd->bx[0], 0);
586 evas_object_smart_calculate( wd->bx[0]);
587 elm_index_item_go((Evas_Object *)data, wd->level);
593 static void _index_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
597 wd = elm_widget_data_get((Evas_Object *)data);
599 ecore_job_add(_index_box_refill_job, (Evas_Object *)data);
603 * Add a new index to the parent
605 * @param parent The parent object
606 * @return The new object or NULL if it cannot be created
611 elm_index_add(Evas_Object *parent)
617 Evas_Coord minw, minh;
620 wd = ELM_NEW(Widget_Data);
621 e = evas_object_evas_get(parent);
623 obj = elm_widget_add(e);
624 ELM_SET_WIDTYPE(widtype, "index");
625 elm_widget_type_set(obj, "index");
626 elm_widget_sub_object_add(parent, obj);
627 elm_widget_data_set(obj, wd);
628 elm_widget_del_hook_set(obj, _del_hook);
629 elm_widget_theme_hook_set(obj, _theme_hook);
631 wd->horizontal = EINA_FALSE;
632 wd->min_obj_height = 0;
633 wd->max_grp_size = 0;
635 wd->max_supp_items_count = 0;
636 wd->tot_items_count[0] = 0;
637 wd->tot_items_count[1] = 0;
639 wd->special_char = edje_object_data_get(wd->base, "special_char");
640 if(wd->special_char == NULL) wd->special_char = eina_stringshare_add("*");
642 wd->base = edje_object_add(e);
643 _elm_theme_object_set(obj, wd->base, "index", "base/vertical", "default");
644 elm_widget_resize_object_set(obj, wd->base);
646 o = evas_object_rectangle_add(e);
648 evas_object_color_set(o, 0, 0, 0, 0);
650 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
651 evas_object_size_hint_min_set(o, minw, minh);
652 edje_object_part_swallow(wd->base, "elm.swallow.event.0", o);
653 elm_widget_sub_object_add(obj, o);
654 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _index_object_resize, obj);
655 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _wheel, obj);
656 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, obj);
657 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _mouse_up, obj);
658 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, obj);
660 if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
662 o = evas_object_rectangle_add(e);
664 evas_object_color_set(o, 0, 0, 0, 0);
665 evas_object_size_hint_min_set(o, minw, minh);
666 edje_object_part_swallow(wd->base, "elm.swallow.event.1", o);
667 elm_widget_sub_object_add(obj, o);
670 wd->bx[0] = evas_object_box_add(e);
671 evas_object_box_layout_set(wd->bx[0], _layout, wd, NULL);
672 elm_widget_sub_object_add(obj, wd->bx[0]);
673 edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
674 evas_object_show(wd->bx[0]);
676 if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
678 wd->bx[1] = evas_object_box_add(e);
679 evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
680 elm_widget_sub_object_add(obj, wd->bx[1]);
681 edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
682 evas_object_show(wd->bx[1]);
685 wd->scale_factor = elm_scale_get();
686 if ( wd->scale_factor == 0.0 ) {
687 wd->scale_factor = 1.0;
689 string = edje_object_data_get(wd->base, "min_1st_level_obj_height");
691 wd->min_1st_level_obj_height = (int) (atoi(string))*wd->scale_factor;
693 wd->min_1st_level_obj_height = MIN_OBJ_HEIGHT*wd->scale_factor;
699 _group_count(Evas_Object *obj, int extraIndex, int adj_pos, int vis_pos)
701 Widget_Data *wd = elm_widget_data_get(obj);
703 int group_count = MIN_GRP_SIZE;
704 while(group_count <= wd->max_grp_size)
706 if(extraIndex <= wd->max_grp_size*adj_pos)
708 if(group_count*adj_pos>=extraIndex) return group_count;
711 return wd->max_grp_size;
713 group_count += MIN_GRP_SIZE;
718 _index_process(Evas_Object *obj)
721 int j,i, group_count;
727 Widget_Data *wd = elm_widget_data_get(obj);
730 if (wd->items_count == 0) return;
732 const int adj_pos = (wd->items_count-1)*0.5;
733 if(wd->tot_items_count[wd->level] <= wd->max_supp_items_count)
734 n = wd->tot_items_count[wd->level];
736 n = wd->max_supp_items_count;
737 group_count = MIN_GRP_SIZE;
739 int *indx = (int*)calloc(n, sizeof(int));
742 const int minh = wd->min_obj_height;
743 EINA_LIST_FOREACH(wd->items, l, it)
745 it->vis_letter = eina_stringshare_add(it->letter);
750 int N = wd->items_count;
757 if (extraIndex < 0) return;
759 group_count = _group_count(obj, extraIndex, adj_pos, N);
760 if (group_count <= 0) return;
762 PlacementPart place[adj_pos];
763 remainder = extraIndex%group_count;
764 numberofparts=(extraIndex/group_count)+(remainder == 0? 0: 1);
766 for (i=0;i<numberofparts; i++)
768 place[i].count=group_count+1;
769 count = (int)(((float)(i+1)/(float)(numberofparts+1))*N);
770 place[i].start= count +i*group_count-1;
773 place[numberofparts-1].count=remainder+1;
775 for (i=0;i<numberofparts;i++)
777 for (j=0;j<place[i].count; j++)
779 indx[((place[i].start)+j)]= MIN_PIXEL_VALUE;
781 indx[(place[i].start+(place[i].count)/2)] = minh-place[i].count+1;
784 EINA_LIST_FOREACH(wd->items, l, it)
786 int size = indx[count];
790 it->vis_letter = eina_stringshare_add(it->letter);
795 eina_stringshare_del(it->vis_letter);
796 it->vis_letter = eina_stringshare_add("");
800 eina_stringshare_del(it->vis_letter);
801 it->vis_letter = eina_stringshare_add(wd->special_char);
803 it->size = size*wd->scale_factor;
812 * Set the active state of the index programatically
814 * @param obj The index object
815 * @param active The active starte
820 elm_index_active_set(Evas_Object *obj, Eina_Bool active)
822 ELM_CHECK_WIDTYPE(obj, widtype);
823 Widget_Data *wd = elm_widget_data_get(obj);
825 if (wd->active == active) return;
830 _index_box_clear(obj, wd->bx[1], 1);
832 _index_box_auto_fill(obj, wd->bx[0], 0);
833 edje_object_signal_emit(wd->base, "elm,state,active", "elm");
836 edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
840 * Sets the level of the item.
842 * @param obj The index object.
843 * @param level To be documented.
848 elm_index_item_level_set(Evas_Object *obj, int level)
850 ELM_CHECK_WIDTYPE(obj, widtype);
851 Widget_Data *wd = elm_widget_data_get(obj);
853 if (wd->level == level) return;
858 * Gets the level of the item.
860 * @param obj The index object
865 elm_index_item_level_get(const Evas_Object *obj)
867 ELM_CHECK_WIDTYPE(obj, widtype) 0;
868 Widget_Data *wd = elm_widget_data_get(obj);
874 * Returns the selected item.
876 * @param obj The index object.
877 * @param level to be documented.
882 elm_index_item_selected_get(const Evas_Object *obj, int level)
884 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
885 Widget_Data *wd = elm_widget_data_get(obj);
888 if (!wd) return NULL;
889 EINA_LIST_FOREACH(wd->items, l, it)
890 if ((it->selected) && (it->level == level)) return it->data;
895 * Appends a new item.
897 * @param obj The index object.
898 * @param letter Letter under which the item should be indexed
899 * @param item The item to put in the index
904 elm_index_item_append(Evas_Object *obj, const char *letter, const void *item)
906 ELM_CHECK_WIDTYPE(obj, widtype);
907 Widget_Data *wd = elm_widget_data_get(obj);
910 it = _item_new(obj, letter, item);
912 wd->items = eina_list_append(wd->items, it);
913 wd->tot_items_count[wd->level]++;
914 _index_box_clear(obj, wd->bx[wd->level], wd->level);
918 * Prepends a new item.
920 * @param obj The index object.
921 * @param letter Letter under which the item should be indexed
922 * @param item The item to put in the index
927 elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item)
929 ELM_CHECK_WIDTYPE(obj, widtype);
930 Widget_Data *wd = elm_widget_data_get(obj);
934 it = _item_new(obj, letter, item);
936 wd->items = eina_list_prepend(wd->items, it);
937 wd->tot_items_count[wd->level]++;
938 _index_box_clear(obj, wd->bx[wd->level], wd->level);
942 * Append an item after @p relative in letter @p letter.
944 * @param obj The index object
945 * @param letter Letter under which the item should be indexed
946 * @param item The item to put in the index
947 * @param relative The item to put @p item after
952 elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative)
954 ELM_CHECK_WIDTYPE(obj, widtype);
955 Widget_Data *wd = elm_widget_data_get(obj);
956 Elm_Index_Item *it, *it_rel;
960 elm_index_item_append(obj, letter, item);
961 wd->tot_items_count[wd->level]++;
964 it = _item_new(obj, letter, item);
965 it_rel = _item_find(obj, relative);
968 elm_index_item_append(obj, letter, item);
969 wd->tot_items_count[wd->level]++;
973 wd->items = eina_list_append_relative(wd->items, it, it_rel);
974 wd->tot_items_count[wd->level]++;
975 _index_box_clear(obj, wd->bx[wd->level], wd->level);
979 * Prepend an item before @p relative in letter @p letter.
981 * @param obj The index object
982 * @param letter Letter under which the item should be indexed
983 * @param item The item to put in the index
984 * @param relative The item to put @p item before
989 elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative)
991 ELM_CHECK_WIDTYPE(obj, widtype);
992 Widget_Data *wd = elm_widget_data_get(obj);
993 Elm_Index_Item *it, *it_rel;
997 elm_index_item_prepend(obj, letter, item);
998 wd->tot_items_count[wd->level]++;
1001 it = _item_new(obj, letter, item);
1002 it_rel = _item_find(obj, relative);
1005 elm_index_item_append(obj, letter, item);
1006 wd->tot_items_count[wd->level]++;
1010 wd->items = eina_list_prepend_relative(wd->items, it, it_rel);
1011 wd->tot_items_count[wd->level]++;
1012 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1016 * Insert a new @p item into the sorted index @p obj in @p letter.
1018 * @param obj The index object
1019 * @param letter Letter under which the item should be indexed
1020 * @param item The item to put in the index
1021 * @param cmp_func The function called for the sort of index items.
1022 * @param cmp_data_func The function called for the sort of the data. It will
1023 * be used when cmp_func return 0. It means the index item already exists.
1024 * So, to decide which data item should be pointed by the index item, a function
1025 * to compare them is needed. If this function is not provided, index items
1026 * will be duplicated. If cmp_data_func returns a non-negative value, the
1027 * previous index item data will be replaced by the inserted @p item. So
1028 * if the previous data need to be free, it should be done in this function,
1029 * because the reference will be lost.
1034 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)
1036 ELM_CHECK_WIDTYPE(obj, widtype);
1037 Widget_Data *wd = elm_widget_data_get(obj);
1045 elm_index_item_append(obj, letter, item);
1049 it = _item_new(obj, letter, item);
1052 lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
1054 wd->items = eina_list_append_relative_list(wd->items, it, lnear);
1056 wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
1059 /* If cmp_data_func is not provided, append a duplicated item */
1061 wd->items = eina_list_append_relative_list(wd->items, it, lnear);
1064 Elm_Index_Item *p_it = eina_list_data_get(lnear);
1065 if (cmp_data_func(p_it->data, it->data) >= 0)
1066 p_it->data = it->data;
1071 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1075 * Remove an item from the index.
1077 * @param obj The index object
1078 * @param item The item to remove from the index
1083 elm_index_item_del(Evas_Object *obj, const void *item)
1085 ELM_CHECK_WIDTYPE(obj, widtype);
1086 Widget_Data *wd = elm_widget_data_get(obj);
1089 it = _item_find(obj, item);
1092 wd->tot_items_count[wd->level]--;
1093 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1097 * Find an index item using item data.
1099 * @param obj The index object
1100 * @param item The item pointed by index item
1101 * @return The index item pointing to @p item
1105 EAPI Elm_Index_Item *
1106 elm_index_item_find(Evas_Object *obj, const void *item)
1108 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1109 Widget_Data *wd = elm_widget_data_get(obj);
1110 if (!wd) return NULL;
1111 return _item_find(obj, item);
1115 * Clears an index of its items.
1117 * @param obj The index object.
1122 elm_index_item_clear(Evas_Object *obj)
1124 ELM_CHECK_WIDTYPE(obj, widtype);
1125 Widget_Data *wd = elm_widget_data_get(obj);
1127 Eina_List *l, *clear = NULL;
1129 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1130 EINA_LIST_FOREACH(wd->items, l, it)
1132 if (it->level != wd->level) continue;
1133 clear = eina_list_append(clear, it);
1135 EINA_LIST_FREE(clear, it) {
1137 wd->tot_items_count[wd->level]--;
1142 * Go to item at @p level
1144 * @param obj The index object
1145 * @param level The index level
1150 elm_index_item_go(Evas_Object *obj, int level)
1152 ELM_CHECK_WIDTYPE(obj, widtype);
1153 Widget_Data *wd = elm_widget_data_get(obj);
1156 _index_process(obj);
1157 _index_box_auto_fill(obj, wd->bx[0], 0);
1158 if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
1162 * Returns the data associated with the item.
1164 * @param it The list item
1165 * @return The data associated with @p it
1170 elm_index_item_data_get(const Elm_Index_Item *it)
1172 if (!it) return NULL;
1173 return (void *)it->data;
1177 * Set the data item from the index item
1179 * This set a new data value.
1181 * @param it The item
1182 * @param data The new data pointer to set
1187 elm_index_item_data_set(Elm_Index_Item *it, const void *data)
1194 * Gets the letter of the item.
1196 * @param it The list item
1197 * @return The letter of @p it
1202 elm_index_item_letter_get(const Elm_Index_Item *it)
1204 if (!it) return NULL;
1209 * Make the Central Button Image invisible.
1211 * @param obj The Index.
1212 * @param invisible Whether button visible or not.
1218 elm_index_button_image_invisible_set(Evas_Object *obj, Eina_Bool invisible)
1220 ELM_CHECK_WIDTYPE(obj, widtype);
1221 Widget_Data *wd = elm_widget_data_get(obj);
1222 wd->hide_button = invisible;
1224 edje_object_signal_emit(wd->base, "elm,state,button,image,hide", "elm");